LATEX-L Archives

Mailing list for the LaTeX3 project

LATEX-L@LISTSERV.UNI-HEIDELBERG.DE

Options: Use Classic View

Use Monospaced Font
Show HTML Part by Default
Condense Mail Headers

Topic: [<< First] [< Prev] [Next >] [Last >>]

Print Reply
Content-Type: text/plain; charset=UTF-8
Date: Tue, 9 Jul 2013 17:36:17 -0400
Reply-To: Mailing list for the LaTeX3 project <[log in to unmask]>
MIME-Version: 1.0
Message-ID: <[log in to unmask]>
Content-Transfer-Encoding: 8bit
Sender: Mailing list for the LaTeX3 project <[log in to unmask]>
From: "Joel C. Salomon" <[log in to unmask]>
Parts/Attachments: text/plain (125 lines)
Folks,

I’ve been following the code changes here, and I’ve asked two
questions on this topic on TeX.SE (“Generate l3keys meta key from
subkey” <http://tex.stackexchange.com/q/120102/2966> and “Can I refer
to key value in general code?”
<http://tex.stackexchange.com/q/120258/2966>), but I think I need some
direction on this.

Here‘s my use-case:  I’ve got a résumé class with a set of pre-defined
layout options.  For example, for Constantia I want
    \DeclareDocumentCommand \& {} { \textit { \jcsres_ampersand: } }
while for Fontin I’ve decided on
    \DeclareDocumentCommand \& {} { \textsc { \jcsres_ampersand: } }
instead.  Packages need to be included.  And so on and so forth; there
are between three and fifteen lines of code for each font-set option.

Based on egreg’s suggestion
(http://tex.stackexchange.com/a/120275/2966), my code looks something
like this (or will, when the new Expl3 updates become available):

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

\clist_get:NN \c_jcs_fonts_clist \c_jcs_default_font_tl

\keys_define:nn { jcsres }
  {
    font .choices:Vn = \c_jcs_fonts_clist
      { \tl_gset:NV \g_jcs_font_option_tl \l_keys_choice_tl },
    font .initial:V = \c_jcs_default_font_tl,
    font .value_required,
    font / unknown .code:n =
      { \msg_warning:nnn { jcsres } { unknown-font-option } { #1 } }
  }

\msg_new:nnn { jcsres } { unknown-font-option }
  { unknown~font~option~`#1';~using~`\c_jcs_default_font_tl'~instead }

\clist_map_inline:Nn \c_jcs_fonts_clist
  {
    \keys_define:nn { jcsres }
      { #1 .meta:n = { font = #1 }, #1 .value_forbidden: }
  }

% Somewhere later in the code...
\ProcessKeysOptions { jcsres }

% Somewhere later yet...
\str_case:VnF \g_jcs_font_option_tl
  {
    { fontin } { … }
    { constantia } { … }
    { lmodern } { … }
    { kpfonts } { … }
  }
  { \msg_error:nnn { jcsres } { still-unknown-font-option } { #1 } }

\msg_new:nnn { jcsres } { still-unknown-font-option }
  { can't~happen:~unknown~font~option~`#1'. }

This all works, but there’s a fair amount of repetition of information.

Bruno has suggested (http://tex.stackexchange.com/a/123201/2966) using
property lists instead.  This feels like a more natural fit for the
problem, and here’s the code I’ve come up with:

\prop_new:N \g_jcs_fontcode_prop

\prop_gput:Nnn \g_jcs_fontcode_prop { lmodern } { … }

\bool_if:nT { \xetex_if_engine_p: || \luatex_if_engine_p: }
  { \prop_gput:Nnn \g_jcs_fontcode_prop { fontin } { … } }

\bool_if:nT { \xetex_if_engine_p: || \luatex_if_engine_p: }
  { \prop_gput:Nnn \g_jcs_fontcode_prop { constantia } { … } }

\bool_if:nF { \xetex_if_engine_p: || \luatex_if_engine_p: }
  { \prop_gput:Nnn \g_jcs_fontcode_prop { kpfonts } { … } }

\tl_const:Nx \c_jcs_default_font_tl
  {
    \bool_if:nTF { \xetex_if_engine_p: || \luatex_if_engine_p: }
      { fontin } { kpfonts }
  }

\tl_new:N \l_jcs_fontcode_tl
\keys_define:nn { jcsres }
  {
    font .code:n =
      {
        \prop_get:NnNTF \g_jcs_fontcode_prop {#1} \l_jcs_fontcode_tl
          { \tl_gset_eq:NN \g_jcs_fontcode_tl \l_jcs_fontcode_tl }
          {
            \msg_warning:nnn { jcsres } { unknown-font-option } { #1 }
            \prop_get:NVN \g_jcs_fontcode_prop \c_jcs_default_font_tl
\l_jcs_fontcode_tl
            \tl_gset_eq:NN \g_jcs_fontcode_tl \l_jcs_fontcode_tl
          }
      },
    font .value_required:,
    font .initial:V = \c_jcs_default_font_tl
   }

\prop_map_inline:Nn \g_jcs_fontcode_prop
  {
    \keys_define:nn { jcsres }
      { #1 .meta:n = { font = #1 }, #1 .value_forbidden: }
  }

% Somewhere later in the code...
\ProcessKeysOptions { jcsres }
\tl_use:N \g_jcs_fontcode_tl

The trick with copying the code sequence (rather than executing it
within the call to \keys_define) is needed so the default code isn’t
run if an option is supplied, or in case the user writes
   \usepackage[font=fontin, font=constantia]{jcsres}
to execute both conflicting options.

Does this begin to sound like the way forward?

—Joel

ATOM RSS1 RSS2