我创建了一个环境,其中各种参数都通过键值进行设置。我不想创建各种布尔值的大杂烩,而是希望某些键有稍微不同的形式来处理某些格式。
具体来说,虽然没有一个键是必需的,但如果我省略了某些键,我需要一种处理方法。所以,我想我会创建带星号的变体。
为了帮助你理解我在下面的 MWE 中试图做什么,这里是基本思想:我有三个可选的标签添加到引号中(title
、description
和author
)。每个键在使用时都应显示在自己的行上。如果未使用该键,则不应执行任何操作。但如果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}