![自动更改目录条目的顺序](https://linux22.com/image/469727/%E8%87%AA%E5%8A%A8%E6%9B%B4%E6%94%B9%E7%9B%AE%E5%BD%95%E6%9D%A1%E7%9B%AE%E7%9A%84%E9%A1%BA%E5%BA%8F.png)
我本质上想要实现相同的目标这问题。但是,与该帖子中的解决方案不同,我无法手动执行此操作,它需要自动执行
我定义了一个\problem
and\solution
命令,其工作原理如下例所示。添加一个带有问题引用的新解决方案将匹配数字,一切顺利。使用tocloft
,我还设法生成了 TOC 样式的“问题列表”。
\documentclass[12pt]{article}
\usepackage{tocloft}
\usepackage{hyperref}
\hypersetup{
colorlinks=true,
linkcolor=black
}
\usepackage{tcolorbox}
\usepackage[parfill]{parskip}
\definecolor{darkgreen}{RGB}{0, 180, 0}
% Create the "List of Problems" object
\newlistof{problems}{prob}{List of Problems}
% Create the look of the problem and solution boxes
\newtcbox{\problembox}{on line,
colframe=red,
colback=red!20,
boxrule=1pt,
arc=4pt,
boxsep=0pt,
left=2pt,
right=2pt,
top=2pt,
bottom=2pt}
\newtcbox{\solutionbox}{on line,
colframe=darkgreen,
colback=darkgreen!20,
boxrule=1pt,
arc=4pt,
boxsep=0pt,
left=2pt,
right=2pt,
top=2pt,
bottom=2pt}
% Create the counter that keeps track of the problem number
\newcounter{problemnb}
% Create the main \problem and \solution commands. These will:
% 1. Print out the problem/solution boxes with the correct number (kept track of by the "problemnb" counter)
% 2. Add a line to the "List of Problems" (with the name given in the optional argument)
% Problems and solutions are linked by the \label-\ref pairs (as with figures e.g.)
% \problem[problem name (optional)]{problem reference}
\newcommand{\problem}[2][Problem \theproblemnb]{%
\newcounter{problem#2counter}
\refstepcounter{problemnb}%
\problembox{\color{red}\textbf{PROBLEM \theproblemnb}\label{#2}}
\addcontentsline{prob}{section}{#1}
}
% \solution[solution name (optional)]{problem reference} (solution name defaults to "Solution" without number)
\newcommand{\solution}[2][Solution]{{%
\hypersetup{linkcolor=darkgreen}
\stepcounter{problem#2counter}
\solutionbox{\color{darkgreen}\textbf{SOLUTION \ref{#2}.\the\value{problem#2counter}}}
\addcontentsline{prob}{subsection}{#1}}
}
\begin{document}
\listofproblems
\problem[First problem]{prob:first} This is the first problem encountered. \\
\solution[Solution to first problem]{prob:first} I fixed it somehow. \\
\solution[Another solution to first problem]{prob:first} Found an even better fix. \\
\\
\problem[Another problem]{prob:another} Oh dear, another problem has arisen. \\
\solution[Good solution to second problem]{prob:another} This is a great fix for it, though. \\
% All good up to now
\solution[Solution to the first problem]{prob:first} This is a solution to the first problem, but it will appear in the LoP as a solution to the second.
\end{document}
现在的问题是,任何放在后续\problem
命令之后的先前问题的解决方案都将放在 LoP 中的新问题之下。这显然是不可取的。
我认为有两种可能的解决方案:
- 使用已经到位的
\label
系统\ref
以某种方式告诉 LoP 将哪些小节放在哪些节下。 - 从一开始就浏览整个文档,列出所有问题及其相应的解决方案,然后“手动”创建整个 LoP(当然使用宏),并将各节和小节放在正确的位置。
现在的问题是,我没有足够的知识/技能来实现其中任何一个。我已经找到了手动创建目录的方法(如策略 2 所要求的),但我必须找到一种方法,在文档的最开始就列出章节和小节的列表。
任何帮助是极大的赞赏。
附言:我并不坚持使用tocloft
,它只是迄今为止我想要做的最简单的方法。
答案1
以下是使用 Expl3 属性列表和序列来跟踪数据的方法。我们创建问题标签和标题的属性列表,以及相应的键序列来跟踪它们的顺序。
每当创建一个新问题时,它都会根据问题标签创建一个新序列,并且该序列将保存该问题的每个解决方案的标题。
最后,我们创建一个在文档末尾运行的命令,将所有问题和解决方案添加到问题列表中。
\documentclass[12pt]{article}
\usepackage{tocloft}
\usepackage{hyperref}
\hypersetup{
colorlinks=true,
linkcolor=black
}
\usepackage{tcolorbox}
\usepackage[parfill]{parskip}
\definecolor{darkgreen}{RGB}{0, 180, 0}
\ExplSyntaxOn
% Property list of problem labels (key) and titles (value)
\prop_new:N \l_PeterPawn_problems_prop
% Since property lists aren’t ordered, we also keep track of the keys in order using a sequence
\seq_new:N \l_PeterPawn_problems_seq
% Add a warning for duplicate keys
\msg_new:nnnn {PeterPawn}{key-exists}{\\This\ problem\ is\ already\ defined!}{Help\ text\ here.}
% command to add a solution for a particular problem
\NewDocumentCommand{\addsolution}{mm}{
\seq_gput_right:cn {l_PeterPawn_#1_solutions_seq} {#2}
}
% command to add a problem to the problem property list and sequence
\NewDocumentCommand{\addproblem}{mm}{
{\prop_get:NnNTF \l_PeterPawn_problems_prop {#1} \l_tmpa_tl
{\msg_warning:nn { PeterPawn } { key-exists }}
{\prop_gput:Nnn \l_PeterPawn_problems_prop {#1} {#2}
\seq_gput_right:Nn \l_PeterPawn_problems_seq {#1}
}}}
% Create the main \problem and \solution commands. These will:
% 1. Print out the problem/solution boxes with the correct number (kept track of by the "problemnb" counter)
% 2. Add a line to the "List of Problems" (with the name given in the optional argument)
% Problems and solutions are linked by the \label-\ref pairs (as with figures e.g.)
% \problem[problem name (optional)]{problem reference}
% Modified to use the \addproblem and \addsolution code
\NewDocumentCommand{\problem}{O{Problem \theproblemnb}m}{%
\newcounter{problem#2counter}
\seq_new:c {l_PeterPawn_#2_solutions_seq}
\refstepcounter{problemnb}%
\problembox{\color{red}\textbf{PROBLEM\ \theproblemnb}\label{#2}}
\addproblem{#2}{#1}
}
\NewDocumentCommand{\solution}{O{Solution}m}{{%
\hypersetup{linkcolor=darkgreen}
\stepcounter{problem#2counter}
\solutionbox{\color{darkgreen}\textbf{SOLUTION\ \ref{#2}.\the\value{problem#2counter}}}
\addsolution{#2}{#1}
}}
% This command must appear at the end of the document text!
\NewDocumentCommand{\makeprobscontents}{}{
\seq_map_function:NN \l_PeterPawn_problems_seq \PeterPawn_addcontents:n}
% function to map problems and solutions to the list of problems
\cs_new_protected:Nn \PeterPawn_addcontents:n {
\tl_set:Nn \l_tmpa_tl {#1}
\prop_get:NnN \l_PeterPawn_problems_prop {#1} \l_tmpb_tl
\addcontentsline{prob}{section}{\l_tmpb_tl}
\seq_map_function:cN {l_PeterPawn_#1_solutions_seq} \PeterPawn_addsolutions:n
}
% function to map solutions to the list of problems
\cs_new_protected:Nn \PeterPawn_addsolutions:n {
\tl_set:Nn \l_tmpa_tl {#1}
\addcontentsline{prob}{subsection}{\l_tmpa_tl}
}
\ExplSyntaxOff
% Create the "List of Problems" object
\newlistof{problems}{prob}{List of Problems}
% Create the look of the problem and solution boxes
\newtcbox{\problembox}{on line,
colframe=red,
colback=red!20,
boxrule=1pt,
arc=4pt,
boxsep=0pt,
left=2pt,
right=2pt,
top=2pt,
bottom=2pt}
\newtcbox{\solutionbox}{on line,
colframe=darkgreen,
colback=darkgreen!20,
boxrule=1pt,
arc=4pt,
boxsep=0pt,
left=2pt,
right=2pt,
top=2pt,
bottom=2pt}
% Create the counter that keeps track of the problem number
\newcounter{problemnb}
\begin{document}
\listofproblems
\problem[First problem]{prob:first} This is the first problem encountered. \\
\solution[Solution to first problem]{prob:first} I fixed it somehow. \\
\solution[Another solution to first problem]{prob:first} Found an even better fix. \\
\\
\problem[Another problem]{prob:another} Oh dear, another problem has arisen. \\
\solution[Good solution to second problem]{prob:another} This is a great fix for it, though. \\
% All good up to now
\solution[Solution to the first problem]{prob:first} This is a solution to the first problem, and it will appear correctly now in the LoP as a solution to the the first problem as desired!.
% Need to issue this command at the end of the document
\makeprobscontents
\end{document}