我的文档包含具有相同结构的“文本块”。它们总是有一个标题(总是一个日期)、一个审查部分和去做部分。代码如下:
\documentclass[11pt]{article}
\usepackage{enumerate}
\newenvironment{review}
{\textbf{Review:} \begin{itemize}}
{\end{itemize}}
\newenvironment{todo}
{\textbf{To do:} \begin{itemize}}
{\end{itemize}}
\begin{document}
\section*{30th November 2013}
\begin{enumerate}[1)]
\item blabla
\end{enumerate}
\begin{review}
\item blabla
\end{review}
\begin{todo}
\item blabla
\end{todo}
\end{document}
我想知道是否有可能省去每次输入此结构的麻烦,并创建一个名为文章为了节省时间并更好地组织我的文档。我该怎么做?
答案1
这里有一个想法:一个由三部分组成的环境,称为Article
,其唯一(强制)参数是日期(指定为{<day>}{<month>}{<year>}
)。
要启动审查部分,只需使用我的\review
宏即可。要启动去做部分,只需使用我的\todo
宏。重命名这些宏以避免与现有宏发生冲突可能是明智之举;例如,我知道包todonotes
定义了一个名为的宏 \todo
。
为了提高可维护性,您可能还想使用用于排版日期的包,例如 Nicola Talbot 的包datetime
,我在示例中使用了它。通过这样做,您无需对日期进行硬编码(如30th November 2013
您的示例中所示),并且您可以在任何阶段更改其排版方式。
\documentclass[11pt]{article}
\usepackage{enumerate}
\usepackage[long,nodayofweek]{datetime}
\newenvironment{Article}[1]
{%
\newcommand\review
{%
\end{enumerate}
\textbf{Review:}
\begin{itemize}
}
\newcommand\todo
{%
\end{itemize}
\textbf{To do:}
\begin{itemize}
}
\section*{\formatdate#1}
\begin{enumerate}[1)]
}{%
\end{itemize}
}
\begin{document}
\begin{Article}{{30}{11}{2013}}
\item foo
\item bar
\review
\item foo
\item bar
\todo
\item foo
\item bar
\end{Article}
\end{document}
答案2
再次,这比您要求的要多一些,但这是一种理想情况,使用密钥可以很好地简化事情(在构建它们的初始开销之后)。
我在此采取四管齐下的方法。
我定义了我将要使用的键。
我为用户界面定义了一个宏。在本例中,
\myarticle
它接受一个键值对参数。然后,该宏调用另一个宏来处理格式。我定义了一个内部宏
\my@article
,它决定要执行什么代码。这有点像中间人,但对于快速重新格式化、更改显示顺序或只是调试来说非常有用。对于决赛的每个方面环境我定义了一个宏来处理格式。每个宏都遵循命名约定
\jeroen@build@...
。有一个宏是为日期,另一个审查,第三个去做。如果您想更改内容的呈现方式,则需要重新定义这些宏。
对于密钥,我说明了三种不同的方法:
- 使用内部机制
.initial
来pgfkeys
存储和调用键值。 - 使用将
.store in
键的值存储在用户定义的宏中。 .code
当调用特定键时,使用来执行一些代码。
我认为.code
在当前背景下,这是最有趣的,因为在接下来的 MWE 中,它将允许用户选择不使用审查列表。此外,对于前页我做了类似的事情:键值像其他键一样传递 - 就像它是一个列表一样 - 但是它的最终格式就像一个普通段落。
这是MWE:
\documentclass{article}
%%-------------------------------------------
%% packages you need for this to work
\usepackage{pgfkeys}
\usepackage{pgffor}
%%-------------------------------------------
%% package OP requested
\usepackage{enumitem}
%%-------------------------------------------
\makeatletter
%%-------------------------------------------
%% These next two macros are not entirely
%% necessary. I put them here to illustrate
%% further possibilities about how `pgfkeys`
%% can manage keys.
\def\jeroen@review@items{}
\def\jeroen@to@do@items{}
\newif\ifjeroen@review@
\newif\ifjeroen@front@matter@
%% define the keys
\pgfkeys{/jeroen/article/.cd,
date/.initial=,
front matter/.code=\jeroen@front@matter@code{#1},
review items/.code=\jeroen@review@code{#1},
to do items/.store in=\jeroen@to@do@items,
}
%% define the macro for user interface
\newcommand\myarticle[1]{%%
\bgroup
\pgfkeys{/jeroen/article/.cd,#1}%%
\build@my@article
\egroup
}
\def\jeroen@front@matter@code#1{%%
\jeroen@front@matter@true
\def\jeroen@front@matter@content{#1}}
\def\jeroen@review@code#1{%%
\jeroen@review@true
\def\jeroen@review@items{#1}}
%% an internal macro for initially handling
%% and formatting the content.
\def\build@my@article{%%
\jeroen@build@date
\jeroen@build@front@matter
\jeroen@build@review
\jeroen@build@to@do
}
%% macro for formatting the "date"
%% If you want to change how the "date" is presented
%% this is the code you should tweak.
\def\jeroen@build@date{%%
\section*{\pgfkeysvalueof{/jeroen/article/date}}}
%% macro for formatting the "front matter"
%% If you want to change how the "front matter" is
%% presented this is the code you should tweak.
\def\jeroen@build@front@matter{%%
\ifjeroen@front@matter@
\foreach \mystuff in \jeroen@front@matter@content
{\mystuff\space}%%
\vspace{2ex}\par
\fi
}
%% macro for working with the list of "review" items
%% This is the code you should tweak to change how
%% the "review" is formatted.
\def\jeroen@build@review{%%
\ifjeroen@review@
\noindent
\textbf{Review:}
\begin{enumerate}%%
\foreach \reviewitem in \jeroen@review@items
{%%
\item \reviewitem
}%%
\end{enumerate}
\fi
}
%% macro for working iwth the list of "to do" items
%% This is the code you should tweak to change how
%% the "to do" is formatted.
\def\jeroen@build@to@do{%%
\noindent
\textbf{To do:}
\begin{itemize}
\foreach \todoitem in \jeroen@to@do@items
{%%
\item \todoitem
}%%
\end{itemize}
}
\makeatother
\begin{document}
\myarticle{
date={November 29, 2013},
review items={
{turkey},
{stuffing},
{yams}
},
to do items={
{apples},
{pears},
{peaches},
{ice cream}}
}
\myarticle{
date={November 30, 2013},
front matter={
{The quick brown fox jumped over the lazy dog.},
{Pack my box with five dozen liquor jugs.}},
to do items={
{carrots},
{celery},
{parsnips},
{ice cream!!}}
}
\end{document}
我应该注意以下几点:
- 中的括号
date={November 30, 2013}
是必要的,以防止pgfkeys
认为逗号日期是分隔器钥匙。 - 其他键的格式应为:
{ {item 1} , {item 2} , {item 3} , ...}
当然,这需要做大量的前期工作。但最终它会为你最终如何格式化内容提供很大的自由度。
答案3
仅向最佳实践者推荐的解决方案。
创建包
由于您希望在许多项目中重复使用环境和项目,最好的解决方案是将它们全部放在一个包中。将包保存在 LaTeX 可访问的目录中(如果您不知道如何操作,稍后会解释)。
在下面的例子中,我选择了mytodolist.sty
作为包的名称。您可以根据需要更改它。
% mytodolist.sty
\NeedsTeXFormat{LaTeX2e}[1994/06/01]
\ProvidesPackage{mytodolist}[2013/12/01 v0.01 LaTeX package for my consistent todo list]
\RequirePackage{enumerate}
\newenvironment{review}
{\textbf{Review:} \begin{itemize}}
{\end{itemize}}
\newenvironment{todo}
{\textbf{To do:} \begin{itemize}}
{\end{itemize}}
\newcommand{\Section}[1][\today]{\section*{#1}}
% items that will be reused many times
\newcommand{\foo}{\item foo}
%\newcommand{\bar}{\item bar} % it cannot be made as \bar is already defined!
\newcommand{\baz}{\item baz}
\endinput
如果有新项目要添加,只需编辑此包。使用\newcommand
而不是\def
确保现有宏不会被重新定义。
使用包
现在您可以按如下方式使用该包。
% main.tex
\documentclass[preview,border=12pt,12pt,varwidth]{standalone}% change it back to your own document class
\usepackage{mytodolist}
\begin{document}
\Section
\begin{review}
\foo
%\bar
\baz
\end{review}
\begin{todo}
\foo
%\bar
\baz
\end{todo}
\Section[Dec 25, 2013]
\begin{review}
\foo
%\bar
\baz
\end{review}
\begin{todo}
\foo
%\bar
\baz
\end{todo}
\end{document}
模拟二合一
以下代码片段可用于模拟动态创建包并使用它。您不应该在生产场景中这样做。
\documentclass[preview,border=12pt,12pt,varwidth]{standalone}% change it back to your own document class
\usepackage{filecontents}
\begin{filecontents*}{mytodolist.sty}
\NeedsTeXFormat{LaTeX2e}[1994/06/01]
\ProvidesPackage{mytodolist}[2013/12/01 v0.01 LaTeX package for my consistent todo list]
\RequirePackage{enumerate}
\newenvironment{review}
{\textbf{Review:} \begin{itemize}}
{\end{itemize}}
\newenvironment{todo}
{\textbf{To do:} \begin{itemize}}
{\end{itemize}}
\newcommand{\Section}[1][\today]{\section*{#1}}
% items that will be reused many times
\newcommand{\foo}{\item foo}
%\newcommand{\bar}{\item bar} % it cannot be made as \bar is already defined!
\newcommand{\baz}{\item baz}
\endinput
\end{filecontents*}
\usepackage{mytodolist}
\begin{document}
\Section
\begin{review}
\foo
%\bar
\baz
\end{review}
\begin{todo}
\foo
%\bar
\baz
\end{todo}
\Section[Dec 25, 2013]
\begin{review}
\foo
%\bar
\baz
\end{review}
\begin{todo}
\foo
%\bar
\baz
\end{todo}
\end{document}