![沿一定距离分布字母](https://linux22.com/image/413390/%E6%B2%BF%E4%B8%80%E5%AE%9A%E8%B7%9D%E7%A6%BB%E5%88%86%E5%B8%83%E5%AD%97%E6%AF%8D.png)
我知道\makebox[*length*][s]{t e x t}
,但我必须在每个字符之间留空格。如果我的文本很长,那就感觉不舒服了。
我见过这个答案经过埃格尔并且它几乎按照我想要的方式工作。我想将长度指定为第一个参数,并使用 xparse 将文本(不单独分隔每个字母)作为第二个参数传递。
\spread{20em}{distribute this text}
\spread{5em}{word}
但不幸的是,我无法修改代码以使其按我想要的方式工作。你能帮我吗?
答案1
首先是一个简单的解决方案,即在字母之间留一个空格,在单词之间留两个空格:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\spreadtext}{mm}
{
\tl_set:Nx \l_tmpa_tl { #2 }
\tl_replace_all:Nnn \l_tmpa_tl { ~ } { {} }
\makebox[#1][s]
{
\skip_set:Nn \spaceskip { 0pt plus 1fill }
\tl_map_inline:Nn \l_tmpa_tl { ##1 ~ } \unskip
}
}
\ExplSyntaxOff
\begin{document}
\spreadtext{20em}{distribute this text}
\spreadtext{5em}{word}
\end{document}
稍有不同,单词之间有更多空格。
您可以先按空格拆分输入,然后按字母拆分每个单词。最后,排版所有内容,在字母之间插入空格,在单词之间插入更大的空格。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\spreadtext}{mm}
{
\antshar_spread_text:nn { #1 } { #2 }
}
\seq_new:N \l__antshar_spread_in_seq
\seq_new:N \l__antshar_spread_out_seq
\seq_new:N \l__antshar_spread_word_seq
\cs_new_protected:Nn \antshar_spread_text:nn
{
\seq_set_split:Nnn \l__antshar_spread_in_seq { ~ } { #2 }
\seq_set_map:NNn \l__antshar_spread_out_seq \l__antshar_spread_in_seq { \antshar_spread_word:n { ##1 } }
\makebox[#1][s]
{
\seq_use:Nn \l__antshar_spread_out_seq { \hspace{1em plus 0.5em minus 0.3em} }
}
}
\cs_new_protected:Nn \antshar_spread_word:n
{
\seq_set_split:Nnn \l__antshar_spread_word_seq { } { #1 }
\seq_use:Nn \l__antshar_spread_word_seq { ~ }
}
\ExplSyntaxOff
\begin{document}
\spreadtext{20em}{distribute this text}
\spreadtext{5em}{word}
\end{document}
该版本还应对参数中的命令。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\spreadtext}{mm}
{
\antshar_spreadtext:nn { #1 } { #2 }
}
\tl_new:N \l_antshar_spreadtext_tl
\cs_new_protected:Nn \__antshar_spreadtext_space:
{
\hspace{1em~plus~0.5em~minus~0.3em}
}
\cs_new_protected:Nn \antshar_spreadtext:nn
{
\tl_set:Nn \l_antshar_spreadtext_tl { #2 }
\regex_replace_all:nnN { \s } { \c{__antshar_spreadtext_space:} } \l_antshar_spreadtext_tl
\regex_replace_all:nnN { (\w) } { \1 \ } \l_antshar_spreadtext_tl
\regex_replace_all:nnN { \s(\c{.*}) } { \1 } \l_antshar_spreadtext_tl
\tl_use:N \l_antshar_spreadtext_tl
}
\ExplSyntaxOff
\begin{document}
\spreadtext{20em}{distribute \emph{this} text}
\spreadtext{5em}{word}
\end{document}
没有包,但不允许命令:
\documentclass{article}
\makeatletter
\newcommand{\spreadtext}[2]{%
\makebox[#1][s]{\spread@text#2\spread@text}%
}
\def\spread@text{\futurelet\next\spread@@text}
\def\spread@@text{%
\ifx\next\spread@text
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\unskip\@gobble}%
{\spread@@@text}%
}
\def\spread@@@text{%
\ifx\next\@sptoken
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\spread@space}%
{\spread@char}%
}
\def\spread@space#1{%
\hspace{1em plus 0.5em minus 0.3em}%
\spread@text#1%
}
\def\spread@char#1{#1 \spread@text}
\makeatother
\begin{document}
\spreadtext{20em}{distribute this text}
\spreadtext{5em}{word}
\end{document}
答案2
使用tokcycle
,我提供了两种形式。第一种,指定字符间距。这在包示例文档中提供。在第二种方法中,使用 OP 首选的语法,用户指定字符串的整体宽度。请注意,目标参数可以包含 完全遵循的格式化宏\spread
。
\spread
相对于的缺点\spaceouttext
是前者不会换行,而后者会。
\documentclass{article}
\usepackage{tokcycle}
\newcommand\spaceouttext[2]{%
\tokcycle{\addcytoks{##1\nobreak\hspace{#1}}}%
{\processtoks{##1}}{\addcytoks{##1}}%
{\addcytoks{##1\hspace{#1}}}{#2}%
\the\cytoks\unskip}
\newcommand\spread[2]{%
\tokcycle
{\addcytoks{##1\hfill}}
{\processtoks{##1}}
{\addcytoks{##1}}
{\addcytoks{##1\hfill}}{#2}%
\makebox[#1]{\the\cytoks\unskip}%
}
\begin{document}
\spaceouttext{3pt plus 3pt}{This \textit{text \textbf{is} very} spaced
out}. Back to regular text.
\spaceouttext{1.5pt}{This \textit{text \textbf{is} somewhat} spaced
out}. Back to regular text.
\fbox{\spread{20em}{distribute \textit{this} text}}
\fbox{\spread{5em}{word}}
\end{document}