
Я пытаюсь создать l3keys
список, который называется , mykeys
который используется для управления поведением команды mycommand:n
. Изначально это просто идентификатор. Установка command=\textit
должна изменить его на \textit
(составленный с идентификатором). В общем, установка command=\foo
должна переопределиться mycommand:n
, чтобы стать #1
↦ \foo{mycommand:n{#1}}
. Однако в том виде, в котором он есть сейчас, он терпит неудачу.Возможно ли это реализовать?
\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\cs_new:Npn \identity:n #1 { #1 }
\keys_define:nn { mykeys }
{
command .multichoice:,
command / none .code:n = {
\cs_set_eq:NN \mycommand:n \identity:n %this resets \mycommand:n
%to become the identity
},
command / unknown .code:n = {
\cs_set:Npx \mycommand:n ##1
{
#1 { \mycommand:n { ##1 } }
}
}
}
\keys_set:nn { mykeys } { command=none }
\ExplSyntaxOff
\begin{document}
\ExplSyntaxOn
\mycommand:n{test1} % should produce test1
\keys_set:nn { mykeys } { command=\textit }
\mycommand:n{test2} % should produce \textit{test2}
\keys_set:nn { mykeys } { command=\textbf }
\mycommand:n{test3} % should produce \textbf{\textit{test3}}
\ExplSyntaxOff
\end{document}
решение1
Мне не особо нравится интерфейс, но здесь я бы хранил команды для приложения в последовательности
\documentclass{article}
\usepackage{expl3,xparse}
\ExplSyntaxOn
\seq_new:N \l__mycommand_cmds_seq
\tl_new:N \l__mycommand_tmp_tl
\keys_define:nn { mykeys }
{
command .code:n =
{
\str_if_eq:nnTF {#1} { none }
{ \seq_clear:N \l__mycommand_cmds_seq }
{ \seq_put_right:Nn \l__mycommand_cmds_seq {#1} }
}
}
\keys_set:nn { mykeys } { command = none }
\cs_new_protected:Npn \mycommand_main:n #1
{
\group_begin:
\tl_set:Nn \l__mycommand_tmp_tl {#1}
\seq_map_inline:Nn \l__mycommand_cmds_seq
{
\tl_set:Nx \l__mycommand_tmp_tl
{ \exp_not:n {##1} { \exp_not:V \l__mycommand_tmp_tl } }
}
\exp_args:NV \group_end:
\l__mycommand_tmp_tl
}
\NewDocumentCommand \mysetup { +m } { \keys_set:nn { mykeys } {#1} }
\NewDocumentCommand \mycommand { m }
{ \mycommand_main:n {#1} }
\ExplSyntaxOff
\begin{document}
\mycommand{test1} % should produce test1
\mysetup{command = \textit}
\mycommand{test2} % should produce \textit{test2}
\mysetup{command = \textbf}
\mycommand{test3} % should produce \textbf{\textit{test3}}
\end{document}
Можно было бы выполнить проверку одного токена/макроса как часть настройки keyval, но это, скорее всего, излишне.
Можно было бы создать список «функциональных» токенов во время настройки keyval, но я подозреваю, что наличие последовательности, доступной для проверки, может быть полезным при отладке.
решение2
до тех пор, пока задействованные команды раскрывают свою реализацию после одного расширения, вы можете сделать что-то вроде следующего
\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\cs_new:Npn \identity:n #1 { #1 }
\cs_new:Npn\wrap_def:NN#1#2{
\exp_after:wN\cs_set:Npn
\exp_after:wN#2\exp_after:wN##\exp_after:wN1\exp_after:wN{
\exp_after:wN#1\exp_after:wN{#2{##1}}}
}
\keys_define:nn { mykeys }
{
command .multichoice:,
command / none .code:n = {
\cs_set_eq:NN \mycommand:n \identity:n %this resets \mycommand:n
%to become the identity
},
command / unknown .code:n = {
\wrap_def:NN #1 \mycommand:n
}
}
\keys_set:nn { mykeys } { command=none }
\ExplSyntaxOff
\begin{document}
\ExplSyntaxOn
\mycommand:n{test1} % should produce test1
\keys_set:nn { mykeys } { command=\textit }
\mycommand:n{test2} % should produce \textit{test2}
\keys_set:nn { mykeys } { command=\textbf }
\mycommand:n{test3} % should produce \textbf{\textit{test3}}
\ExplSyntaxOff
\end{document}
решение3
Реализация предложения Дэвида:
\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\tl_new:N \l_gaussler_command_start_tl
\tl_new:N \l_gaussler_command_end_tl
\keys_define:nn { mykeys }
{
command .multichoice:,
command / none .code:n =
{
\tl_clear:N \l_gaussler_command_start_tl
\tl_clear:N \l_gaussler_command_end_tl
\cs_set_protected:Nn \gaussler_thecommand:n { ##1 }
},
command / unknown .code:n =
{
\tl_put_left:Nn \l_gaussler_command_start_tl { \exp_not:N #1 \gaussler_command_open: }
\tl_put_right:Nn \l_gaussler_command_end_tl { \gaussler_command_close: }
\cs_set_protected:Nx \gaussler_thecommand:n
{
\tl_use:N \l_gaussler_command_start_tl
##1
\tl_use:N \l_gaussler_command_end_tl
}
}
}
\cs_new:Nn \gaussler_command_open: { \if_true: { \else: } \fi: }
\cs_new:Nn \gaussler_command_close: { \if_false: { \else: } \fi: }
\keys_set:nn { mykeys } { command=none }
\ExplSyntaxOff
\begin{document}
\ExplSyntaxOn
\gaussler_thecommand:n{test1} % should produce test1
\keys_set:nn { mykeys } { command=\textit }
\gaussler_thecommand:n{test2} % should produce \textit{test2}
\keys_set:nn { mykeys } { command=\textbf }
\gaussler_thecommand:n{test3} % should produce \textbf{\textit{test3}}
\keys_set:nn { mykeys } { command=none }
\gaussler_thecommand:n{test4}
\ExplSyntaxOff
\end{document}