我知道可以使用该seqsplit
包来拆分长行。以下代码块显示了一个最小的工作示例。
\documentclass{article}
\usepackage[a4paper, showframe]{geometry}
\usepackage{seqsplit}
\begin{document}
Without using seqsplit:
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
Using seqsplit:
\seqsplit{%
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ}
\end{document}
我定义了一个宏,它生成一个包含随机顺序的 ASCII 字母的字符串,名为\randomStringAllASCIILetters
(见下面的代码和屏幕截图)。该宏使用另一个宏,名为,\prunelist
该宏摘自这个答案,它从列表中随机获取项目而不重复。
\documentclass{article}
\usepackage{pgf}
\usepackage{forloop}
\pgfmathsetseed{\number\pdfrandomseed}
\makeatletter
\def\prunelist#1{%
\expandafter\edef\csname pgfmath@randomlist@#1\endcsname
{\the\numexpr\csname pgfmath@randomlist@#1\endcsname-1\relax}%
\count@\pgfmath@randomtemp
\loop
\expandafter\let
\csname pgfmath@randomlist@#1@\the\count@\expandafter\endcsname
\csname pgfmath@randomlist@#1@\the\numexpr\count@+1\relax\endcsname
\ifnum\count@<\csname pgfmath@randomlist@#1\endcsname\relax
\advance\count@\@ne
\repeat}
\makeatother
\newcounter{asciiLetters}
\newcommand\randomStringAllASCIILetters{
% "mylist" contains all ASCII letters in lowercase and
% uppercase. The list was obtained using the following one-liner:
%
% $ python3 -c "import string; print(''.join([f'{{{x}}}' for x in string.ascii_letters]))"
\pgfmathdeclarerandomlist{mylist}{{a}{b}{c}{d}{e}{f}{g}{h}{i}{j}{k}{l}{m}{n}{o}{p}{q}{r}{s}{t}{u}{v}{w}{x}{y}{z}{A}{B}{C}{D}{E}{F}{G}{H}{I}{J}{K}{L}{M}{N}{O}{P}{Q}{R}{S}{T}{U}{V}{W}{X}{Y}{Z}}
% The following loop iterates as many times as the number of
% lowercase and uppercase ASCII letters. The length was obtained
% using the following one-liner.
%
% $ python3 -c "import string; print(len(string.ascii_letters))"
\forloop{asciiLetters}{0}{\value{asciiLetters}<52}{%
\pgfmathrandomitem\z{mylist}\z\prunelist{mylist}%
}%
}
\begin{document}
\par foo
\par \randomStringAllASCIILetters
\par bar
\end{document}
问题是,尽管将宏返回的字符串\randomStringAllASCIILetters
传递给了\seqsplit
,但是宏返回的长字符串没有在正确的位置断开,因此超出了页面限制。
\documentclass{article}
\usepackage[a4paper, showframe]{geometry}
\usepackage{seqsplit}
\usepackage{pgf}
\usepackage{forloop}
\pgfmathsetseed{\number\pdfrandomseed}
\makeatletter
\def\prunelist#1{%
\expandafter\edef\csname pgfmath@randomlist@#1\endcsname
{\the\numexpr\csname pgfmath@randomlist@#1\endcsname-1\relax}%
\count@\pgfmath@randomtemp
\loop
\expandafter\let
\csname pgfmath@randomlist@#1@\the\count@\expandafter\endcsname
\csname pgfmath@randomlist@#1@\the\numexpr\count@+1\relax\endcsname
\ifnum\count@<\csname pgfmath@randomlist@#1\endcsname\relax
\advance\count@\@ne
\repeat}
\makeatother
\newcounter{asciiLetters}
\newcommand\randomStringAllASCIILetters{
% "mylist" contains all ASCII letters in lowercase and
% uppercase. The list was obtained using the following one-liner:
%
% $ python3 -c "import string; print(''.join([f'{{{x}}}' for x in string.ascii_letters]))"
\pgfmathdeclarerandomlist{mylist}{{a}{b}{c}{d}{e}{f}{g}{h}{i}{j}{k}{l}{m}{n}{o}{p}{q}{r}{s}{t}{u}{v}{w}{x}{y}{z}{A}{B}{C}{D}{E}{F}{G}{H}{I}{J}{K}{L}{M}{N}{O}{P}{Q}{R}{S}{T}{U}{V}{W}{X}{Y}{Z}}
% The following loop iterates as many times as the number of
% lowercase and uppercase ASCII letters. The length was obtained
% using the following one-liner.
%
% $ python3 -c "import string; print(len(string.ascii_letters))"
\forloop{asciiLetters}{0}{\value{asciiLetters}<52}{%
\pgfmathrandomitem\z{mylist}\z\prunelist{mylist}%
}%
}
\begin{document}
\seqsplit{%
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ}
\seqsplit{%
\randomStringAllASCIILetters\
\randomStringAllASCIILetters\
\randomStringAllASCIILetters}
\end{document}
我多次编译了上述文档,发现有时会超出页数限制,但有时不会。
在下图中,至少有一个字符超出了页面限制。
下图中,没有超出页面限制的字符。
问题
如上所示,字符串abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
被 正确拆分,\seqsplit{...}
因此字符串不会超出页面限制。但是,\randomStringAllASCIILetters
尽管已将其传递给 ,但 返回的字符串超出了页面限制\seqsplit{...}
。为什么会发生这种情况?
答案1
\seqsplit
迭代输入,在每个标记之间添加空格以允许断点,因此ABC
变成A B C
(具有较小的空间)。
您的输入不是字母序列,而是一些复杂的宏,这些宏在排版时会生成这样的列表,因此它是一个输入,例如
{\def\tmp{A}\edef\tmp{\tmp b}\edef\tmp{\tmp C}\tmp}
这样的结构将排版作为 AbC,但迭代这些标记并添加空格不会产生任何有用的效果
与 pgf 的情况一样(参见\pgfmathresult
),您应该设计宏来在结果宏中构建列表,该列表扩展为一个简单的字母列表,然后将其传递给拆分器。
在 expl3 中执行此操作要容易得多,而不必兼顾 pgf 和 seqsplit 的扩展要求
您只需要从初始 ascii 字母列表中生成一个序列,然后在每次调用时随机排列列表并迭代在每个字母之间添加一个零空格断点。
\documentclass{article}
\ExplSyntaxOn
\seq_new:N \l_rdrg_ascii_seq
\seq_set_split:Nnn \l_rdrg_ascii_seq {} {abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ}
\cs_new:Npn \rdg_ascii_suffle: {
\seq_shuffle:N \l_rdrg_ascii_seq
\seq_use:Nn \l_rdrg_ascii_seq {\hspace{0pt}}
}
\let\asciishuffle\rdg_ascii_suffle:
\ExplSyntaxOff
\begin{document}
\fbox{\parbox[t]{4cm}{
\begin{flushleft}
\asciishuffle
\bigskip
\asciishuffle
\bigskip
\asciishuffle
\end{flushleft}}}
\fbox{\parbox[t]{3cm}{
\begin{flushleft}
\asciishuffle
\bigskip
\asciishuffle
\bigskip
\asciishuffle
\end{flushleft}}}
\end{document}