[Tex/LaTex] How to line-break a long string of numeric digits and hyphens

hyphenationline-breakinglistings

I have a cls file that contains a definition for source code:

\lstnewenvironment{code}[1][]
{
    \lstset{
                    basicstyle=\ttfamily\footnotesize,
                    breaklines=true,
                    frame=lines,
                    extendedchars=true,
                    captionpos=b,
                    caption=#1
    }
}
{
}

I have a problem with code listings and line breaking but only on lines containing strings longer than the line width that consist of digits and hyphens only. Other long strings break fine.

The specific example of a long string that highlighted this problem to me was trying to display a "SID" value in a narrow column. An example of one of these is shown below:

# wbinfo --name-to-sid myuser
S-1-5-21-4099219672-1275272411-291422405-1104 SID_USER (1)

The string "1-5-21-4099219672-1275272411-291422405-1104" is too wide to fit in a narrow column but it is not broken up. As a further (extremely long line) example:

12345-word-67890-word-09876-word-54321-word-12345-word-67890-word-09876-word-54321-word-12345-word-67890-word-09876-word-54321-word-12345-word-67890-word-09876-word-54321-word-12345-word-67890-word-12345-67890-09876-54321-12345-67890-09876-54321-12345-67890-09876-54321-word-54321-word-12345-word-67890-word-09876-word-54321-word-12345-word-67890-word-09876-word-54321-word-12345-word-67890-word-09876-word-54321

gets split where necessary between the letter d of word and the hyphen that follows it. The subsrring consisting of only numbers and hypens is not split regardless of its length.

So, to summarise, line breaking works BUT ONLY when the line contains non-numeric characters.

What I want is for it to break on hyphens (as it does) but to do it always and not only when a hyphen is preceded by a letter.

Best Answer

You can break this using literate turning the - into a discretionary:

\lstset{literate={-}{{-\allowbreak}}{1} }

Sample output

or allowing breaks at -, 0 and 1

\lstset{literate={-}{{-\allowbreak}}{1}
{0}{{0\allowbreak}}{1}
{1}{{1\allowbreak}}{1} }

Sample output

You can allow breaks for other numbers if you so wish by extending the pattern. The format is

{character sequence}{{replacement}}{length}

Note the extra brackets around replacement. Multiple such sequences can be separated by blank space or a newline for readability.

Code for first example

\documentclass[twocolumn]{article}

\usepackage{listings}

\lstnewenvironment{code}[1][]
{
  \lstset{
    basicstyle=\ttfamily\footnotesize,
    breaklines=true,
    frame=lines,
    extendedchars=true,
    captionpos=b,
    caption=#1,
    literate={-}{{-\allowbreak}}{1}
  }
}
{
}

\begin{document}

\begin{code}
  # wbinfo --name-to-sid myuser
  S-1-5-21-4099219672-1275272411-291422405-1104 SID_USER (1)
\end{code}

\end{document}

Code for second example

\documentclass[twocolumn]{article}

\usepackage{listings}

\lstnewenvironment{code}[1][]
{
  \lstset{
    basicstyle=\ttfamily\footnotesize,
    breaklines=true,
    frame=lines,
    extendedchars=true,
    captionpos=b,
    caption=#1,
    literate={-}{{-\allowbreak}}{1}
    {0}{{0\allowbreak}}{1}
    {1}{{1\allowbreak}}{1}
  }
}
{
}

\begin{document}

\begin{code}
  # wbinfo --name-to-sid myuser
  S-1-5-21-4099219672-1275272411-291422405-1104 SID_USER (1)
\end{code}

\end{document}
Related Question