2

In my attempt to learn expl3 programming, I've hacked together a function to fake "smallcaps" by looping through a token list and enlarging any tokens that are capital letters. The code currently "works", but I know I have jumped through more hoops than I needed to. My question is: how can I rewrite the code to better use what expl3 has to offer?

\ExplSyntaxOn
\cs_generate_variant:Nn \tl_if_eq:nnTF { VV }
\cs_generate_variant:Nn \tl_to_str:n { e }

\DeclareDocumentCommand\fakesmallcaps{m} {
    \tl_new:N \__orig_tl
    \tl_new:N \__modified_tl

    \tl_set:Nn \__orig_tl {#1}
    % Put all the spaces in groups so they don't get filtered out when we map over them.
    \tl_replace_all:Nnn \__orig_tl { ~ } { {~} }

    \tl_set:Nn \__modified_tl {
        \tl_map_inline:Nn \__orig_tl {
            \tl_set:Nn \__current_tl {##1}
            \tl_set:NV \__uppercasecurrent_tl {\tl_upper_case:n {##1}}

            \str_set:Nx \__orig_str {\tl_to_str:e {\__current_tl}}
            \str_set:Nx \__uppercasecurrent_str {\tl_to_str:e {\__uppercasecurrent_tl}}

            \tl_if_eq:VVTF {\__orig_str} {\__uppercasecurrent_str} {
                {\Large \__orig_str}
            }{
                \__uppercasecurrent_str
            }
        }
    }

    \tl_use:N \__modified_tl
}
\ExplSyntaxOff

\fakesmallcaps{This Is Cool}

I am aware of solutions using regular expressions here, but I really want to "loop through the tokens". I have also tried and failed to create an \bool__iscapital:n function macro that can be used inside of \bool_if:nTF, so guidance on that would be appreciated! It would also be a huge plus if I could do something like \fakesmallcaps{{\color{blue}The} Windy Road} and have the color preserved.

1 Answers1

1

Here, instead of using expl3, I use my tokcycle package to cycle through the tokens. To each appropriate token, I apply \fauxsctok, which mimics my approach in the cited question, Fake small caps with XeTeX/fontspec?.

The advantage of using tokcycle to the approach in the referenced question is that macros and spaces can be echoed without trying to apply small caps to them. Further, the small-capping can extend into groups within the environment.

The difficulty is that one cannot blindly small-cap each cat-11 token, but only those that are to be typeset. So, in \color{blue}, we wish to avoid applying typesetting commands to blue, since it is a macro argument and not text for typesetting!

In general, TeX has no way of knowing if (and how many) arguments are associated with a macro. So, here, I have to program the list of macro names that might appear in the environment, requiring a non-typesettable argument. In this implementation, I limit that list to macros requiring the "protection" of a single argument. The macros programmed into the current list are \color and \textcolor. While the latter takes two arguments, only the first argument needs to be protected from typesetting.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{xcolor,tokcycle,graphicx}
\def\Hscale{.83}\def\Vscale{.72}\def\Cscale{1.00}
\newif\ifskiparg
\newcommand\fauxsctok[1]{%
  \ifnum`#1>``\ifnum`#1<`\{\scalebox{\Hscale}[\Vscale]{\uppercase{#1}}\else%
    \scalebox{\Cscale}[1]{#1}\fi\else\scalebox{\Cscale}[1]{#1}\fi}
\tokcycleenvironment\fauxsc
  {\addcytoks{\fauxsctok{##1}}}% CHARACTER DIRECTIVE
  {\ifskiparg\addcytoks{##1}\else\processtoks{##1}\fi\aftergroup
    \skipargfalse}% GROUP DIRECTIVE
  {\addcytoks{##1}%
   \ifx\color##1\skipargtrue\fi
   \ifx\textcolor##1\skipargtrue\fi
  }% MACRO DIRECTIVE
  {\addcytoks{##1}}% SPACE DIRECTIVE
\begin{document}
\fauxsc{\color{blue}The} Windy Road

\textcolor{blue}{The} Windy Road\endfauxsc
\ and back to normal.
\end{document}

enter image description here

The fauxsc pseudo-environment builds a token list (\cytoks) by cycling through the tokens of the environment. Characters (things not catcode 0,1,2,10) have \fauxsctok applied to them (inside the \cytoks token list being built).

If a Group is encountered when \ifskiparg is set true, then the group is merely echoed to \cytoks without alteration. However, when \ifskiparg is false, each token of the group will be processed through the token cycle. In either event, \ifskiparg is reset false after the group concludes.

Macros are merely echoed into \cytoks. However, then the macro name has to be compared against the programmed list to see whether \ifskiparg needs to be set true. Finally,

Spaces that are encountered are merely echoed into \cytoks.