Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Can I define a command that takes an argument but does not eval the argument?

share|improve this question
3  
Welcome to tex.sx Dick! Yes, I think you can define such a command, but it depends on exactly what you want to do. If you simply want to display some arbitrary text without interpreting it as LaTeX code you can use \verb|some $%^& text|. However this doesn't work when \verb itself is an argument of another macro. –  Martin Scharrer Mar 5 '11 at 16:03
4  
\newcommand{\commandname}[1]{definition} takes an argument but doesn't evaluate it if you don't use #1 within the definition code. –  Stefan Kottwitz Mar 5 '11 at 16:08
4  
Are you asking this coming from a background with programming languages? The evaluation model of TeX is quite different from (modern) programming languages. If so, there might be some confusion here as TeX does not implement call-by-value as most programming languages. Like others have said, it would be best to know what you want to achieve. –  Christian Lindig Mar 5 '11 at 19:45
4  
Thanks @Lindig. Here is exactly what I am trying to do. I have a file with many commands of the form \href{a}{b} for strings a and b. I would like to redefine \href so that it executes the following: \footnote{\href{a}{b}}. Thus want to change the URL's into footnotes to URL's. –  dick lipton Mar 6 '11 at 1:28
3  
Hmm, you could have been a little bit more explicit about the problem that you were trying to solve. I've just read your blog post (rjlipton.wordpress.com/2011/03/09/tex-is-great-what-is-tex if anyone else is interested) and the problem that you describe there is not what you describe above. –  Andrew Stacey Mar 9 '11 at 21:35
show 4 more comments

4 Answers

Ok, it seems that you mean the so called verbatim mode as "does not eval the argument". This is done in TeX by changing the category codes, short catcodes, of the special characters. This is done using \catcode<ASCII number of character>=<catcode><space or \relax>. The ASCII number of a character can be received by <character>`` or\``. Note that once TeX has read a character its catcode is fixed, so the changes must be made beforehand and should only be local!

The normal way to do is (1) change the catcodes in a group (2) call a second macro which reads the argument and closes the group (3) process the argument and read further arguments if required. LaTeX helps here a little and provides \dospecials which holds all special characters preceded with \do, e.g. \do\\\do\%\do\& ..., so you only have to define \do to a macro which changes the catcode of these characters to something neutral, which is catcode 12 "other". The \@makeother macro does this for you! However, in this case the { and } must be changed back to there original catcodes 1 and 2 in order to be able to read the argument.

\documentclass{article}

\usepackage{hyperref}

\makeatletter

