2

I have wasted most of my afternoon on this one and can't figure it out. I have prepared an MWE that demonstrates the problem. In my \displaylink command I invoke \href{raw_url}{anchor} (from package hyperref) but I want to build the raw_url with another command, \createurl, which manipulates its argument with one of the xstring utilities.

In the MWE there are two versions of \createurl, one without the command from xstring and one (\createurlx) with it. If you comment out the line labeled "fails", and uncomment the line labelled "works", you see that all three commands (\createurl, \createurlx and \displaylink) work fine. If, however, you comment out the "works" like and uncomment the "fails" line, meaning that from \displaylink you invoke \createurlx which has the call to \StrGobbleLeft from xstring, then things stop working. So it seems to be the nesting of these two commands that's the problem. Why, I have no idea.

BTW my current workaround is that things also work if I put the \StrGobbleLeft inside \displaylink, but I don't want to do that because the \createurlx is a command that's used in other places too. (And of course you realize that these manipulations have been simplified here for the purpose of the MWE---they're somewhat less trivial in the actual document.)

\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 fails with:

    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.

EDIT: as @egreg correctly surmises in a comment, this is not the actual string manipulation I need. The actual one requires transforming an input like 2010-x03-y10 into 2010x3y10, that is to say removing the hyphens and any leading zeros---and then adding a constant prefix and suffix. I have had no trouble coding that up as a sequence of xstring operations and storing the result in a command name (the \chopped of my MWE), but I have not been able to "handle the obtained string to \href" (in plain Latex please if possible---but I'm told by @Herbert below that it's not).

  • Most of the xstring macros are not expandable and cannot be fed into other macros – user31729 Jan 2 at 18:54
  • This simple manipulation doesn't seem the real one you need. Complex string manipulations can often only be done in non-expandable way, so they have to be performed before handing the obtained string to \href. Can you please be more detailed about what manipulations you really need? – egreg Jan 2 at 21:23
1

If no expl3 features are to be used, I suggest to apply \StrGobbleLeft in \displaylink and apply \chopped there. The \StrGobbleLeft macro can still be applied in \createurlx anyway.

\StrGobbleLeft is like almost any of the xstring macros not expandable, since it does 'severe' manipulations ('assignments') of the input strings and has optional arguments -- this is not expandable and can as such not occur in \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}
  • Yes, thanks, this works and is basically my current workaround as I described in the third paragraph of my question. – st01 Jan 2 at 19:20
  • @st01: I know that you described it there -- I suggest it to you as one of the 'easiest' approachest however. Better setups require more information. – user31729 Jan 2 at 19:21
  • Thanks. It feels broken to have to duplicate the code of \createurl (which is useful on its own) inside \displaylink, with the usual issues of later updating things in one place but not the other, but if what I already have is deemed one of the easiest approaches then I may stick with it. – st01 Jan 2 at 19:27
0

\StrGobbleLeft can not be used in such arguments. If you really only want to remove one char you can use \tl_tail:n from expl3, this is expandable:

\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}
  • There is a % missing in \createurl (It's not really important, because that command is not used most likely) – user31729 Jan 2 at 19:05
  • No, unfortunately \StrGobbleLeft was only used as a MWE placeholder for a bunch of xstring-related manipulations that I need to do to create the url. What's the reason the xstring macros cannot be used in such arguments, and how could I have guessed that from the obscure "TeX capacity exceeded" error message? – st01 Jan 2 at 19:12
  • \href wants to manipulate tokens too. Change your url before the \href (check the regex-commands of expl3 too) and fed a simple macro to the \href. Be careful with special chars like ~ or #. – Ulrike Fischer Jan 2 at 19:16
0
\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}
  • Wow! Thanks! It works, but I have no idea how or why ;-) What do the exclamation marks do? Care to enlighten me? – st01 Jan 2 at 19:15
  • \createURLX#1!! has the two !! to define the end of the string. You can choose any character which will not be part of the url. \def\createURLX#1#2!! uses #1 as the first character (token) in the input and #2 everything else until the !! – user2478 Jan 2 at 19:19
  • Both of these explanations are somewhat on the terse side and I need to understand a bit more about this if I am going to port this to my non-minimal piece of code. I am leafing through the latex book but can't find a mention of this: where should I be looking? – st01 Jan 2 at 19:25
  • 1
    That is no LaTeX magic but TeX magic and ctan.org/pkg/texbytopic?lang=de maybe a good starter. It cannot be learned in a couple of minutes ;-) – user2478 Jan 2 at 19:27
  • 1
    in LaTeX3 yes, but not really in the current LaTeX2e – user2478 Jan 2 at 19:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.