# How can I test the first character on each line of a listing?

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?

\documentclass{article}

\usepackage{listings}

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

\makeatletter
\def\detectF#1{\ifx f#1 YES#1\fi}
\newcount\mycount
\makeatother

\begin{document}

\makeatletter

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

\lstinputlisting[basicstyle=\ttfamily]{sample.c}

\makeatother

\end{document}

• 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. Feb 7, 2014 at 23:10
• @JosephWright How do you insert showtokens into the hook? \makeatletter \lst@AddToHook{EveryLine}{\showtokens} \makeatother returns an error. 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}} Feb 8, 2014 at 7:05

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

\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
\makeatother
\begin{document}

\makeatletter

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


• Thanks again. At some stage, I should really allocate some time to read the listings source code from beginning to end. Feb 8, 2014 at 12:25
• @Jubobs: You can use: \def\@splitfirstchar#1#2#3\@nil{\gdef\@detectFirst{#1}\gdef\@detectSecond{#2}} Feb 8, 2014 at 20:13