Here we have to take care of two things: dropping empty lines at the end of a listing and the different column formats. Both use \lst@lostspace. Lines containing only tabulators and spaces should be viewed as empty. In order to achieve this, tabulators and spaces at the beginning of a line don’t output any characters but advance \lst@lostspace. Whenever this dimension is positive we insert that space before the character string is output. Thus, if there are only tabulators and spaces, the line is ‘empty’ since we haven’t done any output.
We have to do more for flexible columns. Whitespaces can fix the column alignment: if the real line is wider than expected, a tabulator is at least one space wide; all remaining space fixes the alignment. If there are two or more space characters, at least one is printed; the others fix the column alignment.
Tabulators are processed in three stages. You have already seen the last stage
\lst@GotoTabStop. The other two calculate the necessary width and take care of visible tabulators and spaces.
tabsize We check for a legal argument before saving it. Default tabsize is 8 as proposed by Rolf Niepraschk.
898\lst@Key{tabsize}{8}
899 {\ifnum#1>\z@ \def\lst@tabsize{#1}\else
900 \PackageError{Listings}{Strict positive integer expected}%
901 {You can’t use ‘#1’ as tabsize. \@ehc}%
902 \fi}
showtabs tab
Two more user keys for tab control.
903\lst@Key{showtabs}f[t]{\lstKV@SetIf{#1}\lst@ifshowtabs}
904\lst@Key{tab}{\kern.06em\hbox{\vrule\@height.3ex}%
905 \hrulefill\hbox{\vrule\@height.3ex}}
906 {\def\lst@tab{#1}}
\lst@ProcessTabulator A tabulator outputs the preceding characters, which decrements\lst@posby the number of printed characters.
907\def\lst@ProcessTabulator{%
908 \lst@XPrintToken \lst@whitespacetrue
Then we calculate how many columns we need to reach the next tabulator stop:
we add\lst@tabsizeuntil\lst@posis strict positive. In other words,\lst@pos is the column modulotabsizeand we’re looking for a positive representative. We assign it to\lst@length and reset\lst@posin the submacro.
909 \global\advance\lst@column -\lst@pos
910 \@whilenum \lst@pos<\@ne \do
911 {\global\advance\lst@pos\lst@tabsize}%
912 \lst@length\lst@pos
913 \lst@PreGotoTabStop}
\lst@PreGotoTabStop Visible tabs print\lst@tab.
914\def\lst@PreGotoTabStop{%
915 \lst@ifshowtabs
916 \lst@TrackNewLines
917 \setbox\@tempboxa\hbox to\lst@length\lst@width
918 {{\lst@currstyle{\hss\lst@tab}}}%
919 \lst@CalcLostSpaceAndOutput
920 \else
If we are advised to keep spaces, we insert the correct number of them.
921 \lst@ifkeepspaces
922 \@tempcnta\lst@length \lst@length\z@
923 \@whilenum \@tempcnta>\z@ \do
924 {\lst@AppendOther\lst@outputspace
925 \advance\@tempcnta\m@ne}%
926 \lst@OutputOther
927 \else
928 \lst@GotoTabStop
929 \fi
930 \fi
931 \lst@length\z@ \global\lst@pos\z@}
Spaces are implemented as described at the beginning of this subsection. But first we define some user keys.
\lst@outputspace
\lst@visiblespace
The first macro is a default definition, . . .
932\def\lst@outputspace{\ }
933\def\lst@visiblespace{\lst@ttfamily{\char32}\textvisiblespace}
showspaces keepspaces
. . . which is modified on user’s request.
934\lst@Key{showspaces}{false}[t]{\lstKV@SetIf{#1}\lst@ifshowspaces}
935\lst@Key{keepspaces}{false}[t]{\lstKV@SetIf{#1}\lst@ifkeepspaces}
936\lst@AddToHook{Init}
937 {\lst@ifshowspaces
938 \let\lst@outputspace\lst@visiblespace
939 \lst@keepspacestrue
940 \fi}
941\def\lst@keepspacestrue{\let\lst@ifkeepspaces\iftrue}
\lst@ProcessSpace We look whether spaces fix the column alignment or not. In the latter case we append a space; otherwise . . . Andrei Alexandrescu tested the spaceflexible column setting and found a bug that resulted from \lst@PrintToken and
\lst@whitespacetruebeing out of order here.
942\def\lst@ProcessSpace{%
943 \lst@ifkeepspaces
944 \lst@PrintToken
945 \lst@whitespacetrue
946 \lst@AppendOther\lst@outputspace
947 \lst@PrintToken
948 \else \ifnum\lst@newlines=\z@
. . . we append a ‘special space’ if the line isn’t empty.
949 \lst@AppendSpecialSpace
950 \else \ifnum\lst@length=\z@
If the line is empty, we check whether there are characters in the output queue. If there are no characters we just advance\lst@lostspace. Otherwise we append the space.
951 \global\advance\lst@lostspace\lst@width
952 \global\advance\lst@pos\m@ne
953 \lst@whitespacetrue
954 \else
955 \lst@AppendSpecialSpace
956 \fi
957 \fi \fi}
Note that this version works for fixed and flexible column output.
\lst@AppendSpecialSpace If there are at least two white spaces, we output preceding characters and advance
\lst@lostspace to avoid alignment problems. Otherwise we append a space to the current character string. Also, \lst@whitespacetrue has been moved after\lst@PrintTokenso that the token-printer can correctly check whether it is printing whitespace or not; this was preventing thespaceflexiblecolumn setting from working correctly.
958\def\lst@AppendSpecialSpace{%
959 \lst@ifwhitespace
960 \lst@PrintToken
961 \global\advance\lst@lostspace\lst@width
962 \global\advance\lst@pos\m@ne
963 \lst@gobbledwhitespacetrue
964 \else
965 \lst@PrintToken
966 \lst@whitespacetrue
967 \lst@AppendOther\lst@outputspace
968 \lst@PrintToken
969 \fi}
Form feeds has been introduced after communication with Jan Braun.
formfeed let the user make adjustments.
970\lst@Key{formfeed}{\bigbreak}{\def\lst@formfeed{#1}}
\lst@ProcessFormFeed Here we execute some macros according to whether a new line has already begun or not. No \lst@EOLUpdate is used in the else branch anymore—Kalle Tuulos sent the bug report.
971\def\lst@ProcessFormFeed{%
972 \lst@XPrintToken
973 \ifnum\lst@newlines=\z@
974 \lst@EOLUpdate \lsthk@InitVarsBOL
975 \fi
976 \lst@formfeed
977 \lst@whitespacetrue}