我正在尝试做一些我认为可能的事情,但我却无法轻易找到方法来实现它。
[这个例子与我的实际例子非常接近,但为了避免需要深奥的领域知识而进行了更改。]
假设我有 LaTeX 格式的足球规则手册。它有很多关于犯规和处罚的参考。我假设我可以浏览并标记出这些处罚在正文中的位置。
我想添加一个附录,列出按处罚分类的各种内容。因此,您可以转到此附录并找到“按类型列出的犯规列表”,其中包含(对于美国人来说)“5 码罚球犯规”;“10 码犯规”;“15 码犯规”;“罚球犯规”;等等...或(对于世界上大多数其他国家来说)“间接任意球犯规”;“直接任意球犯规”;“黄牌犯规”;“红牌犯规”。
在正文中列出这些内容有一个标准方法,所以我已经有了一个类似于和的宏,\tenyardfoul{ describe it here }
我\redcardfoul{ describe it here }
可以修改它来添加钩子或其他东西。我在格式化这些内容方面也有一定的灵活性。我确实考虑过把它们做成表格,这样我就可以获得一个完整的列表,\listoftables
但把它分成几类对我来说是无法做到的。
感谢您的帮助!
答案1
最终,我还是设法解决了一些问题。感觉有点像我在滥用 caption 包来做到这一点,所以如果有人知道更简洁/更惯用的方式来做到这一点,我洗耳恭听(或者 - 鉴于自然文本 - 如果你想吹毛求疵的话,我会全神贯注地听)。
当前的问题
- 以其他项目可能不希望出现的方式全局影响所有字幕。(我刚好侥幸逃脱了。)
- 如果您有很多这样的列表(我有 13 个),您可能会遇到“没有空间进行新的 \write”错误。我用 修复了这个问题,
\usepackage{morewrites}
但我似乎记得在 caption 包中看到过一种修复方法,但我无论如何也找不到它了。
实际解决方案
我将继续使用我的足球类比,并展示如何将其应用于黄牌和 15 码罚球。
我使用这些包。我不能 100% 确定我需要 float 包来实现这一点,但我在其他地方依赖它,所以我不能轻易地将其移除进行测试。
\usepackage{caption}
\usepackage{float}
首先我为每个列表声明一个标题类型:
\DeclareCaptionType{yellowcardf}
\DeclareCaptionType{fifteenyardpenaltyf}
% etc...
“f”后缀是为了避免名称冲突。
当我执行该\listof
命令时,我实际上想跳过添加标题。这样我就可以设置自己的标题并添加介绍性段落。因此我这样做:
\makeatletter
\renewcommand*{\listof}[2]{%
\@ifundefined{ext@#1}{\float@error{#1}}{%
\expandafter\let\csname l@#1\endcsname \l@figure
%\float@listhead{#2}% <-------------------------- % comment this line out
\begingroup
\setlength\parskip{0pt plus 1pt}%
\@starttoc{\@nameuse{ext@#1}}%
\endgroup}}
\makeatother
我设置了我想要的字幕的样子,如下所示:
\captionsetup{labelformat=empty,singlelinecheck=off,justification=raggedright}
\setlength{\abovecaptionskip}{0pt}
\setlength{\belowcaptionskip}{0pt}
\setlength{\intextsep}{1pt}
我不确定是否可以针对每个字幕类型执行此操作(几乎可以肯定),但在您的项目中这样做可能是一个好主意。这会影响全局所有字幕。幸运的是,这对我的特定项目无关紧要。祝你好运,希望另一位评论员可以告诉你这一点。
现在我设置一个用于列表的通用命令:
\newcommand{\genericpenalty}[3] {\begin{#1}[H]
\caption[\textbf{\thesubsubsection} --- #3]{\textbf{Penalty: #2} --- #3}
\end{#1}}
最后,每个列表都有自己的包装器:
\newcommand{\yellowcard}[1]{\genericpenalty{yellowcardf}{yellow card}{#1}}
\newcommand{\fifteenyardpenalty}[1]{\genericpenalty{redcardf}{red card}{#1}}
现在,我可以在我的文档中写\yellowcard{unsportsmanlike conduct}
和\yellowcard{reckless tackle}
或\fifteenyyardpenalty{chop blocking}
和\fifteenyardpenalty{grabbing the facemask}
,它会为我创建一个漂亮的小插入文本(我也可以很好地格式化它 - 但我在这里删除了所有内容,因为它大部分都是噪音)。它还会将其添加到我创建的列表中,如下所示:
\newcommand{\addlistofpenalties}[3]{\subsection{#2}
#3
\listof{#1}{}
}
进而:
\section{List of offences by penalty}
\subsection{Football (soccer) penalties}
\addlistofpenalties{yellowcardf}{Yellow card penalties}{The referee should caution a player for these offences:}
\subsection{Football (American) penalties)
\addlistofpenalties{fifteenyardpenaltyf}{15-yard penalties}{These penalties move the fouled team 15-yards towards their opponent's end-zone:}
这将使用简短的标题创建一个处罚列表,在本例中包括子部分参考,以便于查找。
如果我将\usepackage{hyperref}
这些变成可点击的超链接也是免费的!
我确信这里还有一些改进的空间,但如果你正在寻找这个问题的解决方案,请随意使用和调整它(使用 Windows 上的 pdflatex 构建,FWIW,虽然我相信它应该是可移植的)并且如果你有改进请告诉我,我很乐意更新它以反映最佳答案。
答案2
如果您为每种类型的惩罚分配一个数字,您可以让 LaTeX 将所有惩罚的条目写入同一个辅助文件中,并让 -commands\listof...
为您进行过滤,方法是将变量设置为要在输入辅助文件之前创建列表的惩罚类型的编号。
\documentclass{article}
\usepackage{hyperref}
\makeatletter
%-------------------------------------------------------------------------------
% \CsNameToCsToken<stuff not in curly braces>{CsToken}
% yields:
% <stuff not in curly braces>\CsToken
%
% E.g. ,
% \CsNameToCsToken\newcommand*{foobar}...
% yields:
% \newcommand*\foobar...
%...............................................................................
\@ifdefinable\CsNameToCsToken{\long\def\CsNameToCsToken#1#{\romannumeral0\InnerCsNameToScToken{#1}}}%
\newcommand\InnerCsNameToScToken[2]{\expandafter\exchange\expandafter{\csname#2\endcsname}{ #1}}%
\newcommand\exchange[2]{#2#1}%
%-------------------------------------------------------------------------------
\newcommand\penaltytypecount{0}%
\newcommand\steppenaltytypecount{%
\xdef\penaltytypecount{\number\numexpr\penaltytypecount+1\relax}%
}%
\newif\ifpenaltyitemfound
\newcommand\newpenaltytype[7]{%
% #1 - name of the penalty type
% #2 - textual phrase denoting the kind of penalty
% #3 - formatting of the counter for counting penalites of the type
% #4 - numbered within-counter
% #5 - Command for writing the penalty within the main-text
% #6 - \listof-command
% #7 - sectioning-command for starting the list of penalites
\steppenaltytypecount
% Mapping "name of the penalty type" to automatically created number of penalty type:
\CsNameToCsToken\@ifdefinable{penaltynum@#1}{\CsNameToCsToken\xdef{penaltynum@#1}{\penaltytypecount}}%
% Counter for penalties of type #1:
\ifcat$\detokenize{#4}$\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{\newcounter{#1cnt}}{\newcounter{#1cnt}[{#4}]}%
% Apply command(s) #3 for formatting the counter:
\CsNameToCsToken\renewcommand*{the#1cnt}{#3{#1cnt}}%
% Define the command for writing the penalty within the main-text:
\expandafter\newcommand\expandafter#5\expandafter{%
\expandafter\@ifnextchar\expandafter[\expandafter{%
\romannumeral0\@firstoftwo{\expandafter\expandafter\expandafter}{} %
\romannumeral\CsNameToCsToken0 \expandafter{\expandafter\@gobble\string#5@opt}%
\expandafter}%
\expandafter{%
\romannumeral\CsNameToCsToken0 {\expandafter\@gobble\string#5@noopt}}%
}%
\CsNameToCsToken\newcommand{\expandafter\@gobble\string#5@opt}[2][]{%
% #1 - name of the penalty type
% #2 - textual phrase denoting the kind of penalty
% ##1 - short description of penalty
% ##2 - long description of penalty
\textbf{\refstepcounter{allpenalties}\refstepcounter{#1cnt}Penalty~}%
\@ifundefined{NR@gettitle}{}{\NR@gettitle{#2~\CsNameToCsToken{the#1cnt}}}%
\addtocontents{lpn}{%
\string\penaltyitem{#1}%
{\CsNameToCsToken{the#1cnt}}%
{\thepage}%
{\@ifundefined{@currentHref}{}{\@currentHref}}%
{#2}%
{##1}\protected@file@percent
}%
\textbf{\CsNameToCsToken{the#1cnt}: #2} --- ##2%
}%
\CsNameToCsToken\expandafter\newcommand\expandafter{\expandafter\@gobble\string#5@noopt}%
\expandafter[\expandafter1\expandafter]\expandafter{%
\romannumeral\CsNameToCsToken0 {\expandafter\@gobble\string#5@opt}[{##1}]{##1}%
}%
% Define the \listof...-command:
\newcommand*#6{%
#7%
\AtEndDocument{%
\@ifundefined{tf@lpn}{%
\if@filesw
\newwrite\tf@lpn
\immediate\openout\tf@lpn\jobname.lpn\relax
\fi
}{}%
}%
\begingroup\makeatletter
\edef\penaltytypecount{\CsNameToCsToken{penaltynum@#1}}%
\global\penaltyitemfoundfalse
\IfFileExists{\jobname.lpn}{%
\begin{description}%
\@input{\jobname.lpn}%
\ifpenaltyitemfound\else\expandafter\item\expandafter\leavevmode\expandafter\null\fi
\end{description}%
}{}%
\@nobreakfalse\endgroup
}%
}%
\newcommand\listofallpenalties{%
\subsection*{List of all penalties}%
\AtEndDocument{%
\@ifundefined{tf@lpn}{%
\if@filesw
\newwrite\tf@lpn
\immediate\openout\tf@lpn\jobname.lpn\relax
\fi
}{}%
}%
\begingroup\makeatletter
\let\penaltyitem\allpenaltyitem
\IfFileExists{\jobname.lpn}{%
\begin{description}%
\@input{\jobname.lpn}%
\ifpenaltyitemfound\else\expandafter\item\expandafter\leavevmode\expandafter\null\fi
\end{description}%
}{}%
\@nobreakfalse\endgroup
}%
\newcommand\penaltyitem[6]{%
% #1 name of penalty
% #2 number of penalty
% #3 page number where the penalty is described in the text
% #4 hyperref-anchor if hyperref is loaded
% #5 textual phrase denoting the kind of penalty
% #6 (short) description of the penalty
\ifnum\penaltytypecount=\@ifundefined{penaltynum@#1}{0}{\CsNameToCsToken{penaltynum@#1}} %
\expandafter\@firstofone\else\expandafter\@gobble\fi
{%
\ifpenaltyitemfound\else\global\penaltyitemfoundtrue\fi
\item[\@ifundefined{hyperlink}{\@firstofone}{\hyperlink{#4}}{\textbf{#2 (on page~#3):}}] #6%
}%
}%
\newcommand\allpenaltyitem[6]{%
% #1 name of penalty
% #2 number of penalty
% #3 page number where the penalty is described in the text
% #4 hyperref-anchor if hyperref is loaded
% #5 textual phrase denoting the kind of penalty
% #6 (short) description of the penalty
\@ifundefined{penaltynum@#1}{}{%
\ifpenaltyitemfound\else\global\penaltyitemfoundtrue\fi
\item[\@ifundefined{hyperlink}{\@firstofone}{\hyperlink{#4}}{\textbf{#2 (#5, on page #3):}}] #6%
}%
}%
\makeatother
\newcounter{allpenalties}[section]%
\renewcommand\theallpenalties{\thesection.\arabic{allpenalties}}%
\newpenaltytype{YellowCards}%
{Yellow Card}%
{Y\protect~\thesection.\arabic}% If you wish all penalties to use the same counter, then try: {\theallpenalties\csname @gobble\endcsname}%
{section}%
{\YellowCard}%
{\listofYellowCards}%
{\subsection*{List of Yellow Card penalties}}
\newpenaltytype{RedCards}%
{Red Card}%
{R\protect~\thesection.\arabic}% If you wish all penalties to use the same counter, then try: {\theallpenalties\csname @gobble\endcsname}%
{section}%
{\RedCard}
{\listofRedCards}%
{\subsection*{List of Red Card penalties}}
\newpenaltytype{GreenCards}%
{Green Card}%
{G\protect~\thesection.\arabic}% If you wish all penalties to use the same counter, then try: {\theallpenalties\csname @gobble\endcsname}%
{section}%
{\GreenCard}
{\listofGreenCards}%
{\subsection*{List of Green Card penalties}}
\begin{document}
\section*{Lists of penalties:}
\listofRedCards
\listofYellowCards
\listofGreenCards
\listofallpenalties
\section{First Section}
\noindent\YellowCard[This is the first section's first Yellow Card's short description.]{This is the first section's first Yellow Card's long description.}
\noindent\RedCard[This is the first section's first Red Card's short description.]{This is the first section's first Red Card's long description.}
\noindent\GreenCard[This is the first section's first Green Card's short description.]{This is the first section's first Green Card's long description.}
\noindent\GreenCard{This is the first section's second Green Card's description.}
\noindent\YellowCard{This is the first section's second Yellow Card's description.}
\noindent\RedCard{This is the first section's second Red Card's description.}
\section{Second Section}
\noindent\YellowCard[This is the second section's first Yellow Card's short description.]{This is the second section's first Yellow Card's long description.}
\noindent\RedCard[This is the second section's first Red Card's short description.]{This is the second section's first Red Card's long description.}
\noindent\GreenCard[This is the second section's first Green Card's short description.]{This is the second section's first Green Card's long description.}
\noindent\GreenCard{This is the second section's second Green Card's description.}
\noindent\YellowCard{This is the second section's second Yellow Card's description.}
\noindent\RedCard{This is the second section's second Red Card's description.}
\end{document}