考虑我有以下命令:
\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}
我已将您未自行定义的键传递给\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
可以正确读取。
有很多话要说,希望我在这里能给你一个良好的快速入门,并不断探索成为一名专家!