我想要针对这些 LaTeX 文档运行查询:
- 获取所有方程的列表,即使有人声明
\def\be{\begin{equation}}
并使用它; - 获取某个命令 (例如
\marginpar
) 的所有参数的列表,该命令已在文档中使用(同样,即使有人声明\def\m\marginpar
并调用这个宏); - 得到具有给定反值的定理。
这个任务似乎需要完全编译所有的宏,但我想在不是扩展形式 --- 不是作为块和胶水,而是作为用户的输入(如果可能的话)。
我怎能做这样的事?
更新:理想情况下,我想使用“语义标记”来标记文档的各个部分并生成它们的不同视图。假设我有这样的内容:
\beginBlock{calculus}
\beginBlock{content}
... lectures...
\endBlock
\beginBlock{exam}
... problems...
\beginBlock{comments}
... comments about criteria and how to evaluate typical mistakes...
\endBlock
\endBlock[exam]
\endBlock[calculus]
和其他文件中的线性代数类似;我想生成一份包含微积分和线性代数部分的报告,其中仅包含考试问题,例如
答案1
让我们看看\marginpar
。您想要重新定义此命令以将其参数保存在要打印的某个列表中,例如在文档末尾。
我们必须看一下 的定义\marginpar
,发现它是不是带有参数的命令,它会执行一系列相当复杂的任务。因此,我们不能简单地向其中添加一些操作,而不详细检查所使用的宏。
一个好的策略是收集论据,然后将它们放回原来的地方\marginpar
。
\makeatletter
\let\saved@marginpar\marginpar
\renewcommand\marginpar[2][]{%
\if\relax\detokenize{#1}\relax
\let\saved@mp@optional\@empty
\else
\def\saved@mp@optional{[#1]}%
\fi
\def\saved@mp@mandatory{{#2}}%
\saved@mp@add{\saved@mp@print{#1}{#2}}%
\expandafter\expandafter\expandafter\saved@marginpar
\expandafter\saved@mp@optional\saved@mp@mandatory}
\newtoks\saved@mp@toks
\def\saved@mp@add#1{\global\saved@mp@toks=\expandafter{\the\saved@mp@toks#1}}
\def\printmarginpars{\the\saved@mp@toks}
\def\saved@mp@print#1#2{\par\noindent Marginpar\\
Optional: #1\\
Mandatory: #2\par\medskip}
\makeatother
如果你说,后此代码,
\newcommand{\mpx}{\marginpar}
那么它将起到同样的作用。
宏起什么作用?
\marginpar
在保存了原始命令的副本后,被重新定义为具有可选参数和强制参数。如果可选参数为空,那么我们将其定义
\saved@mp@optional
为\@empty
,否则我们将其定义为扩展为括号中的可选参数。类似地,我们定义
\saved@mp@mandatory
扩展为括号中的强制参数。我们将参数的内容添加到我们分配的令牌列表中。
我们把参数放回后面
\saved@marginpar
,这样 LaTeX 就会像什么都没发生一样完成其正常工作。
例子
\documentclass{article}
\makeatletter
\let\saved@marginpar\marginpar
\renewcommand\marginpar[2][]{%
\if\relax\detokenize{#1}\relax
\let\saved@mp@optional\@empty
\else
\def\saved@mp@optional{[#1]}%
\fi
\def\saved@mp@mandatory{{#2}}%
\saved@mp@add{\saved@mp@print{#1}{#2}}%
\expandafter\expandafter\expandafter\saved@marginpar
\expandafter\saved@mp@optional\saved@mp@mandatory}
\newtoks\saved@mp@toks
\def\saved@mp@add#1{\global\saved@mp@toks=\expandafter{\the\saved@mp@toks#1}}
\def\printmarginpars{\the\saved@mp@toks}
\def\saved@mp@print#1#2{\par\noindent Marginpar\\
Optional: #1\\
Mandatory: #2\par\medskip}
\makeatother
\newcommand{\mpx}{\marginpar}
\begin{document}
a\marginpar{xxx}
b\mpx[yyy]{zzz}
\printmarginpars
\end{document}
答案2
我认为您最好使用您最喜欢的语言(如python
或)的外部脚本perl
。
如果您想使用 LaTeX 来完成此操作,则可采用一种方法,至少对于非环境的命令,将命令的内容保存在文件中或列表中。
我将演示如何使用“marginpars”。首先定义一个列表:
\def\alist{}
然后定义宏添加到列表中:
\def\addtolist#1#2{
\lst@lAddTo\alist{#2}
}
\long\gdef\addmp#1#2{\addtolist\alist{#1,}}
\def\AddMP#1#2{%
\long\expandafter\gdef\csname#1\endcsname{\textbf{#1}: #2}
\addmp{#1}{#2}\marginpar{#2}
}
marginpar
注意最后一个,您可以使用保存内容addmp
,然后打印它。
完整 MWE:
\documentclass[11pt]{book}
\usepackage{lstdoc,lipsum}
\begin{document}
\makeatletter
\def\alist{}
\def\addtolist#1#2{
\lst@lAddTo\alist{#2}
}
\long\gdef\addmp#1#2{\addtolist\alist{#1,}}
\def\AddMP#1#2{%
\long\expandafter\gdef\csname#1\endcsname{\textbf{#1}: #2}
\addmp{#1}{#2}\marginpar{#2}
}
\def\PrintMP{%
\@for \i:=\alist\do{%
\csname\i\endcsname}
}
%example
\AddMP{mp}{\lipsum[2]}
\AddMP{mp}{\lipsum[3]}
\AddMP{mp}{\lipsum[1]}
% print the marginpars
\Printmp
\makeatother
\end{document}
编辑
根据原帖作者提供的新信息,可以使用.dtx
系统文件doc/docstrip
。这样您就可以将文档的各个部分保存到不同的文件中。
答案3
好的,现在我理解得更清楚了。一个相当普遍的想法是有一个“主”文档,它会在不同的“模式”下产生不同的输出。
这意味着您将进行不同的“配置”,其中您提到的环境定义不同。通过激活一个具有特定环境定义的“配置”,您将获得不同版本的文档。一个“配置”可以是.tex
包含环境定义的文件(其中一个是\input
),也可以是代表不同环境定义的专用包的不同选项。
另一个非常复杂的大型包装可用于这种事情:AcroTeX 教育套件。
可能相关的问题:
比较有助于排版练习和解决方案的软件包:练习 vs. 答案 vs. probsoln
还有一个问题与此高度相关,但现在我找不到了。它涉及如何将不同的内容部分存储在一个公共文件中,并将它们组合成不同的文档。也许其他人还记得。