TeX - LaTeX Asked on May 19, 2021
I was wondering if it was possible to make the listings package show a return symbol like "⮑" when a line break occurs.
With default line numbering settings this is not needed, as the line break creates a blank space between two consecutive line numbers, but it may be useful if one is using interval line numbering (e.g. 1-5-10-15-20), where only few lines are numbered.
My idea was redefining the line break macro searching for "ifbreaklines" (the option name) in lstmisc.sty
, but I can’t find any implementation guide and the file has no comments.
EDIT: tokens added with prebreak={}
and postbreak={}
are part of the lines and are copied along with it, so they are not an ideal solution (and you can’t use unicode characters or macros there)
MWE if someone would like to help and experiment:
documentclass[a4paper,12pt]{article}
usepackage{xcolor}
usepackage{listings}
lstset{
basicstyle=footnotesizettfamily,
breakatwhitespace=true,
breaklines=true,
firstnumber=1,
frame=leftline,
keepspaces=true,
numbers=left,
showspaces=false,
showstringspaces=false,
showtabs=false,
stepnumber=1,
language=java,
numberstyle=color{darkgray},
commentstyle=color{gray},
stringstyle=color{red},
keywordstyle=color{blue},
rulecolor=color{black}
}
begin{document}
begin{lstlisting}
public int nextInt(int n) {
if (n<=0)
throw new IllegalArgumentException("n is not positive");
// this is a very very very very very very very very very very very very very very very very very very very very very very very very very very very long line
if ((n & -n) == n) // i.e., n is a power of 2
return (int)((n * (long)next(31)) >> 31);
int bits, val;
do {
bits = next(31);
val = bits % n;
} while(bits - val + (n-1) < 0);
return val;
}
end{lstlisting}
begin{lstlisting}[stepnumber=5,caption={You cannot easily tell where line breaks occur}]
public int nextInt(int n) {
if (n<=0)
throw new IllegalArgumentException("n is not positive");
// this is a very very very very very very very very very very very very very very very very very very very very very very very very very very very long line
if ((n & -n) == n) // i.e., n is a power of 2
return (int)((n * (long)next(31)) >> 31);
int bits, val;
do {
bits = next(31);
val = bits % n;
} while(bits - val + (n-1) < 0);
return val;
}
end{lstlisting}
end{document}
I found the proper macro!
Jasper's suggestion to use tikzmark
listings library gave me the possibility to better understand the underlying listings
code
Search for "postbreak" in lstmisc.sty
:
gdeflst@@discretionary{%
discretionary{letspacelst@spacekernlst@prebreak}%
{llap{lsthk@EveryLine
kernlst@breakcurrindent kern-@totalleftmargin}%
letspacelst@spacekernlst@postbreak}{}}
Now copy it to the current document and find the right spot where to put the symbol:
makeatletter
gdeflst@@discretionary{%
discretionary{letspacelst@spacekernlst@prebreak}%
{llap{HERE lsthk@EveryLine
kernlst@breakcurrindent kern-@totalleftmargin}%
letspacelst@spacekernlst@postbreak}{}}
makeatother
One probably wants to use the same line numbering color, in that case it is sufficient to replace "HERE" with {color{darkgray}→ }
. I am using "→" because the unicode symbol I wanted doesn't appear.
Result:
Correct answer by Polizi8 on May 19, 2021
When answering another answer, I found out that the tikzmark
library for TikZ provides some features for use with the listings
package. The following still requires you to manually place the return marks, so it is not done fully automatically. But it may still be better than no return marks at all ...
The macro takes two arguments, the first for the line number in question and the second for the number of line breaks. Note that I assumed the line spacing of the listings environment to be 1em, but it may be different in other circumstances.
documentclass[a4paper,12pt]{article}
usepackage{xcolor}
usepackage{listings}
usepackage{tikz}
usetikzlibrary{tikzmark}
usetikzmarklibrary{listings}
newcommand{continuingline}[2]{%
begin{tikzpicture}[remember picture, overlay]
foreach i in {1,...,#2} {
node[anchor=base, align=center] at ([xshift=-1.25em, yshift={-i*1em}]pic cs:line-code-#1-start) {$hookrightarrow$};
}
end{tikzpicture}%
}
lstset{
basicstyle=footnotesizettfamily,
breakatwhitespace=true,
breaklines=true,
firstnumber=1,
frame=leftline,
keepspaces=true,
numbers=left,
showspaces=false,
showstringspaces=false,
showtabs=false,
stepnumber=1,
language=java,
numberstyle=color{darkgray},
commentstyle=color{gray},
stringstyle=color{red},
keywordstyle=color{blue},
rulecolor=color{black},
}
begin{document}
begin{lstlisting}[caption={You can easily recognize line breaks}, name=code]
public int nextInt(int n) {
if (n<=0)
throw new IllegalArgumentException("n is not positive");
// this is a very very very very very very very very very very very very very very very very very very very very very very very very very very very long line
if ((n & -n) == n) // i.e., n is a power of 2
return (int)((n * (long)next(31)) >> 31);
int bits, val;
do {
bits = next(31);
val = bits % n;
} while(bits - val + (n-1) < 0);
// this is another although not very very very very long but still quite long line
return val;
}
end{lstlisting}
continuingline{6}{2}
continuingline{15}{1}
end{document}
Update: Better solution that also works for more than only one lstlisting
environment.
The macro now takes three mandatory arguments, the first being the name of the listing, which has to be set via name=...
as option to the relevant lstlisting
environment. The second and third argument is again the relevant line number and the number of line breaks respectively.
Furthermore, the macro takes one optional argument, in case that the lineskip is something other than 1em. It defaults to 1em.
continuingline[
<lineskip>]{
<listings name>}{
<line number>}{
<line breaks>}
documentclass[a4paper,12pt]{article}
usepackage{xcolor}
usepackage{listings}
usepackage{tikz}
usetikzlibrary{tikzmark}
usetikzmarklibrary{listings}
newcommand{continuingline}[4][1em]{%
begin{tikzpicture}[remember picture, overlay]
foreach i in {1,...,#4} {
node[anchor=base, align=center] at ([xshift=-1.25em, yshift={-i*#1}]pic cs:line-#2-#3-start) {$hookrightarrow$};
}
end{tikzpicture}%
}
lstset{
basicstyle=footnotesizettfamily,
breakatwhitespace=true,
breaklines=true,
firstnumber=1,
frame=leftline,
keepspaces=true,
numbers=left,
showspaces=false,
showstringspaces=false,
showtabs=false,
stepnumber=1,
language=java,
numberstyle=color{darkgray},
commentstyle=color{gray},
stringstyle=color{red},
keywordstyle=color{blue},
rulecolor=color{black},
}
begin{document}
begin{lstlisting}[caption={You can easily recognize line breaks}, name=codea]
public int nextInt(int n) {
if (n<=0)
throw new IllegalArgumentException("n is not positive");
// this is a very very very very very very very very very very very very very very very very very very very very very very very very very very very long line
if ((n & -n) == n) // i.e., n is a power of 2
return (int)((n * (long)next(31)) >> 31);
int bits, val;
do {
bits = next(31);
val = bits % n;
} while(bits - val + (n-1) < 0);
// this is another although not very very very very long but still quite long line
return val;
}
end{lstlisting}
continuingline{codea}{6}{2}
continuingline{codea}{15}{1}
begin{lstlisting}[caption={You can again easily recognize line breaks}, name=codeb]
public int nextInt(int n) {
if (n<=0)
throw new IllegalArgumentException("n is not positive");
// this is another unbelievably long and probably under normal circumstances totally unnesessary line
return val;
}
end{lstlisting}
continuingline{codeb}{4}{1}
begin{lstlisting}[caption={You can again easily recognize line breaks}, name=codec, basicstyle=footnotesizettfamilylinespread{1.2}selectfont]
public int nextInt(int n) {
if (n<=0)
throw new IllegalArgumentException("n is not positive");
// this is yet another unbelievably long and probably under normal circumstances totally unnesessary line
return val;
}
end{lstlisting}
continuingline[1.2em]{codec}{4}{1}
end{document}
Answered by Jasper Habicht on May 19, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP