6

Consider any snippet of minted code that contains a large string not containing any spaces like:

\documentclass{article}
\usepackage{minted}
\setminted{breaklines}
\begin{document}
\begin{minted}{xml}
<?xml version="1.0"?>
abracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabra
<project name="Package tcolorbox" default="documentation" basedir=".">
<description>
Apache Ant build file (http://ant.apache.org/)
</description>
</project>
\end{minted}
\end{document}

The documentation stated that, when using the option breaklines, line breaks are only inserted when a space occurs. My question is: is there a way to extent this principles so that line breaks are permitted at any time. I.e. the abra.. string gets a break any time it crosses \textwidth.

4
+50

Here's an approach that scans through each line and attempts to insert potential breaks at all possible locations, using \discretionary. Heiko Oberdiek's approach will probably be superior when the long strings are natural language and have existing hyphenation patterns. But it seems to allow at most one break, and doesn't break strings that mix letters and numbers. My approach will be more fragile if you are doing fancy things with verbatim, although the typical things (mathescape, etc.) seem to work.

All of the code is written as an extension of fancyvrb. A refined version of this code will probably go into the next version of minted and pythontex. Eventually, I plan to separate out this and other code into a package that extends and patches fancyvrb.

\documentclass[11pt]{article}

\usepackage[T1]{fontenc}

\usepackage{minted}
\setminted{style=default}

\makeatletter

%%%% First, a general solution for verbatim text, potentially with mathescape.
%%%% This doesn't allow breaks within macro args, because we can't know in
%%%% general (at least not without a lot of work) if a macro arg needs to be
%%%% left literal or have potential breaks inserted.
%%%% This reads a line into a temp macro, inserting potential break points.

%Characters inserted at break
\def\FancyVerbBreakChars{\discretionary{-}{}{}}

\def\FV@BreakAnywhere{%
  \def\FV@Tmp{}%
  \FV@BreakAnywhere@i
}

\def\FV@EndBreakAnywhere{\FV@Tmp}

\begingroup
\catcode`\$=3%
\gdef\FV@BreakAnywhere@i{%
  \@ifnextchar\FV@EndBreakAnywhere%
   {}%
   {\ifx\@let@token$\relax
      \let\FV@BreakAnywhere@Next\FV@BreakAnywhere@Math
    \else
      \ifx\@let@token\bgroup\relax
        \let\FV@BreakAnywhere@Next\FV@BreakAnywhere@Group
      \else
        \let\FV@BreakAnywhere@Next\FV@BreakAnywhere@Token
      \fi
    \fi
    \FV@BreakAnywhere@Next}%
}

\gdef\FV@BreakAnywhere@Math$#1${%
  \g@addto@macro{\FV@Tmp}{$#1$}%
  \FV@BreakAnywhere@i}
\endgroup

\def\FV@BreakAnywhere@Group#1{%
  \g@addto@macro{\FV@Tmp}{{#1}}%
  \FV@BreakAnywhere@i
}

\begingroup
\catcode`\a=11%
\catcode`\+=12%
\gdef\FV@BreakAnywhere@Token#1{%
  \ifcat\noexpand#1a\g@addto@macro{\FV@Tmp}{\FancyVerbBreakChars#1}%
  \else
    \ifcat\noexpand#1+\g@addto@macro{\FV@Tmp}{\FancyVerbBreakChars#1}%
    \else
      \g@addto@macro{\FV@Tmp}{#1}%
    \fi
  \fi
  \FV@BreakAnywhere@i
}
\endgroup

\patchcmd{\FV@SaveLineBox}%
 {\strut#1\strut}%
 {\strut\FV@BreakAnywhere#1\FV@EndBreakAnywhere\strut}%
 {}%
 {\errmessage{\noexpand\FV@SaveLineBox could not be patched}}


%%%% Next, a way to allow breaks in macro args.
%%%% This is needed for the Pygments style macros.
%%%% This is basically just a wrapper for what's already been defined,
%%%% used again as needed within macros.

\let\FancyVerbBreakAnywhereStart\FV@BreakAnywhere
\let\FancyVerbBreakAnywhereStop\FV@EndBreakAnywhere

% This assumes `default` Pygments style
% This needs `\setminted{style=default}` in the preamble, so that the
% style macros will already exist.
% Don't try breaks in Pygments `esc`apes, since they may contain 
% arbitrary LaTeX that my approach can't handle.
\let\OldPYG\PYGdefault
\def\PYGdefault#1#2{%
  \ifstrequal{#1}{esc}%
    {\OldPYG{#1}{#2}}
    {\OldPYG{#1}{\FancyVerbBreakAnywhereStart #2\FancyVerbBreakAnywhereStop}}}

\makeatother


\begin{document}


\begin{minted}[breaklines]{xml}
<?xml version="1.0"?>
abracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabra
<project name="Package tcolorbox" default="documentation" basedir=".">
<description>
Apache Ant build file (http://ant.apache.org/)
</description>
</project>
\end{minted}


\begin{minted}[breaklines]{xml}
<?xml version="1.0"?>
abracadabraabracadabra34534abracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabra34534abracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabra34534abracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabra
<project name="Package tcolorboxtcolorboxtcolorboxtcolorboxtcolorboxtcolorbox" default="documentation" basedir=".">
<description>
Apache Ant build file (http://ant.apache.org/)
</description>
</project>
\end{minted}


\begin{minted}[breaklines]{xml}
<?xml version="1.0"?>
abracadabraabracadabra34534abracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabra34534abracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabra34534abracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabra
<project name="Package tcolorboxtcolorboxtcolorboxtcolorboxtcolorboxtcolorboxtcolorbox" default="documentation" basedir=".">
<description>
Apache Ant build file (http://ant.apache.org/)
</description>
</project>
\end{minted}

\end{document}

Here is the original code block:

enter image description here

And here is the code with a much longer first string that mixes letters and numbers. One of the strings in the project tag is also longer, but since there is a space, it can still fit onto one line after a normal break.

enter image description here

Now the string in the project tag is so long that it must be broken between characters.

enter image description here

  • @GPoore Your observations make an interesting case. Indeed, Heiko's solution has a drawback when multiple breaks are needed. Your solution should probably go into the package soon, but may I ask that you look at removing the hyphenation character - or offer a way to disable this. When source code needs formatting and such a sign pops up, people think that it is part of the original code. When do you think the next version will be released containing your proposed fix? – Pieter Stroobants Jun 26 '15 at 2:42
  • @PieterStroobants The code based on this will be on GitHub within the next day or so. This is probably the last thing before I release the next version, so the next version will be out within a week or so, once there has been time to do a little more testing. I am adding more customization for the version that is going on GitHub...if you have suggestions once the code is up, please open an issue there. – G. Poore Jun 26 '15 at 3:07
  • @PieterStroobants GitHub issue for discussion. – G. Poore Jun 28 '15 at 7:06
8

The code is set in a environment Verbatim of package fancyvrb. The breaklines feature is an addition of package minted. The overlong lines are processed in macro \FV@SaveLineBox. The example patches this macro to add support for normal hyphenation. In font \ttfamily the hyphenation is usually disabled via a negative \hyphenchar, see question "Hyphenate \ttfamily without hyphen dash".

With invisible hyphen (OT1 or T1 encoding):

\documentclass{article}
\usepackage{minted}
\usepackage{ragged2e}
\setminted{breaklines}
%\usepackage[T1]{fontenc}
%\usepackage{lmodern}

\usepackage{etoolbox}
\makeatletter
\patchcmd{\FV@SaveLineBox}{%
  \strut#1\strut
}{%
  \hyphenchar\font=%
    % Invisible hyphen:
    \if\expandafter\@car\f@encoding\relax\@nil O 255 \else 23 \fi
    % Visible hyphen:
    % `\- %
  \strut
  \nobreak % prevent line break by next \hspace
  \hspace{0pt}% allow hyphenation of first word
  #1%
  \nobreak % without the following \strut would prevent hyphenation of previous word
  \strut
}{}{%
  \errmessage{\noexpand\FV@SaveLineBox could not be patched}%
}
\makeatother

