1

I am using a lstlisting environment in several spots in some stuff I'm writing up, with the language being set to either Python or Mathematica. In both cases, the equals signs merge together to look like one long equals sign (or, if they're not actually merged, they're close enough it's annoying). How can I fix this?

My thought was just to add \, after the first equal sign when there are double equals signs, but a. lstlisting purposefully turns off LaTeX commands and b. that's tedious and annoying.

MWE:

\documentclass{article}
\usepackage{listings}
\begin{document}
\begin{lstlisting}
something == something
\end{lstlisting}
\end{document}
auden
  • 1,458
  • Have a look at https://latex.org/forum/viewtopic.php?t=6975 – moewe Jun 25 '18 at 20:33
  • You could use a fixed-width font with basicstyle=\ttfamily, that changes the font to typewriter/fixed-width. Or you could have a look at §2.10 Fixed and flexible columns of the listings documentation. In particular columns=flexible or columns=fullflexible may be of interest. To quote the manual: "In the abstract one can say: The fixed column format ruins the spacing intended by the font designer, while the flexible formats ruin the column alignment (possibly) intended by the programmer." If you are a Python person you may want to look at minted – moewe Jun 25 '18 at 20:43
  • @moewe the problem with changing column width and such around is one of the languages I'm writing code up for, Python, relies upon indentation to work properly. I'll take a look at basicstyle=\ttfamily. – auden Jun 25 '18 at 20:44
  • @moewe hmm, the thing with basicstyle=\ttfamily is it removes the language specific formatting - is there any way to remedy this? Other than that it seems to work well. – auden Jun 25 '18 at 20:46
  • As far as I can see columns=flexible and columns=fullflexible do preserved some amount of indentation, but I'm not sure if that is what you need. It seems to me you are between a rock and a hard place: columns=flexible gives bad results with fonts that have no fixed character widths, the simple solution would be to use basictstyle=\ttfamily in that case (all characters have the same width, everything is tickety boo). If you don't want \ttfamily you need to switch to a different columns format to avoid the letters running into each other. – moewe Jun 25 '18 at 20:48
  • What language-specific formatting is removed? I assume the actual problems is that your \ttfamily has no italic or bold shape. In that case the answer is to use a font that has. – moewe Jun 25 '18 at 20:49
  • @moewe bolding of keywords is removed. I suppose I'll figure out how to get a new font then, because I think ttfamily is the better of the two solutions here. If you write this up, I'll accept it. – auden Jun 25 '18 at 20:49
  • Yeah, like I said computer modern's typewriter font has no bold family: https://tex.stackexchange.com/q/33039/35864 \usepackage{lmodern} is probably the least intrusive method, but you may want to choose a different font altogether. – moewe Jun 25 '18 at 20:50
  • @moewe adding the \renewcommand and \bfseries commands suggested there bolds everything, not just the keywords. – auden Jun 25 '18 at 20:53
  • Sorry, what did you add where? The [basicstyle=\ttfamily\bfseries] in the link was just an example to show the bold font. You should only do [basicstyle=\ttfamily] as suggested above. – moewe Jun 25 '18 at 20:53
  • @moewe \renewcommand{\ttdefault}{cmtt} at the beginning of the document and [basicstyle=\ttfamily\bfseries] after the \begin{lstlisting} as per the answer you linked here. Sorry for misunderstanding. – auden Jun 25 '18 at 20:54
  • Oh, my update came too late. The [basicstyle=\ttfamily\bfseries] in the link was just to show that bold face works, you only want [basicstyle=\ttfamily]. – moewe Jun 25 '18 at 20:55
  • @moewe thank you very much, this works perfectly! – auden Jun 25 '18 at 20:56
  • Very well. It's a bit late where I am, so I think I will only be able to type up a proper answer tomorrow if that is alright with you. – moewe Jun 25 '18 at 20:58
  • @moewe sounds good, I'll accept it when you post it. Thanks again, and have a good night! =) – auden Jun 25 '18 at 21:03
  • Just for it to be linked (related): https://tex.stackexchange.com/questions/353098/listings-package-increase-spacing-between-in – TeXnician Jun 26 '18 at 09:49

