2

I want to include Python code to be formatted with listings but I just want the code neat and compact. No comments shall be printed at all, as well as no empty lines.

The easy way would be to strip the code of comments, but that's bypassing the problem and not finding a solution. I want a solution. A solution would mean I do NOT have to edit the source file being imported.

I have tried the following:

Approach 1

\lstdefinestyle{py_without_comments}{%
    language     = python,
    morecomment  = [l][\nullfont]{\#},
    emptylines   = *1,
}

Which doesn't print the comments, but the lines stay there since the text reach the output, just LaTeX prints it with nullfont.

Approach 2

\lstdefinestyle{py_without_comments}{%
    language     = python,
    morecomment  = [is]{\#}{\^^M},
    emptylines   = *1,
}

Approach 2 ignores all comment lines from the # to the end of the line. Problem is, the end of the line also disappears! Say you have this code:

def foo():
    if cond1: bar() #Some explanation
    if cond2: baz() #Some other explanation
    if cond3: bye() #Even more explanations

It would print like this:

def foo():
    if cond1: bar()        if cond2: baz()        if cond3: bye()

Which is undesirable, unpythonic, and ugly.

Approach 3

\lstdefinestyle{py_without_comments}{%
    language     = python,
    morecomment  = [il]{\#},
    emptylines   = *1,
}

This one should work like a charm, but for some reason it wipes out all the code from the first comment on (see foo() example).

Thus I am looking for something else to try. Could it be that this is not possible with listings?

Cheers and thanks in advance.


Edit 1:

MWE can be found here

2

1 Answer 1

2

Here's something that works. It plays with some of listings' internals. I'm not sure if there's a better solution. Consuming the end-of-line delimiter (your approach 2, above) and adding it back if the line is not empty does not seem to work.

\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}

The result is: Result

It may print an empty line at the end of the text, if there are comments there; I'm not sure how to remove this.


Edit: My original answer used hook OutputBox instead of PostOutput. This did not work well with tabs.

5
  • Thanks for the swift answer! Indeed it works but \incomment does the same as \nullfont. If you have comment lines (comment only) \incomment does not print the text but you get a blank line. If your comment line is 3-lines tall then you get 3 blank lines.
    – Kyordhel
    Commented Feb 8 at 18:12
  • @Kyordhel, this is not what I see with the example in my answer (LaTeX source and result). Could you provide a Python script that is wrongly formatted?
    – nickie
    Commented Feb 9 at 18:12
  • First and foremost, thanks for your time and help, @nickie. I updated the MWE (output here). When the code is all compact your code works, but if you have some blank lines above comments everything goes broken. In python this becomes nonsensical since indentation matters.
    – Kyordhel
    Commented Feb 11 at 21:20
  • @Kyordhel, it seems that my solutions does not work well with tab characters. I never use tabs in code, especially for Python, because it's problematic anyway.
    – nickie
    Commented Feb 12 at 8:48
  • @Kyordhel, check my revised answer. I only changed hook OutputBox to PostOutput. This seems to have fixed the issue with the tabs.
    – nickie
    Commented Feb 13 at 1:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .