使用应用间接格式的灵魂(使用带有 2 个参数的宏,其中一个可能是可选的)

使用应用间接格式的灵魂(使用带有 2 个参数的宏,其中一个可能是可选的)

这是使用间接格式的 Soul,其中确定使用\soulregister允许soul在参数中包含字体切换宏(特别是\ul在这种情况下)。但是,如果宏有多个参数,我就无法让它工作。

单个参数:\ApplyStyleA

如果宏有一个强制参数,这似乎可以正常工作,如使用间接格式的 Soul

两个必需参数:\ApplyStyleB

但是,如果宏有两项强制性规定参数,然后我得到:

额外的 },或者被遗忘的 \endgroup

两个参数(一个可选):\ApplyStyleC

或者,对于存在的情况一个可选的参数和一项强制性规定参数,我得到:

TeX 容量超出,抱歉 [输入堆栈大小=5000]

笔记:

  • 下面的 MWE 编译正常,因为有问题的两行被注释掉了。因此,需要取消注释其中一行才能重现问题。

代码:

\documentclass{article}
\usepackage{xparse}
\usepackage{xcolor}
\usepackage{soul}
\usepackage{xspace}


%% ----------------------------------------------------------------
%%                https://tex.stackexchange.com/questions/36894/
%%                    underline-omitting-the-descenders
%%
%%
\makeatletter
\ExplSyntaxOn
    \cs_new:Npn \white_text:n #1
      {
        \fp_set:Nn \l_tmpa_fp {.01}
        \fp_mul:Nn \l_tmpa_fp {#1}
        \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<>{5} O{0.2ex} O{0.1ex} +m } {%
\begingroup
\setul{#2}{#3}%
\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{#4}%
\endgroup
}%
\makeatother
%% ----------------------------------------------------------------


\newcommand{\ApplyStyleA}[1]{\textit{#1}}
\soulregister\ApplyStyleA{1}

\newcommand{\ApplyStyleB}[2]{\textit{#1}}
\soulregister\ApplyStyleB{2}

\newcommand{\ApplyStyleC}[2][]{\textit{#2}}
\soulregister\ApplyStyleC{2}

\begin{document}
This one works just fine:
\varul{\ApplyStyleA{special text}\xspace}%

\medskip
These one leads to ``Extra \}, or forgotten \verb|\endgroup|."
%\varul{\ApplyStyleB{special text}{second paramater}\xspace}%

\medskip
This one leads to ``TeX capacity exceeded, sorry [input stack size=5000]"
%\varul{\ApplyStyleC[first optional paramater]{special text}\xspace}%
\end{document}

答案1

所使用的数字\soulregister本身并不指定参数的数量。

它用作标识符。数字78和分别9用于\textsuperscript(“和类似”)\footnote和重音符号。

根据两个参数的作用\ApplyStyleB(它们都是需要排版的内容还是其中一个用于其他目的),有多种可能的解决方案。

对于宏来说也是如此,\ApplyStyleC尽管这更难修复,因为默认值#1是隐藏的。

\ApplyStyleBa请注意简单扩展(type ) 与扩展内容之间的区别3,简单扩展会将下划线应用于所有内容\ApplyStyleBa\ApplyStyleBb宏使用正确的宏方式1,并将souling 仅应用于其参数 (type 2)。

类型4包括一个可选参数。如果您希望soul的效果也影响默认可选参数(在您的情况下为空字符串,在我的情况下为I'm the default!),则应提取所述默认文本并将其用于 的重新定义\SOUL@@

但是,如果您使用可选参数不是为了排版,而是为了在其他地方使用,则需要采用不同的方法。一些宏(\minipage\parbox)将其第一个强制参数用作维度,将可选参数用作对齐。对于这两者,都不应应用下划线。

代码

\documentclass{article}
\usepackage{xparse}
\usepackage{xcolor}
\usepackage{soul}
\usepackage{xspace}


%% ----------------------------------------------------------------
%%                http://tex.stackexchange.com/questions/36894/
%%                    underline-omitting-the-descenders
%%
%%
\makeatletter
\ExplSyntaxOn
    \cs_new:Npn \white_text:n #1
      {
        \fp_set:Nn \l_tmpa_fp {.01}
        \fp_mul:Nn \l_tmpa_fp {#1}
        \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<>{5} O{0.2ex} O{0.1ex} +m } {%
\begingroup
\setul{#2}{#3}%
\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{#4}%
\endgroup
}%

\def\SOUL@docmd#1#2{%
    \ifx9#1%
        \def\SOUL@@{\SOUL@addgroup{#2}}%
    \else\ifx8#1%
        \SOUL@doword
        \def\SOUL@@##1{%
            \SOUL@token={\footnotemark}%
            \SOUL@everytoken
            \SOUL@syllable={\footnotemark}%
            \SOUL@everysyllable
            \footnotetext{##1}%
            \SOUL@doword
            \SOUL@scan
        }%
    \else\ifx7#1%
        \SOUL@doword
        \def\SOUL@@##1{%
            \SOUL@token={#2{##1}}%
            \SOUL@everytoken
            \SOUL@syllable={#2{##1}}%
            \SOUL@everysyllable
            \SOUL@doword
            \SOUL@scan
        }%
    \else\ifx1#1%
        \SOUL@doword
        \def\SOUL@@##1{%
            #2{\protect\SOUL@do{##1}}%
            \SOUL@scan
        }%
    \else\ifx2#1%
        \SOUL@doword
        \def\SOUL@@##1##2{%
            #2{\protect\SOUL@do{##1}}{\protect\SOUL@do{##2}}%
            \SOUL@scan
        }%
    \else\ifx3#1%
        \SOUL@doword
        \def\SOUL@@{\expandafter\SOUL@scan#2}%
    \else\ifx4#1
        \SOUL@doword
        \def\@tempa{\renewcommand\SOUL@@[2][}%
        \expandafter\expandafter\expandafter\@tempa\expandafter\SOUL@get@optional@argument#2]{#2[\protect\SOUL@do{##1}]{\protect\SOUL@do{##2}}}%
    \else
        \SOUL@doword
        #2%
        \let\SOUL@@\SOUL@scan
    \fi\fi\fi\fi\fi\fi\fi
    \SOUL@@
}
\def\SOUL@get@optional@argument#1#2#3#4{#4}%
\makeatother
%% ----------------------------------------------------------------


\newcommand{\ApplyStyleA}[1]{\textit{#1}}
\soulregister\ApplyStyleA{1}

\newcommand{\ApplyStyleBa}[2]{\textit{#1} affected? (#2)}
\soulregister\ApplyStyleBa{2}
\newcommand{\ApplyStyleBb}[2]{\textit{#1} affected? (#2)}
\soulregister\ApplyStyleBb{3}

\newcommand{\ApplyStyleC}[2][I'm the default!]{\textit{#2} (I'm not affected again) [#1]}
\soulregister\ApplyStyleC{4}

\begin{document}
\varul{\ApplyStyleA{special text}\xspace}%

\medskip
\varul{\ApplyStyleBa{special text}{second paramater}\xspace}\par %
\varul{\ApplyStyleBb{special text}{second paramater}\xspace}% only expansion

\medskip
\varul{\ApplyStyleC[first optional paramater]{special text}\xspace}\par
\varul{\ApplyStyleC{special text}\xspace}%
\end{document}

输出

在此处输入图片描述

相关内容