使 soulutf8 与 \(...\) 一起工作

使 soulutf8 与 \(...\) 一起工作

有没有什么简单的方法可以适应soulutf8LaTeX 数学模式分隔符?

截至目前,编译

\documentclass{article}
\usepackage{xcolor,soulutf8}
\begin{document}
Well, \hl{\(e^{i\pi}=-1\)}.
\end{document}

结果pdflatex

! Extra }, or forgotten $.
\SOUL@doword ...hskip \z@ \relax \the \SOUL@word }
                                                  \let \SOUL@errmsg \SOUL@er...
l.4 Well, \hl{\(e^{i\pi}=-1\)}
                              .
? X

让我们不要进入讨论哪一个更好:$...$或者\(...\);理所当然地认为排字员有他/她的理由选择第二对分隔符。

PS 正如 Heiko 指出的那样,同样的问题也存在于 soul 中(不幸的是,目前它似乎缺少一个活跃的维护者),其文档特别提到了这个限制。

答案1

可以解析 的参数,\hl用 替换该参数中的所有\(...\)内容$...$,然后使用 的原始定义\hl。我不完全确定以下内容是否完全稳定,尽管到目前为止它对我遇到的所有问题都有效。

编辑:通过删除从不匹配的情况(##3是点并且##2不是)来最小化代码,并且不在\(.\)替换的每次递归中包含标记,而只包含一次(这足够了,因为##3在递归的情况下它们存在)。

请注意,存在有效但奇怪的语法的情况(如果在 的参数之外使用\hl)会在这里失败:如果将和或$之一混合作为分隔符,则提供的代码会失败;尽管或是有效语法,但会失败,因为它们与 的所需参数模式不匹配。\(\)$a^b\)\(a^b$\hl{$a^b\)}\hl{\(a^b$}\hl@grab

\documentclass{article}
\usepackage{xcolor,soulutf8}
\usepackage[]{amsmath}
\usepackage{letltxmacro}
\LetLtxMacro\hlBAK\hl
\begingroup
\makeatletter
\catcode`.=4% changing catcode so the dot is never matched by ordinary text
\def\zz%
  {\endgroup
    \renewcommand\hl[1]
      {%
        \hl@grab##1\(.\)\endhl@grab
      }%
    \long\def\hl@grab##1\(##2\)##3\endhl@grab%
      {%
        \hl@grab@ifdot{##2}
          {\hlBAK{##1}}
          {\hl@grab##1$##2$##3\endhl@grab}%
      }%
    \long\def\hl@grab@ifdot##1%
      {%
        \ifx.##1%
          \expandafter\@firstoftwo
        \else
          \expandafter\@secondoftwo
        \fi
      }%
  }%
\zz
\begin{document}
Well, \hl{\(.e^{i\pi}=-1\) text \(2=2\).}
\end{document}

在此处输入图片描述

编辑:下面使用两个宏来提供替换,一个宏用于替换\(,另一个宏用于替换\)。 因此, 和 的奇怪(但技术上正确)语法\(a^b$$a^b\)应该作为 的参数\hl(尽管这种方式\hl{\(a^b\( text $a^b$}也可以工作,但显然不是正确的语法)。

\documentclass{article}
\usepackage{xcolor,soulutf8}
\usepackage[]{amsmath}
\usepackage{letltxmacro}
\LetLtxMacro\hlBAK\hl
\begingroup
\makeatletter
\catcode`.=4% changing catcode so the dot is never matched by ordinary text
\def\zz%
  {\endgroup
    \renewcommand\hl[1]
      {%
        \hl@grab@A##1\(.\endhl@grab
      }%
    \long\def\hl@grab##1\(##2\)##3\endhl@grab%
      {%
        \hl@grab@ifdot{##2}
          {\hlBAK{##1}}
          {\hl@grab##1$##2$##3\endhl@grab}%
      }%
    \long\def\hl@grab@A##1\(##2\endhl@grab%\)
      {%
        \hl@grab@ifdot{##2}
          {\hl@grab@B##1\).\endhl@grab}
          {\hl@grab@A##1$##2\endhl@grab}%
      }%
    \long\def\hl@grab@B##1\)##2\endhl@grab%
      {%
        \hl@grab@ifdot{##2}
          {\hlBAK{##1}}
          {\hl@grab@B##1$##2\endhl@grab}%
      }%
    \long\def\hl@grab@ifdot##1%
      {%
        \ifx.##1%
          \expandafter\@firstoftwo
        \else
          \expandafter\@secondoftwo
        \fi
      }%
  }%
\zz
\begin{document}
Well, \hl{\(.e^{i\pi}=-1\) text \(2=2\).}

\hl{$a^b\)}\hl{\(a^b$}

\hl{\(a \(b$ $}
\end{document}

作为etl一种更快但功能较少的替代方法,也可以替换l3regex大括号内的:\(\)

\documentclass{article}
\usepackage{xcolor,soul}
\usepackage{etl}
\NewCommandCopy\hlBAK\hl
\ExplSyntaxOn
\renewcommand\hl[1]
  {
    \exp_args:Ne \hlBAK
      {
        \etl_token_replace_all_deep:eNn
          { \etl_token_replace_all_deep:nNn {#1} \( { $ } }
          \) { $ }
      }
  }
\cs_generate_variant:Nn \etl_token_replace_all_deep:nNn { e }
\ExplSyntaxOff

\begin{document}
\hl{\emph{Some important \( m = ath \)}}
\end{document}

答案2

使用l3regex模块非常容易,并且适用于所有soul命令。想法是重新定义\SOUL@start,即根据调用宏的设置执行所有操作的宏。

\documentclass{article}
\usepackage{amsmath}
\usepackage{xcolor,soulutf8}

\ExplSyntaxOn
\tl_new:N \__l_SOUL_argument_tl
\cs_set_eq:Nc \SOUL_start:n { SOUL@start }
\cs_generate_variant:Nn \SOUL_start:n { V }
\cs_set_protected:cpn {SOUL@start} #1
 {
  \tl_set:Nn \__l_SOUL_argument_tl { #1 }
  \regex_replace_all:nnN
   { \c{\(} (.*?) \c{\)} } % look for \(...\) (lazily)
   { \cM\$ \1 \cM\$ }      % replace with $...$
   \__l_SOUL_argument_tl
  \SOUL_start:V \__l_SOUL_argument_tl % do the usual
 }
\ExplSyntaxOff

\begin{document}

Well, \hl{\(e^{i\pi}=-1\) text \(2=2\).}

Well, \ul{\(e^{i\pi}=-1\) text \(2=2\).}

Well, \so{\(e^{i\pi}=-1\) text \(2=2\).}

Well, \caps{\(e^{i\pi}=-1\) text \(2=2\).}

Well, \st{\(e^{i\pi}=-1\) text \(2=2\).}

\end{document}

在此处输入图片描述

答案3

程序包不支持使用\(和,来自\)soul文档

§3数学:

例子:\so{foo$x^3$bar}

允许使用数学公式,只要它们被 包围即可$

请注意,LaTeX 等效项\(...\)不起作用。

因此,解决方法$仍然是:

\hl{$e^{i\pi}=-1$}

相关内容