6

I am trying to defer processing of some latex code.

This works,

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

but I need to move up the importing of codeToBeDeferred (containing the \href), and render/process it in the same place. So I changed it to this.

\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}

This works, except for the # in the \href, note the # was not a problem in the original code.

side note: I am reading the code early and deferring processing because the code is merged together by a preprocessor, the preprocessor needs to process the deferred code early, but latex needs to do it latter.

Well all this works, except when the codeToBeDeferred has a # in it. \newcommand does not like it. If I put a \ before the # it fixes it, however I do not want to do this: there are a lot of historic versions of this code, I don't want to have to remember when I write new code. The code is valid latex when not part of a \newcommand

How can I allow a # in a \newcommand? or How else can I defer the processing of this block of code?


The # is in a \href in the deferred code, it works outside of a \newcommand.

What I am hoping for, is a wrapper to stop the # being a problem. If the # is only a problem when in a \newcommand then this may be possible.

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

I know that I can escape the # with a \ (changing it to \#), but am hoping for another way.

I don't want to edit the code to be deferred. There is a choice of hundreds of them, I don't want them to be constrained by me doing this deferral trick to fix another problem.

  • I think you could clarify a little bit the question. What's exactly what you are trying to achieve? Using # as “text”? I think a more particular example would be great. – Manuel Jul 09 '14 at 11:30
  • 1
    If you want to typeset a # then you need \# in anycase unrelated to \newcommand \begin{document} a # b \end{document} is an error you need a \# b – David Carlisle Jul 09 '14 at 11:32
  • I guess that the OP wants a later execution/expansion of code with some # character, however, this stands as a placeholder for the number of a specific argument. As the command \deferredcode has no argument, LaTeX will complain about a direct # occuring somewhere inside the command, especially, if not followed by a number from 1 up to 9. –  Jul 09 '14 at 11:54
  • @richard: I am unsure whether you rather mean something like \noexpand or \unexpanded. Could you also explain in short why there are # characters in the command body? –  Jul 09 '14 at 11:56
  • 2
    Does your deferred code perhaps itself include definitions which thus use #1, etc.? If so, you are probably looking for http://tex.stackexchange.com/questions/42463/what-is-the-meaning-of-double-pound-symbol-1-in-an-argument – Joseph Wright Jul 09 '14 at 11:59
  • The \href info is new. Could you add a minimal compilable example which we could compile to reproduce your problem? – Manuel Jul 09 '14 at 12:02
  • @JosephWright: However, this ##1 by a nested \def or \(re)newcommand etc. wouldn't be needed if there is no #1 at all, or am I misinterpreting that? –  Jul 09 '14 at 12:02
  • @ChristianHupfer You always need to double # tokens to allow nesting. Thus def\foo{\def\foo##1{##1}} needs two # for the inner definition even though the outer one has no parameters. – Joseph Wright Jul 09 '14 at 12:06
  • @JosephWright: Ok, thanks for that information, I have not done this so far, since there was no need of doing so. –  Jul 09 '14 at 12:07
  • @richard: If \href is used, than you refer to an external document and in this case a \# is needed. –  Jul 09 '14 at 12:08
  • I have added a foot note to question. There is no \newcommand of definitions in the deferred code. Just a \href, it was working for yours without the deferring (use of \newcommand). – ctrl-alt-delor Jul 09 '14 at 12:10
  • @richard: Well, you have a \newcommand in order to define your \deferredcode command. And all this cases, as commented by David Carlisle, Joseph Wright, Manuel and me, the # character has a special meaning, which must be escaped by using \# –  Jul 09 '14 at 12:20
  • I was hoping that, because the \href works outside of a \newcommand, that there would be a way to wrap all of the deferred code in the \new command to make it behave. – ctrl-alt-delor Jul 09 '14 at 12:24
  • @richard: Please see the comment by J. Wright below my answer. I think, he answered it more complete than me;-) –  Jul 09 '14 at 12:35
  • @richard since you are using \href I can think that you load hyperref and hence url is loaded (you should provide a complete compilable example, as always). Those packages offer capabilities to define urls, so it might be better here to define urls once out of \newcommand and then use the defined urls inside it, avoiding problems with #. – Manuel Jul 09 '14 at 12:40
  • I don't want to change the code that is deferred, I added a note about this to question. – ctrl-alt-delor Jul 09 '14 at 12:54
  • @ChristianHupfer I have looked at \noexpand \unexpanded, but can not workout if they are what I need. – ctrl-alt-delor Jul 09 '14 at 13:04
  • @richard \unexpanded won't help here as you still end up with a token of category code 6 (macro parameter). – Joseph Wright Jul 09 '14 at 13:08
  • @richard: I proposed \noexpand etc. before I knew about the \href issue. I should have removed that comment or writing an update, that it would be of no use. –  Jul 09 '14 at 13:46

4 Answers4

8

Once TeX has tokenized input, which occurs for example when you save the input in a macro, then it's not generally straight-forward to alter the nature of the tokens. In particular, this restricts our ability to use verbatim or verbatim-like input in the arguments and definitions of macros. The \href command needs to use a verbatim-like approach to allow for example # inside hyperlinks, so that causes the problem.

In the question, you've noted that using \# is not a usable solution. This the most obvious approach is to alter the category code of # for the duration of the block you want to defer:

\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}

(Category code 12 is 'other' and so is harmless). Of course this prevents the deferred block containing any macro definitions requiring parameters, or at least that you pick some other character for that purpose.

Joseph Wright
  • 259,911
  • 34
  • 706
  • 1,036
2

When using the reference to external labels, the # character is used, according to the hypertext specification, but this means, that has to be escaped with\# within another command such as \newcommand.

\documentclass[12pt]{scrbook}

\usepackage{hyperref}


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

\begin{document}

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

Where anotherfile.tex contains

\documentclass[12pt]{scrbook}

\usepackage{hyperref}

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

I omitted a screenshot, since it does not reveal much.

  • Perhaps note why this is required inside a definition but not outside (verbatim-like reading of arguments is possible only if they've not been tokenized). – Joseph Wright Jul 09 '14 at 12:28
  • @JosephWright: I will add you comment, with reference to you, of course, but is it possible to prevent the tokenizing? –  Jul 09 '14 at 12:36
0

This is not as good as the other solutions, but why not use this code:

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

Make sure to put this as the definition for \deferredcode to make it work.

Someone
  • 539
0

You can define \deferredCode in terms of \edef while applying \string to problematic characters:

\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}

You can define a command which reads one argument in verbatim-catcode-régime and defines another command to apply \scantokens to that argument:

\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}

Ulrich Diez
  • 28,770