How to capitalize letter (using \uppercase) that has been assigned to \let (or to \def)?
\uppercase
and \lowercase
- do only apply to explicit character tokens.
- do not trigger expansion after finding
- either the left brace
{
of the⟨balanced text⟩
that is to be uppercased/lowercased. - or the single not-brace-nested unexpandable non-
⟨filler⟩
-token that is to be uppercased/lowercased. (⟨filler⟩
denotes a sequence of\relax
and/or explicit/implicit spaces.)
- either the left brace
When using \csname..\endcsname
instead of using the control-word-token directly, you can probably do somehing like this:
\let\zTest=t
\let\ZTEST=T
\let\ztest=t
\def\Ztest{t}
% \zTest and \ZTEST and \ztest are implicit character tokens.
% Let`s use uppercased/lowercased \csname..\endcsname for selecting
% which implicit character token to use:
\csname zTest\endcsname
\uppercase{\csname zTest\endcsname}%
\lowercase{\csname zTest\endcsname}%
% \Ztest is a macro, expanding to explicit character token "t".
% You can use \expandafter for triggering "toplevel-expansion"
% while \uppercase/\lowercase still searches the "{" that
% marks the begin of the balanced text:
\Ztest
\uppercase\expandafter{\Ztest}%
\lowercase\expandafter{\Ztest}%
% With more recent TeX-engines, where \expanded is available,
% you can do:
% \lowercase\expandafter{\expanded{\Ztest}}%
% "toplevel-expansion" of \expanded<general text> will deliver
% "total expansion" of the content of the <general text>'s
% <balanced text>
\bye
The following is a macro that is able to uppercase a let token if it was let to a letter (e.g., with \let\foo=t
assuming standard category codes). It does so by first checking whether the magic tokens the letter
are the start of the meaning of the passed in token, and then grabs the letter following it and uppercases that, if the meaning doesn't seem to be a letter then the input is output. The test is only applied to the first token of the input, but it is not checked whether the input is only a single token (so \uppercaselettoken{t more stuff}
would see that t
is a letter but passes more stuff
to \uppercase
, too. So this is only a proof-of-concept not a stable implementation.
\documentclass[]{article}
\let\foo=t
\makeatletter
\def\uppercaselettoken@ifletter#1%
{%
\def\uppercaselettoken@ifletter##1#1##2\end
{%
\if\relax\detokenize{##2}\relax
\expandafter\@secondoftwo
\else
\if\relax\detokenize{##1}\relax
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\expandafter\@firstoftwo}
{\expandafter\@secondoftwo}%
\fi
}%
\def\uppercaselettoken@letter#1##1\end{\uppercase{##1}}%
}
\expandafter\uppercaselettoken@ifletter\expandafter{\detokenize{the letter }}
\long\edef\uppercaselettoken@#1#2%
{%
\noexpand\uppercaselettoken@ifletter#1\detokenize{the letter }\noexpand\end
{%
\noexpand\uppercaselettoken@letter#1\noexpand\end
}%
{#2}% not a letter, no uppercasing
}
\newcommand\uppercaselettoken[1]
{%
\expandafter\uppercaselettoken@\expandafter{\meaning#1}{#1}%
}
\makeatother
\usepackage{unravel}
\begin{document}
\uppercaselettoken{\foo}
\uppercaselettoken{t}% works too
\end{document}
While it is possible to implement something that interrogates the meaning of unexpandable tokens, recognises implicit characters defined by \let
and look up their upper case form, there are very few reasons to get into that situation, using \def
(or \renewcommand
) is the documented LaTeX interface and is essentially trivial to make work as you just have to expand the macros before uppercasing, and it works out of the box using LaTeX:
\documentclass{article}
\begin{document}
\let\zza=a
\let\zzb=b
\let\zzc=c
1 \MakeUppercase{\zza\zzb\zzc}
\renewcommand\zza{a}
\renewcommand\zzb{b}
\renewcommand\zzc{c}
2 \MakeUppercase{\zza\zzb\zzc}
\end{document}