CSV 列表版本

CSV 列表版本

这是具有 keyval 选项的类,由 keyval 对列表组成。 在这个问题的答案斯基尔蒙展示了如何编写一个提供命令的类,\people该命令采用以逗号分隔的键值对组列表,然后在列表中排版该信息。

我想另外定义两个新的宏\specialpersonone和一个可选宏,它们将排版在该列表的开头以及另一页上的表格中。除了另一个键值对之外,\specialpersontwo它们还将具有相同的键值对。\peoplefield

这是一个不起作用的最小示例。我试图遵循斯基尔蒙以前做过,但我不太明白如何expkv处理参数。似乎在我尝试排版参数之前,参数没有被处理。

非工作mwe

我的类名.cls

\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{myclass}

\LoadClass[oneside,letterpaper]{memoir}

\RequirePackage{expkv-def}

\ekvdefinekeys{myclass/people}
  {
     long store title = \myclass@people@title
    ,long store role  = \myclass@people@role
    ,long store name  = \myclass@people@name
  }
\ekvsetdef\myclass@people@options{myclass/people}
\newcommand\people[1]{\edef\myclass@people{\unexpanded{#1}}}

\ekvdefinekeys{myclass/special-person-one}
  {
     long store title = \myclass@specialpersonone@title
    ,long store role = \myclass@specialpersonone@role
    ,long store name = \myclass@specialpersonone@name
    ,long store field = \myclass@specialpersonone@field
  }
\ekvsetdef\myclass@specialpersonone@options{myclass/special-person-one}
\newcommand\specialpersonone[1]{\edef\myclass@specialpersoone{\unexpanded{#1}}}

\ekvdefinekeys{myclass/special-person-two}
  {
     long store title = \myclass@specialpersontwo@title
    ,long store role = \myclass@specialpersontwo@role
    ,long store name = \myclass@specialpersontwo@name
    ,long store field = \myclass@specialpersontwo@field
  }
\ekvsetdef\myclass@specialpersontwo@options{myclass/special-person-two}
\newcommand\specialpersontwo[1]{\edef\myclass@specialpersotwo{\unexpanded{#1}}}

\newcommand*\mypeople[1]
  {%
    \unless\ifx\myclass@people\@empty
      \begin{itemize}
        \item \myclass@specialpersonone@title\space\myclass@specialpersonone@name, Special Role 1
        \unless\ifx\myclass@specialpersontwo@\empty
          \item \myclass@specialpersontwo@title\space\myclass@specialpersontwo@name, Special Role 2
        \fi
        \expandafter\ekvcsvloop\expandafter\mypeople@aux\expandafter{#1}%
      \end{itemize}%
    \fi
  }
\newcommand\mypeople@aux[1]
  {%
    \item
    \begingroup
      \myclass@people@options{#1}%
      \unless\ifx\myclass@people@title\@empty
        \myclass@people@title\space
      \fi
      \myclass@people@name
      \unless\ifx\myclass@people@role\@empty
        , \myclass@people@role
      \fi
    \endgroup
  }

\newcommand{\makemypage}{%
  \pagestyle{empty}
  \thispagestyle{empty}
  \begin{titlingpage}
    \begin{center}
      \mypeople{\myclass@people}
    \end{center}
  \end{titlingpage}}
  
\newcommand{\makemytablepage}{%
  \pagestyle{empty}
  \thispagestyle{empty}
  \begin{titlingpage}
    \begin{center}
      \begin{tabular}{ll}
        Special people ~ & \myclass@specialpersonone@name\\
        ~ & \myclass@specialpersonone@field\\
        ~ &~\\
        \unless\ifx\myclass@specialpersontwo@\empty
          ~ & \myclass@specialpersontwo@name\\
          ~ & \myclass@specialpersontwo@field\\
          ~ & ~\\
        \fi
      \end{tabular}
    \end{center}
  \end{titlingpage}}

\endinput

我的文件.tex

\documentclass[]{myclass}
\specialpersonone{title={Doctor}, name={Special Person}, field={Field 1}}
\specialpersontwo{title={Doctor}, name={Second Person}, field={Field 2}}
\people{
  {title={Doctor},name={John Smith},role={Role}},
  {title={Doctor},name={Jane Smith},role={}}}

\begin{document}
  \makemypage
  \makemytablepage
\end{document}

答案1

expkv\myclass@people@options在您调用或\myclass@specialpersonone@options或的地方解析选项,并\myclass@specialpersontwo@options使用key = value列表作为参数(或\ekvset{<set>}\ekvsetdef\<macro>{<set>}只是为此定义一个快捷方式(这确实比执行要快一点\ekvset{<set>});这对于所有key = value接口都相同,您必须调用前端宏来实际设置值)。 我上一个答案中的代码在里面完成了这一步\mypeople@aux。 由于您从未为特殊人员执行过此操作,因此他们不会将值分配给内部。

下面是两个版本,输入语法略有不同(我更喜欢第二个,但选择权在您手中)。优点是输入不太复杂(少了一个键,这从来都不是可选的,每个人都应该有一个名字!)。

CSV 列表版本

但是,将完整的 key=value 列表存储在宏中(就像使用\specialpersonone和 那样\specialpersontwo)对于这些宏来说并不是必需的,因为这不是您想要在以后解析的 csv 列表。因此,我将它们更改为当场进行 key=value 解析。然后,分配的值通过临时辅助宏从组中偷运出来\myclass@tmp

此外,为了减少重复代码,我改变了 key=value 设置的结构。现在有一个针对特殊人员的集合,如果使用未知密钥,则会转到针对人员的一般集合(通过unknown redirect)。

我还创建了两个便利宏来减少测试量\ifx\@empty,以及一个用于特殊人员输出的便利宏。

类文件:

\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{myclass}

\LoadClass[oneside,letterpaper]{memoir}

\RequirePackage{expkv-def}
\RequirePackage{booktabs}

\ekvdefinekeys{myclass/people}
  {
     long store title = \myclass@people@title
    ,long store role  = \myclass@people@role
    ,long store name  = \myclass@people@name
  }
\ekvsetdef\myclass@people@options{myclass/people}

\ekvdefinekeys{myclass/specialpeople}
  {
     long store field = \myclass@people@field
    ,unknown redirect = myclass/people
  }
\ekvsetdef\myclass@specialpeople@options{myclass/specialpeople}

% initialise macros
\newcommand*\myclass@people{}
\newcommand\people[1]{\edef\myclass@people{\unexpanded{#1}}}

% special persons are handled differently, the options are evaluated on the spot
% and then stored in other macros via \myclass@copyspecialperson calls
\newcommand\specialpersonone{\specialperson@aux{A}}
\newcommand\specialpersontwo{\specialperson@aux{B}}
\newcommand\specialperson@aux[2]
  {%
    % group to keep the assignments to \myclass@people@role etc. local
    \begingroup
      \myclass@specialpeople@options{#2}%
      % smuggle out the settings inside of \myclass@tmp (with
      % \myclass@copyspecialperson)
      \def\myclass@tmp{}%
      \ekvcsvloop{\myclass@copyspecialperson{#1}}{title,role,name,field}%
      % close the group after expanding the temporary macro once
      \expandafter
    \endgroup
    \myclass@tmp
  }
\newcommand\myclass@copyspecialperson[2]
  {%
    \edef\myclass@tmp
      {%
        \unexpanded\expandafter{\myclass@tmp}% keep old contents
        \def
        \unexpanded\expandafter{\csname myclass@specialperson@#1@#2\endcsname}%
        {%
          \unexpanded\expandafter\expandafter\expandafter
            {\csname myclass@people@#2\endcsname}%
        }%
      }%
  }
% to detect whether the special persons were used we initialise the @name macros
\newcommand*\myclass@specialperson@A@name{}
\newcommand*\myclass@specialperson@B@name{}

\newcommand\myclass@unlessempty[3]
  {%
    % #1: macro
    % #2: pre
    % #3: post
    \unless\ifx\@empty#1%
      \expandafter\@secondoftwo
    \fi
    \@gobble{#2#1#3}%
  }
\newcommand\myclass@unlessempty@special[1]
  {\expandafter\myclass@unlessempty\csname myclass@specialperson@#1\endcsname}

\newcommand\myclass@specialperson@output[1]
  {%
    \myclass@unlessempty@special{#1@name}
      {%
        \item
        \myclass@unlessempty@special{#1@title}{}{ }%
      }%
      {%
        \myclass@unlessempty@special{#1@role}{, }{}%
        % \myclass@unlessempty@special{#1@field}{, }{}% TODO: is this needed?
      }%
  }

\newcommand*\mypeople[1]
  {%
    \unless\ifx\myclass@people\@empty
      \begin{itemize}
        \myclass@specialperson@output{A}%
        \myclass@specialperson@output{B}%
        \ekvcsvloop\mypeople@aux{#1}%
      \end{itemize}%
    \fi
  }
\newcommand\mypeople@aux[1]
  {%
    \item
    \begingroup
      \myclass@people@options{#1}%
      \myclass@unlessempty\myclass@people@title{}{ }%
      \myclass@people@name
      \myclass@unlessempty\myclass@people@role{, }{}%
    \endgroup
  }

\newcommand{\makemypage}{%
  \pagestyle{empty}
  \thispagestyle{empty}
  \begin{titlingpage}
    \begin{center}
      \expandafter\mypeople\expandafter{\myclass@people}
    \end{center}
  \end{titlingpage}}
  
\newcommand{\makemytablepage}
  {%
    % check whether at least one of the two special persons was used
    \begingroup
      \edef\myclass@tmp
        {%
          \unexpanded\expandafter{\myclass@specialperson@A@name}%
          \unexpanded\expandafter{\myclass@specialperson@B@name}%
        }%
      \expandafter
    \endgroup
    \unless\ifx\myclass@tmp\@empty
      \pagestyle{empty}
      \thispagestyle{empty}
      \begin{titlingpage}
        \begin{center}
          \begin{tabular}{ll}
            Special people
              \myclass@unlessempty@special{A@name}{&}%
                {%
                  \\
                  \myclass@unlessempty@special{A@field}{&}{\\}%
                  \addlinespace
                }%
              \myclass@unlessempty@special{B@name}{&}%
                {%
                  \\
                  \myclass@unlessempty@special{B@field}{&}{\\}%
                }%
          \end{tabular}
        \end{center}
      \end{titlingpage}%
    \fi
  }

\endinput

文档:

\documentclass[]{myclass}

\specialpersonone{title={Doctor}, name={Special Person}, field={Field 1}}
\specialpersontwo{title={Doctor}, name={Second Person}, field={Field 2}}
\people{
  {title={Doctor},name={John Smith},role={Role}},
  {title={Doctor},name={Jane Smith}}}

\begin{document}
  \makemypage

  \makemytablepage
\end{document}

输出:

在此处输入图片描述

在此处输入图片描述


名称={key=val} 版本

由于使用建议的接口所需的更改<name>={<key=val>}很少,我决定只提供它。如果 a<name>应该包含逗号,您可以使用它{<name>}={<key=val>}来保护该名称。如果名称不需要 atitle或 ,role您可以直接使用它而不使用={<key=val>}

类文件:

\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{myclass}

\LoadClass[oneside,letterpaper]{memoir}

\RequirePackage{expkv-def}
\RequirePackage{booktabs}

\ekvdefinekeys{myclass/people}
  {
     long store title = \myclass@people@title
    ,long store role  = \myclass@people@role
  }
\ekvsetdef\myclass@people@options{myclass/people}

\ekvdefinekeys{myclass/specialpeople}
  {
     long store field = \myclass@people@field
    ,unknown redirect = myclass/people
  }
\ekvsetdef\myclass@specialpeople@options{myclass/specialpeople}

% initialise macros
\newcommand*\myclass@people{}
\newcommand\people[1]{\edef\myclass@people{\unexpanded{#1}}}

% special persons are handled differently, the options are evaluated on the spot
% and then stored in other macros via \myclass@copyspecialperson calls
\newcommand\specialpersonone{\specialperson@aux{A}}
\newcommand\specialpersontwo{\specialperson@aux{B}}
\newcommand\specialperson@aux[3]
  {%
    \expandafter\def\csname myclass@specialperson@#1@name\endcsname{#2}%
    % group to keep the assignments to \myclass@people@role etc. local
    \begingroup
      \myclass@specialpeople@options{#3}%
      % smuggle out the settings inside of \myclass@tmp (with
      % \myclass@copyspecialperson)
      \def\myclass@tmp{}%
      \ekvcsvloop{\myclass@copyspecialperson{#1}}{title,role,field}%
      % close the group after expanding the temporary macro once
      \expandafter
    \endgroup
    \myclass@tmp
  }
\newcommand\myclass@copyspecialperson[2]
  {%
    \edef\myclass@tmp
      {%
        \unexpanded\expandafter{\myclass@tmp}% keep old contents
        \def
        \unexpanded\expandafter{\csname myclass@specialperson@#1@#2\endcsname}%
        {%
          \unexpanded\expandafter\expandafter\expandafter
            {\csname myclass@people@#2\endcsname}%
        }%
      }%
  }
% to detect whether the special persons were used we initialise the @name macros
\newcommand*\myclass@specialperson@A@name{}
\newcommand*\myclass@specialperson@B@name{}

\newcommand\myclass@unlessempty[3]
  {%
    % #1: macro
    % #2: pre
    % #3: post
    \unless\ifx\@empty#1%
      \expandafter\@secondoftwo
    \fi
    \@gobble{#2#1#3}%
  }
\newcommand\myclass@unlessempty@special[1]
  {\expandafter\myclass@unlessempty\csname myclass@specialperson@#1\endcsname}

\newcommand\myclass@specialperson@output[1]
  {%
    \myclass@unlessempty@special{#1@name}
      {%
        \item
        \myclass@unlessempty@special{#1@title}{}{ }%
      }%
      {%
        \myclass@unlessempty@special{#1@role}{, }{}%
        % \myclass@unlessempty@special{#1@field}{, }{}% TODO: is this needed?
      }%
  }

\newcommand*\mypeople[1]
  {%
    \unless\ifx\myclass@people\@empty
      \begin{itemize}
        \myclass@specialperson@output{A}%
        \myclass@specialperson@output{B}%
        \ekvparse{\item\@firstofone}\mypeople@aux{#1}%
      \end{itemize}%
    \fi
  }
\newcommand\mypeople@aux[2]
  {%
    \item
    \begingroup
      \myclass@people@options{#2}%
      \myclass@unlessempty\myclass@people@title{}{ }%
      #1%
      \myclass@unlessempty\myclass@people@role{, }{}%
    \endgroup
  }

\newcommand{\makemypage}{%
  \pagestyle{empty}
  \thispagestyle{empty}
  \begin{titlingpage}
    \begin{center}
      \expandafter\mypeople\expandafter{\myclass@people}
    \end{center}
  \end{titlingpage}}
  
\newcommand{\makemytablepage}
  {%
    % check whether at least one of the two special persons was used
    \begingroup
      \edef\myclass@tmp
        {%
          \unexpanded\expandafter{\myclass@specialperson@A@name}%
          \unexpanded\expandafter{\myclass@specialperson@B@name}%
        }%
      \expandafter
    \endgroup
    \unless\ifx\myclass@tmp\@empty
      \pagestyle{empty}
      \thispagestyle{empty}
      \begin{titlingpage}
        \begin{center}
          \begin{tabular}{ll}
            Special people
              \myclass@unlessempty@special{A@name}{&}%
                {%
                  \\
                  \myclass@unlessempty@special{A@field}{&}{\\}%
                  \addlinespace
                }%
              \myclass@unlessempty@special{B@name}{&}%
                {%
                  \\
                  \myclass@unlessempty@special{B@field}{&}{\\}%
                }%
          \end{tabular}
        \end{center}
      \end{titlingpage}%
    \fi
  }

\endinput

文档:

\documentclass[]{myclass}

\specialpersonone{Special Person}{title={Doctor}, field={Field 1}}
\specialpersontwo{Second Person}{title={Doctor}, field={Field 2}}
\people
  {
     John Smith={title={Doctor},role={Role}}
    ,Jane Smith={title={Doctor}}
    ,John Doe
  }

\begin{document}
  \makemypage

  \makemytablepage
\end{document}

输出:与上文类似(除了附加项目符号“• John Doe”)。

相关内容