3

So, I have listings wrapping lines in my code listing using the breaklines option. Fortunately, I can let the default breaks stand in most cases, as I am listing Python code which is fairly tolerant of line wrapping (PEP8 prefers implicit continuation to explicit continuation, even). However, there is one exception to that rule, and that is comments. Python has no block comments, only line comments, and wrapping a line comment means you have to put a comment character (#) after the linebreak, as Python comments cannot be continued with a backslash

For instance:

\documentclass{article}
\usepackage{listings}
\begin{document}
\begin{lstlisting}[language=python,breaklines=true]
# This is a really quite long Python comment that causes lines to wrap.  We keep on going...and going...and going, just like a snake that swallowed the Energizer bunny.
\end{lstlisting}
\end{document}

which yields a quite suboptimal result (you can't copy-pasta it back into an editor and run it without cleaning things up first):

output of above LaTeX code

I know from this answer that you can use a macro for postbreak=, but how do I get the conditional behavior I want so that it inserts the # only when wrapping a comment, not a regular source code line?

  • Python has sort of block comments: Use """ to start and end the block. – Skillmon Jun 25 '17 at 18:23
  • @Skillmon -- those really aren't comments -- they're triple-quote string constants instead (the syntax difference can be important) – ThreePhaseEel Jun 25 '17 at 18:29
  • I know that, that's way I said "sort of". – Skillmon Jun 25 '17 at 18:30
  • (I also plan to use this logic with C++ as well, BTW -- the Python case is what I'm dealing with now as a PoC as adapting it should be pretty straightforward) – ThreePhaseEel Jun 25 '17 at 18:32
  • 1
    I think that there is no need to do this... the symbol of line breaking is fine... you will produce just a pdf... try to copy and paste to a plain text editor from your pdf with lstlisting environment... it is really bad... following the symbol of line break the reader can find out if it comes from a comment or not... He will not copy paste it anyway... But I will try to think a way – koleygr Jun 25 '17 at 18:46
5

I found a way to let every consecutive row of a comment start with #. I didn't test this extensively, so I'm not sure whether this does break other things or not.

\documentclass{article}
\usepackage{listings}

\makeatletter
\lst@AddToHook{AfterBeginComment}{%
    \CommentLinetrue%
}
\makeatother

\newif\ifCommentLine%
\newcommand*{\CommentLineContinued}{\ifCommentLine\#\space\fi}
\begin{document}
\begin{lstlisting}[%
    language=python%
    ,breaklines=true%
    ,postbreak=\CommentLineContinued%
]
this is a test of a really long python code line which causes lines to wrap. We keep on going...and going...and going, just like a snake that swallowed the Energizer bunny.

# This is a really quite long Python comment that causes lines to wrap.  We keep on going...and going...and going, just like a snake that swallowed the Energizer bunny.

this is a test of a really long python code line which causes lines to wrap. We keep on going...and going...and going, just like a snake that swallowed the Energizer bunny.
\end{lstlisting}
\end{document}

enter image description here

EDIT: An alternative definition of \CommentLineContinued, that makes the macro a bit more versatile (if you intend to use this approach for mutliple languages in the same document):

\newcommand*{\CommentLineContinuedSymbol}{\#\space}% default value
\newcommand*{\CommentLineContinued}[1][]{%
    \ifx\relax#1\relax\else%
        \gdef\CommentLineContinuedSymbol{#1}%
    \fi%
    \ifCommentLine\CommentLineContinuedSymbol\fi}%

This way you can use an optional argument to alter the symbol which is used up until the next time the optional argument is used.

If you specify the optional argument outside of the postbreak= key, it should only alter the symbol but don't print anything.

Note that if you want to use the optional argument inside of a key=value list, you'll have to enclose the command with curly braces: postbreak={\CommentLineContinued[//\space]} (for C++ like comments).

  • Will try this and get back to you with the results – ThreePhaseEel Jun 26 '17 at 4:45
  • @ThreePhaseEel have you tried it so far? Does it work seamlessly? – Skillmon Jun 26 '17 at 15:45
  • Sadly, I was not able to get it to work at all here -- I just gave up on autobreaking and tweaked the culprit comments themselves to fix the issue – ThreePhaseEel Jul 31 '17 at 2:22
  • Was worth a shot though -- thanks anyway – ThreePhaseEel Jul 31 '17 at 2:41
  • @ThreePhaseEel sorry to hear (though I wonder why it doesn't work, worked great in my examples...) – Skillmon Jul 31 '17 at 8:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.