Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I know how to define a macro that will take the rest of the paragraph as parameter. Simply write \def\a#1\par{\textbf{#1}}.

But, how do I write a macro whose argument will extend to the end of the line?

share|improve this question
    
Please see tex.stackexchange.com/editing-help to learn how to format your posts correctly. I took the liberty to do this for you here. –  Martin Scharrer Feb 6 '11 at 20:14
    
if you are looking to catch all lines, individually in a block of text you can see my reply for this tex.stackexchange.com/questions/9657/… –  Yiannis Lazarides Feb 7 '11 at 2:57
    
fixed the formatting, thanks Martin! –  Yossi Gil Feb 7 '11 at 10:26

3 Answers 3

up vote 10 down vote accepted

This answer builds upon Martin Scharrer's updated solution (which was based on mine, based on his... ;-p).

\documentclass{article}
\begin{document}
\newcommand*{\newlinecommand}[2]{%
  \newcommand*{#1}{%
    \begingroup%
    \escapechar=`\\%
    \catcode\endlinechar=\active%
    \csname\string#1\endcsname%
  }%
  \begingroup%
  \escapechar=`\\%
  \lccode`\~=\endlinechar%
  \lowercase{%
    \expandafter\endgroup
    \expandafter\def\csname\string#1\endcsname##1~%
  }{\endgroup#2\space}%
}

%%% USAGE:
\newlinecommand{\emphline}{\emph{#1}}

First words \emphline rest of line
some more text

\end{document}

\emphline sets up the catcode of the end-line character to be active (we could have used a few other choices, as long as it is consistent). It then calls \\emphline, which takes care of grabbing the argument until the end of the line, and applies \emph{ } to it (this is #2 in the definition of \newlinecommand).

We use \begingroup and \endgroup to limit the scope of our change in catcode of \endlinechar to the inside of \emphline.

In order to grab the end of the line, we use a delimited argument, but for this, we need to have an active end-of-line character. Two possibilities:

  • change the catcode locally and then use this active end-of-line in the definition, but this fails in our case, because we are already inside a definition (of \newlinecommand), and catcodes cannot change anymore

  • use \lowercase{~} after defining a lowercase ~ to be the end-of-line character.

Finally, the construction \csname\string#1\endcsname makes the control sequence \\emphline in our case (because #1 is \emphline). We make sure that \string produces \emphline by setting the escape character (that TeX uses for \string) to actually be \.

share|improve this answer
    
Absolutely brilliant! Maybe this should go into a small package? –  Yossi Gil Feb 7 '11 at 6:33
    
@Bruno: Nice solution. Yes, you can modify it to avoid the doubling of #. See my updated example. Also @Yossi. –  Martin Scharrer Feb 7 '11 at 7:21
    
@Bruno: Very nice answer! Could you edit it so that the best updated solution is shown first? There is no need to keep a (visible) record of how the answer was improved over time. Editing history is always available by clicking on the link next to “edited”. –  Juan A. Navarro Feb 7 '11 at 10:14
    
@Juan: since it was accepted, I assumed that I shouldn't change it without some form of consent from someone. I guess a moderator is enough ;). –  Bruno Le Floch Feb 7 '11 at 10:19
    
@Bruno: Nice adaption again. I don't like the name newlinecommand very much because its reads more like a command for newline s. I don't think the code is used so often by many people to justify an own package. Maybe it could be added to an existing package which provides new command definition macros. –  Martin Scharrer Feb 7 '11 at 10:22

The end-of-line character in TeX is the ASCII 13 Carriage Return character which can be represented by ^^M (M=13th character in the alphabet). This is independent of the actual input file format (i.e. DOS/Windows vs. Unix vs. Mac end-of-line characters).

However you cannot simply write \def\a#1^^M{\textbf{#1}} because TeX doesn't like this. One way is to redefine the catcode (see The TeXBook) of it:

\def\restofline{%
    \begingroup
    \catcode`\^^M=\active
    \irestofline
}
\begingroup
\catcode`\^^M=\active %
\gdef\irestofline#1^^M{%
  \iirestofline{#1}%
  \endgroup %
  \space % Readd effective space from removed end-of-line
}%
\endgroup %

\def\iirestofline#1{\textbf{#1}}

%%% USAGE:
First words \restofline rest of line

This worked in my tests, but might be flawed somehow and there might be better/more efficient ways to do it.

Please note that the end-of-line can be commented out using % in which case this macro will also read the next line.


Here a variation of the solution of Bruno Le Floch (which is based on my solution above) where # in #1 doesn't have to be doubled. The trick is to use a second macro for this. Note that \csname\string#1\endcsname generates a command sequence \\foo from \foo.

\documentclass{article}
\begin{document}
\makeatletter
\newcommand*{\newlinecommand}[1]{%
  \newcommand*{#1}{%
    \begingroup%
    \lccode`\~=\endlinechar%
    \lowercase{\def\restofline@aux####1~}{\endgroup\csname\string#1\endcsname{####1}\space}%
    \catcode\endlinechar=\active%
    \restofline@aux%
  }%
  \expandafter\def\csname\string#1\endcsname##1%
}
\makeatother

%%% USAGE:
\newlinecommand{\emphline}{\emph{#1}}

First words \emphline rest of line
some more text

\end{document}

Please also note that there is a parselines package which might be used. Its code might be a good read for people interested in this kind of parsing.

share|improve this answer
    
it is even possible to get rid of the \def\restofline@aux (see my updated answer). Do you think that this is useful enough that we should package it? –  Bruno Le Floch Feb 7 '11 at 10:11

Here is a crude solution that relies on changing catcodes:

\def\TEST
  {\begingroup
   \catcode`\^^M=13
   \doTEST}

\begingroup
\catcode`\^^M=13
\gdef\doTEST#1^^M%
  {\endgroup The line argument is :#1:}
\endgroup

\TEST this is a command that takes on line
as an argument

some more text

\bye
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.