嵌套 hyperref 和 xstring 两个命令时超出 TeX 容量

嵌套 hyperref 和 xstring 两个命令时超出 TeX 容量

我在这个问题上浪费了大部分下午的时间,但还是搞不清楚。我准备了一个 MWE 来演示这个问题。在我的\displaylink命令中,我调用\href{raw_url}{anchor}(来自包hyperref),但我想用另一个命令构建 raw_url,\createurl该命令使用其中一个xstring实用程序来操纵其参数。

在 MWE 中,有两个版本的\createurl,一个没有命令 from xstring,另一个\createurlx有命令 ( )。如果您注释掉标有“fails”的行,并取消注释标有“works”的行,您会发现所有三个命令(\createurl\createurlx\displaylink)都可以正常工作。但是,如果您注释掉“works”行并取消注释“fails”行,这意味着\displaylink您调用的 from 调用\createurlx了对\StrGobbleLeftfrom 的调用xstring,那么一切都会停止工作。所以问题似乎是这两个命令的嵌套。为什么,我不知道。

顺便说一句,我目前的解决方法是,如果我将 放在 里面\StrGobbleLeft,事情也会起作用\displaylink,但我不想这样做,因为 是\createurlx一个在其他地方也使用的命令。(当然,您会意识到,这些操作在这里已经为 MWE 的目的进行了简化——它们在实际文档中不那么简单。)

\documentclass{article}
\usepackage{hyperref}
\usepackage{xstring}

\newcommand{\createurl}[1]{
  http://www.foobar.com/documents/#1.pdf
}

\newcommand{\createurlx}[1]{
    \StrGobbleLeft{#1}{1}[\chopped]
    http://www.foobar.com/documents/\chopped.pdf
}

\newcommand{\displaylink}[1]{
  % \href{\createurl{#1}}{\mbox{#1}} % works
  \href{\createurlx{#1}}{\mbox{#1}} % fails
}

\begin{document}
The generated url looks like this: \createurl{my-stuff}.
The chopped url looks like this: \createurlx{my-stuff}.
The calling code wants to display a hyperlink: \displaylink{my-stuff}.
\end{document}

失败原因:

    This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/Debian) (preloaded format=pdflatex)
 restricted \write18 enabled.
entering extended mode
(./mwe2.tex
LaTeX2e <2017-04-15>
Babel <3.18> and hyphenation patterns for 84 language(s) loaded.
(/usr/share/texlive/texmf-dist/tex/latex/base/article.cls
Document Class: article 2014/09/29 v1.4h Standard LaTeX document class
(/usr/share/texlive/texmf-dist/tex/latex/base/size10.clo))
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty
(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/hobsub-hyperref.sty
(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/hobsub-generic.sty))
(/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty)
(/usr/share/texlive/texmf-dist/tex/generic/ifxetex/ifxetex.sty)
(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/auxhook.sty)
(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/kvoptions.sty)
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/pd1enc.def)
(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/hyperref.cfg)
(/usr/share/texlive/texmf-dist/tex/latex/url/url.sty))
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hpdftex.def
(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/rerunfilecheck.sty))
(/usr/share/texlive/texmf-dist/tex/generic/xstring/xstring.sty
(/usr/share/texlive/texmf-dist/tex/generic/xstring/xstring.tex)) (./mwe2.aux)
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty
(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/gettitlestring.sty))
(./mwe2.out) (./mwe2.out)
! TeX capacity exceeded, sorry [input stack size=5000].
\Hy@href {->\hyper@normalise 
                             \href@ {
l.25 ...o display a hyperlink: \displaylink{stuff}
                                                  .
!  ==> Fatal error occurred, no output PDF file produced!
Transcript written on mwe2.log.

编辑:正如@egreg在评论中正确推测的那样,这不是我真正需要的字符串操作。真正的操作需要将输入转换 2010-x03-y102010x3y10,也就是说删除连字符和任何前导零---然后添加常量前缀和后缀。我毫不费力地将其编码为xstring操作序列并将结果存储在命令名称中(\chopped我的MWE的),但我无法“将获得的字符串交给\href”(如果可能的话,请使用普通的Latex---但下面的@Herbert告诉我不是这样)。

答案1

如果不想expl3使用任何功能,我建议先申请\StrGobbleLeft\displaylink然后再申请\chopped。无论如何\StrGobbleLeft,宏仍然可以应用\createurlx

\StrGobbleLeft与几乎所有xstring不可扩展的宏一样,因为它对输入字符串进行“严重”操作(“分配”)并且具有可选参数——这是不可扩展的,因此不会出现在\href

\documentclass{article}
\usepackage{xstring}
\usepackage{hyperref}

\newcommand{\displaylink}[1]{%
  \StrGobbleLeft{#1}{1}[\chopped]%
  \href{http://www.foobar.com/documents/\chopped.pdf}{\mbox{#1}}
}

\begin{document}
The calling code wants to display a hyperlink: \displaylink{my-stuff}.
\end{document}

答案2

\StrGobbleLeft不能在这样的参数中使用。如果你真的只想从 expl3 中删除一个可以使用的字符\tl_tail:n,这是可扩展的:

\documentclass{article}
\usepackage{hyperref}
\usepackage{expl3}

\newcommand{\createurl}[1]{
  http://www.foobar.com/documents/#1.pdf
}

\ExplSyntaxOn
\newcommand{\createurlx}[1]
 {
    http://www.foobar.com/documents/\tl_tail:n{#1}.pdf
 }

\ExplSyntaxOff

\newcommand{\displaylink}[1]{%
  \href{\createurlx{#1}}{\mbox{#1}}% 
}

\begin{document}
The generated url looks like this: \createurl{my-stuff}.
The chopped url looks like this: \createurlx{my-stuff}.
The calling code wants to display a hyperlink: \displaylink{my-stuff}.
\end{document}

答案3

\documentclass[a4paper]{article}
\usepackage[margin=1cm]{geometry}
\usepackage{hyperref}

\newcommand{\createurl}[1]{%
    http://www.foobar.com/documents/#1.pdf%
}    
\newcommand\createurlx[1]{\createURLX#1!!}
\def\createURLX#1#2!!{%
    http://www.foobar.com/documents/#2.pdf%
}
\newcommand{\displaylink}[1]{%
    \href{\createurlx{#1}}{\mbox{#1}}% 
}

\begin{document}
The generated url looks like this: \createurl{my-stuff}.

The chopped url looks like this: \createurlx{my-stuff}.

The calling code wants to display a hyperlink: \displaylink{my-stuff}.
\end{document}

相关内容