我在 latex 文档中定义并使用了一些用户定义的命令。我需要一种方法来检查是否有任何命令被使用。我想根据命令中使用的参数做出决定。我可以通过定义用户定义的环境来做到这一点吗?请告诉我这里应该做什么。
示例代码:
\documentclass[12pt]{article}
\usepackage{ulem}
\usepackage{color}
\newcommand{\deleteline}[2]{\textsuperscript{\textcolor{black}{ #1}} \textcolor{red}{\sout{#2}}}
\title{Latex Document}
\author{Eddy}
\begin{document}
\maketitle
As part of this project, we intend to study the complex structures of Latex. \deleteline{eddy}{This line will be stroked through.}
我想通过编程找出\deleteline
内容中是否使用了命令。我还想找出使用的第一个参数是什么。
编辑:我将添加当前需求的详细用例。我的输入代码如下。请注意,这\begin{analyze}{eddy}
是尚未定义的新环境。
\documentclass[12pt]{article}
\usepackage{ulem}
\usepackage{color}
\newcommand{\deleteline}[2]{\textsuperscript{\textcolor{black}{ #1}} \textcolor{red}{\sout{#2}}}
\newcommand{\addline}[2]{\textsuperscript{\textcolor{black}{ #1}} \textcolor{green}{#2}}
\title{Latex Document}
\author{Eddy}
\begin{document}
\maketitle
\begin{analyze}
As part of this project, we intend to study the complex structures of Latex. \deleteline{eddy}{This line will be stroked through.} \addline{Margret}{This line is to be added.}
\end{analyze}
\end{document}
If no argument is passed to the new environment,
\begin{analyze}
As part of this project, we intend to study the complex structures of Latex. \deleteline{eddy}{This line will be stroked through.} \addline{Margret}{This line is to be added.}
\end{analyze}
输出:所有用户所做的所有更改均被考虑在内
如果输入的是‘eddy’,
\begin{analyze}{eddy}
As part of this project, we intend to study the complex structures of Latex. \deleteline{eddy}{This line will be stroked through.} \addline{Margret}{This line is to be added.}
\end{analyze}
输出:仅考虑 Eddy 所做的更改。其他用户的更改将被忽略。
\begin{analyze}{Margret}
As part of this project, we intend to study the complex structures of Latex. \deleteline{eddy}{This line will be stroked through.} \addline{Margret}{This line is to be added.}
\end{analyze}
输出:仅考虑 Margret 所做的更改。所有其他更改均被忽略。
答案1
这cmdtrack
软件包就是为此而设计的。其摘要如下:
该软件包会跟踪文档前言中定义的命令是否在文档的某个地方实际使用。在将软件包加载到文档的前言中后,
\newcommand
该点与文档开头之间的所有内容(以及类似的命令定义)都将被标记为要记录。在文档末尾,TeX 日志中将打印命令使用情况的报告,例如: – “mdash 在第 25 行使用”; – “ndash 从未使用过”。
它不跟踪每一个命令,但确实处理诸如\newtheorem
之类的事情\newcommand
。有关完整详细信息,请参阅文档。
答案2
您可以通过保存旧定义\let
然后使用\renewcommand
向其添加代码来修改任何命令。analyze
此处的环境重新定义了\deleteline
和\addline
宏,因此重新定义在analyze
环境内是本地的。因此,在此环境之外,这两个宏的行为与最初定义的一样:
笔记:
- 我用过包裹
xstring
用于字符串比较。
参考:
- 正如 A.Ellett 提到的,使用
\let
宏并不适用于所有情况,您需要改用\LetLtxMacro
。请参阅何时使用 \LetLtxMacro?更多细节。
代码:
\documentclass[12pt]{article}
\usepackage{ulem}
\usepackage{color}
\usepackage{xstring}
\newcommand{\deleteline}[2]{\textsuperscript{\textcolor{black}{ #1}} \textcolor{red}{\sout{#2}}}
\newcommand{\addline}[2]{\textsuperscript{\textcolor{black}{ #1}} \textcolor{green}{#2}}
\title{Latex Document}
\author{Eddy}
%
% Keep original defintion of "\deleteline" and "\addline" around
\let\OldDeleteline\deleteline%
\let\OldAddline\addline%
\newcommand*{\AnalyzeUserName}{}%
\newenvironment{analyze}[1][]{%
\edef\AnalyzeUserName{#1}% set this to the given user name
% These redefinitions are only within this environment
\renewcommand{\deleteline}[2]{%
\IfStrEq{\AnalyzeUserName}{}{%
% We allow all users changes
\OldDeleteline{##1}{##2}%
}{%
% Since some non-empty name was specified only allow if name matches.
\IfStrEq{\AnalyzeUserName}{##1}{%
\OldDeleteline{##1}{##2}%
}{%
% Don't do anything here as the name did not match given name.
}%
}%
}%
\renewcommand{\addline}[2]{%
\IfStrEq{\AnalyzeUserName}{}{%
% We allow all users changes
\OldAddline{##1}{##2}%
}{%
% Since some non-empty name was specified only allow if name matches.
\IfStrEq{\AnalyzeUserName}{##1}{%
\OldAddline{##1}{##2}%
}{%
% Don't do anything here as the name did not match given name.
}%
}%
}%
}%
\begin{document}
\maketitle
% -----------------
\textbf{No option}\par
\begin{analyze}
As part of this project, we intend to study the complex structures of Latex. \deleteline{eddy}{This line will be stroked through.} \addline{Margret}{This line is to be added.}
\end{analyze}
\textbf{option=eddy}\par
\begin{analyze}[eddy]
As part of this project, we intend to study the complex structures of Latex. \deleteline{eddy}{This line will be stroked through.} \addline{Margret}{This line is to be added.}
\end{analyze}
\textbf{option=Margret}\par
\begin{analyze}[Margret]
As part of this project, we intend to study the complex structures of Latex. \deleteline{eddy}{This line will be stroked through.} \addline{Margret}{This line is to be added.}
\end{analyze}
\end{document}
答案3
我认为这里不需要环境。如果您只设置一个用于比较的主变量,那就更容易了。
\documentclass{report}
\usepackage{ulem}
\makeatletter
\def\@mytemp{}
\newcommand\setmaster[1]{
\def\@mytemp{#1}
}
\newcommand\del[2]{%
\def\@mytempa{#1}%%
\ifx\@mytempa\@mytemp%
\sout{#2}%
\fi%
}
\makeatother
\setmaster{eddy}
\begin{document}
Some text \del{eddy}{See me striked out.}\del{andy}{See me not at all}
\end{document}
正如您在此处看到的,所有未由主程序编写的内容都不会出现。宏本身会在每次调用时检查“eddy”。这意味着必须通过设置“master” \setmaster
。请注意,这使用了非常低级别的比较。如果您需要更复杂的比较,可以涉及etoolbox
或 l3。
更新(编辑后)
现在首先看一下输出:
我使用了可选参数,因为它是可选的。您可以根据需要添加样式和颜色。您也可以比我更仔细地控制空间。
\documentclass{report}
\usepackage{ulem}
\makeatletter
\newenvironment{analyse}[1][]{\bgroup%
\def\@myarga{#1}%
%
\ifx\@myarga\empty% if #1 is nothing we simply whant everything
\def\del##1##2{\textsuperscript{##1} \sout{##2}}%
\def\add##1##2{\textsuperscript{##1} ##2}%
\else% if name given:
\def\del##1##2{%
\def\@master{##1}%
\ifx\@myarga\@master% if name in local macro is = name in envir arg
\textsuperscript{##1}\sout{##2}%
\fi%
%
}
\def\add##1##2{% Just another command, same logic
\def\@master{##1}%
\ifx\@myarga\@master%
\textsuperscript{##1}##2%
\fi%
}
%
\fi%
}%
{\egroup\par}
\makeatother
\begin{document}
\begin{analyse}[eddy]
Argument \texttt{[eddy]}: \del{eddy}{See me striked out.}\add{andy}{See me not at all}
\end{analyse}
\begin{analyse}[andy]
Argument \texttt{[andy]}: \del{eddy}{See me striked out.}\add{andy}{See me not at all}
\end{analyse}
\begin{analyse}[]
Argument \texttt{[]} (empty): \del{eddy}{See me striked out.}\add{andy}{See me not at all}
\end{analyse}
\begin{analyse}
No Argument: \del{eddy}{See me striked out.}\add{andy}{See me not at all}
\end{analyse}
\end{document}
正如我之前所说,环境在这里没有多大意义。一个简单的宏来切换名称(或什么都不做)就足够了。顺便说一句。这不会决定是否动态运行\add
或\del
命令,如果条件不满足,它只会吞噬(不执行任何操作)给定的参数。
答案4
这只需 12 行代码即可完成工作,提供可嵌套的环境,并允许使用以下代码独立于环境打开/关闭编辑架:\on{eddy}/\off{eddy
\documentclass[12pt]{article}
\usepackage{ulem}
\usepackage{color}
\def\on #1{\csname #1true\endcsname \relax}
\def\off #1{\csname #1false\endcsname \relax}
\def\analyze #1{\def\analyzename{#1}\on\analyzename}
\def\endanalyze {\off\analyzename}
\def\editor #1{\expandafter\newif\csname if#1\endcsname \off{#1}}
\newcommand{\deleteline}[2]{%
\expandafter{\let\ifbyeditor=}\csname if#1\endcsname
\ifbyeditor
\textsuperscript{\textcolor{black}{ #1}}%
\textcolor{red}{\sout{#2}}
\off{#1} %Now it won't match the name again
\fi}
\title{Latex Document}
\author{Eddy}
\editor{eddy} \editor{amy}
\begin{document}
\maketitle
\def\line{\texttt{\analyzename} : One
\deleteline{eddy}{Eddy del}
Two
\deleteline{amy}{Amy del}
Three.}
\section{eddy}
\begin{analyze}{eddy}
\line
\end{analyze}
\section{amy}
\begin{analyze}{amy}
\line
\end{analyze}
\section{nested eddy/amy}
\begin{analyze}{eddy}
\begin{analyze}{amy}
\line
\end{analyze}
\end{analyze}
% The following code will fail, with a csname \jontrue undefined error
% \begin{analyze}{jon}
% \line
% \end{analyze}
% Likewise, with csname \ifjon undefined:
% \deleteline{jon}{Jon del}
% All editor names need to be declared with \editor or \newif
\end{document}
编辑代码的第三版本,感谢 bloodworks、David Carlisle,尤其是聊天中的 egreg 指出代码早期版本中的问题。