7

The listings package defines a hook called EveryLine to allow users to execute TeX code at the beginning of each line of a listing; the following is taken directly from the listings source code (listings.dtx):

\hookname{EveryLine}

Executed at the beginning of each \emph{output} line, i.e.~more than
once for broken lines. This hook must not change the horizontal or
vertical position.

The code below is my attempt at using this hook to test whether the first character of each line is f and insert YES before it in that case. However, as you can see below, I'm not getting the expected output.

At first, I thought if might be a grouping problem: the code inserted at the EveryLine might be buried inside a group and, as a result, my test could not access the first token on the line, because that token lies outside the group in question. However, a quick test (consisting in locally incrementing a TeX register) shows that it's not the case.

Any idea what I'm doing wrong?

enter image description here

\documentclass{article}

\usepackage{listings}

\usepackage{filecontents}
\begin{filecontents*}{sample.c}
foo
bar
frivolous
thing
discourse
fragile
\end{filecontents*}

\makeatletter
\lst@AddToHook{EveryLine}{\@ddedToEveryline}
\def\detectF#1{\ifx f#1 YES#1\fi}
\newcount\mycount
\def\advandprintCount{\advance\mycount by \@ne\the\mycount}
\makeatother

\begin{document}

\makeatletter

\let\@ddedToEveryline\detectF
\lstinputlisting[basicstyle=\ttfamily]{sample.c}

\let\@ddedToEveryline\advandprintCount
\lstinputlisting[basicstyle=\ttfamily]{sample.c}

\makeatother

\end{document}
3
  • Not sure this is an answer, but 'this won't work'. If you insert a \showtokens into th ehook, you'll find that #1 is not the start of the line of output but a load of listings code: you therefore never see the letter you are after.
    – Joseph Wright
    Feb 7, 2014 at 23:10
  • @JosephWright How do you insert showtokens into the hook? \makeatletter \lst@AddToHook{EveryLine}{\showtokens} \makeatother returns an error.
    – jub0bs
    Feb 7, 2014 at 23:18
  • \def\detectF#1{\showtokens{#1}\ifx f#1 YES#1\fi}} then \def\detectF#1{\showtokens\expandafter{#1}\ifx f#1 YES#1\fi}}
    – Joseph Wright
    Feb 8, 2014 at 7:05

1 Answer 1

6
+50

Here's my try:

\documentclass{article}
\usepackage{pdftexcmds}
\usepackage{listings}

\usepackage{filecontents}
\begin{filecontents*}{sample.c}
foo
bar
frivolous
thing
discourse
fragile
\end{filecontents*}

\makeatletter
\lst@AddToHook{EveryLine}{\@ddedToEveryline}

\def\@splitfirstchar#1#2\@nil{\gdef\@detectF{#1}}
\def\splitfirstchar#1{\@splitfirstchar#1\@nil} 
\def\@detectF{%
%  -\the\lst@token-
  \expandafter\splitfirstchar\expandafter{\the\lst@token}%
  \def\@tempa{f}%
%  -\@detectF-
  \ifnum\pdf@strcmp{\@detectF}{\@tempa}=\z@
     YES
  \else
     NO
  \fi%
}
\newcount\mycount
\def\advandprintCount{\advance\mycount by \@ne\the\mycount}
\makeatother
\begin{document}

\makeatletter

\let\@ddedToEveryline\@detectF
\lstinputlisting[basicstyle=\ttfamily]{sample.c}

\let\@ddedToEveryline\advandprintCount
\lstinputlisting[basicstyle=\ttfamily]{sample.c}

\makeatother

\end{document}

enter image description here

4
  • The output looks promising! Your code returned an error, so I took the liberty to edit it. Let me experiment with it a bit more before I give you the checkmark, but your solution looks like what I was looking for. Thanks so much!
    – jub0bs
    Feb 8, 2014 at 11:30
  • Thanks again. At some stage, I should really allocate some time to read the listings source code from beginning to end.
    – jub0bs
    Feb 8, 2014 at 12:25
  • Marco, here is a follow-up question (assuming it's not too involved): how could I also peek at the second token on the line?
    – jub0bs
    Feb 8, 2014 at 19:06
  • @Jubobs: You can use: \def\@splitfirstchar#1#2#3\@nil{\gdef\@detectFirst{#1}\gdef\@detectSecond{#2}} Feb 8, 2014 at 20:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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