使用 l3keys模拟 pgfkeys /.code 2 args
(或更一般而言/.code n args
)处理程序的推荐方法是什么?例如,使用 pgfkeys 可以执行
\documentclass{article}
\usepackage{pgfkeys}
\newcommand{\cmdA}{init A}
\newcommand{\cmdB}{init B}
\pgfkeys{
somekey/.code 2 args={%
\renewcommand{\cmdA}{#1}%
\renewcommand{\cmdB}{#2}%
}
}
\begin{document}
\cmdA\ \cmdB
\pgfkeys{somekey={new A}{new B}}
\cmdA\ \cmdB
\end{document}
使用l3keys 的处理程序时,只允许使用.code:n
单个参数。#1
\ExplSyntaxOn
\keys_define:nn { mymodule } {
somekey .code:n = {
\tl_set:Nn \cmdA { #1 }
%\tl_set:Nn \cmdB { #2 } % want to be able to do this
}
}
\ExplSyntaxOff
我已经想出了如何通过扩展参数并将其传递给辅助宏来做到这一点:
\documentclass{article}
\newcommand{\cmdA}{init A}
\newcommand{\cmdB}{init B}
\newcommand{\auxmacro}[2]{%
\renewcommand{\cmdA}{#1}%
\renewcommand{\cmdB}{#2}%
}
\ExplSyntaxOn
\keys_define:nn { mymodule } {
somekey .code:n = { \exp_after:wN \auxmacro #1 }
}
\ExplSyntaxOff
\begin{document}
\cmdA\ \cmdB
\SetKeys[mymodule]{somekey={new A}{new B}}
\cmdA\ \cmdB
\end{document}
但是有没有办法在键定义中直接使用更多参数#2
,等等?#3
答案1
正如评论中所述,我们有意不提供“分割值”功能l3keys
。相反,额外的处理预计将委托给一个以值作为输入的专用函数
\keys_define:nn { foo }
{
my-key .code:n = \__foo_process_my_key:n {#1}
}
\cs_new_protected:Npn \__foo_process_my_key:n #1
{
% Whatever is appropriate here
}
答案2
为了说明这一点,约瑟夫·赖特 (Joseph Wright) 描述的两步过程允许步骤 #1 具有开放式的特征:例如,它可以是一个数据结构:
同样的foo
,三种不同的输出:
(有点类似于 DNA\RNA。)
平均能量损失
\documentclass{article}
\usepackage{xcolor}
\ExplSyntaxOn
\keys_define:nn { foo }
{
my-key .code:n = \__foo_process_my_key:n {#1}
}
\cs_new_protected:Npn \my_func:n #1 {
\tl_set:Nx
\l_tmpb_tl
{
\seq_item:Nn
\_tmpa_seq
{ #1 }
}
\seq_set_split:NnV
\_tmpb_seq
{ ; }
\l_tmpb_tl
% \seq_show:N
% \_tmpb_seq
\tl_set:Nn
\l_tmpb_tl
{
\textcolor { \seq_item:Nn \_tmpb_seq { 3 }} { \seq_item:Nn \_tmpb_seq { 1 } }
}
\tl_use:N
\l_tmpb_tl
}
\cs_new_protected:Npn \__foo_process_my_key:n #1
{
% Whatever is appropriate here
\tl_set:Nn \l_tmpa_tl { #1 }
\seq_set_split:NnV
\_tmpa_seq
{ / }
\l_tmpa_tl
\int_step_function:nnnN { 1 } { 1 } { \seq_count:N \_tmpa_seq } \my_func:n
}
\NewDocumentCommand { \foo } { o } {
\keys_set:nn { foo } { #1 }
}
\ExplSyntaxOff
\begin{document}
\foo[my-key=
ABCDE $\mapsto$~;;black
/A;z;red
/B;y;green
/C;x;blue
/D;w;yellow
/E;v;cyan
]
\foo[my-key=
The cat;;black
/~sat;;red
/~on the mat;;black
].
\foo[my-key=
The quick~;;black
/{\large brown};;red
/\kern-0.4pt\llap{{\large brown}};;blue
/~jumps over the lazy dog;;black
].
\end{document}
编辑
关于代码模糊性的评论,可以在代码本身中内置一个帮助选项,将代码与前端分开。有点像挂毯的背面和正面。
这是对有关多色字母的 SE 答案的解释尝试。
顺便说一句,expl3 使某些事情(例如 lettrining 某些东西)变得几乎微不足道(但并非不复杂 - 要解决的问题决定了任何解决方案的复杂性级别;在这里它是易读性和足够令人愉快的阅读体验)。
平均能量损失
\documentclass{article}
\usepackage{fontspec}
\usepackage{xcolor}
\setmainfont{NotoSerif}
\newfontfamily\fcmd{NotoSans}[Colour=blue]
\newcommand\cmd[1]{{\fcmd#1}}
\newcommand\trimahelptext{%
letter in the string of characters can be overprinted up to \cmd{number-of-colours=} times (max of 4) using colours \cmd{trimacolour[a-d]=} clipped from the left in increasing order with \cmd{trimawidth[a-d]=} and formatted with switches such as \cmd{\textbackslash bfseries} (bold) and \cmd{\textbackslash itshape} (italic) using \cmd{format=}. For example, the above heading's trima scheme was done with:\\\\
{\ttfamily
\textbackslash trima[\\
trimawidtha=1pt,\\
trimawidthb=2.5pt,\\
trimawidthc=5pt,\\
trimawidthd=8pt,\\
trimacoloura=red,\\
trimacolourb=blue,\\
trimacolourc=red!60!yellow,\\
trimacolourd=green,\\
]\{\} \\
}
}
\ExplSyntaxOn
\tl_new:N \l_trima_coloura_tl
\tl_new:N \l_trima_colourb_tl
\tl_new:N \l_trima_colourc_tl
\tl_new:N \l_trima_colourd_tl
\dim_new:N \l_trima_widtha_dim
\dim_new:N \l_trima_widthb_dim
\dim_new:N \l_trima_widthc_dim
\dim_new:N \l_trima_widthd_dim
\int_new:N \l_trima_numcolours_int
\tl_new:N \l_trima_format_tl
\keys_define:nn { trima }
{
trimacoloura .tl_set:N = \l_trima_coloura_tl,
trimacolourb .tl_set:N = \l_trima_colourb_tl,
trimacolourc .tl_set:N = \l_trima_colourc_tl,
trimacolourd .tl_set:N = \l_trima_colourd_tl,
trimacoloura .default:n = { \tl_set:Nn \l_trima_coloura_tl {red} },
trimacolourb .default:n = { \tl_set:Nn \l_trima_colourb_tl {blue} },
trimacolourc .default:n = { \tl_set:Nn \l_trima_colourc_tl {red!40!yellow} },
trimacolourd .default:n = { \tl_set:Nn \l_trima_colourd_tl {black} },
trimacoloura .initial:n = { \tl_set:Nn \l_trima_coloura_tl {red} },
trimacolourb .initial:n = { \tl_set:Nn \l_trima_colourb_tl {blue} },
trimacolourc .initial:n = { \tl_set:Nn \l_trima_colourc_tl {red!40!yellow} },
trimacolourd .initial:n = { \tl_set:Nn \l_trima_colourd_tl {black} },
number-of-colours .int_set:N = \l_trima_numcolours_int,
number-of-colours .initial:n = 4,
number-of-colours .default:n = 4,
format .tl_set:N = \l_trima_format_tl,
trimawidtha .dim_set:N = \l_trima_widtha_dim,
trimawidthb .dim_set:N = \l_trima_widthb_dim,
trimawidthc .dim_set:N = \l_trima_widthc_dim,
trimawidthd .dim_set:N = \l_trima_widthd_dim,
trimawidtha .default:n = 2em,
trimawidthb .default:n = 1.5pt,
trimawidthc .default:n = 3.0pt,
trimawidthd .default:n = 4.0pt,
trimawidtha .initial:n = 2em,
trimawidthb .initial:n = 1.5pt,
trimawidthc .initial:n = 3.0pt,
trimawidthd .initial:n = 4.0pt,
help .code:n = { \trimahelp },
}
\box_new:N \l_trima_cola_box
\box_new:N \l_trima_colb_box
\box_new:N \l_trima_colc_box
\box_new:N \l_trima_cold_box
\tl_new:N \l_trima_result_tl
\tl_new:N \l_trima_text_tl
%--------------------------
\cs_new_protected:Npn \trima_dotrim:n #1 {
\tl_set:Nn \l_trima_text_tl {
\group_begin:
\tl_use:N \l_trima_format_tl
#1
\group_end:
}
%\tl_show:N \l_trima_coloura_tl
\hbox_set:Nn
\l_trima_cola_box
{ \textcolor{\tl_use:N \l_trima_coloura_tl}{ \tl_use:N \l_trima_text_tl } }
\hbox_set:Nn
\l_trima_colb_box
{ \textcolor{\tl_use:N \l_trima_colourb_tl}{ \tl_use:N \l_trima_text_tl } }
\box_set_trim:Nnnnn
\l_trima_colb_box
{\dim_use:N \l_trima_widthb_dim} {0pt} {0pt} {0pt}
\box_clip:N
\l_trima_colb_box
\hbox_set:Nn
\l_trima_colc_box {
\textcolor{\tl_use:N \l_trima_colourc_tl}{ \tl_use:N \l_trima_text_tl } }
\box_set_trim:Nnnnn
\l_trima_colc_box
{\dim_use:N \l_trima_widthc_dim}
{0pt} {0pt} {0pt}
\box_clip:N
\l_trima_colc_box
\hbox_set:Nn
\l_trima_cold_box
{ \textcolor{\tl_use:N \l_trima_colourd_tl}{ \tl_use:N \l_trima_text_tl } }
\box_set_trim:Nnnnn
\l_trima_cold_box
{\dim_use:N \l_trima_widthd_dim}
{0pt} {0pt} {0pt}
\box_clip:N
\l_trima_cold_box
\tl_clear:N \l_trima_result_tl
\int_case:nnTF
{ \l_trima_numcolours_int }
{
{ 1 } {
\tl_set:Nn
\l_trima_result_tl
{
\box_use:N \l_trima_cola_box
}
}
{ 2 } {
\tl_set:Nn
\l_trima_result_tl
{
\box_use:N \l_trima_cola_box
\llap{\box_use:N \l_trima_colb_box}
}
}
{ 3 } {
\tl_set:Nn
\l_trima_result_tl
{
\box_use:N \l_trima_cola_box
\llap{\box_use:N \l_trima_colb_box}
\llap{\box_use:N \l_trima_colc_box}
}
}
{ 4 } {
\tl_set:Nn
\l_trima_result_tl
{
\box_use:N \l_trima_cola_box
\llap{\box_use:N \l_trima_colb_box}
\llap{\box_use:N \l_trima_colc_box}
\llap{\box_use:N \l_trima_cold_box}
}
}
}
{}{}
% {
\tl_use:N
\l_trima_result_tl
% }
}
\NewDocumentCommand { \trimahelp } { } {
\trima[
trimawidtha=1pt,
trimawidthb=2.5pt,
trimawidthc=5pt,
trimawidthd=8pt,
trimacoloura=red,
trimacolourb=blue,
trimacolourc=red!60!yellow,
trimacolourd=green,
]{{\rule{\textwidth}{0.5pt}}}
\section*{\trima{Introductory \ Tutorial\ to\ \textbackslash} trima\ \trima{Command}}
\input Acorn.fd
\hbox_set:Nn
\l_tmpa_box
{
\fontsize{60pt}{72pt}\usefont{U}{Acorn}{xl}{n}
E
}
\box_use:N \l_tmpa_box
\vspace{-1.3\box_ht:N \l_tmpa_box}
\hangindent=\dim_eval:n {0.4em+\box_wd:N \l_tmpa_box}
\hangafter=-\fp_to_int:n { 2 + \box_ht:N \l_tmpa_box / \baselineskip }
\noindent
\kern-0.3em\textsc{ach}\ \trimahelptext
\tex_par:D
\noindent
:\hfill\rule{0.32\textwidth}{0.5pt}\hfill :
}
\NewDocumentCommand { \trima } { o m } {
% \tl_show:N \l_trima_colourd_tl
% \dim_show:N \l_trima_widthc_dim
\tl_if_novalue:nF{#1}
{\keys_set:nn { trima } { #1 } }
% \tl_show:N \l_trima_colourd_tl
\tl_set:Nn \l_tmpa_tl { #2 }
\mode_leave_vertical:
\tl_map_function:NN
\l_tmpa_tl
\trima_dotrim:n
}
\ExplSyntaxOff
%\newcommand\trima[1]{%
% \textcolor{red}{#1}%
%\llap{\clipbox{2.5pt 0pt 0pt 0pt}{\textcolor{blue}{#1}}}%
%\llap{\clipbox{3.0pt 0pt 0pt 0pt}{\textcolor{red!40!yellow}{#1}}}%
%\llap{\clipbox{4.0pt 0pt 0pt 0pt}{\textcolor{black}{#1}}}%
%}
\begin{document}
\large
a
\trima[
trimacoloura=red,
trimacolourb=blue,
trimacolourc=red!40!yellow,
trimacolourd=black,
number-of-colours=4,
trimawidtha,
trimawidthb,
trimawidthc,
trimawidthd,
format=\itshape,
]{abxyz}
\trima{abxyz}
\trima[number-of-colours=2,
]{QWERTY}
\trima{uiop}
\trima[
number-of-colours=4,
trimacolourd=green,%!60!yellow!40,
]{qazdxc}
\trima[
format=\Huge,
]{Q}
\trima[format=\normalsize,
]{{\rule{1.5em}{1em}}}
The
\trima[
trimacoloura=black,
trimacolourb=black,
trimacolourc=black,
trimacolourd=black,
format=\itshape\bfseries,
]{cat}
sat on the
\trima{mat}.
\trima[
trimawidtha=1pt,
trimawidthb=2.5pt,
trimawidthc=5pt,
trimawidthd=8pt,
trimacoloura=red,
trimacolourb=blue,
trimacolourc=red!60!yellow,
trimacolourd=green,
]{{\rule{1.5em}{1em}}}
\section{\trima{Introduction}}
\trima[help]{}
\end{document}