\begin{document}
\begin{minted}{xml}
<?xml version="1.0"?>
abracadabraabracadabraabracadabraabracadabraabracadabraabracadabraabracadabraab
<project name="Package tcolorbox" default="documentation" basedir=".">
  <description>
    Apache Ant build file (http://ant.apache.org/)
  </description>
</project>
\end{minted}
\end{document}

Result with invisible hyphen

And with the visible hyphen (\hyphenchar\font=`\-):

Result with visible hyphen

Thus the solution does not break the lines at each character, but follows the hyphenation patterns of the current language.

  • Very impressive dissection! – Steven B. Segletes Jun 24 '15 at 16:14
  • @HeikoOberdiek Thanks, this is exactly what I needed, the code does not end up in the side anymore and there is a preference for breaking at spaces (default preference). – Pieter Stroobants Jun 24 '15 at 23:36
2

Minted provides such break by breaksymbol = =\small\carriagereturn. This breaksymbol defines the symbol to break. So you can use this symbol where ever you want a break. For example, we use carriage return. You can put a carriage return the place you want a break.

\usepackage{minted}
\usepackage{dingbat}

\begin{document}

\begin{minted}[breaklines, breaksymbolleft=\carriagereturn]{xml}
<?xml version="1.0"?>
abracadabraabracadabraabracadabr
aabracadabraabracadabraabracadab
raabracadabraabracadabraabracada
braabracadabra
<project name="Package tcolorbox" default="documentation" basedir=".">
<description>
Apache Ant build file (http://ant.apache.org/)
</description>
</project>
\end{minted}
\end{document}
1

None of the other answers worked for my as October of 2019. After researching, I could find that minted has implemented this with the option breakanywhere: Allow line breaks anywhere

  • Thank you very much ! It saved my day ! – jujuBee Nov 25 at 19:11
  • Indeed, the 'breakanywhere' option of minted is an answer to my question. The author also refers explicitly to this post. – Pieter Stroobants Nov 27 at 17:13

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.