\newcommand 具有易于配置的可选参数

\newcommand 具有易于配置的可选参数

考虑我有以下命令:

\newcommand{\ListStartSimple}{\begin{itemize}[label={}, leftmargin=0.15in]}
\newcommand{\ListStartLineSimple}{\begin{itemize}[label={}, leftmargin=0.38in]}

\newcommand{\ListStartBullet}{\begin{itemize}[label=\textbullet, leftmargin=0.15in]}
\newcommand{\ListStartLineBullet}{\begin{itemize}[label=\textbullet, leftmargin=0.38in]}

\newcommand{\ListStartBulletTiny}{\begin{itemize}[label=\tiny\textbullet, leftmargin=0.15in]}
\newcommand{\ListStartLineBulletTiny}{\begin{itemize}[label=\tiny\textbullet, leftmargin=0.38in]}

\newcommand{\ListStartDash}{\begin{itemize}[label=\textendash, leftmargin=0.15in]}
\newcommand{\ListStartLineDash}{\begin{itemize}[label=\textendash, leftmargin=0.38in]}

\newcommand{\ListEnd}[1][-5]{\end{itemize}\vspace{#1pt}}

因此,在我的 Tex 文件中,我可以轻松地开始列出我的配置。

\documentclass[a4paper,11pt]{article}

\begin{document}

\ListStartSimple \item This is a list \ListEnd
\ListStartLineSimple \item This is a list \ListEnd
\ListStartBullet \item This is a list \ListEnd
\ListStartLineBullet \item This is a list \ListEnd
\ListStartBulletTiny \item This is a list \ListEnd
\ListStartLineBulletTiny \item This is a list \ListEnd
\ListStartDash \item This is a list \ListEnd
\ListStartLineDash \item This is a list \ListEnd

\end{document}

这给了我:

图像

我需要什么?

如您所见,这些命令是多余的,可以轻松总结为一个命令。\newcommand我更喜欢使用不同的命令,而不是只有一个带hasmargin, label, labelsize参数的命令。所以我可以用类似这样的内容生成与上面完全相同的图像:

\List \item This is a list \ListEnd
\List[withmargin] \item This is a list \ListEnd
\List[bullet] \item This is a list \ListEnd
\List[withmargin,bullet] \item This is a list \ListEnd
\List[bullet,tiny] \item This is a list \ListEnd
\List[hasmargin,bullet,tiny] \item This is a list \ListEnd
\List[dash] \item This is a list \ListEnd
\List[hasmargin,dash] \item This is a list \ListEnd

答案1

xkeyval 包提供了接受密钥的接口:

\documentclass[a4paper]{article}

\usepackage[margin=2.5cm]{geometry}
\usepackage{xkeyval}
\usepackage{enumitem}

% BEGIN Source:
% https://tex.stackexchange.com/questions/598048/newcommand-with-easily-configurable-optional-parameters
\makeatletter
\def\ListLabelSize{}
\def\ListLabel{}
\newlength\ListLeftmargin
\def\ListItemSep{}
\def\ListDefaults{}

\define@key{List}{simple}[]{
    \def\ListLabel{}
}

\define@key{List}{bullet}[]{
    \def\ListLabel{\textbullet}
}

\define@key{List}{dash}[]{
    \def\ListLabel{\textendash}
}

\define@key{List}{tiny}[]{
    \def\ListLabelSize{\tiny}
}

\define@key{List}{normalsize}[]{
    \def\ListLabelSize{\normalsize}
}

\define@key{List}{large}[]{
    \def\ListLabelSize{\large}
}

\define@key{List}{withmargin}[]{
    \setlength\ListLeftmargin{0.38in}
}

\define@key{List}{hasmargin}[]{
    \setlength\ListLeftmargin{0.38in}
}

\define@key{List}{nomargin}[]{
    \setlength\ListLeftmargin{0.15in}
}

\newcommand\SetListDefaults[1]{
    \def\ListDefaults{simple,nomargin,normalsize,#1}
}

\newcommand\ListStart[1][]{
    \def\@applyList##1{
        \setkeys*{List}{##1}
    }
    \expandafter\@applyList\expandafter{\ListDefaults,#1}
    \def\createbeginitemize##1{
        \begin{itemize}[
            label={\ListLabelSize\ListLabel},
            leftmargin={\ListLeftmargin},
            ##1
        ]
    }
    % XKV@rm contains the keys we didn't define ourselves, we pass
    % them to itemize
    \expandafter\createbeginitemize\expandafter{\XKV@rm}
}

\newcommand\ListEnd[1][0]{
    \end{itemize}\vspace{#1pt}
}
\makeatother
% END Source

\SetListDefaults{topsep=0pt,itemsep=0pt}

\newenvironment{List}[1][]{
    \ListStart[#1]
}{
    \ListEnd[]
}

\begin{document}

\List \item This is a list \ListEnd
\List[withmargin] \item This is a list \ListEnd
\List[bullet] \item This is a list \ListEnd
\List[withmargin,bullet] \item This is a list \ListEnd
\List[bullet,tiny] \item This is a list \ListEnd
\List[hasmargin,bullet,tiny] \item This is a list \ListEnd
\List[dash] \item This is a list \ListEnd
\List[hasmargin,dash] \item This is a list \ListEnd

\begin{List}[bullet,large]
    \item This is a list
    \item With items
\end{List}

\end{document}

清单如 OP 中所述

我已将您未自行定义的键传递给\begin{itemize}[]。这样,您就可以使用topsep=0pt而无需先为其定义键。另外,请注意我如何制作了一个方便的\SetListDefaults。您可以随时更改这些默认值,也可以在文档中更改。这很方便,可以避免重复。

希望你满意:)

这个回答对你有帮助吗?

编辑:

要了解\define@key等等是如何工作的,最好的地方是xkeyval软件包文档:https://www.ctan.org/pkg/xkeyval

代码中还有更多值得学习的东西。例如 和\makeatletter\makeatother命令名称中的 '@' 符号是一种儿童锁:通常,您不能使用 '@' 符号来标记命令。但是如果您使用 ,则可以\makeatletter。因此,您可以创建“内部”命令,您的软件包的用户不会意外地使用这些命令来代替真正的命令。

\def工作原理与 非常相似\newcommand,但更轻量一些。(查看TeXbyTopic,第 109 页)。您会看到我如何使用它们来捕获其中的值。此外,还使用了长度(https://en.wikibooks.org/wiki/LaTeX/Lengths#Length_manipulation)。

还有一些事情,例如在宏中定义宏时,你使用##1它的参数,因为#1它是为封闭的宏保留的。

最后,为什么我有时会定义这些微小的辅助宏:这是因为我想“粘贴”我所捕获的内容。如果我将\ListDefaults其他键一起传递,LaTeX 会认为\ListDefaults只是一个键,例如。当然,它找不到那个键。我们需要自己“扩展”它:直接bullet将内容放入。\ListDefaults

为了解决这个问题,我定义了一个宏,它可以将内容粘贴到正确的位置。接下来,我使用\expandafter's,它“扩展”'之后'。查看扩展的不同步骤(用(~0)I 表示 LaTeX 正在执行的位置,用 表示(~1)执行后将在哪里恢复):

(~0)\expandafter(~1)\createbeginitemize\expandafter{\XKV@rm}
(~1)\createbeginitemize(~0)\expandafter{\XKV@rm}
(~1)\createbeginitemize{(~0)\XKV@rm}
(~1)\createbeginitemize{bullet,large}
(~0)\createbeginitemize{bullet,large}

您会看到,\expandafter's 允许您“跳过”命令或括号。现在,它不会读取\ListDefaults,但bullet,large可以正确读取。

有很多话要说,希望我在这里能给你一个良好的快速入门,并不断探索成为一名专家!

相关内容