这是上一个问题的延伸(关联)。我想将以下xparse
保存值的键值存储包含name
到以下文档中:
% Key-value store
\ExplSyntaxOn
\prop_new:N \list_prop
\keys_define:nn {bio} {%
name .code:n={ \prop_put:Nnn \list_prop {name} {#1} },
}
\NewDocumentCommand{\update}{+m}{%
\keys_set:nn {bio} {#1}%
}
\cs_new:Npn \getvalue#1{%
\prop_item:Nn \list_prop {#1}
}
\ExplSyntaxOff
% Default variable values
\update{%
name={John Doe}
}
我想使用下面定义的存储name
来自动更新。换句话说,将根据上述键值存储中的值自动定义。理想的做法是保留该函数以获得灵活性,但在未传递参数时将其设为默认值。l_adam_name_full_tl
\adam_name_define:n
l_adam_name_full_tl
\definename
\getvalue{name}
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\definename}{m}
{
\adam_name_define:n { #1 }
}
\NewDocumentCommand{\makebold}{m}
{
\adam_name_makebold:n { #1 }
}
\tl_new:N \l_adam_name_full_tl
\tl_new:N \l_adam_name_first_tl
\tl_new:N \l_adam_name_last_tl
\tl_new:N \l_adam_name_initials_tl
\tl_new:N \l__adam_name_input_tl
\cs_new_protected:Nn \adam_name_define:n
{
\tl_set:Nn \l_adam_name_full_tl { #1 }
\tl_set_eq:NN \l_adam_name_first_tl \l_adam_name_full_tl
\tl_set_eq:NN \l_adam_name_last_tl \l_adam_name_full_tl
\regex_replace_once:nnN { (.*)\s[^\s]*\Z } { \1 } \l_adam_name_first_tl
\regex_replace_once:nnN { .*\s([^\s]*)\Z } { \1 } \l_adam_name_last_tl
\tl_set_eq:NN \l_adam_name_initials_tl \l_adam_name_first_tl
\regex_replace_all:nnN { ([[:alpha:]])[[:alpha:]]+ } { \1. } \l_adam_name_initials_tl
}
\cs_new_protected:Nn \adam_name_makebold:n
{
\tl_set:Nn \l__adam_name_input_tl { #1 }
% full name
\regex_replace_once:nnN
{
(
\u{l_adam_name_full_tl} % name surname
|
\u{l_adam_name_initials_tl} \s \u{l_adam_name_last_tl} % initials surname
|
\u{l_adam_name_last_tl} , \s \u{l_adam_name_first_tl} % surname, name
|
\u{l_adam_name_last_tl} , \s \u{l_adam_name_initials_tl} % surname, initials
)
}
{ \c{textbf} \cB\{ \1 \cE\} }
\l__adam_name_input_tl
% print
\tl_use:N \l__adam_name_input_tl
}
\ExplSyntaxOff
\begin{document}
\definename{John Doe}
\makebold{His name was John Doe.}
\makebold{His name was J. Doe.}
\makebold{His name was Doe, J..}
\definename{John T. Doe}
\makebold{His name was John T. Doe.}
\makebold{His name was J. T. Doe.}
\makebold{His name was Doe, J. T..}
\end{document}
预期输出:
他以前的名字是约翰·多伊。
他以前的名字是多伊,约翰。
他以前的名字是J·多伊。
他以前的名字是多伊,J.。
他以前的名字是约翰·T·多伊。
他以前的名字是JT Doe。
他以前的名字是多伊,JT。
答案1
您可以使用\prop_set_from_keyval:Nn
而不是定义键,但这不是重点。
这里我定义了\update
填充属性列表,并调用\adam_name_define:x
提取name
属性。这里你可以看到一个优点expl3
:该函数只是\adam_name_define:n
它的一个变体,它在执行工作之前会对其参数进行完全扩展。
请参阅其他答案以了解对正则表达式代码的注释。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\definename}{m}
{
\adam_name_define:n { #1 }
}
\NewDocumentCommand{\makebold}{m}
{
\adam_name_makebold:n { #1 }
}
\NewDocumentCommand{\makeboldlastname}{m}
{
\adam_name_makebold_lastname:n { #1 }
}
\NewDocumentCommand{\update}{m}
{
\prop_clear:N \l_adam_name_bio_prop
\prop_set_from_keyval:Nn \l_adam_name_bio_prop { #1 }
\adam_name_define:x { \prop_item:Nn \l_adam_name_bio_prop { name } }
}
\prop_new:N \l_adam_name_bio_prop
\tl_new:N \l_adam_name_full_tl
\tl_new:N \l_adam_name_first_tl
\tl_new:N \l_adam_name_last_tl
\tl_new:N \l_adam_name_initials_tl
\tl_new:N \l__adam_name_input_tl
\cs_new_protected:Nn \adam_name_define:n
{
\tl_set:Nn \l_adam_name_full_tl { #1 }
\tl_set_eq:NN \l_adam_name_first_tl \l_adam_name_full_tl
\tl_set_eq:NN \l_adam_name_last_tl \l_adam_name_full_tl
\regex_replace_once:nnN { (.*)\s[^\s]*\Z } { \1 } \l_adam_name_first_tl
\regex_replace_once:nnN { .*\s([^\s]*)\Z } { \1 } \l_adam_name_last_tl
\tl_set_eq:NN \l_adam_name_initials_tl \l_adam_name_first_tl
\regex_replace_all:nnN { ([[:alpha:]])[[:alpha:]]+ } { \1. } \l_adam_name_initials_tl
}
\cs_generate_variant:Nn \adam_name_define:n { x }
\cs_new_protected:Nn \adam_name_makebold:n
{
\tl_set:Nn \l__adam_name_input_tl { #1 }
% full name
\regex_replace_once:nnN
{
(
\u{l_adam_name_full_tl} % name surname
|
\u{l_adam_name_initials_tl} \s \u{l_adam_name_last_tl} % initials surname
|
\u{l_adam_name_last_tl} , \s \u{l_adam_name_first_tl} % surname, name
|
\u{l_adam_name_last_tl} , \s \u{l_adam_name_initials_tl} % surname, initials
)
}
{ \c{textbf} \cB\{ \1 \cE\} }
\l__adam_name_input_tl
% print
\tl_use:N \l__adam_name_input_tl
}
\cs_new_protected:Nn \adam_name_makebold_lastname:n
{
\tl_set:Nn \l__adam_name_input_tl { #1 }
\regex_replace_once:nnN
{ (\u{l_adam_name_last_tl}) }
{ \c{textbf} \cB\{ \1 \cE\} }
\l__adam_name_input_tl
\tl_use:N \l__adam_name_input_tl
}
\ExplSyntaxOff
\begin{document}
\update{
name=John Doe,
town=London,
birth=1888-05-01,
}
\makebold{His name was John Doe.}
\makebold{His name was J. Doe.}
\makebold{His name was Doe, John.}
\makebold{His name was Doe, J. again.}
\makeboldlastname{Again, Doe was his last name.}
\makebold{Jackson, Bob and J. Doe.}
\update{
name=John T. Doe,
town=New York,
}
\makebold{His name was John T. Doe.}
\makebold{His name was J. T. Doe.}
\makebold{His name was Doe, John T. again.}
\makebold{His name was Doe, J. T. again.}
\makeboldlastname{Again, Doe was his last name.}
\definename{Brutus Cyclops Dull}
\makebold{His name was Brutus Cyclops Dull.}
\makebold{His name was B. C. Dull.}
\makebold{His name was Dull, Brutus Cyclops again.}
\makebold{His name was Dull, B. C. again.}
\makeboldlastname{Again, Dull was his last name.}
\end{document}