如何检查宏后的下一个字符是什么

如何检查宏后的下一个字符是什么

有没有办法检查宏后面的字符是什么?例如,假设我有一个\foo{...}格式化某些文本的命令,但如果下一个字符是逗号或分号,我想调整间距,如foo{...},。我查看了以下内容,但似乎无法让它适用于我的情况:根据宏后面的字符进行条件判断

我遇到的具体问题是,我正在使用一个下划线命令,省略了降部,改编自省略下划线(调整只是使下划线的深度和厚度与当前字体大小相匹配)。在大多数情况下,这种方法效果很好。但由于我喜欢使用 TeX Gyre Pagella 作为字体,逗号字符会进入下划线:

逗号碰到下划线

一个简单的解决方法是在打印下划线的文本后添加手册\kern 0.075em,可以在命令定义中,或者如果下一个字符是逗号则手动添加,这样可以产生更好看的结果:

手动调整修复

如果我将其添加\kern到命令中,它每次都会添加,这并不总是正确的(如果下一个字符是句点或空格,它会添加不必要的空格)。如果可能的话,我希望避免在下一个字符是逗号或分号时手动执行此操作---我希望能够检查宏后的字符是什么并确定是否以\kern这种方式添加。有办法做到这一点吗?

梅威瑟:

\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} 

答案1

您可以非常轻松地测试下一个字符。我还使代码更像expl3-。但如果您完全避免下划线,它会简单得多。

\documentclass{article}

\usepackage{fontspec} % For setting the typeface
\usepackage{xcolor}
\usepackage{soul}
\usepackage{xparse}

\setmainfont{TeX Gyre Pagella} % Set the typeface

\makeatletter

\newlength{\myfontsize}

\ExplSyntaxOn

\cs_new_protected:Npn \jigsaw_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}}
 }
