I use pythontex
to typeset my Python listings. I'd like to have some kind of L-shaped lines, like the ones I added in the image below to clearly exhibit the indentation level of every line of code.
Any ideas?
\documentclass[varwidth,margin = 1mm]{standalone}
\usepackage{pythontex}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\begin{document}
\begin{pygments}[frame=single]{python}
def f(n):
if n == 1:
return 1
else:
return f(n-1)
print(f(4))
\end{pygments}
\end{document}
Best Answer
Thank you for very interesting problem.
You can use following macros:
This means that you must write:
And you get:
Of course,
pygments
environment needs to runpythontex example
after TeXing in order to syntax highlighting.Explanation The
\makeL
macro redefines\FancyVerbFormatLine
used for verbatim output bypygments
environment as\Lformat
. This macro counts the line and counts the number of spaces in the front of the line and saves it as macro\L:num-spaces
with the contentsline-number
. Then the list of L symbols is stored for current line into\Llist
macro. Each L symbol is represented in the form\Ldraw{right}{up}
whereright
is the width of L (the number of the columns) andup
is the height of the L (the number of the lines). Finally, the L symbols (i. e.\Ldraw
) are processed using\pdfiteral
.Limitation: this macro expects that no page breaks are in the middle of the code. But a skillful macro programmer can add such feature as an exercise.
Dependences: you need not any additional package. You can process the macros by
pdflatex
orlualatex
orxelatex
. Whenxelatex
is used then you must define:Edit The second version of my macros below (at the end of this post) simplifies the input and allows page breaks in the middle of the code.
The input can be prepared as normally in
Verbatim
(from fancyvrb) orpygments
(from pythontex) environments. If the new key-value pairindent=L
is present then the L indentations is calculated and printed else these environments work normally. Example:or
In order to allow page breaking we must decompose the large
L
(over more lines) to one or moreI
s ended by smallL
:Then we can print Is and Ls in each line separately and the code can be broken to more lines. There is only one little problem: we must know the indentation of the following line when printing current line in order to decide if L or I must be printed. Fortunately, the
fancyverb.sty
keeps current line in the box and it print this box after reading next line. So, we can calculate the indentation of the next line and print the box from previous line overlapped by Ls or Is. This work is done by\Lbox
macro (instead original\box
in thefancyvrb.sty
macros). And\Lbox
uses\Llist
calculated from previous line where is a list of\Ldraw
macros desribed above. And\Ldraw
macro draws L or I simply by:where
\tmpnum
includes the current column number and\spacenum
the number of spaces of the next line.The example follows. My macros must be included after loading
pythontex.sty
orfancyvrb.sty
because some internal macros fromfancyvrb.sty
are re-defined.Because of the
\Lshape
macro (gray, roundend corners), the detail of the result looks like: