我如何定义一个贪婪宏?

我如何定义一个贪婪宏?

我感觉这在某处是重复的,但我如何确保 TeX 将继续扫描直到\relax或类似的东西?

\documentclass{article}
\usepackage{xparse}

\pagestyle{empty}
\setlength\parindent{0pt}

\begin{document}

Plain:

\def\test#1/#2/#3{
  year:#1   \newline
  month:#2  \newline
  day:#3    \newline
}
\test 01/02/03

\bigskip

Expl3:

\ExplSyntaxOn
\cs_new:Npn \test:w #1/#2/#3 {
  year:#1   \newline
  month:#2  \newline
  day:#3    \newline
}

\test:w 01/02/03
\ExplSyntaxOff

\bigskip

Keys:

\ExplSyntaxOn
\keys_define:nn { test } {
  date .code:n = { \test:w #1 },
  title .code:n = { title: #1 \newline},
}

\keys_set:nn {test} { title = hello, date = 15/16/17, title = hi}
\ExplSyntaxOff
\end{document}

输出

我意识到我可以引入一些标记(也许是夸克\q_stop)来l3keys .code:n“正常”地终止它。有没有办法在不引入此类标记的情况下做到这一点?

答案1

参数可以是定界的,也可以是非定界的;在后一种情况下,只有第一个标记或括号组被用作参数。您的\test:w宏有一个非定界的第三个参数;也定界第三个参数并在该部分中添加最后的定界符.code:n

\documentclass{article}
\usepackage{xparse}

\pagestyle{empty}
\setlength\parindent{0pt}

\begin{document}

\ExplSyntaxOn
\cs_new:Npn \test:www #1 / #2 / #3 \q_stop {
  year:#1   \newline
  month:#2  \newline
  day:#3    \newline
}

\test:w 01/02/03 \q_stop
\ExplSyntaxOff

\bigskip

Keys:

\ExplSyntaxOn
\keys_define:nn { test } {
  date .code:n = { \test:www #1 \q_stop },
  title .code:n = { title: #1 \newline},
}

\keys_set:nn {test} { title = hello, date = 15/16/17, title = hi}
\ExplSyntaxOff
\end{document}

在此处输入图片描述


可能更好的代码不显式使用分隔参数。效率可能较低,但更清晰。您可以添加几个检查以确保日期是否合法;错误的输入\test:www会导致无法理解的错误。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\test}{ m }
 {
  \keys_set:nn { sean/test } { #1 }
 }

\cs_new:Npn \sean_test:nn #1 #2
 {
  \seq_set_split:Nnn \l__sean_date_seq { #1 } { #2 }
  \int_compare:nTF { \seq_count:N \l__sean_date_seq == 3 }
   {
    year: ~\seq_item:Nn \l__sean_date_seq { 1 } \newline
    month:~\seq_item:Nn \l__sean_date_seq { 2 } \newline
    day:  ~\seq_item:Nn \l__sean_date_seq { 3 } \newline
   }
   {
    BAD~DATE!
   }
 }
\cs_generate_variant:Nn \sean_test:nn { V }

\keys_define:nn { sean/test }
 {
  date-delimiter .tl_set:N = \l_sean_date_delimiter_tl,
  date-delimiter .initial:n = { / },
  date .code:n = { \sean_test:Vn \l_sean_date_delimiter_tl { #1 } },
  title .code:n = { title: ~ #1 \newline },
 }
\ExplSyntaxOff

\setlength{\parindent}{0pt}
\pagestyle{empty}

\begin{document}

\test{ title = hello, date = 15/16/17, title = hi }

\bigskip

\test{ title = hi, date-delimiter = - , date = 01-02-03 }

\end{document}

在此处输入图片描述

答案2

不确定你需要什么,也许:

\documentclass{article}
\usepackage{xparse}

\pagestyle{empty}
\setlength\parindent{0pt}

\begin{document}

Plain:

\def\test#1/#2/#3 {
  year:#1   \newline
  month:#2  \newline
  day:#3    \newline
}
\test 01/02/03

\bigskip

Expl3:

\ExplSyntaxOn
\cs_new:Npn \test:w #1/#2/#3~{
  year:#1   \newline
  month:#2  \newline
  day:#3    \newline
}

\test:w 01/02/03~
\ExplSyntaxOff

\bigskip

Keys:

\ExplSyntaxOn
\keys_define:nn { test } {
  date .code:n = { \test:w #1~ },
  title .code:n = { title: #1 \newline},
}

\keys_set:nn {test} { title = hello, date = 15/16/17, title = hi}
\ExplSyntaxOff
\end{document}

相关内容