8

as the title suggests, I'm looking for a way to get the first (printable) line in an environment. My first naive attempt (ignoring the printable requirement) was something like this:

\newcommand*{\theline}{}
\newcommand*{\getline}[1]{%
  \renewcommand*{\theline}{#1}%
  #1%
}

\newenvironment{anewenvironment}{%
  \getline%
}{}

However, afterwards \theline is only the first character. Eg.

\begin{anewenvironment}
  Test
\end{anewenvironment}
Line: \theline

prints:

Test
Line: T

when the required output is:

Test
Line: Test

I suppose this indicates a fundamental misunderstanding about how TeX/LaTeX handles arguments on my part, so any ideas or more broad clarification on how arguments are handled would be appreciated. Thanks.

P.S. I understand that the concept of a "line" is rather vague — "paragraph" might be a better term in retrospect, though "X words" would also fit my use case.

EDIT: The aim of this is to find a way to automatically get incipits for poetry or blocks of text. See this issue on PoetryTeX for more info.

EDIT 2: Looks like none of these solutions are very good for what I need, however, they did answer my question so I've marked an answer.

  • It would be interesting to know what exactly you want to achieve. – Hendrik Vogt Feb 13 '13 at 16:36
  • @Hendrick Vogt: I'm attempting to automatically generate an incipit for poetry (https://github.com/SamWhited/poetrytex/issues/1) –  Feb 13 '13 at 16:55
  • Do you need a variable number of first words or will it be a constant number for all of the incipits? – Gonzalo Medina Feb 13 '13 at 17:19
  • Variable number would be nice. I'm exploring the solution below by bloodworks, but I think the answer will end up being a recursive command. Unfortunately I'm not really sure what's feasible while keeping the solution robust. –  Feb 13 '13 at 17:22
  • 2
    It's possible but a bit fragile, but it would be more normal latex style to add markup to mark the incipit If you have \incipit{a part of the first line} as markup at the start of your poem it would be easy to define that to do whatever you need. – David Carlisle Feb 13 '13 at 18:27
  • @DavidCarlisle You're probably right; I was hoping to automate the task a bit more than that, but you solution is closer to the "LaTeX way." I may end up doing just that. –  Feb 13 '13 at 18:30
  • 1
    See for similar http://tex.stackexchange.com/a/87087/963 – yannisl Feb 13 '13 at 19:25
  • @YiannisLazarides: Thanks for the link; I'm surprised I didn't find that before. –  Feb 13 '13 at 19:54
  • 1
    Possibly useful related question: http://tex.stackexchange.com/questions/47570/newtoks-token-seems-to-have-local-scope (uninformative title). I didn't even try to find the first line programmatically. – Ethan Bolker Feb 15 '13 at 16:16

2 Answers2

7

If you like to scan for more than one token you need to tell TeX so. \def\x#1{...} will scan exactly one token. While \def\x#1\\{...} will scan until a \\ is reached (and raise an error if no such thing is present.)

So to scan one paragraph we do \def\x#1\par{...} and hope that somewhen a \par occurs.

\documentclass{report}

\begin{document}


\def\getline#1\par{%
\gdef\theline{#1}#1%
}

\newenvironment{anewenvironment}{%
  \getline%
}{}

\begin{anewenvironment}
Test

New par

\end{anewenvironment}
Line: \theline

\end{document}

Scans the 'first line'. Will raise error if there is no par in the environment.

Output will be

Test new par
Line: Test
bloodworks
  • 10,178
  • This does also gobble the \par, but could be re-inserted if needed. – Werner Feb 13 '13 at 17:12
  • Thanks for the answer; I have a feeling this is going to be a bit fragile (not in the TeX sense; in a general "it's easy for the user to break it" sense) — but I'm exploring it as a possibility. Thanks again! –  Feb 13 '13 at 17:23
  • 3
    To make it more robust one has to scan for \par and \end; but the safest way is probably inputting the "first paragraph" as an argument to the environment. – egreg Feb 13 '13 at 17:30
  • @egreg: How can one scan for \par and \end? Unfortunately first paragraph as an argument isn't an option (part of the feature request is to automate the process as much as possible). –  Feb 13 '13 at 17:36
  • @Werner yes. Thoug it should be quite clear how to reinsert \par again. @egreg true enough. I just intended to keep it simply since i really don't know what's @SamWhited's aim. A true argument would be my choice too. – bloodworks Feb 13 '13 at 18:16
  • I added some clarification on the actual use of this in the question. Thanks again to those who have answered / helped out so far! –  Feb 13 '13 at 18:34
  • Sorry to downvote, but the \par in the end-environment code will never be seen by \getline. – Bruno Le Floch Feb 13 '13 at 21:47
  • @BrunoLeFloch indeed i should have known that. I have corrected the statement. – bloodworks Feb 14 '13 at 07:30
  • I've reversed my vote :). – Bruno Le Floch Feb 14 '13 at 11:57
  • Thanks for your help; unfortunately this doesn't really work in my situation, but it was the first answer that answered the question I asked, so I've marked it as the answer. Thanks again! –  Feb 15 '13 at 15:03
7

Here's a possibility that however can easily break if there are nested environments or the first \par (blank line) is hidden by braces.

\documentclass{report}
\usepackage{environ}

\NewEnviron{anewenvironment}
 {\expandafter\getpar\BODY\par\end\BODY}
\long\def\getpar#1\par#2\end{\gdef\theline{#1}}

\begin{document}

\begin{anewenvironment}
Testa

New par

\end{anewenvironment}
Line: \theline

\begin{anewenvironment}
Testb
\end{anewenvironment}
Line: \theline
\end{document}
egreg
  • 1,121,712
  • 1
    environ is cheating! ;-) – bloodworks Feb 13 '13 at 18:16
  • Thanks; it seems like this is even more of a challenge than I thought. Maybe the answer is to use a recursive function to gobble words until some token (maybe \incipitend and/or just \end) is reached. Will play with this as well and see what I can come up with. –  Feb 13 '13 at 18:28