有没有办法检查宏后面的字符是什么?例如,假设我有一个\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
前言:
你知道下划线很糟糕。如果逗号离前一个单词较远,那么……
如果逗号在 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}