2 Answers2

2

Have a look at §2.10 Fixed and flexible columns of the listings documentation.

In the MWE you are using columns=fixed with a variable-width font. That means that the different glyphs/characters of the font have a different width. If you were to write a line of ls and a line of Ms, the 'l's and 'M's would not line up. So to maintain the proper indentation and alignment of the code listings has to do some tricks.

[T]he fixed format puts n characters into a box of width n × ‘base width’, where the base width is 0.6em in the example. The format shrinks and stretches the space between the characters to make them fit the box. [...]

If you don’t need or like this, you should use a flexible format. All characters are typeset at their natural width. In particular, they never overlap. If a word requires more space than reserved, the rest of the line simply moves to the right. The difference between the three formats is that the full flexible format cares about nothing else, while the normal flexible and space-flexible formats try to fix the column alignment if a character string needs less space than ‘reserved’.

The documentation explains

In the abstract one can say: The fixed column format ruins the spacing intended by the font designer, while the flexible formats ruin the column alignment (possibly) intended by the programmer.

Since the equal signs are quite long it just so happens that the space between them is shrunken to such as degree that the two equal signs merge together.

So what can you do to solve this problem?

  1. Use a fixed-width typewriter font. In those fonts all characters have the same width making it unnecessary to stretch and shrink spaces a lot. Everything aligns naturally.

    basicstyle=\ttfamily
    

    If you want to keep bold and italic/slanted markup you will have to find typewriter font that supports bold and slanted. The default Computer Modern \ttfamily has no bold version (Using \ttfamily with \bfseries (or how to enable bold in fixed-width font)). Latin Modern (\usepackage{lmodern}) has a bold font, which is quite similar to the regular variant, so you may want to try lighttt (in which case you need to be aware of italic font in lmodern-lighttt).

    <code>basicstyle=\ttfamily,</code>

  2. You can increase the basewidth parameter. That makes the box into which the glyphs need to fit wider allowing for a bit of space around the equal signs. Of course all other words will suffer from increased letter spacing.

    <code>basicstyle=\normalfont, basewidth=0.7em</code>

    The default value for fixed mode is 0.6em, for flexible mode 0.45em. In the example here it has been increased to 0.7em. The space is still quite faint, so one might be tempted to increase the width further, but of course that drags the other letters even further apart from each other.

  3. Use columns=flexible

    <code>basicstyle=\normalfont, columns=flexible</code>

    or columns=fullflexible

    <code>basicstyle=\normalfont, columns=fullflexible</code>

    While it may not be easy to count the exact number of spaces with here, the fact that the second line is indented is still very clearly visible. Indentation levels don't get lost with these settings only the exact number of spaces can be hard to figure out.

\documentclass{article}
\usepackage[lighttt]{lmodern}
\usepackage{listings}
\lstset{%
  basicstyle=\ttfamily,
  language=python,
}
\begin{document}
\begin{lstlisting}
if something == something:
    somethingelse(something)
\end{lstlisting}

\begin{lstlisting}[basicstyle=\normalfont, basewidth=0.7em]
if something == something:
    somethingelse(something)
\end{lstlisting}

\begin{lstlisting}[basicstyle=\normalfont, columns=flexible]
if something == something:
    somethingelse(something)
\end{lstlisting}

\begin{lstlisting}[basicstyle=\normalfont, columns=fullflexible]
if something == something:
    somethingelse(something)
\end{lstlisting}
\end{document}
moewe
  • 175,683
1

If you want to use the standard font for the listings, I suggest to set flexible or full flexible columns; if you prefer fixed columns (at the cost of obnoxious interletter spaces), increase the width (this depends on the document font).

\documentclass{article}
\usepackage{listings}

\lstset{
  basewidth={0.7em,0.5em},
}

\begin{document}

\begin{lstlisting}[language=C]
something == something
\end{lstlisting}

\begin{lstlisting}[language=C,columns=flexible]
something == something
\end{lstlisting}

\begin{lstlisting}[language=C,columns=fullflexible]
something == something
\end{lstlisting}

\end{document}

enter image description here

egreg
  • 1,121,712