[Tex/LaTex] Listings – break on whitespace+

line-breakinglistings

I'm using listings for the first time, and have some rather long lines of code. I get that I can break lines automatically with breaklines=true, and I can break only on whitespace with breakatwhitespace=true, but is there any way to add more breaking characters to the list?

For example:

\documentclass[a4paper,twoside]{book}
\usepackage{listings}
\usepackage{xcolor}

\definecolor{mygreen}{rgb}{0,0.6,0}
\lstset{ %
  basicstyle=\footnotesize\ttfamily,        % the size of the fonts that are used for the code
  breakatwhitespace=true,          % sets if automatic breaks should only happen at whitespace
  breakindent=1em,
  breaklines=true,                 % sets automatic line breaking
  commentstyle=\color{mygreen},  % comment style
  keepspaces=true,                 % keeps spaces in text, useful for keeping indentation of code (possibly needs columns=flexible)
  keywordstyle=\color{blue},       % keyword style
  linewidth=\textwidth,
  morekeywords={*,...},            % if you want to add more keywords to the set
  numbers=left,                    % where to put the line-numbers; possible values are (none, left, right)
  numbersep=5pt,                   % how far the line-numbers are from the code
  numberstyle=\tiny\color{gray},   % the style that is used for the line-numbers
  showlines=true,
  stepnumber=1,                    % the step between two line-numbers. If it's 1, each line will be numbered
  stringstyle=\color{red},         % string literal style
  tabsize=2,                       % sets default tabsize to 2 spaces
  title=\lstname                   % show the filename of files included with \lstinputlisting; also try caption instead of title
}

\begin{document}
    \lstinputlisting[language=Python,caption={},firstline=202,lastline=203]{somefile.py}
\end{document}

gives:
enter image description here

i.e. the first line extends past the right margin.

I can obviously do one of two things to the source:

  • break lines manually
  • manually add spaces after commas (for example), as necessary

But is there any way to automate breaking after commas (or some other character, but commas would work nicely for me). The manual doesn't seem to give me anything.

I see a similar question has been asked before with no answer – so I'm not all that hopeful.

Edit: After trawling through the package code, which is largely beyond me as I suspected, I can't find a listings-specific definition of whitespace – can I assume this is a LaTeX-wide definition?

Best Answer

The listings package divides all characters in 3 categories: letters, digits and others.

This is a screenshot of its documentation where these categories are listed:

enter image description here

Now, if you use both breaklines=true and breakatwhitespace=true then line breaks are allowed only when a whitespace is encountered.

If you omit breakatwhitespace=true then all characters listed as "other" are good points to break (including whitespaces).

If you want to remove some characters from this list, you have to declare them as letters with the option alsoletter.

The following is a modified version of your MWE where I declared that the characters ()[].= cannot be used for line breaking since they are now letters:

\documentclass[a4paper,twoside]{book}
\usepackage{listings}
\usepackage{xcolor}

\definecolor{mygreen}{rgb}{0,0.6,0}
\lstset{ %
  basicstyle=\footnotesize\ttfamily,        % the size of the fonts that are used for the code
% breakatwhitespace=true,          % sets if automatic breaks should only happen at whitespace
  breakindent=1em,
  breaklines=true,                 % sets automatic line breaking
  commentstyle=\color{mygreen},  % comment style
  keepspaces=true,                 % keeps spaces in text, useful for keeping indentation of code (possibly needs columns=flexible)
  keywordstyle=\color{blue},       % keyword style
  linewidth=\textwidth,
  morekeywords={*,...},            % if you want to add more keywords to the set
  numbers=left,                    % where to put the line-numbers; possible values are (none, left, right)
  numbersep=5pt,                   % how far the line-numbers are from the code
  numberstyle=\tiny\color{gray},   % the style that is used for the line-numbers
  showlines=true,
  stepnumber=1,                    % the step between two line-numbers. If it's 1, each line will be numbered
  stringstyle=\color{red},         % string literal style
  tabsize=2,                       % sets default tabsize to 2 spaces
  title=\lstname                   % show the filename of files included with \lstinputlisting; also try caption instead of title
}

\begin{document}
\begin{lstlisting}[language=Python,caption={},alsoletter={()[].=}]
plt.contourf(xi,yi,Ti,50,cmap=palette,norm=colors.Normalize(vmin=max([0,np.nanmin(Ti)]),vmax=np.
\end{lstlisting}
\end{document} 

Note alsoletter={()[].=} in the options of the lstlisting environment.

As you can see, the result is that the line is broken at a comma:

enter image description here

If you want lines to break only at commas, add the remaining characters in the "other" list.

Beware anyway that this also affects keywords and other things... So, my suggestion is to simply use breaklines without breakatwhitespace.