This is a question about token processing in TeX. What am I doing wrong when implementing \FutureLetNoSpace?
The book TEX in Practice: Volume III: Tokens, Macros, by Stephan v. Bechtolsheim, really does a good job explaining TeX in detail. However, I ran into a stumbling block that I cannot solve using \tracingall alone.
Could someone demonstrate how I might use the code from the book. I also thought \FutureLetNoSpace is the user-level/document-level command. It seems to imitate \futurelet.
Code
Here I write the text "Hello there!", and inject my token checker immediately after the "t". It checks for the token "h". If found, it should yield a nice log message and "TRUE" in the document.
\documentclass{article}
\usepackage{fontspec}% xelatex
%\tracingall % all hell breaks loose
\catcode`@=11 % or \makeatletter to change category code of @ to 11 and temporarily to access kernel macro \@tabularcr
\long\def\DoLongFutureLet #1#2#3#4{%
\def\@FutureLetDecide{% hangs here
#1#2\@FutureLetToken% becomes \ifx#2\@FutureLetToken, which compares two expanded tokens
\def\@FutureLetNext{#3}%
\else
\def\@FutureLetNext{#4}%
\fi% the \@FutureLetNext gets grabbed into \futurelet below
\@FutureLetNext
}%
\futurelet\@FutureLetToken\@FutureLetDecide
}
\def\DoFutureLet #1#2#3#4{%
\DoLongFutureLet{#1}{#2}{#3}{#4}
} % identical to \DoLongFutureLet
\def\FutureLetNoSpace #1#2{%
\def\@FutureLetNoSpaceA{#1}% save arg
\def\@FutureLetNoSpaceB{#2}% save arg
\@FutureLetOne
}
\def\@FutureLetOne{%
\DoFutureLet{\ifx}{ }%
{\@FutureLetThree}{\@FutureLetOk}% \@FutureLetThree if it is a space token.
}
\edef\@FutureLetNoSpaceTemp{%
\def\noexpand\@FutureLetThree\space{\noexpand\@FutureLetOne}% force expansion of space into a space token and recall \@FutureLetOne
}
\@FutureLetNoSpaceTemp% why are we calling this macro here?
\def\@FutureLetOk{% called when no space is found
\expandafter\futurelet\@FutureLetTokenA\@FutureLetTokenB
}
\long\def\DoLongFutureLetNoSpace #1#2#3#4{%
\def\@FutureLetDecideNoSpace{% \@FutureLetTokenNoSpace is self-contained by this macro
#1#2\@FutureLetTokenNoSpace% becomes \ifx#2\@FutureLetTokenNoSpace, which compares two expanded tokens
\def\@FutureLetNextNoSpace{#3}%
\else
\def\@FutureLetNextNoSpace{#4}% whatever should get executed on match
\fi
\@FutureLetNextNoSpace
}
\FutureLetNoSpace{\@FutureLetTokenNoSpace}%
{\@FutureLetDecideNoSpace}% call \@FutureLetDecideNoSpace instead of \futurelet
}
\def\DoFutureLetNoSpace #1#2#3#4{%
\DoLongFutureLetNoSpace{#1}{#2}{#3}{#4}%
}
\catcode`@=12 % or \makeatother to restore category code of @ to 12
\begin{document}
Hello t\DoFutureLetNoSpace{\ifx}{h}{\typeout{\noexpand\@FutureLetTokenNoSpace value: \meaning\@FutureLetTokenNoSpace}}TRUE}{\typeout{\noexpand\@FutureLetTokenNoSpace value: \meaning\@FutureLetTokenNoSpace}FALSE}here!
\end{document}
Trace
The last four lines of the trace in the console:
\DoFutureLet #1#2#3#4->\DoLongFutureLet {#1}{#2}{#3}{#4}
#1<-\ifx
#2<-
#3<-\@FutureLetThree


\@ifnextchar– David Carlisle May 18 '18 at 13:04\afterassignmentlike in Manuel's answer. – Jonathan Komar May 18 '18 at 13:41\afterassignment? It's more secure to do\def\foo{\afterassignment\nextstep\let\gobble= }than\expandafter\def\expandafter\foo\space{\nextstep}. – Manuel May 18 '18 at 16:35Hello t\@ifnextchar{h}{TRUE}{FALSE}here!– Manuel May 18 '18 at 16:48