我实现了一个简短的宏,它处理以逗号分隔的参数列表并对其进行格式化。
因此通过调用
\macroa{ABC, DEF}
它将把文本格式化为 ABC防御
现在我想要一个宏或命令(更好的宏),通过调用
\macrob{{ABC, DEF}, {GHI, JKL}, {MNO, PQR}}
可以通过调用我定义的宏 macroa 列出给定的列表,传递给 macrob 的列表数量是可变的,但肯定少于 10。结果是输出 ABC防御;高血压杰凯伦;移动网络运营商质检总局。
第二个问题比较高级,但不是必需的。如果我想考虑每个列表的第二个参数来确定使用分号还是逗号,是否有一个简单的实现,即修改宏来实现?比如说,我想要一个空的第二个参数来使用逗号连接传递的下一个列表。
\macroc{{ABC, }, {GHI, }, {MNO, PQR}, {STU, VWX}}
ABC、GHI、MNO质检总局;圣路易斯大学垂直风洞
最后,我想知道这种“列表”的专业术语。
非常感谢您的帮助!
问题已部分解决。谢谢@egreg!!!
\documentclass[12pt,a4paper,notitlepage,openright]{report}
\usepackage{xparse}
\makeatletter
\def\awarddegree#1{\gdef\@awarddegree{#1 }}
\def\@awarddegree{\@latex@warning@no@line{No \noexpand\awarddegree given}}
\def\pastdegree#1{\expandafter\pastdegree@i#1\@nil}
\def\pastdegree@i#1,#2\@nil{\gdef\@pastdegree{#1 \textit{#2}}}
\def\@pastdegree{\@latex@warning@no@line{No \noexpand\pastdegree given}}
\def\atry#1{\expandafter\atry@i#1\@nil}
\def\atry@i#1,#2\@nil{\gdef\@atry{\pastdegree{#1}\@pastdegree; \pastdegree{#2}\@pastdegree}}
\def\@atry{\@latex@warning@no@line{No \noexpand\atry given}}
\makeatother
\atry{{B.A.,H.K.},{M.Phil.,Oxon.}}
\begin{document}
\makeatletter
\@atry
\makeatother
\end{document}
我看到
- 列表或嵌套列表中的元素之间不能有空格,这样元素才能成功传递。(通过 \tracingmarcros=1,在另一篇文章中发现了这种调试方法)
- 对于 \def\atry@i#1,#2\@nil 行,之前只有 \gdef\@atry{\pastdegree{#1} \pastdegree{#2}},因此没有输入。因此,观察 \@macro 和 \macro 的使用,我发现 \macro 可能是 C 意义上的“定义”,而 \@macro 是“定义”的调用/使用,因此我将这一行更改为上述解决方案。
再次感谢@egreg。今晚我学到了很多东西!
最终解决方案
\makeatletter
\def\pastdegree#1{\expandafter\pastdegree@i#1\@nil}
\def\pastdegree@i#1,#2\@nil{\gdef\@pastdegree{#1\IfStrEq{#2}{}{}{ }\textit{#2}}}
\def\@pastdegree{\@latex@warning@no@line{No \noexpand\pastdegree given}}
\newcommand{\ifsameinstitute}[1]{\IfEndWith{#1}{,}{,}{;}}
% WRITING A MACRO WITH COMMA EXPANSION LIST
%
% http://tex.stackexchange.com/questions/15716/how-do-i-write-a-macro-having-comma-separated-and-variable-number-of-arguments
\def\degreelist#1{\expandafter\degreelist@i#1,,,,,,,,\@nil}
\def\degreelist@i#1,#2,#3,#4,#5,#6,#7,#8,#9\@nil{%
\ifx$#2$ \gdef\@degreelist{\pastdegree{#1}\@pastdegree}
\else
\ifx$#3$ \gdef\@degreelist{\pastdegree{#1}\@pastdegree\ifsameinstitute{#1} %
\pastdegree{#2}\@pastdegree}
\else
\ifx$#4$ \gdef\@degreelist{\pastdegree{#1}\@pastdegree\ifsameinstitute{#1} %
\pastdegree{#2}\@pastdegree\ifsameinstitute{#2} %
\pastdegree{#3}\@pastdegree}
\else
\ifx$#5$ \gdef\@degreelist{\pastdegree{#1}\@pastdegree\ifsameinstitute{#1} %
\pastdegree{#2}\@pastdegree\ifsameinstitute{#2} %
\pastdegree{#3}\@pastdegree\ifsameinstitute{#3} %
\pastdegree{#4}\@pastdegree}
\else
\ifx$#6$ \gdef\@degreelist{\pastdegree{#1}\@pastdegree\ifsameinstitute{#1} %
\pastdegree{#2}\@pastdegree\ifsameinstitute{#2} %
\pastdegree{#3}\@pastdegree\ifsameinstitute{#3} %
\pastdegree{#4}\@pastdegree\ifsameinstitute{#4} %
\pastdegree{#5}\@pastdegree}
\else
\ifx$#7$ \gdef\@degreelist{\pastdegree{#1}\@pastdegree\ifsameinstitute{#1} %
\pastdegree{#2}\@pastdegree\ifsameinstitute{#2} %
\pastdegree{#3}\@pastdegree\ifsameinstitute{#3} %
\pastdegree{#4}\@pastdegree\ifsameinstitute{#4} %
\pastdegree{#5}\@pastdegree\ifsameinstitute{#5} %
\pastdegree{#6}\@pastdegree}
\else
\ifx$#8$ \gdef\@degreelist{\pastdegree{#1}\@pastdegree\ifsameinstitute{#1} %
\pastdegree{#2}\@pastdegree\ifsameinstitute{#2} %
\pastdegree{#3}\@pastdegree\ifsameinstitute{#3} %
\pastdegree{#4}\@pastdegree\ifsameinstitute{#4} %
\pastdegree{#5}\@pastdegree\ifsameinstitute{#5} %
\pastdegree{#6}\@pastdegree\ifsameinstitute{#6} %
\pastdegree{#7}\@pastdegree}
\else
\gdef\@degreelist{\pastdegree{#1}\@pastdegree\ifsameinstitute{#1} %
\pastdegree{#2}\@pastdegree\ifsameinstitute{#2} %
\pastdegree{#3}\@pastdegree\ifsameinstitute{#3} %
\pastdegree{#4}\@pastdegree\ifsameinstitute{#4} %
\pastdegree{#5}\@pastdegree\ifsameinstitute{#5} %
\pastdegree{#6}\@pastdegree\ifsameinstitute{#6} %
\pastdegree{#7}\@pastdegree\ifsameinstitute{#7} %
\pastdegree{#8}\@pastdegree}
\fi\fi\fi\fi\fi\fi\fi
}
\def\@degreelist{\@latex@warning@no@line{No \noexpand\degreelist given}}
\makeatother
\degreelist{{B.A.,},{M.Phil.,H.K.},{Ph.D.,Cantab.}}
\begin{document}
{\@degreelist}
\end{document}
打印名词后缀
答案1
实现方式不是最好的,但只是看看它可以做到:
\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand{\macroa}{ >{\SplitArgument{1}{,}}m }
{%
\processtwo#1%
}
\NewDocumentCommand{\processtwo}{ m m }
{%
\IfNoValueTF{#2}
{%
\semicolonfalse
#1, %
}
{%
\semicolontrue
#1 \textbf{\textit{#2}}%
}%
}
\newcounter{liststep}
\newif\ifsemicolon
\NewDocumentCommand{\macrob}{ >{\SplitList{,}}m }
{%
\setcounter{liststep}{0}%
\semicolonfalse
\ProcessList{#1}{\macroamod}%
}
\NewDocumentCommand\macroamod{m}
{%
\ifnum\value{liststep}>0 \ifsemicolon; \else\semicolontrue\fi\fi
\macroa{#1}%
\stepcounter{liststep}%
}
\begin{document}
\macroa{ABC, DEF}
\macrob{{ABC, DEF}, {GHI, JKL}, {MNO, PQR}}
\macrob{{ABC}, {GHI}, {MNO, PQR}, {STU, VWX}}
\end{document}
也许,知道目的是什么,就可以设计出一些不那么笨拙的东西,包括界面。
更好的实现,具有更简洁的语法。
用空格分隔的字符串列表被视为来自单个机构的标题,如果有多个项目,则为最后一个指定的机构
此类列表可以通过用分号分隔来连接。
这是代码。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\degreelist}{m}
{
\dominic_degree_list:n { #1 }
}
\seq_new:N \l_dominic_degrees_input_seq
\seq_new:N \l_dominic_degrees_output_seq
\seq_new:N \l_dominic_inst_seq
\tl_new:N \l_dominic_inst_tl
\cs_new_protected:Npn \dominic_degree_list:n #1
{
\seq_set_split:Nnn \l_dominic_degrees_input_seq { ; } { #1 }
\seq_set_map:NNn \l_dominic_degrees_output_seq \l_dominic_degrees_input_seq
{
\dominic_inst:n { ##1 }
}
\seq_use:Nn \l_dominic_degrees_output_seq { ;~ }
}
\cs_new_protected:Npn \dominic_inst:n #1
{
\seq_set_split:Nnn \l_dominic_inst_seq { ~ } { #1 }
\int_compare:nTF { \seq_count:N \l_dominic_inst_seq == 1 }
{
#1
}
{
\seq_pop_right:NN \l_dominic_inst_seq \l_dominic_inst_tl
\seq_use:Nn \l_dominic_inst_seq { ,~ }
\c_space_tl
\textbf{ \textit{ \l_dominic_inst_tl } }
}
}
\ExplSyntaxOff
\begin{document}
\degreelist{ABC DEF}
\degreelist{ABC DEF; GHI JKL; MNO PQR}
\degreelist{ABC; GHI MNO PQR; STU VWX}
\end{document}
答案2
尽管在我以前的文章中,我不太愿意推荐使用LuaLaTeX
,但现在代码已经足够成熟,而且 LuaTeX 团队做得非常出色,我衷心建议任何“论文类”认真考虑使用LuaLaTeX
。论文模板是关于强制执行样式的,而解析是 Lua 的强项之一。如果您希望格式化敬语(样式手册与样式手册不同),我建议您再看一眼此类代码的 UI。
让用户输入以下内容会更简单:
\honorific {BSc (Lond.) Ph.D. MSc. M.Phil Oxon., OBE}
比输入有各种规则。
使用少量 Lua 代码,您可以解析字符串,将字符串数组拆分为表,然后在哈希表中查找值。
\documentclass{article}
\usepackage{luacode,filecontents}
\begin{filecontents*}{honorific.lua}
-- module honorific
-- @return Univ. of Anywhere formatted honorific suffix
local M = {}
local t = {}
t['phd'] = {'PhD', '\\textup{PhD}'}
t['ma'] = {'MA', '\\textup{MA}'}
t['mphil'] = {MPhil, '\\textbf{MPhil}'}
t['msc'] = {MSc, 'MSc'}
t['obe'] = {OBE, '\\textit{Stiff Upper Lip}'}
function split(str, pat)
local t = {}
local fpat = "(.-)" .. pat
local last_end = 1
local s, e, cap = str:find(fpat, 1)
while s do
if s ~= 1 or cap ~= "" then
table.insert(t,cap)
end
last_end = e+1
s, e, cap = str:find(fpat, last_end)
end
if last_end <= #str then
cap = str:sub(last_end)
table.insert(t, cap)
end
return t
end
function split_honorific(str)
return split(str, '[%s]')
end
M.honorific = function (text)
-- split string
text = split_honorific(text)
for k,v in ipairs (text) do
local tmp = string.lower(v)
tmp = string.gsub(tmp,'%.','')
if t[tmp] then
tex.print(t[tmp][2])
else
tex.print(v)
end
end
end
return M
\end{filecontents*}
\makeatletter
\def\honorific#1{%
\luadirect{
m = require'honorific'
m.honorific('#1')
}%
}
\makeatother
\begin{document}
\honorific {BSc (Lond.) Ph.D.
MSc. M.Phil Oxon., OBE}
\end{document}
这种类型的问题乍一看很简单,但如果必须将其扩展到例如牛津日历Lua 本来是唯一的选择。我喜欢 Lua 解决方案的原因是它可以简化作者界面。可以扩展上面的代码,甚至不必要求用户使用任何宏。只需解析输入文件,然后将其传递给 TeX,然后根据需要插入宏和字符串替换即可。请注意,样式只是为了演示目的而虚构的。