If you need to do without Lua-extensions, you can make ! an active character which causes TeX to "look" at the meaning of the next token via \futurelet (or via \let and \afterassignment which would require you to write things down in a way where \let gets all the optional spaces which it discards according to the TeXBookTeXbook).
If you need to do without Lua-extensions, you can make ! an active character which causes TeX to "look" at the meaning of the next token via \futurelet (or via \let and \afterassignment which would require you to write things down in a way where \let gets all the optional spaces which it discards according to the TeXBook).
If you need to do without Lua-extensions, you can make ! an active character which causes TeX to "look" at the meaning of the next token via \futurelet (or via \let and \afterassignment which would require you to write things down in a way where \let gets all the optional spaces which it discards according to the TeXbook).
(Please take this answer for a moot / rather "academical" thing.)
If you need to do without Lua-extensions, you can make ! an active character which causes TeX to "look" at the meaning of the next token via \futurelet (or via \let and \afterassignment which would require you to write things down in a way where \let gets all the optional spaces which it discards according to the TeXBook).
If the meaning of the next token equals the meaning of an active character, you can (without loosing braces) have TeX catch that next token as an undelimited argument and then by means of macros that internally use active ! as argument delimiter have TeX check if that token really is an active ! and not some control sequence or active non-!-character \let equal to active !.
\documentclass{article} \usepackage{color}% \makeatletter \newcommand\UD@firstoftwo[2]{#1}% \newcommand\UD@secondoftwo[2]{#2}% \newcommand\UD@Exchange[2]{#2#1}% %%---------------------------------------------------------------------- %% Check whether argument is empty: %%...................................................................... %% \UD@CheckWhetherNull{<Argument which is to be checked>}% %% {<Tokens to be delivered in case that argument %% which is to be checked is empty>}% %% {<Tokens to be delivered in case that argument %% which is to be checked is not empty>}% %% %% The gist of this macro comes from Robert R. Schneck's \ifempty-macro: %% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J> %% %% (\romannumeral expansion was introduced by me in order to overcome the %% concerns and worries about improperly balanced \if..\else..\fi constructs.) \newcommand\UD@CheckWhetherNull[1]{% \romannumeral0\expandafter\UD@secondoftwo\string{\expandafter \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter \UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}% \UD@secondoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@firstoftwo}% }% \newcommand\UDtempa{} \begingroup \renewcommand\UDtempa[1]{% \endgroup %%----------------------------------------------------------------------------- %% Check whether brace-balanced argument starts with an active ! %%............................................................................. %% \UD@CheckWhetherLeadingExclam{<Argument which is to be checked>}% %% {<Tokens to be delivered in case <argument %% which is to be checked>'s 1st token is an %% active exclamation mark>}% %% {<Tokens to be delivered in case <argument %% which is to be checked>'s 1st token is not %% an active exclamation mark>}% \newcommand\UD@CheckWhetherLeadingExclam[1]{% \romannumeral0\UD@CheckWhetherNull{##1}% {\expandafter\expandafter\UD@firstoftwo{ }{}\UD@secondoftwo}% {\expandafter\UD@secondoftwo\string{\UD@CheckWhetherLeadingExclamB.##1#1}{}}% }% \newcommand\UD@CheckWhetherLeadingExclamB{}% \long\def\UD@CheckWhetherLeadingExclamB##1#1{% \expandafter\UD@CheckWhetherNull\expandafter{\UD@secondoftwo##1{}}% {\UD@Exchange{\UD@firstoftwo}}{\UD@Exchange{\UD@secondoftwo}}% {\UD@Exchange{ }{\expandafter\expandafter\expandafter\expandafter \expandafter\expandafter\expandafter}\expandafter\expandafter \expandafter}\expandafter\UD@secondoftwo\expandafter{\string}% }% \newcommand#1{\futurelet\UDtempa\@ChkSecondExclam}% \newcommand\@ChkSecondExclam{% \ifx\UDtempa#1\expandafter\UD@firstoftwo\else\expandafter\UD@secondoftwo\fi {\@ChkThirdExclam}% {!}% }% \newcommand\@ChkThirdExclam[1]{% \UD@CheckWhetherLeadingExclam{##1}{\futurelet\UDtempa\@FinishChkThirdExclam}{!!}% }% \newcommand\@FinishChkThirdExclam{% \ifx\UDtempa#1\expandafter\UD@firstoftwo\else\expandafter\UD@secondoftwo\fi {\@gobbleactiveexclam}{!!}% }% \newcommand\@gobbleactiveexclam[1]{% \UD@CheckWhetherLeadingExclam{##1}{% \par\bigskip \noindent\textcolor{red}{\mbox{!!! This is an admonition note. !!!}}% \par\bigskip }{!!!}% }% }% \catcode`\!=13 \UDtempa{!}%<-this does the \endgroup \makeatother \begin{document} \catcode`\!=13 hello world!!!hello world!!hello world!hello world!!!hello world \bigskip \let\misleading=! hello world!\misleading!hello world!!hello world!hello world\misleading!\misleading hello world \bigskip But there is the edge case of a token \verb|\let| equal to active \verb|!| being trailed by two active \verb|!| : hello world \misleading!! \end{document}