[Tex/LaTex] Custom verbatim that sets all spaces (” “) as visible spaces (“␣”) that can line-break

line-breakingmacrosspacingverbatim

It makes sense to typeset code in a monospaced font. Sometimes such code needs to be embedded in a paragraph context, and then it will be useful to allow it to linebreak. In order to visualize spaces properly, I would like a macro \code that typesets its argument with all spaces replaced by visible spaces that can line-break (on both sides). For example, it'd typeset

\code{string with  spaces}

as string␣with␣␣spaces where each can linebreak on either side. As my question is about code that is to be embedded in paragraph text, we can assume that the argument to such a \code macro won't contain any paragraph breaks.

Actually my use case is more specific. I typeset string constants using the macro \strC shown below. This might still be interesting to others, as it is a bit more than just a variation on \verb, with the custom \textsl potentially complicating the solution.

I presently use an explicit call to a macro \vsp (simply defined as \allowbreak\textvisiblespace\allowbreak; both \allowbreaks are needed) as a workaround, but it would be nice to be able to just type (one or more) spaces inside the macro argument.

\documentclass{article}

\newcommand*{\strC}[1]{\textnormal{`\textsl{\texttt{#1}}'}} % string constant
\newcommand*{\vsp}{\allowbreak\textvisiblespace\allowbreak} % visible space

\begin{document}

\hspace*{31em}\strC{hello world}
% linebreaks as:  ‘hello / world’    (space disappears)

\hspace*{31em}\strC{hello\textvisiblespace{}world}
% linebreaks as:  ‘hello␣world’ / ∅  (no linebreak)

\hspace*{31em}\strC{hello\vsp{}world}
% linebreaks as:  ‘hello / ␣world’   (as intended; a linebreak after ␣ would also be ok)

\end{document}

For this code specifically the idea would be to type \strC{hello world} but to get the same result as with \strC{hello\vsp{}world}. Multiple typed spaces should yield multiple -characters; a string ␣␣␣␣␣ may break anywhere (beginning, anywhere in the middle, end).

Here is a related question also asking about functional conversion of input (in this case for the specific purpose of pasting).


Summary of answers:
Both answers are very good, and the comment pair (just below) by user cacamailg is very good too, but no solution as of the time of this edit is perfect. For now I'll stick with my manual \vsp macro, which is quick to type and gives me full control. If someone has a refinement of one of the three approaches that is flawless, I'll accept that as the answer.

Best Answer

You have to change the meaning of the active space. (Of course this means that \code cannot be in the argument to another command (see below*), though careful usage of \scantokens might help.)

\documentclass{article}

\newcommand*{\strC}{\begingroup
  \obeyspaces
  \begingroup\lccode`~=`\ %
  \lowercase{\endgroup\let~}\vsp
  \dostrC}
\newcommand{\dostrC}[1]{\textnormal{`{\slshape\ttfamily#1}'}\endgroup} % string constant
\newcommand*{\vsp}{\allowbreak\textvisiblespace\allowbreak} % visible space

\begin{document}

\hspace*{31em}\strC{hello world  x   y}

\end{document}

enter image description here


*For example, if we wrap the command into a macro \ident that doesn't modify its argument (\newcommand*{\ident}[1]{#1}), the result of

\ident{\strC{hello world  x   y}}

turns out to be as if we had used the original \strC macro without any explicit visible spaces: all space sequences will be shrunk to an ordinary (i.e., line-breaking and disappearing ("soft")) space.

Related Question