4

I was wondering if it's at all possible to change a catcode for use only inside a macro definition. In this case, I need to have one macro defined as \example#1#2, and another defined as \example^#1#2. The code below is working if \test{\example^25} is omitted. Thanks in advance (eplain answers only please).

\catcode`^=11

\def\example^#1#2{%
this is \#1: #1. this is \#2: #2}

\catcode`^=7

\def\test#1{%
\catcode`^=11
#1
\catcode`^=7}

\test{\example^25}

\bye
Cfun
  • 1,840
  • Welcome to TeX.SX! No, it's not possible in that way (unless you allow \scantokens which is not in Knuth TeX). – egreg Nov 20 '15 at 21:43
  • I might be getting my jargon messed up. Maybe I meant etex and not eplain? scantokens is available to me, I just tried it with "\edef\test{\scantokens{test\noexpand}}" and \test expands to the text "test". I will look into scantokens now, thank you. – user92531 Nov 20 '15 at 21:50
  • Are you bond to plain-TeX? – yo' Nov 20 '15 at 22:11

1 Answers1

4

It mostly depends on what \example is supposed to do. The standard way is to delay reading the argument: if you expect that \test can have both \example and \example^ in its argument, define it as

\def\test{\begingroup\catcode`^=11 \dotest}
\def\dotest#1{#1\endgroup}

so the category code change happens before the argument is grabbed and catcodes frozen. Of course this has the limitation that \test cannot be itself used in the argument to another command.

A different strategy is to have just one \example macro:

\def\example{\futurelet\next\doexample}
\def\doexample{\ifx^\next\let\next\examplehat
  \else\let\next\examplenohat\fi\next}

\def\examplehat^#1#2{this is \#1: #1. this is \#2: #2}
\def\examplenohat#1#2{No hat (#1,#2)}

No category code change.

Full code:

\def\example{\futurelet\next\doexample}
\def\doexample{\ifx^\next\let\next\examplehat
  \else\let\next\examplenohat\fi\next}

\def\examplehat^#1#2{this is \#1: #1. this is \#2: #2}
\def\examplenohat#1#2{No hat (#1,#2)}

\example25

\example^25

\def\test#1{#1}

\test{\example25}

\test{\example^25}

\bye

enter image description here

With \scantokens we still have to delay grabbing the argument or it would already be tokenized at the category code change and control sequences formed.

\begingroup
\catcode`^=11
\gdef\example^#1#2{this is \#1: #1. this is \#2: #2}
\endgroup

\def\example#1#2{No hat (#1,#2)}

\def\test{\begingroup\catcode`^=11 \dotest}
\def\dotest#1{\scantokens{#1\noexpand}\endgroup}

X\test{\example25}X

X\test{\example^25}X

\bye

enter image description here

egreg
  • 1,121,712