Is there a way to check what the character following a macro is? For instance, suppose I have a command \foo{...} that formats some text, but I want to adjust the spacing if the next character is a comma or a semicolon, as in foo{...},. I've looked at the following, but can't seem to get it to work for my case: Conditional based on character following the macro.
The specific issue that I have is that I'm using a command for underlines omitting the descenders, adapted from underline omitting the descenders (the adaptation just makes the depth and thickness of the underline scale to the current font size). In most cases, this works great. But since I like using TeX Gyre Pagella as my font, the comma character runs into the underline:
An easy fix is to add a manual \kern 0.075em after printing the underlined text, either in the command definition or manually if the next character is a comma, which produces this better-looking result:
If I add this \kern to the command, it adds it every time, which doesn't always look right (if the next character is a period or a space, it adds unnecessary space). And I'd like to avoid having to do this manually whenever the next character is a comma or a semicolon if possible---I'd like to be able to check what the character after the macro is and determine whether to add a \kern that way. Is there a way to do this?
MWE:
\documentclass{article}
\usepackage{fontspec} % For setting the typeface
\setmainfont{TeX Gyre Pagella} % Set the typeface
\usepackage{xcolor}
\usepackage{soul}
\usepackage{xparse}
\makeatletter
\newlength{\myfontsize}
\ExplSyntaxOn
\cs_new:Npn \white_text:n #1
{
\fp_set:Nn \l_tmpa_fp {#1 * .01}
\llap{\textcolor{white}{\the\SOUL@syllable}\hspace{\fp_to_decimal:N \l_tmpa_fp em}}
\llap{\textcolor{white}{\the\SOUL@syllable}\hspace{-\fp_to_decimal:N \l_tmpa_fp em}}
}
\NewDocumentCommand{\whiten}{ m }
{
\int_step_function:nnnN {1}{1}{#1} \white_text:n
}
\ExplSyntaxOff
\NewDocumentCommand{ \varul }{ D<>{10} +m }{%
\begingroup
\setlength{\myfontsize}{\f@size pt}%
\setul{0.094\myfontsize}{0.047\myfontsize}%
\def\SOUL@uleverysyllable{%
\setbox0=\hbox{\the\SOUL@syllable}%
\ifdim\dp0>\z@%
\SOUL@ulunderline{\phantom{\the\SOUL@syllable}}%
\whiten{#1}%
\llap{%
\the\SOUL@syllable%
\SOUL@setkern\SOUL@charkern%
}%
\else%
\SOUL@ulunderline{%
\the\SOUL@syllable%
\SOUL@setkern\SOUL@charkern%
}%
\fi}%
\ul{#2}%
\endgroup
}
\makeatother
\begin{document}
\noindent testing \varul{hello}, world
\end{document}






expl3. Isn't the present question an example of the type of macro for which\futureletwas intended? Nice article on\futureletis in this TUGBoat article – John Mar 31 '20 at 23:43\peek_meaning:NTF. Most of theexpl3code from the OP's question does other things, things which are unrelated to “inspecting the next character.” This answer can afford to be short because it simply removed these other things (that doesn't mean it is uninteresting!). – frougon Apr 01 '20 at 07:24expl3being quite unfairly blamed because people judge on overall code length (including spaces used for indentation and readability) without even understanding said code. And this happens very often on this site! One last thing: the\futureletprimitive is the cornerstone around which\@ifnextcharand\peek_meaning:NTF, as well as its sister functions, are built. – frougon Apr 01 '20 at 07:57