Ocultando comentários python com listagens

Ocultando comentários python com listagens

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 listingsinternos. 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}

O resultado é: Resultado

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 OutputBoxem vez de PostOutput. Isso não funcionou bem com guias.

informação relacionada