\def\hreffootnote{%
    %\unskip
    \begingroup
    \let\do\@makeother
    \dospecials
    \catcode`\{=1\relax
    \catcode`\}=2\relax
    \href@footnote
}
\def\href@footnote#1{%
    \endgroup
    \href@@footnote{#1}%
}
\let\realhref\href
\def\href@@footnote#1#2{%
    \footnote{\realhref{#1}{#2}}%
}

\begin{document}

Text\hreffootnote{http://foobar.com/~test/%^&*$_##/test}{there} after

Text \href{http://foobar.com/~test/%^&*$_##/test}{there} after

\let\href\hreffootnote
Text \href{http://foobar.com/~test/%^&*$_##/test}{there} after

Hello\href{http://www.google.com/#sclient=psy&hl=en&site=&source=hp&q=numbers&aq=f&aqi=&aql=&oq=&pbx=1&fp=d5033c56880e0199}{b} world.

\end{document}

Update 2011-07-27:

I now published a new version of newverbs which provides \collectverb and \Collectverb to collect verbatim arguments easily. See my answer to Changing href's to footnotes for an example for footnotes.

share|improve this answer
add comment

To answer the clarification of the question in the comments, this seems to work (though I'm no expert on the hyperref package so this might break something else, but if it does I'm sure that someone will stop by and say so).

\documentclass{article}

\usepackage{hyperref}

\let\oldhref=\href
\def\href#1#2{\footnote{\oldhref{#1}{#2}}}

\begin{document}

Hello\href{a}{b} world.

\end{document}
share|improve this answer
    
@dick: This approach of '\let the original to a saved name, then redefine the original' is standard TeX programming. TeX is a macro language, after all. –  Joseph Wright Mar 6 '11 at 17:59
    
@Joseph: Yes, I should probably add that to my answer. I didn't want to post a long answer initially as I wasn't sure that this was what was wanted, and (as I said) I can't be sure that it doesn't break something else (I have the impression that the hyperref package is a bit touchy, but then I'm not sure that \href is coming from \hyperref either). –  Andrew Stacey Mar 6 '11 at 18:09
    
To clarify: I know that there is a command \href in the hyperref package, but I don't know if there is another package that also defines it and that Dick is using instead of hyperref. (And \hyperref -> hyperref) –  Andrew Stacey Mar 6 '11 at 18:10
    
@Andrew thanks very much. I tried the earlier solutions and they work partially. The issue is more complex url's. The solutions seem to die when the url's include _ and & for example. –  dick lipton Mar 7 '11 at 13:22
1  
@Andrew for example this breaks::: which is Wikipedia url \documentclass{article} \usepackage{hyperref} \let\oldhref=\href \def\href#1#2{\footnote{\oldhref{#1}{#2}}} \begin{document} Hello\href{google.com/…}{b} world. \end{document} –  dick lipton Mar 7 '11 at 13:25
show 1 more comment

I posted this already on Dick's blog. I think there is an easier way to do what Dick wants to do (if I understand him correctly) by using the \url command provided by the hyperref package. In this case, you can just define the macro like this:

\newcommand\hreffootnote[2]{#2\footnote{\url{#1}}}`

Edit: This does not treat special characters in URLs correctly. But this seems to work (using hyperref):

\makeatletter
\newcommand\myhref@[2]{#2\footnote{\url@{#1}}}
\DeclareRobustCommand{\myhref}{\hyper@normalise\myhref@}
\makeatother
share|improve this answer
add comment

Just a point of clarification supporting Martin's answer, together with an attempt to put the behaviour in more of a programming language theory context and address some points in your weblog.

The problem here is the highly dynamic staged approach Tex takes to its input, described by Knuth in terms of an analogy with the digestive tract. Tex takes its input a character at a time as it evaluates and "looks" at them with its "eye" - what happens at this stage is that the characters get catcodes. Expansion is the next thing that happens to these tokens, when they are "chewed" by its "mouth". At the time a macro "takes" an argument, it assigns catcodes ahead enough that it has all of the argument: you can't avoid this, but you can change the catcodes before this happens. Martin's answer uses his package to change the catcodes to all be letters (I think), so that the URL can be treated as a normal string when the argument is read in.

If the set of valid Tex programs are those that terminate by executing the command behind the \bye primitive and the pure Tex programs are those that only read from one .tex file and do not write to it, then it is pretty much clear that the set of pure valid Tex programs is not recursive. To actually prove this, I think one would need to prove some things about Tex the program, because it does not have a formal specification. Then again. Knuth does have an implementation-independent notion of correctness for Tex, since has written cheques to bug hunters.

Knuth has never been one for the kind of discipline advocated by software engineers. Indeed, he weighed into the discussion following Dijkstra's "Goto considered harmful" paper with an opinion along the lines that goto is fine, even a good thing, if you know what you are doing (Knuth, 1974, "Structured Programming with go to Statements", Computing Surveys 6: 261–301). I guess the real problem with this style of programming is that it does not scale: two Knuths are not going to collaborate well.

Tex is not entirely eccentric as a programming language. It can be considered as a child of Strachey's GPM. But none of the other GPM-derived languages I've seen are routinely used with such a drastically dynamic approach to syntax.

share|improve this answer
    
I read somewhere that Knuth has stopped actually writing cheques to bug-hunters because lots of small-denomination cheques got flagged as possibly fraudulent behaviour by his bank... –  Seamus Jul 27 '11 at 15:04
    
@Seamus: Really? I've changed the tense in that assertion. So what happens if you find a bug now? –  Charles Stewart Jul 27 '11 at 15:57
    
I wish I could remember where I'd read this... From what I can remember, you still get a cheque, but for some reason, it isn't actually possible to cash it. (it isn't dated or it is invalid in some other way). I read this several years ago, so I could be wrong... –  Seamus Jul 27 '11 at 16:08
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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