[Tex/LaTex] How to redefine verbatim to wrap lines (add break before or after spaces)

line-breakingpatchingverbatim

Before continuing, I would like to inform readers that I know it is generally discouraged to reimplement functionality that packages already support.

Packages that provide support for literal characters

  • LaTeX2e's native verbatim
  • verbatim a reimplementation of native LaTeX2e's verbatim
  • spverbatim offshoot of verbatim that almost does what I want but only supports spaces and does not support custom environment names
  • fancyvrb
  • listings supports breaklines=true but has limitations with UTF-8 support and XeLaTeX and causes white text when used in combination with tcolorbox and xelatex (see Why is text turning white (possible scope leak?) after page break and listings + tcolorbox + xelatex?)
  • minty requires external scripts and does not support page breaks
  • verbments requires external python scripts

Goals

I hope to get an answer and gain some understanding here by doing it (partially) myself. Ultimately, I'd like to understand how line-breaking in verbatim text works.

  • verbatim supports page breaks, but not line breaks (in programming terminology, line wrapping). I would like to utilize the verbatim package for code, but with line breaks.

  • After reading through the verbatim and spverbatim documentation, I learned that the definition of \@xobeysp is the target macro for implementing breaks at spaces. For fun as well as a practical reason, I'd like to implement what the spverbatim package does to verbatim on my own. In the process, I'd like to understand what the verbatim documentation means when it says that I can use the \every@verbatim hook to modify the environments.

  • Maybe I can use \addto@hook<nameofhook>{commands to be added} mentioned on page 4 of verbatim v. 2001/03/12?

Both packages are pretty well documented. Still, I need a little help to get me over the curve.

My idea for verbatim environments that allow for line breaking

Maybe code could be injected at \verbatim@processline that breaks a line when the total length of the characters in a line has approximately reached \textwidth.

My Idea for custom verbatim environments (an unsupported function of spverbatim) with breaks allowed at spaces

The verbatim mechanism for creating custom environments is explained in the documentation on page 2 of version 2001/03/12.

Attempt 1

Try to hack verbatim directly using \addto@hook.

\usepackage{verbatim}% http://ctan.org/pkg/verbatim
\makeatother
\addto@hook\every@verbatim{\def\xobeysp{\mbox{}\space}}
\makeatletter

Attempt 2

Try to imitate spverbatim.

Changing nonbreakable spaces to breakable spaces is made possible by redefining \def\@xobeysp{\leavevmode\penalty10000\ } to \def\@xobeysp{\mbox{}\space}

I know I am really close to creating my own environment with breakable spaces!
spverbatim.sty is small enough that I can easily clone it and modify the name of the environment. However, it seems that I am still missing some step.

\NeedsTeXFormat{LaTeX2e}[1999/12/01]
\ProvidesPackage{myverbatim}
    [2016/05/11 v1.0 Verbatim with breakable spaces based on spverbatim]
\gdef\spverb{%
  \bgroup
  \let\spverb@ve=\verb@egroup
  \def\verb@egroup{\spverb@ve\egroup}%
  \def\@xobeysp{\mbox{}\space}%
  \verb
}
\begingroup
  \catcode`|=0
  \catcode`[=1
  \catcode`]=2
  \catcode`\{=12
  \catcode`\}=12
  \catcode`\\=12
  |gdef|spv@xverbatim#1\end{mycode}[#1|end[mycode]]
|endgroup
\newenvironment{mycode}{%
  \def\@xobeysp{\mbox{}\space}%
  \let\@xverbatim=\spv@xverbatim
  \verbatim
}{%
}
\endinput

Now I have a mycode environment.

\documentclass{article}
\usepackage{fontspec} % typeset with xelatex
\usepackage{myverbatim} % custom package providing "mycode" env

\begin{mycode}
line-breakable literal characters { [ ] } $ &.
\end{mycode}
\end{document}

The parser is still reading passed the \end{mycode} and casuing an error.

Something like

! LaTeX Error: \begin{mycode} on input line 5 ended by \end{document}.

What am I doing wrong here?

Attempt 3

Clone the verbatim.sty code and replace the \xobeysp definition:

%\def\@xobeysp{\leavevmode\penalty\@M\ }
\def\@xobeysp{\mbox{}\space}

After replacing \usepackage{verbatim} with my new version, I can compile documents, but the lines are still not breaking at spaces.

Limitation of spverbatim

This package does not allow me to create my own environments like in verbatim. I e-mailed the author about this at the time of writing this question.

Create Custom Environments in verbatim

For the sake of completeness, here is how you would create a new environment:

\newenvironment{mycode}%
  {\endgraf\small\verbatim}%
  {\endverbatim}

Pseudo-code from Attempt 1

\documentclass{article}
\usepackage{fontspec} % typeset with xelatex
\usepackage{verbatim}
\makeatother
  \addto@hook\every@verbatim{\def\xobeysp{\mbox{}\space}}% similar to http://ctan.org/pkg/spverbatim
\makeatletter

\begin{document}
\begin{mycode}
Here is some nice long code that should support breaks after each space, and not have the original penalty of 10000 like in the verbatim package such that each line will automatically be broken. A bonus would be to indent all wrapped lines by a given amount, but I realize that the logic involved here is somewhat more complex.
\end{mycode}
\end{document}

Related Questions

Best Answer

I'm not sure this is what you're looking for, but here it is.

\documentclass{article}
\usepackage{verbatim}

\makeatletter
\newenvironment{mycode}
 {\def\@xobeysp{\ }\verbatim\rightskip=0pt plus 6em\relax}
 {\endverbatim}
\makeatother

\begin{document}

\begin{mycode}
aaa { \ } aaa { \ } aaa { \ } aaa { \ } aaa { \ } aaa { \ } aaa { \ } aaa { \ } aaa { \ } aaa { \ } aaa { \ } aaa { \ } 
bbb { \ } bbb { \ } bbb { \ } bbb { \ } bbb { \ } bbb { \ } bbb { \ } bbb { \ } bbb { \ } bbb { \ } bbb { \ } bbb { \ } 
\end{mycode}

\end{document}

enter image description here