soul 包命令 \hl 无法处理转义空格

soul 包命令 \hl 无法处理转义空格

似乎\hlsoul 包中的命令无法处理逃逸空间。一个最小的非工作示例是

\documentclass{article}
\usepackage{xcolor, soul}

\colorlet{mycolor}{red!30}
\sethlcolor{mycolor}

\begin{document}

\hl{can\ we\ highlight}

\end{document}

错误信息是

包灵魂错误:重建失败。

一些帖子(例如,这里这里) 建议使用\mbox(或\hbox)来换行,或者使用\protect。虽然这些方法有效,但它们有一些缺点:

  • 如果\mbox使用,长文本将无法正常换行。
  • 如果\protect使用,文本的背景颜色将会消失。

如何更加优雅的解决这个问题?

编辑

Skillmon 分享的解决方案适用于英语,但不适用于中文。下面的 MWE 将对此进行说明。

\documentclass{ctexart}
\usepackage{xcolor, soul}
\usepackage{xparse}

\let\hlORIG\hl

\colorlet{mycolor}{red!30}
\sethlcolor{mycolor}

\ExplSyntaxOn
\tl_new:N \l_jdhao_hlx_tl
\RenewDocumentCommand \hl { +m }
  {
    \tl_set:Nn \l_jdhao_hlx_tl { #1 }
    \tl_replace_all:Nnn \l_jdhao_hlx_tl { \  } { ~ }
    \exp_args:NV \hlORIG \l_jdhao_hlx_tl
  }
\ExplSyntaxOff


\begin{document}

\hl{test\ test}  %% pass!
\hl{测试\ 测试} %% fail!

\end{document}

有趣的是,英文测试通过了,中文测试却失败了,错误信息是一样的。

答案1

使用辅助宏将所有显式空间(\)转换为普通空间,这是可能的(我重新定义了\hl宏,以便您不必更改任何其他内容):

\documentclass{article}
\usepackage{xcolor, soul}
\usepackage{xparse}
\let\hlORIG\hl

\colorlet{mycolor}{red!30}
\sethlcolor{mycolor}

\ExplSyntaxOn
\tl_new:N \l_jdhao_hlx_tl
\RenewDocumentCommand \hl { +m }
  {
    \tl_set:Nn \l_jdhao_hlx_tl { #1 }
    \tl_replace_all:Nnn \l_jdhao_hlx_tl { \  } { ~ }
    \exp_args:NV \hlORIG \l_jdhao_hlx_tl
  }
\ExplSyntaxOff

\begin{document}

\hl{can\ we\ highlight}

\end{document}

enter image description here

编辑:使用中文输入,但破坏自动连字功能(您仍然可以使用 进行手动连字\-):

\documentclass{ctexart}
\usepackage{xcolor, soul}
\usepackage{xparse}
%\usepackage[chinese,main=english]{babel}
\let\hlORIG\hl

\colorlet{mycolor}{red!30}
\sethlcolor{mycolor}

\ExplSyntaxOn
\tl_new:N \l_jdhao_hlx_tl
\RenewDocumentCommand \hl { m }
  {
    \tl_set:Nn \l_jdhao_hlx_tl { #1 }
    \tl_replace_all:Nnn \l_jdhao_hlx_tl { \  } { ~ }
    \regex_replace_all:nnN { [^\s\c{-}] } { \c{hbox} \0 } \l_jdhao_hlx_tl
    \exp_args:NV \hlORIG \l_jdhao_hlx_tl
  }
\ExplSyntaxOff

\begin{document}
% for comparison of hyphenating 
\rule{.9\textwidth}{1pt}possibility\ to\ highlight

\rule{.9\textwidth}{1pt}\hl{possibility\ to\ highlight}

\rule{.9\textwidth}{1pt}\hl{pos\-sibility\ to\ highlight}

\rule{.9\textwidth}{1pt}\hlORIG{possibility to highlight}

\hl{汤面}
\hl{汤面}
\hl{测试\ 测试}
%\hlORIG{汤面}

\end{document}

enter image description here

编辑2:

还有另一个版本允许您在 的参数中使用括号和其他内容\hl。请注意,此版本和第二个版本都会破坏 的参数中的数学运算\hl。您可以更改用作 的第一个参数的正则表达式来\regex_replace_all:nnN解决您面临的更多问题,我不愿意花更多时间去摆弄它。

\documentclass{ctexart}
\usepackage{xcolor, soul}
\usepackage{xparse}
%\usepackage[chinese,main=english]{babel}
\let\hlORIG\hl

\colorlet{mycolor}{red!30}
\sethlcolor{mycolor}

\ExplSyntaxOn
\tl_new:N \l_jdhao_hlx_tl
\RenewDocumentCommand \hl { m }
  {
    \tl_set:Nn \l_jdhao_hlx_tl { #1 }
    \tl_replace_all:Nnn \l_jdhao_hlx_tl { \  } { ~ }
    \regex_replace_all:nnN { \c[^CBEMTPUDA]\S } { \c{hbox} \0 } \l_jdhao_hlx_tl
    \exp_args:NV \hlORIG \l_jdhao_hlx_tl
  }
\ExplSyntaxOff

\begin{document}
% for comparison of hyphenating 
\rule{.9\textwidth}{1pt}possibility\ to\ highlight

\rule{.9\textwidth}{1pt}\hl{possibility\ to\ highlight}

\rule{.9\textwidth}{1pt}\hl{pos\-sibility\ \textbackslash{} to\ highlight}

\rule{.9\textwidth}{1pt}\hlORIG{possibility\textbackslash{} to highlight}

\hl{汤面}
\hl{汤面}
\hl{测试\ 测试}

\end{document}

相关内容