\cs_new_protected:Npn \jigsaw_whiten:n #1
 {
  \int_step_function:nN {#1} \jigsaw_white_text:n
 }

\dim_new:N \jigsaw_fontsize_dim

\NewDocumentCommand{ \varul }{ D<>{10} +m }
 {
  \group_begin:
  \dim_set:Nn \jigsaw_fontsize_dim {\f@size pt}
  \setul{0.094\jigsaw_fontsize_dim}{0.047\jigsaw_fontsize_dim}
  \cs_set_protected:Npn \SOUL@uleverysyllable
   {
    \hbox_set:Nn \l_tmpa_box { \the\SOUL@syllable }
    \dim_compare:nTF { \box_dp:N \l_tmpa_box > 0pt }
     {% depth > 0
      \SOUL@ulunderline{\phantom{\the\SOUL@syllable}}%
      \jigsaw_whiten:n { #1 }
      \llap
       {
        \the\SOUL@syllable%
        \SOUL@setkern\SOUL@charkern%
       }
     }
     {% depth = 0
      \SOUL@ulunderline
       {
        \the\SOUL@syllable
        \SOUL@setkern\SOUL@charkern%
       }
     }
   }
  \ul{#2}%
  \group_end:
  \jigsaw_check_next:
 }

\cs_new_protected:Npn \jigsaw_check_next:
 {
  \peek_charcode:NTF , { \kern 0.075em } 
   {
    \peek_charcode:NT ; { \kern 0.075em }
   }
 }

\ExplSyntaxOff
\makeatother 

\begin{document}

testing hello world

testing \varul{hello} world

testing hello, world

testing \varul{hello}, world

testing hello; world

testing \varul{hello}; world

testing hello. world

testing \varul{hello}. world

\end{document} 

在此处输入图片描述

答案2

在 TeX 原始级别,您可以使用\futurelet原始命令。在下面的示例中,我没有使用 LaTeX 构造,因为它似乎比我们需要的更复杂。我们只想展示如何\futurelet工作。该线\vtop{...}忽略了框的深度,执行下划线。这种原始 TeX 构造在 LaTeX 中也有效:)。

重要的是\futurelet\next\utextA在宏的末尾。它保持以下字符(或空格)不变,但它确实\let\next= 此字符并运行。您可以通过此宏\utextA测试下一个字符。\ifx

\fontfam[pagella] % pagella font family if you are using OPmac or OpTeX

\def\utext#1{\leavevmode
   \vtop{\hbox{#1}\kern-\prevdepth \kern.2ex\hrule height.6pt}%
   \futurelet\next\utextA
}
\def\utextA{\ifx\next,\kern.075em \fi}

\utext{hello}, \utext{hello}.

\bye

答案3

前言:

  1. 你知道下划线很糟糕。如果逗号离前一个单词较远,那么……

  2. 如果逗号在 LaTeX 标记之后按原样出现,则解决方案有效;但是,通过这种方式无法检测到\varul{...}来自位于之后的宏调用扩展的逗号。\varul{...}

考虑到这些,你可以用它\peek_meaning:NTF来检测逗号无需沿途吃掉和丢弃太空代币。此应用程序的问题\@ifnextchar在于,您不希望在调用宏后忽略空格,但\@ifnextchar比较下一个非空白标记在输入流中将其添加到其第一个参数(使用\ifx),并吃掉在其间遇到的任何空格标记(\peek_meaning_ignore_spaces:NTF顺便说一下,会做同样的事情)。

我修改了和之间的部分代码\ExplSyntaxOn\ExplSyntaxOff以便更好地遵循expl3惯例(函数命名方案,使用\hbox_overlap_left:n而不是\llap\jigsaw_white_text:n用 声明,\cs_new_protected:Npn因为它不可扩展……)。\jigsaw_varul:nn不过,可以在 的定义中做更多这样的事情。

\documentclass{article}
\usepackage{fontspec} % For setting the typeface
\setmainfont{TeX Gyre Pagella} % Set the typeface
\usepackage{xcolor}
\usepackage{soul}
\usepackage{xparse}

\makeatletter
\ExplSyntaxOn
\newlength{\myfontsize}

\cs_new_protected:Npn \jigsaw_white_text:n #1
  {
    \fp_set:Nn \l_tmpa_fp { #1 * .01 }
    \hbox_overlap_left:n
      {
        \textcolor { white } { \the\SOUL@syllable }
        \hspace { \fp_to_decimal:N \l_tmpa_fp em }
      }
    \hbox_overlap_left:n
      {
        \textcolor { white } { \the\SOUL@syllable }
        \hspace { -\fp_to_decimal:N \l_tmpa_fp em }
      }
  }

\NewDocumentCommand \whiten { m }
  {
    \int_step_function:nnnN {1} {1} {#1} \jigsaw_white_text:n
  }

\cs_new_protected:Npn \jigsaw_varul:nn #1#2
  {
    \group_begin:
      \setlength{\myfontsize}{\f@size pt}
      \setul{0.094\myfontsize}{0.047\myfontsize}
      \cs_set:Npn \SOUL@uleverysyllable
        {
          \setbox0=\hbox{\the\SOUL@syllable}
          \ifdim \dp0>\z@ \scan_stop:
            \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}
    \group_end:
    \peek_meaning:NT , { \kern 0.075em \scan_stop: }
  }

% I changed '+m' into 'm' because I don't think it would be wise to underline
% several *whole* paragraphs.
\NewDocumentCommand \varul { D<>{10} m }
  {
    \jigsaw_varul:nn {#1} {#2}
  }
\ExplSyntaxOff
\makeatother

\begin{document}
  \noindent
  Testing \varul{hello}, world.\\
  Testing \varul{hello} world.
\end{document}

在此处输入图片描述

为了进行比较,如果不添加\kern,则会得到:

在此处输入图片描述

答案4

\noul这与其说是修复,不如说是一种解决方法。在这里,只需在和后续标点符号之间添加宏即可\varul{...}。它的作用是用白色划线标点符号,从而有效地消除重叠。

\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 
\newcommand\noul[1]{\textcolor{white}{\rlap{\varul{#1}}}#1}
\begin{document}
    \noindent testing \varul{hello}, world

    \noindent testing \varul{hello}\noul, world
\end{document} 

在此处输入图片描述

相关内容