构建 \externaldocument 命令的参数以实现可编程的交叉引用

构建 \externaldocument 命令的参数以实现可编程的交叉引用

我的 ver12.tex 和 ver12_SM.tex 文档使用 xr 包相互交叉引用。我该如何对它们进行编程,以便当转到 ver13 时,两个 \externaldocument 命令可以完成它们的工作,而无需手动将当前文件名硬编码到它们中。

以下行会产生编译错误:

\usepackage{xstring}
\usepackage{xr}
\externaldocument[M-]{\StrBefore*{\jobname}{_SM}

谢谢!

答案1

你可以使用一种方式

\externaldocument{\jobname_SM}

在另一个中你可以使用

{
\catcode`\_=12
\catcode`\S=12
\catcode`\M=12
\gdef\stripsm#1_SM{#1}
}

\externaldocument{\expandafter\stripsm\jobname}

答案2

那么这两个文件的名字的模式就是
⟨common part of the two filenames⟩.tex
⟨common part of the two filenames⟩_SM.tex

宏的问题字符串-package 的一个缺点是它们不可扩展。
这意味着它们不只是提供在 LaTeX 的胃中处理/扩展的标记,并且在扩展后产生字符标记序列。它们还提供不可扩展的标记,用于执行\def在 LaTeX 的胃中执行的临时任务(等等)。这种不可扩展的非字符标记不能成为文件名的一部分。在胃中,形成文件名的字符标记序列应该已经存在,而不是与其他不可扩展的标记交错,因为文件名的进一步处理也在胃中进行。
因此,使用宏字符串-package 您需要使用它们的可选参数来定义扩展为操作结果的宏:

\documentclass{article}
\usepackage{xr}
\usepackage{xstring}

%======================================================================%
% This will check whether the token-sequence that forms the expansion  %
% of \jobname ends with "_SM".                                         %
% If so, \JobNameWithOrWithoutSMPhrase will be defined to expand to    %
% the result of removing the last occurrence of "_SM" from the         % 
% expansion of \jobname.                                               %
% If not so, \JobNameWithOrWithoutSMPhrase will be defined to expand   %
% to the result of appending the phrase "_SM" to the expansion of      %
% \jobname.                                                            %
\newcommand\JobNameWithOrWithoutSMPhrase{}%
\begingroup
\makeatletter
\def\SMPhrase{_SM}%
\@onelevel@sanitize\SMPhrase
\IfEndWith{\jobname}{\SMPhrase}{%
  \StrCount{\jobname}{\SMPhrase}[\JobNameWithOrWithoutSMPhrase]%
  \StrBefore[\JobNameWithOrWithoutSMPhrase]{\jobname}{\SMPhrase}[\JobNameWithOrWithoutSMPhrase]%
}{%
  \expandafter\expandafter
  \expandafter            \def
  \expandafter\expandafter
  \expandafter            \JobNameWithOrWithoutSMPhrase
  \expandafter\expandafter
  \expandafter            {%
  \expandafter\jobname
  \SMPhrase}%
}%
\global\let\JobNameWithOrWithoutSMPhrase=\JobNameWithOrWithoutSMPhrase
\endgroup
%======================================================================%

\message{^^J\string\jobname\space expands to:^^J\jobname}
\message{^^JPress return to proceed.}
\immediate\read-1 to\MyScratchmacro

\message{^^JMeaning of \string\JobNameWithOrWithoutSMPhrase\space is:^^J\meaning\JobNameWithOrWithoutSMPhrase}
\message{^^JPress return to proceed.}
\immediate\read-1 to\MyScratchmacro

\externaldocument[M-]{\JobNameWithOrWithoutSMPhrase}
\begin{document}

Bla Bla

\end{document}

而不是使用字符串您可以使用分隔参数让 LaTeX 检测形成扩展的标记序列是否\jobname以该序列结尾_SM,如果是,则定义控制字标记以扩展为删除短语\JobNameWithOrWithoutSMPhrase的扩展,如果不是,则定义控制字标记以扩展为附加短语的扩展。\jobname_SM\JobNameWithOrWithoutSMPhrase\jobname_SM

您可能面临的一个问题是,在对 .tex-input-file 中的\jobname短语进行标记时,通常会产生类别代码为 8(下标)的下划线 ( ),后面跟着类别代码为 11(字母)的和。因此,对于从 .tex-input 标记的字符标记序列,您可能需要申请将所有这些字符转换为类别代码为 12(其他)的挂件。(至于空格的例外:将空格字符标记转换为类别代码为 10(空格)的空格字符标记。)_SM_SM\@onelevel@sanitize\@onelevel@sanitize

\documentclass{article}
\usepackage{xr}

%======================================================================%
% This will check whether the token-sequence that forms the expansion  %
% of \jobname ends with "_SM".                                         %
% If so, \JobNameWithOrWithoutSMPhrase will be defined to expand to    %
% the result of removing the last occurrence of "_SM" from the         % 
% expansion of \jobname.                                               %
% If not so, \JobNameWithOrWithoutSMPhrase will be defined to expand   %
% to the result of appending the phrase "_SM" to the expansion of      %
% \jobname.                                                            %
% For detecting the end, advantage is taken of the fact that the       %
% expansion of \jobname cannot contain any control-sequence-token      %
% and therefore cannot contain the control-word-token \relax.          %
% The empty-test via \if\relax<stuff>\relax..\else..\fi also takes     %
% advantage of this fact and of the fact that \if triggers expansion   %
% until finding two non-expandable tokens whose character-codes can be %
% compared, while for control-word-tokens like \relax a character-code %
% outside the range of character-codes possible for character-tokens   %
% is assumed.                                                          %
\newcommand\JobNameWithOrWithoutSMPhrase{}%
\begingroup
\makeatletter
\def\SMPhrase{_SM}%
\@onelevel@sanitize\SMPhrase
\expandafter\def\expandafter\GobbleToSMPhraseNRelax
\expandafter#\expandafter1\SMPhrase\relax{}%
\expandafter\def\expandafter\RemoveSMPhraseNRelax
\expandafter#\expandafter1\SMPhrase\relax{#1}%
\edef\JobNameWithOrWithoutSMPhrase{%
  \if\relax\expandafter\expandafter
           \expandafter           \GobbleToSMPhraseNRelax
           \expandafter\jobname
           \expandafter\relax
           \SMPhrase\relax\relax
    \jobname\SMPhrase
  \else
    \expandafter\RemoveSMPhraseNRelax\jobname\relax
  \fi
}%
\global\let\JobNameWithOrWithoutSMPhrase=\JobNameWithOrWithoutSMPhrase
\endgroup
%======================================================================%

\message{^^J\string\jobname\space expands to:^^J\jobname}
\message{^^JPress return to proceed.}
\immediate\read-1 to\MyScratchmacro

\message{^^JMeaning of \string\JobNameWithOrWithoutSMPhrase\space is:^^J\meaning\JobNameWithOrWithoutSMPhrase}
\message{^^JPress return to proceed.}
\immediate\read-1 to\MyScratchmacro

\externaldocument[M-]{\JobNameWithOrWithoutSMPhrase}
\begin{document}

Bla Bla

\end{document}

顺便一提:

test.tex您可以通过在 shell 上保存并运行 latex 来测试上述示例。

如果你运行不带 -option 的 latex -jobname,即,latex test.tex\jobname则会扩展为test(类别代码 12(other) 的所有字符) 并\meaning\test显示:macro:->test_SM

如果您使用 -option 运行 latex-jobname以提供尾随的_SM,即,latex -jobname=test_SM test.tex那么\jobname将扩展为test_SM(类别代码 12(其他) 的所有字符) 并\meaning\test显示:macro:->test

相关内容