# putting spaces within text block

I have a block of text that I would like to automatically break in blocks of equal length. Something like what \num does with numbers.

What I need is a definition for what I called \makeBlocks. The MWE below should output: aaaaa bbbbb ccccc ddddd followed by abc def ghi

\documentclass{article}

\newcommand{\makeBlocks}[1]{???}

\begin{document}
\makeBlocks{5}{aaaaabbbbbcccccddddd}
followed by
\makeBlocks{3}{abcdefghi}
\end{document}

• Is ist something like the following pseudocode? if NextChar equals CurrentChar then put space before NextChar else fi Did i understand this correctly? Jan 27, 2014 at 15:06
• @Johannes_B It has nothing to do with the next charactor. I'll update the MWE accordingly. Jan 27, 2014 at 15:07
• You want equal length: A space after #1 number of chars? Jan 27, 2014 at 15:08
• Right! To be precise, not equal space, but equal numbers of charactors. Jan 27, 2014 at 15:09
• How should \makeBlocks handle the content if the number doesn't divide the length of the string, as in \makeBlocks{4}{abcdefghi}?
– Werner
Jan 27, 2014 at 15:24

Here's an implementation with l3regex:

\documentclass{article}
\usepackage{xparse,l3regex}
\ExplSyntaxOn

\NewDocumentCommand\makeBlocks{mm}
{
\geoff_makeblocks:nn { #1 } { #2 }
}

\tl_new:N \l_geoff_blocks_input_tl

\cs_new_protected:Npn \geoff_makeblocks:nn #1 #2
{
\tl_set:Nn \l_geoff_blocks_input_tl { #2 }
%\tl_reverse:N \l_geoff_blocks_input_tl
\regex_replace_all:nnN { (.{0,#1}) } { \1 \c{,} } \l_geoff_blocks_input_tl
\regex_replace_once:nnN { \c{,} \c{,} \Z } { } \l_geoff_blocks_input_tl
%\tl_reverse:N \l_geoff_blocks_input_tl
\tl_use:N \l_geoff_blocks_input_tl
}

\ExplSyntaxOff

\begin{document}

\makeBlocks{3}{abcdef}

\makeBlocks{3}{abcdefg}

\makeBlocks{3}{abcdefghi}

\makeBlocks{5}{aaaaabbbbbccccc}

\end{document}


This counts starting from the left. If you want to start counting from the right, just reverse twice the token list, by uncommenting the two \tl_reverse:N lines. Here's what you'd get:

If you want a normal space between blocks, just change the two \regex lines into

\regex_replace_all:nnN { (.{0,#1}) } { \1 \cS\  } \l_geoff_blocks_input_tl
\regex_replace_once:nnN { \cS. \cS. \Z } { } \l_geoff_blocks_input_tl


A “full featured” macro that starts either from left or from right (this with the *-variant) and accepts the separator as optional argument (default a space).

\documentclass{article}
\usepackage{xparse,l3regex}
\ExplSyntaxOn

\NewDocumentCommand\makeBlocks{s O{~} m m }
{
\IfBooleanTF{#1}
{
\geoff_makeblocks:nnnn { #2 } { #3 } { #4 } { \__geoff_from_right: }
}
{
\geoff_makeblocks:nnnn { #2 } { #3 } { #4 } { }
}
}

\tl_new:N \l_geoff_blocks_input_tl
\tl_new:N \l_geoff_block_separator_tl

\cs_new_protected:Npn \geoff_makeblocks:nnnn #1 #2 #3 #4
{
\tl_set:Nn \l_geoff_block_separator_tl { #1 }
\tl_set:Nn \l_geoff_blocks_input_tl { #3 }

#4 % this will be nothing or \tl_reverse:N \l_geoff_blocks_input_tl

% search blocks of #2 tokens and put the separator after them
\regex_replace_all:nnN
{ (.{#2}) } % search
{ \1 \u{l_geoff_block_separator_tl} } % replace
\l_geoff_blocks_input_tl % in this list

% if the number of tokens is a multiple of #2, one too much
% separator is inserted, remove it
\regex_replace_once:nnN
{ \u{l_geoff_block_separator_tl} \Z } % search
{ } % replace
\l_geoff_blocks_input_tl % in this list

#4

\tl_use:N \l_geoff_blocks_input_tl
}

\cs_new:Npn \__geoff_from_right:
{
\tl_reverse:N \l_geoff_blocks_input_tl
}

\ExplSyntaxOff

\begin{document}

From left: \makeBlocks{3}{abcdef}

From left: \makeBlocks{3}{abcdefg}

From right: \makeBlocks*{3}{abcdefgh}

With different separator: \makeBlocks[ x ]{3}{abcdefghi}

With different number: \makeBlocks{5}{aaaaabbbbbccccc}

\end{document}


• This works as stated, but now I realise it doesn't wrap at the end of the line (for a very long word). I tried wrapping it in a parbox but that didn't help. Jan 27, 2014 at 15:55
• @Geoff That's because I added \, between blocks. I'll add the modification to get a normal space. Jan 27, 2014 at 16:20
• @Geoff I added a more complete version where you can also choose a different separator. Jan 28, 2014 at 0:15

You could use the xstring package:

## Notes:

• This is an enhanced version of the solution at Using \newcommand to format numbers/strings according to a pattern.
• There is a limit in this code of 400 characters, so please adjust the ending value of the \foreach as desired.
• By default the split is done from the left. If you desire the split to be from the right, you need to pass in the first optional parameter with something other than L.
• The separator is defined in \Separator so a simple \renewcommand would allow you to change that.

## Code:

\documentclass{article}
\usepackage{xstring}
\usepackage{pgf,pgffor}

\newcommand*{\StringLength}{}%
\newcommand*{\FirstOutputStringLength}{}%
\newcommand*{\TempStringA}{}%
\newcommand*{\TempStringB}{}%
\newcommand*{\Separator}{\,}%
\newcommand*{\makeBlocks}[3][L]{%
\edef\TempStringA{#3}%
\IfStrEq{#1}{L}{%
\foreach \x in {1,...,100} {%
\StrLeft{\TempStringA}{#2}%
\StrGobbleLeft{\TempStringA}{#2}[\TempStringB]%
\xdef\TempStringA{\TempStringB}%
\IfStrEq{\TempStringA}{}{\breakforeach}{\Separator}%
}%
}{%
\StrLen{\TempStringA}[\StringLength]%
\IfEq{\StringLength}{0}{}{%
\pgfmathtruncatemacro{\FirstOutputStringLength}{mod(\StringLength,#2)}%
\IfEq{\FirstOutputStringLength}{0}{%
\xdef\TempStringB{\TempStringA}%
}{%
\StrLeft{\TempStringA}{\FirstOutputStringLength}\Separator%
\StrGobbleLeft{\TempStringA}{\FirstOutputStringLength}[\TempStringB]%
}%
}%
\makeBlocks[L]{#2}{\TempStringB}%
}%
}
\begin{document}
\begin{tabular}{cll}
Num of Char    & \multicolumn{1}{c}{Left} & \multicolumn{1}{c}{Right} \\
5 & \makeBlocks{5}{AB1234567890}   & \makeBlocks[R]{5}{AB1234567890}\\
5 & \makeBlocks{5}{AB123456789}    & \makeBlocks[R]{5}{AB123456789}\\
5 & \makeBlocks{5}{AB12345678}     & \makeBlocks[R]{5}{AB12345678}\\
5 & \makeBlocks{5}{AB1234567}      & \makeBlocks[R]{5}{AB1234567}\\
5 & \makeBlocks{5}{AB12}           & \makeBlocks[R]{5}{AB12}\\
5 & \makeBlocks{5}{AB}             & \makeBlocks[R]{5}{AB}\\
5 & \makeBlocks{5}{A}              & \makeBlocks[R]{5}{A}\\ [2.0ex]
4 & \makeBlocks{4}{AB1234567890}   & \makeBlocks[R]{4}{AB1234567890}\\
3 & \makeBlocks{3}{AB123456789}    & \makeBlocks[R]{3}{AB123456789}\\
2 & \makeBlocks{2}{AB12345678}     & \makeBlocks[R]{2}{AB12345678}\\
1 & \makeBlocks{1}{AB1234567}      & \makeBlocks[R]{1}{AB1234567}\\
\end{tabular}

\bigskip
\renewcommand{\Separator}{-}%
With different separator:

\makeBlocks{4}{AB1234567890}

\makeBlocks{1}{AB1234567890}

\end{document}