有没有办法为键值系统定义带星号的变体?

有没有办法为键值系统定义带星号的变体?

我创建了一个环境,其中各种参数都通过键值进行设置。我不想创建各种布尔值的大杂烩,而是希望某些键有稍微不同的形式来处理某些格式。

具体来说,虽然没有一个键是必需的,但如果我省略了某些键,我需要一种处理方法。所以,我想我会创建带星号的变体。

为了帮助你理解我在下面的 MWE 中试图做什么,这里是基本思想:我有三个可选的标签添加到引号中(titledescriptionauthor)。每个键在使用时都应显示在自己的行上。如果未使用该键,则不应执行任何操作。但如果author未调用该键,则我需要一种处理换行符的方法,以避免不必要的额外空格。在这种情况下,应使用带星号的变体。

以下是 MWE:

\documentclass{article}
\newcommand{\attrib}[1]{\nopagebreak{\par\raggedleft\footnotesize #1\par}}
%%----------
\makeatletter
%%----------
\let\ae@source@title\relax
\let\ae@source@description\relax
\let\ae@source@author\relax
%%----------
\newlength{\widthofwidestline}
\newlength{\afterEpigraphSkip}
\setlength{\widthofwidestline}{3in}
\setlength{\afterEpigraphSkip}{1\baselineskip}
%%----------
\RequirePackage{pgfkeys}
\pgfkeys
  {
    /ae/my/epigraph/environment/set/options/.cd,
    title/.code         = {\def\ae@source@title{#1\\}},
    description/.code   = {\def\ae@source@description{#1\\}},
    author/.code        = {\def\ae@source@author{#1}},
%% variants for handling `title` and `description` when `author`
%% (and possibly other keys) are missing.
    title*/.code         = {\def\ae@source@title{#1}},
    description*/.code   = {\def\ae@source@description{#1}},
%% length parameters
    longest line/.code  = {\settowidth{\widthofwidestline}{#1}},
    afterskip/.code     = {\setlength{\afterEpigraphSkip}{#1}},
  }
\newenvironment{epigraph}[1]
  {\pgfkeys{ /ae/my/epigraph/environment/set/options/.cd, #1 }%
   \par\hspace*{\fill}%
   \begin{minipage}[t]{\dimexpr\widthofwidestline+1em}%
  }
  {\attrib{%
     \ae@source@title
     \ae@source@description
     \ae@source@author
     \makebox[0pt][r]{\rule[-0.8pt]{1in}{0.4pt}}%
    }%
   \end{minipage}%
   \hspace*{\fill}%
   \vspace{\afterEpigraphSkip}%
  }
\makeatother

\pagestyle{empty}
\begin{document}

\begin{epigraph}{title={title},
                 description={description},
                 author={me},
                 longest line=abcdefghijklm}
  Scenario 1
\end{epigraph}

\begin{epigraph}{author={me},
                 longest line=abcdefghijklm}
  Scenario 2
\end{epigraph}

\begin{epigraph}{title={title},
                 description={description},
                 longest line=abcdefghijklm}
  Scenario 3
\end{epigraph}

\begin{epigraph}{title={title},
                 description*={description},
                 longest line=abcdefghijklm}
  Scenario 4
\end{epigraph}

\begin{epigraph}{title*={title},
                 longest line=abcdefghijklm}
  Scenario 5
\end{epigraph}

\begin{epigraph}{description*={description},
                 longest line=abcdefghijklm}
  Scenario 6
\end{epigraph}

\end{document}

Scenario 3说明了我想要避免的情况。此 MWE 产生:

在此处输入图片描述

我不太想创建新的 epigraph 命令:我知道有这样的包。我还知道我可以设置和处理布尔值来处理这个问题自动地。但正如我提到的,我确实想避免创建布尔开关。

我更感兴趣的是更大的问题,即使用键值,但有时你可能希望以略有不同的方式处理某些键通常: 因此有星号变体。

我在文档中没有找到任何允许这样做的内容。我也没有在这个网站上找到任何与带星号的密钥变体相关的内容。

我主要感兴趣的是有关这种情况下的最佳实践的反馈。

答案1

我使用实际的值键。这些是用.initial处理程序设置的(​​每个值都有一个初始值)。在我看来,这可以减少开销。因为它只是解决方案的包装器\csname。路径的键/tree/sub/name存储在宏中\pgfk@/tree/sub/name。我不明白为什么要定义一个仅设置另一组宏的键。

环境中以 开头的宏\@epi@…仅仅是临时宏,因为它们仅在环境(对其内容进行分组)中定义。

代码

\documentclass{article}
\newcommand{\attrib}[1]{\nopagebreak{\par\raggedleft\footnotesize #1\par}}
%%----------
\makeatletter
%%----------
\newlength{\widthofwidestline}
\newlength{\afterEpigraphSkip}
\setlength{\widthofwidestline}{3in}
%%----------
\RequirePackage{pgfkeys}
\def\epigraphset{\pgfqkeys{/ae/my/epigraph/environment/set/options}}
\def\epigraphgetvalue#1{\pgfkeysgetvalue{/ae/my/epigraph/environment/set/options/#1}}
\epigraphset{
    title/.initial      =,
    description/.initial=,
    author/.initial     =,
    longest line/.code  = {\settowidth{\widthofwidestline}{#1}},
    afterskip/.code     = {\setlength{\afterEpigraphSkip}{#1}},
    afterskip=1\baselineskip
  }
\newenvironment{epigraph}[1]{
  \epigraphset{#1}%
  \par\hspace*{\fill}%
  \begin{minipage}[t]{\dimexpr\widthofwidestline+1em}%
}{
  \attrib{%
     \epigraphgetvalue{title}\@epi@title
     \epigraphgetvalue{description}\@epi@desc
     \epigraphgetvalue{author}\@epi@author
%     \noindent % needed (?) if you use \\
     \@epi@title
     \ifx\@epi@desc\pgfkeys@empty\else
       \par\@epi@desc
     \fi
     \ifx\@epi@author\pgfkeys@empty\else
       \par\@epi@author
     \fi
     \makebox[0pt][r]{\rule[-0.8pt]{1in}{0.4pt}}%
  }%
  \end{minipage}%
  \hspace*{\fill}%
  \vspace{\afterEpigraphSkip}%
}
\makeatother

\pagestyle{empty}
\begin{document}
\epigraphset{longest line=abcdefghijklm}
\begin{epigraph}{title=title,description=description,author=me}
  TDA
\end{epigraph}

\begin{epigraph}{author=me}
  \_\_A
\end{epigraph}
\begin{epigraph}{description=description}
  \_D\_
\end{epigraph}
\begin{epigraph}{title=title}
  T\_\_
\end{epigraph}

\begin{epigraph}{title=title,description=description}
  TD\_
\end{epigraph}
\begin{epigraph}{title=title,author=author}
  T\_A
\end{epigraph}
\begin{epigraph}{description=description,author=author}
  \_DA
\end{epigraph}

\end{document}

输出

在此处输入图片描述

答案2

我不知道 PGF 键,但我的想法是测试值是否为空:

\documentclass{article}
\usepackage{xparse}

\NewDocumentCommand{\attrib}{m}{%
  \nopagebreak{\par\raggedleft\footnotesize #1\par}}

\ExplSyntaxOn
\keys_define:nn { ae/epigraph }
 {
  title .tl_set:N = \l_ae_epigraph_title_tl,
  title .initial:n = {},
  description .tl_set:N = \l_ae_epigraph_description_tl,
  description .initial:n = {},
  author .tl_set:N = \l_ae_epigraph_author_tl,
  author .initial:n = {},
  longestline .code:n = \ae_settowidth:n { #1 },
  afterskip .skip_set:N = \l_ae_epigraph_afterskip_skip,
  afterskip .initial:n = 1\baselineskip,
 }
\dim_new:N \l_ae_epigraph_longestline_dim
\dim_set:Nn \l_ae_epigraph_longestline_dim { 3in }

\cs_new_protected:Npn \ae_settowidth:n #1
 {
  \hbox_set:Nn \l_tmpa_box { #1 }
  \dim_set:Nn \l_ae_epigraph_longestline_dim { \box_wd:N \l_tmpa_box }
 }


\NewDocumentEnvironment{epigraph}{O{}}
  {
   \keys_set:nn { ae/epigraph } { #1 }
   \par\hspace*{\fill}
   \begin{minipage}[t]{\dim_eval:n { \l_ae_epigraph_longestline_dim+1em } }
  }
  {
   \par
   \group_begin:
   \raggedleft\footnotesize
   \tl_if_empty:NF \l_ae_epigraph_title_tl
    { \l_ae_epigraph_title_tl \\ }
   \tl_if_empty:NF \l_ae_epigraph_description_tl
    { \l_ae_epigraph_description_tl \\ }
   \tl_if_empty:NF \l_ae_epigraph_author_tl
    { \l_ae_epigraph_author_tl \\ }
   \vspace{-\prevdepth}
   \group_end:
   \vspace{1ex}
   \hrule
   \end{minipage}%
   \hspace*{\fill}%
   \vspace{\l_ae_epigraph_afterskip_skip}
  }
\ExplSyntaxOff

\pagestyle{empty}
\begin{document}

\begin{epigraph}[
  title={title},
  description={description},
  author={me},
  longestline=abcdefghijklm
]
  Scenario 1
\end{epigraph}

\begin{epigraph}[
  author={me},
  longestline=abcdefghijklm
]
  Scenario 2
\end{epigraph}

\begin{epigraph}[
  title={title},
  description={description},
  longestline=abcdefghijklm
]
  Scenario 3
\end{epigraph}

\begin{epigraph}[
  title={title},
  description={description},
  longestline=abcdefghijklm
]
  Scenario 4
\end{epigraph}

\begin{epigraph}[
  title={title},
  longestline=abcdefghijklm
]
  Scenario 5
\end{epigraph}

\begin{epigraph}[
  description={description},
  longestline=abcdefghijklm
]
  Scenario 6
\end{epigraph}

\end{document}

在此处输入图片描述

相关内容