我有一个 .tex 文件,里面有以下神奇的代码来翻译阿达迪页码罗马相等的。
\makeatletter
\newcommand{\aresame}[2]{%
\aresame@massage\aresame@tempa{#1}%
\aresame@massage\aresame@tempb{#2}%
\ifx\aresame@tempa\aresame@tempb
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}
\def\aresame@massage#1#2{%
\begingroup\let\@xp\expandafter\let\@nx\noexpand
\everyeof{}%
\catcode`{=9 \catcode`}=9
\catcode`<=1 \catcode`>=2
\begingroup\edef\x{%
\endgroup\@nx\scantokens{\def\@nx\1<#2>\@nx\empty}%
}\x
\uppercase\@xp{\@xp\endgroup\@xp\def\@xp#1\@xp{\1}}%
}
\makeatother
附带以下代码:
\def\myadadipage{\getpagerefnumber{lastpreamblepage}} %this reads the page number in *adadi*, since we used \pagenumbering{adadi} for the preamble part of the document.
\newcounter{searchforadadi}
\loop
\relax%
\ifnum\value{searchforadadi} < 1000
\addtocounter{searchforadadi}{1}%
\aresame{\myadadipage}{\adadi{searchforadadi}}{\xdef\myromanpage{\roman{searchforadadi}}}{}%
\repeat
现在我可以\myromanpage
在文档的任何位置使用,没有任何问题。
但
我的问题是:
“我怎样才能将这些代码移动到补充
.cls
文件并将它们精确地放在另一个命令中,我很好奇如何定义一个命令,像这个,但可以正常工作,内部/本地在另一个命令中?”
因为当我简单地将所有这些代码从文件复制.tex
到.cls
文件中时,我需要\aresame
在另一个命令的定义中使用该命令,比如\@setabstract
,用于排版/分页英语摘要/总结作品页面,
\def\@setabstract{%
\newcommand{\aresame}[2]{%
\aresame@massage\aresame@tempa{#1}%
\aresame@massage\aresame@tempb{#2}%
\ifx\aresame@tempa\aresame@tempb
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}
\def\aresame@massage#1#2{%
\begingroup\let\@xp\expandafter\let\@nx\noexpand
\everyeof{}%
\catcode`{=9 \catcode`}=9
\catcode`<=1 \catcode`>=2
\begingroup\edef\x{%
\endgroup\@nx\scantokens{\def\@nx\1<#2>\@nx\empty}%
}\x
\uppercase\@xp{\@xp\endgroup\@xp\def\@xp#1\@xp{\1}}%
}
\newpage
\thispagestyle{empty}
\if@bachelor
\else
\begin{framed}
Number of Pages:
\xdef\myadadipage{\getpagerefnumber{lastpreamblepage}}
\newcounter{searchforadadi}
\loop
\relax%
\ifnum\value{searchforadadi} < 1000
\addtocounter{searchforadadi}{1}%
\aresame{\myadadipage}{\adadi{searchforadadi}}{\xdef myromanpage{\roman{searchforadadi}}}{}%
\repeat
\pageref{LastPage} + \myromanpage
\end{framed}}%end of set abstract
我会收到类似这样的错误:
! Illegal parameter number in definition of \@setabstract.
<to be read again>
1
l.697 \aresame@massage\aresame@tempa{#1
}%
?
让我澄清一下,如果我将这些代码粘贴到定义之外,那么它是全局可访问的,并且不会发现任何错误!但我想知道我是否可以将它们放在本地,只是为了\@setabstract
函数。
提前致谢!
这个问题是另一个 TeX.SX 问题的后续问题,可能是找到这里。
答案1
嵌套命令时需要#
正确处理的“基础知识”已在参数中的双井号(数字符号,哈希字符)##1 是什么意思?。这里,\@setabstract
不带参数,所以 TeX 不允许#1
出现在其中(没有参数可以引用)。里面的嵌套定义\@setabstract
需要#
加倍,所以#1
变成##1
,ETC。因此,人们可能会倾向于
\def\@setabstract{%
\newcommand{\aresame}[2]{%
\aresame@massage\aresame@tempa{##1}%
....
这将避免错误,但仍然不是一个好主意。作为宏语言,TeX 没有与定义相关的分组,只有显式组。因此,使用上述代码,如果您尝试使用\@setabstract
两次,则会收到错误,因为第二次使用\newcommand
将检测到\aresame
已经定义。有不需要\aresame
在其中定义(\@setabstract
通常只有在存在一些上下文依赖性时才需要)。相反,你应该简单地\aresame
全局定义并在其中使用它\@setabstract
\def\@setabstract{%
... % Code using \aresame
}
\newcommand{\aresame}[2]{%
\aresame@massage\aresame@tempa{#1}%
\aresame@massage\aresame@tempb{#2}%
\ifx\aresame@tempa\aresame@tempb
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}
要进行局部定义,你需要一个组。它可能看起来像这样
\def\@setabstract{%
\begingroup
\def\aresame##1##2{%
\aresame@massage\aresame@tempa{##1}%
\aresame@massage\aresame@tempb{##2}%
\ifx\aresame@tempa\aresame@tempb
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}%
\def\aresame@massage##1##2{%
\begingroup\let\@xp\expandafter\let\@nx\noexpand
\everyeof{}%
\catcode`{=9 \catcode`}=9
\catcode`<=1 \catcode`>=2
\begingroup\edef\x{%
\endgroup\@nx\scantokens{\def\@nx\1<##2>\@nx\empty}%
}\x
\uppercase\@xp{\@xp\endgroup\@xp\def\@xp##1\@xp{\1}}%
}%
% Use of \aresame here
\endgroup
}
但这样做没什么意义。将所有定义都放在里面\@setabstract
会使代码更难阅读,而且没有任何明显的好处,同时你现在必须注意所有内容是否都已排版、全局保存或“偷运”出组。我强烈建议不要这样做。
\newcommand
请注意,在组中使用“一次性”定义没有什么意义,因此我放弃它而选择\def
。