2

As intentioned in the title I want a macro \skipfirstletters in plain-TeX, that skips the first letters (catcode 11) from the \jobname. For instance if the TeX-file is named Test0xy.tex it should expand to just 0xy.

I tried the following lines as Test0xy.tex:

\def\skipfirstletters#1{\ifcat A#1\expandafter\skipfirstletters\else#1\fi}
\skipfirstletters Test0xy\par
\skipfirstletters\jobname\par
\expandafter\skipfirstletters\jobname

\bye

The result is just
0xy Test0xy Test0xy

I don't understand alot, e.g. why the expanded \jobname in Line 4 (is it expanded before \skipfirstletters?) does not behave like the plain tokens in Line 2.

I want to use the expanded macro as argument for others if this matters.

Thanks a lot to the community and sorry for my poor knowledge of TeX.

4
  • 1
    the tokens in jobname are all catcode 12 or 10 Commented Apr 10, 2018 at 9:07
  • 12 ok, but why 10? i thought catcode 10 means "spaces"... Commented Apr 10, 2018 at 9:10
  • 1
    If a space character somehow creeps in \jobname, its category code will be 10.
    – egreg
    Commented Apr 10, 2018 at 9:12
  • 1
    All characters in \jobname have catcode 12 (other) to avoid trouble with special characters like \ or % in it. The only exception is the space. I guess this is because file name strings once saved internally do not have catcodes anymore, as there are not material to be typeset but to be used internally. If you reinsert them into the typeset content a neutral catcode is selected to be on the save side, I guess. The TeXBook surely states the reason. Commented Apr 10, 2018 at 9:29

2 Answers 2

6

the tokens in \jobname are like \string and have catcode 12 (or 10 if it is a space), however you can still test the catcode settings for the slots to test whether it is a letter or not:

\def\skipfirstletters#1{%
\ifnum11=\catcode`#1 \expandafter\skipfirstletters\else#1\fi}
\skipfirstletters Test0xy\par
\expandafter\skipfirstletters\jobname\par
\expandafter\skipfirstletters\jobname

\bye
0
0

An expl3 based answer that automatically checks whether \skipfirstletters is a macro and doesn't eat what follows because the string to be cut is passed as an argument.

\input expl3-generic

\ExplSyntaxOn

\cs_new:Npn \skipfirstletters #1
 {
  \bool_lazy_and:nnTF { \tl_if_single_p:n { #1 } } { \token_if_cs_p:N #1 }
   {
    \egreg_skipfirstletters:o { #1 }
   }
   {
    \egreg_skipfirstletters:n { #1 }
   }
 }

\cs_new:Npn \egreg_skipfirstletters:n #1
 {
  \__egreg_skipfirstletters:N #1 \q_nil
 }
\cs_generate_variant:Nn \egreg_skipfirstletters:n { o }

\cs_new:Npn \__egreg_skipfirstletters:N #1
 {
  \quark_if_nil:NF #1
   {
    \int_compare:nNnTF { \char_value_catcode:n { `#1 } } = { 11 }
     {% check the next one
      \__egreg_skipfirstletters:N
     }
     {% output the character and the rest
      #1 \__egreg_skipfirstletters_end:w
     }
   }
 }

\cs_new:Npn \__egreg_skipfirstletters_end:w #1 \q_nil { #1 }

\ExplSyntaxOff

\edef\fakejobname{\detokenize{Test0xy}}

\skipfirstletters{Test0xy}

\skipfirstletters{\fakejobname}

X\skipfirstletters{abc}X

\edef\test{\skipfirstletters{Test0xy}} {\tt\meaning\test}

\edef\test{\skipfirstletters{\fakejobname}} {\tt\meaning\test}

\bye

Here \fakejobname is defined so I don't have to rename the file to make tests: with \detokenize we get the same result as `\jobname, that is, all characters are category code 12 except for spaces that keep category code 10.

enter image description here

1
  • I should release the expl3 version that stores Unicode character class in the format (or loads it as needed in plain) ;)
    – Joseph Wright
    Commented Dec 12, 2022 at 22:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .