处理“列表”的“列表”

处理“列表”的“列表”

我实现了一个简短的宏,它处理以逗号分隔的参数列表并对其进行格式化。

因此通过调用

\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}

我看到

  1. 列表或嵌套列表中的元素之间不能有空格,这样元素才能成功传递。(通过 \tracingmarcros=1,在另一篇文章中发现了这种调试方法)
  2. 对于 \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}

也许,知道目的是什么,就可以设计出一些不那么笨拙的东西,包括界面。

在此处输入图片描述

更好的实现,具有更简洁的语法。

  1. 用空格分隔的字符串列表被视为来自单个机构的标题,如果有多个项目,则为最后一个指定的机构

  2. 此类列表可以通过用分号分隔来连接。

这是代码。

\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,然后根据需要插入宏和字符串替换即可。请注意,样式只是为了演示目的而虚构的。

相关内容