我可以在通用代码中引用键值吗?

我可以在通用代码中引用键值吗?

有关的:keyreader:如何将选择键值保存到宏

我在用着l3keys2e,但我怀疑这可能不是我想要做的事情的理想方式。

我正在构建一个私人包,其中对字体设置进行了各种调整:

\bool_if:nTF { \xetex_if_engine_p: || \luatex_if_engine_p: }
  { \clist_const:Nn \c_jcsfonts_clist { lmodern, fontin, constantia } }
  { \clist_const:Nn \c_jcsfonts_clist { cmodern, kpfonts } }

我正在尝试进行设置,以便\usepackage[font = choice]{jcsfonts}启用正确的自定义批次,列表中的第一个条目为默认条目。这似乎不起作用:

\cs_generate_variant:Nn \quark_new:N {c}
\clist_map_inline:Nn \c_jcsfonts_clist { \quark_new:c { q_jcsfonts_ #1 } }

\keys_define:nn { jcsfonts }
  {
    font .choice_code:n =
      { \cs_set_eq:Nc \q_jcsfonts { q_jcsfonts \tl_use:N \l_keys_choice_tl } } ,
    font .generate_choices:n = { \clist_use:Nnnn \c_jcsfonts_clist {,} {,} {,} } ,
  }

\prg_new_conditional:Npnn \jcsfonts_if:n #1 { p, T, F, TF }
  {
    \cs_if_eq:NcTF \q_jcsfonts { q_jcsfonts_ #1 }
      { \prg_return_true: } { \prg_return_false: }
  }

\ProcessKeysOptions { jcsfonts }

实现这一目标的首选方法是什么?

答案1

我可能误解了您想要实现的目标,但这里有一种将代码与键的各种可能值相关联的简单方法。构造将模块的\keys_define:nn键定义为“选择”键,这意味着为 给出的值决定执行什么代码。有两种方法可以定义每个可能选择的代码:要么通过引入键、等,就像我在这里做的那样,要么(使用可能比 2013 年 8 月更新的 expl3 版本 — 这是未来)使用,它一次性定义多个选择,使用相同的代码。fontjcsfontsfontfont/choice-afont/choice-b.choices:nn

\documentclass{article}
\usepackage{expl3, xparse}
\ExplSyntaxOn
\keys_define:nn { jcsfonts }
  {
    font .choice: ,
    font / lmodern .code:n = { \RequirePackage{lmodern} } ,
    font / kpfonts .code:n = { \RequirePackage{kpfonts} } ,
  }
\NewDocumentCommand { \JcsSetup } { m }
  {
    \keys_set:nn { jcsfonts }
      { font = {#1} }
  }
\ExplSyntaxOff
\JcsSetup{kpfonts}
\begin{document}
Hello world!
\end{document}

如果你希望选择集取决于引擎,只需执行以下操作

\keys_define:nn { jcsfonts } { font .choice: }
\cs_new_protected:Npn \jcs_fonts_new:nnnn #1#2#3#4
  {
    \pdftex_if_engine:T { \keys_define:nn { jcsfonts } { font / #1 = {#2} } }
    \xetex_if_engine:T  { \keys_define:nn { jcsfonts } { font / #1 = {#3} } }
    \luatex_if_engine:T { \keys_define:nn { jcsfonts } { font / #1 = {#4} } }
  }
\msg_new:nnn { jcsfonts } { font-bad-engine }
  { Cannot~use~font~'#1'~in~engine~'#2'. }
\jcs_fonts_new:nnnn { kpfonts }
  { \RequirePackage{kpfonts} } % code for pdfTeX
  { \RequirePackage{kpfonts} } % code for XeTeX
  {
    \msg_error:nnnn { jcsfonts } { font-bad-engine }
      { kpfonts } { LuaTeX }
  } % code for LuaTeX... that font works, but I needed an example

如果您更普遍地想要将一些代码与一些字符串选择中的某个字符串关联起来,我会使用属性列表:

\prop_new:N \g__jcs_fonts_code_prop
\prop_gput:Nnn \g__jcs_fonts_code_prop
  { kpfonts }
  { RequirePackage{kpfonts} }
% ...
\tl_new:N \l__jcs_fonts_code_tl
\keys_define:nn { jcsfonts }
  {
    font .code:n =
      {
        \prop_get:NnNTF
          \g__jcs_fonts_code_prop {#1} \l__jcs_fonts_code_tl
          { \tl_use:N \l_jcs_fonts_code_tl }
          { \msg_error:nnn { jcsfonts } { cannot-use-font } {#1} }
      }
  }
\msg_new:nnn { jcsfonts } { cannot-use-font }
  { Cannot~use~font~'#1'. }

再次,您可以根据所使用的引擎以不同的方式填充属性列表,从而使字体列表依赖于引擎。

答案2

我不确定你对 quark 的使用;如果你想根据启动时定义的常量 clist 的值生成选择键,你可以稍微扩展可用的工具并定义一个.generate_choice:V属性:

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn

\tl_new:N \g_jcs_fonts_font_tl

\bool_if:nTF { \xetex_if_engine_p: || \luatex_if_engine_p: }
 { \clist_const:Nn \c_jcsfonts_clist { lmodern, fontin, constantia } }
 { \clist_const:Nn \c_jcsfonts_clist { lmodern, kpfonts } }

%%% The property .generate_choice:V doesn't exist, so we create it
\cs_generate_variant:Nn \__keys_choices_generate:n { V }
\cs_new_protected:cpn { \c__keys_props_root_tl .generate_choices:V } #1
  { \__keys_choices_generate:V {#1} }

\keys_define:nn { jcsfonts }
 {
  font .choice_code:n = \tl_gset:NV \g_jcsfonts_font_tl \l_keys_choice_tl,
  font .generate_choices:V = \c_jcsfonts_clist,
 }

\NewDocumentCommand{\try}{m}
 {
  \keys_set:nn { jcsfonts } { #1 }
  \tl_show:N \g_jcsfonts_font_tl
 }
\NewDocumentCommand{\compare}{m}
 {
  \str_if_eq:nVTF { #1 } \g_jcsfonts_font_tl
   { \typeout{The ~ chosen ~ font ~ is ~ #1} }
   { \typeout{The ~ chosen ~ font ~ is ~ not ~ #1} }
 }

\ExplSyntaxOff

\try{font=lmodern} % works both in latex and xelatex
\compare{lmodern}
\compare{xyz}

\try{font=fontin}  % fails in latex

\stop

我相信这.generate_choice:V会是工具的一个有用补充。您可以通过邮件列表提出功能请求。


使用该属性的替代版本.choices:nn(但具有如上所示的变体)。

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn

\tl_new:N \g_jcs_fonts_font_tl

\bool_if:nTF { \xetex_if_engine_p: || \luatex_if_engine_p: }
 { \clist_const:Nn \c_jcsfonts_clist { lmodern, fontin, constantia } }
 { \clist_const:Nn \c_jcsfonts_clist { lmodern, kpfonts } }

%%% The property .choices:Vn doesn't exist, so we create it
\cs_generate_variant:Nn \__keys_choices_make:nn { V }
\cs_new_protected:cpn { \c__keys_props_root_tl .choices:Vn } #1
  { \__keys_choices_make:Vn #1 }

\keys_define:nn { jcsfonts }
 {
  font .choices:Vn = \c_jcsfonts_clist
   {
    \tl_gset:NV \g_jcsfonts_font_tl \l_keys_choice_tl
   }
 }
\NewDocumentCommand{\try}{m}
 {
  \keys_set:nn { jcsfonts } { #1 }
  \tl_show:N \g_jcsfonts_font_tl
 }

\NewDocumentCommand{\compare}{m}
 {
  \str_if_eq:nVTF { #1 } \g_jcsfonts_font_tl
   { \typeout{The ~ chosen ~ font ~ is ~ #1} }
   { \typeout{The ~ chosen ~ font ~ is ~ not ~ #1} }
 }

\ExplSyntaxOff

\try{font=lmodern} % works both in latex and xelatex
\compare{lmodern}
\compare{xyz}

\try{font=fontin}  % fails in latex

\stop

相关内容