
Quero incluir o código Python para ser formatado com listagens, mas só quero que o código seja limpo e compacto. Nenhum comentário deve ser impresso, assim como nenhuma linha vazia.
OfácilA maneira seria retirar os comentários do código, mas isso é contornar o problema e não encontrar uma solução. Eu quero uma solução. Uma solução significaria que NÃO preciso editar o arquivo de origem que está sendo importado.
Eu tentei o seguinte:
Abordagem 1
\lstdefinestyle{py_without_comments}{%
language = python,
morecomment = [l][\nullfont]{\#},
emptylines = *1,
}
O que não imprime os comentários, mas as linhas ficam lá desde que o texto chega à saída, apenas o LaTeX imprime com nullfont
.
Abordagem 2
\lstdefinestyle{py_without_comments}{%
language = python,
morecomment = [is]{\#}{\^^M},
emptylines = *1,
}
A abordagem 2 ignora todas as linhas de comentários do #
final da linha. O problema é que o fim da linha também desaparece! Digamos que você tenha este código:
def foo():
if cond1: bar() #Some explanation
if cond2: baz() #Some other explanation
if cond3: bye() #Even more explanations
Seria impresso assim:
def foo():
if cond1: bar() if cond2: baz() if cond3: bye()
O que é indesejável, antitônico e feio.
Abordagem 3
\lstdefinestyle{py_without_comments}{%
language = python,
morecomment = [il]{\#},
emptylines = *1,
}
Este deve funcionar perfeitamente, mas por algum motivo apaga todo o código desde o primeiro comentário (veja foo()
o exemplo).
Portanto, estou procurando outra coisa para tentar. Será que isso não é possível com listagens?
Cumprimentos e agradecimentos antecipados.
Editar 1:
MWE pode ser encontradoaqui
Responder1
Aqui está algo que funciona. Ele brinca com alguns dos listings
internos. Não tenho certeza se existe uma solução melhor. Consumir o delimitador de fim de linha (sua abordagem 2, acima) e adicioná-lo novamente se a linha não estiver vazia não parece funcionar.
\documentclass[11pt]{article}
\usepackage{xcolor}
\usepackage{listings}
% Default settings.
\lstset{
basicstyle=\ttfamily,
numbers=left,
numbersep=5pt,
numberstyle=\tiny\color{gray},
rulecolor=\color{black},
}
% The \incomment macro and auxiliary stuff.
\newif\ifnocomment
\newif\ifemptyline
\makeatletter
% When a line starts, it's empty and we're not in a comment.
\lst@AddToHook{InitVarsBOL}{\global\emptylinetrue\global\nocommenttrue}
% When something is printed, the line is not empty.
\lst@AddToHook{PostOutput}{\global\emptylinefalse}
% When we're in a comment...
\def\incomment#1{%
% if we just entered...
\ifnocomment%
\global\nocommentfalse%
% and the line is empty, then remove this line.
\ifemptyline\global\advance\lst@newlines\m@ne\fi%
\fi}
\makeatother
\lstdefinestyle{python_without_comments}{%
language=python,
morecomment=[l][\incomment]{\#},
}
\begin{document}
\begin{lstlisting}[style=python_without_comments]
def f(x): return x + 1 #
# This is function foo...
def foo():
if cond1: bar() # Some explanation
if cond2: baz() # Some other explanation
if cond3: bye() # Even more explanations
# And this is function bar
def bar(): # let's see
# some more comment
return 42 # here?
\end{lstlisting}
\end{document}
Pode imprimir uma linha vazia no final do texto, caso haja comentários; Não tenho certeza de como remover isso.
Editar: minha resposta original usou hook OutputBox
em vez de PostOutput
. Isso não funcionou bem com guias.