我正在寻找一个宏,它可以接受一个字符串(最好说是单词序列),并在保留部分序列之前先输出最后一个单词。我想将此宏放入用于为某人排版个人信息的环境的定义中:
\newenvironment{person}[2]%
{% begin definition
\section*{#2}\label{#1}
\addcontentsline{toc}{section}{#2}
}{% end definition
\clearpage
}
因此
\addcontentsline{toc}{section}{#2}
应该有
\addcontentsline{toc}{section}{\reverseit{#2}}
宏\reverseit
应该产生阿尔文·汉内斯从汉内斯·阿尔文和艾伦·詹姆斯·范从詹姆斯·范艾伦。它还应该处理当其参数由单个单词组成时的特殊情况(例如,亚里士多德)。
是否可以在 TeX 框架内或者使用 Lua 或 LaTeX3 编写这样的宏?
提出的收据是为了回答我怎样才能颠倒字母/标记的顺序?仅当序列由两个单词组成时才解决我的问题。
答案1
\documentclass{article}
\protected\def\reverseit#1{\xreverseit{}#1 \relax}
\def\xreverseit#1#2 #3{%
\ifx\relax#3%
#2#1%
\expandafter\xthree
\fi
\xreverseit{#1 #2}#3}
\def\xthree#1#2#3{}
\begin{document}
\reverseit{Hannes Alfv\'{e}n}
\reverseit{}
\reverseit{one}
\reverseit{one two}
\reverseit{one two three}
\end{document}
答案2
LaTeX3 提供了有用的工具,希望它们比 David 的代码(示例毫不掩饰地取自他的解决方案)更容易理解。
\documentclass{article}
\usepackage{expl3, xparse}
\ExplSyntaxOn
\seq_new:N \l_input_seq % declare a list (seq) variable
\tl_new:N \l_last_word_tl % declare a "token list" variable
\NewDocumentCommand{\reverseit}{m}
{
\tl_if_blank:nF {#1} % If the input contains no words, do nothing.
{
% Split the argument into words (~ stands for a space here).
\seq_set_split:Nnn \l_input_seq { ~ } {#1}
% Remove the last word from the seq.
\seq_pop_right:NN \l_input_seq \l_last_word_tl
% Put the last word on the left of the sequence.
\seq_put_left:NV \l_input_seq \l_last_word_tl
% Use the contents of the sequence, separating words by a space (~).
\seq_use:Nnnn \l_input_seq { ~ } { ~ } { ~ }
}
}
\ExplSyntaxOff
\begin{document}
\reverseit{Hannes Alfv\'{e}n}
\reverseit{}
\reverseit{one}
\reverseit{one two}
\reverseit{one two three}
\end{document}