如何允许 \newcommand 中使用 # 而不使用 \# 或其他方法来推迟处理代码部分

如何允许 \newcommand 中使用 # 而不使用 \# 或其他方法来推迟处理代码部分

我正在尝试推迟处理一些乳胶代码。

这是有效的,

\documentclass[a4paper,final,11pt]{article}
\usepackage{hyperref}
\begin{document}
here comes a reference
\href{http://www.example.com/doc#list}{doc}
\end{document}

但我需要将 的导入codeToBeDeferred(包含\href)上移,并在同一位置渲染/处理它。所以我把它改成了这样。

\documentclass[a4paper,final,11pt]{article}
\usepackage{hyperref}
\newcommand{\deferredCode}{
    \href{http://www.example.com/doc#list}{doc}
}
\begin{document}
here comes a reference
\deferredCode
\end{document}

这是可行的,除了#中的\href,请注意#在原始代码中这不是一个问题。

旁注:我正在提前阅读代码并推迟处理,因为代码是由预处理器合并在一起的,预处理器需要尽早处理延迟的代码,但 latex 需要稍后进行处理。

好吧,所有这些都有效,除了当codeToBeDeferred里面有一个#的时候。\newcommand不喜欢它。如果我\在它之前放#一个,它就会修复它,但是我不想这样做:这个代码有很多历史版本,我不想在编写新代码时记住它。当不属于时,代码是有效的 latex\newcommand

我怎样才能允许 a#在 a 中\newcommand?或者我还能怎样推迟此代码块的处理?


#在延迟代码中,它\href在 之外工作\newcommand

我希望有一个包装器可以阻止#出现问题。如果#只有在出现问题时才会出现问题,\newcommand那么这可能是可能的。

%somePreambleCode
\newcommand{\deferredCode}{
    \wrapper{
        \href{http://www.example.com/doc#list}{doc}
    }
}
%someOtherCode
\deferredCode

我知道我可以用(将其改为)#来逃避,但我希望有另一种方法。\\#

我不想编辑要推迟的代码。有数百种选择,我不想因为我使用这种推迟技巧来解决另一个问题而限制它们。

答案1

一旦 TeX 对输入进行了标记化(例如,当您将输入保存在宏中时),通常就无法直接改变标记的性质。特别是,这限制了我们在宏的参数和定义中使用逐字或类似逐字的输入的能力。该\href命令需要使用类似逐字的方法来允许例如#内部超链接,因此这会导致问题。

在问题中,您已经注意到使用不是一个可用的解决方案。最明显的方法是在您想要推迟的块的持续时间内\#更改类别代码:#

\documentclass[a4paper,final,11pt]{article}
\usepackage{hyperref}
\catcode`\#=12 %
\newcommand*\deferredCode{%
    \href{http://www.example.com/doc#list}{doc}%
}
\catcode`\#=6 %
\begin{document}
here comes a reference
\deferredCode
\end{document}

(类别代码 12 为“其他”,因此无害)。当然,这会阻止延迟块包含任何需要参数的宏定义,或者至少阻止您为此目的选择其他字符。

答案2

当使用对外部标签的引用时,#根据超文本规范,使用字符,但这意味着必须\#在另一个命令(例如)中使用进行转义\newcommand

\documentclass[12pt]{scrbook}

\usepackage{hyperref}


\newcommand{\deferredcode}{%
  \href{anotherfile.pdf\#mylabel}{Some Text}
}%

\begin{document}

In chapter \deferredcode we saw that
\end{document}

其中anotherfile.tex包含

\documentclass[12pt]{scrbook}

\usepackage{hyperref}

\begin{document}
\chapter{first}\label{mylabel}%
\end{document}

我省略了截图,因为它没有透露太多信息。

答案3

这不如其他解决方案好,但为什么不使用这个代码呢:

\href{http://www.example.com/doc{\char`\#}list}{doc}

确保将其作为定义以\deferredcode使其发挥作用。

答案4

您可以在应用于有问题的字符\deferredCode时定义:\edef\string

\documentclass[a4paper,final,11pt]{article}
\usepackage{hyperref}

\csname @ifdefinable\endcsname\deferredCode{%
  \edef\deferredCode{\noexpand\href{http://www.example.com/doc\string#list}{doc}}%
}%

\begin{document}
here comes a reference
\deferredCode
\end{document}

您可以定义一个命令,该命令读取 verbatim-catcode-régime 中的一个参数,并定义另一个命令应用于\scantokens该参数:

\documentclass[a4paper,final,11pt]{article}
\usepackage{hyperref}
\usepackage{xparse}

\begingroup
\catcode`\^^A=14\relax
\catcode`\%=12\relax
\csname @firstofone\endcsname{^^A
  \endgroup^^A
  \NewDocumentCommand\DefineScantokenscommandFromVerbArg{m+v}{^^A
    \newcommand#1{\scantokens{#2%}}^^A
  }^^A
}%

\DefineScantokenscommandFromVerbArg\deferredCode|\href{http://www.example.com/doc#list}{doc}|

\begin{document}
here comes a reference
\deferredCode
\end{document}

相关内容