在下面的 MWE 中,代码:
\MyUl{abd \soulomit{\MyLink{www.google.com}{The Google}} ghi}
完全按照预期工作:
但是,当我尝试将其包装在宏中并使用时
\MyUl{abd \SoulOmitMyLink{www.google.com}{The Google} ghi}
我得到:
\SoulOmitMyLink 的参数有一个额外的}。
问题:
\SoulOmitMyLink
为了使其发挥作用,需要进行哪些改变?
笔记:
以下不是我当前用例的选项:
\MyUl{abd} \MyLink{www.google.com}{The Google} \MyUl{ghi}
代码:
\documentclass{article}
\usepackage{xcolor}
\usepackage{xparse}
\usepackage{soul}
\setulcolor{red}
\usepackage{hyperref}
\NewDocumentCommand{\MyUl}{%
s% #1 = starred variant
O{}% #2 = options, if any
m% #3 = mandatory param
}{%
\ul{#3}%
}%
\NewDocumentCommand{\MyLink}{%
s% #1 = starred variant (unused as of yet)
O{}% #2 = options, if any (unused as of yet)
m% #3 = link text
m% #4 = link target
}{%
\href{#3}{#4}%
}%
\NewDocumentCommand{\SoulOmitMyLink}{%
s% #1 = starred variant (unused as of yet)
O{}% #2 = options, if any (unused as of yet)
m% #3 = link text
m% #4 = link target
}{%
\IfBooleanTF{#1}{%
\soulomit{\MyLink*[#2]{#3}{#4}}%
}{%
\soulomit{\MyLink[#2]{#3}{#4}}%
}%
}%
\begin{document}
\MyUl{abd \soulomit{\MyLink{www.google.com}{The Google}} ghi}
%\MyUl{abd \SoulOmitMyLink{www.google.com}{The Google} ghi}% I want this
\end{document}
答案1
正如约瑟夫·赖特在他的回答包soul
不支持任意命令。以下示例显示了如何soul
扩展以支持。它挂接到处理数据的\SoulOmitMyLink
代码中。针对第二个参数为的情况插入代码。然后还测试第一个参数中的命令,看它是否为,并添加针对这种情况的特殊处理。\SOUL@docmd
\soulregister
\soulregister
8
\SoulOmitMyLink
\documentclass{article}
\usepackage{xcolor}
\usepackage{xparse}
\usepackage{soul}
\setulcolor{red}
\usepackage[colorlinks]{hyperref}
\NewDocumentCommand{\MyUl}{%
s% #1 = starred variant
O{}% #2 = options, if any
m% #3 = mandatory param
}{%
\ul{#3}%
}%
\NewDocumentCommand{\MyLink}{%
s% #1 = starred variant (unused as of yet)
O{}% #2 = options, if any (unused as of yet)
m% #3 = link text
m% #4 = link target
}{%
\href{#3}{#4}%
}%
\NewDocumentCommand{\SoulOmitMyLink}{%
s% #1 = starred variant (unused as of yet)
O{}% #2 = options, if any (unused as of yet)
m% #3 = link text
m% #4 = link target
}{%
\IfBooleanTF{#1}{%
\soulomit{\MyLink*[#2]{#3}{#4}}%
}{%
\soulomit{\MyLink[#2]{#3}{#4}}%
}%
}%
%%% Patch begin %%%
\usepackage{etoolbox}
\makeatletter
\patchcmd\SOUL@docmd{\else\ifx7}{%
\ifx\SoulOmitMyLink#2%
\SOUL@doword
\let\SOUL@@\@undefined
\NewDocumentCommand{\SOUL@@}{sO{}mm}{%
\IfBooleanTF{##1}{%
\soulomit{\SoulOmitMyLink*[##2]{##3}{##4}}%
}{%
\soulomit{\SoulOmitMyLink[##2]{##3}{##4}}%
}%
\SOUL@scan
}%
\fi
\else\ifx7%
}{%
\soulregister{\SoulOmitMyLink}{8}%
}{}
\makeatother
%%% Patch end %%%
\begin{document}
\MyUl{abd \soulomit{\MyLink{www.google.com}{The Google}} ghi}
\MyUl{abd \SoulOmitMyLink{www.google.com}{The Google} ghi}% I want this
\end{document}
(我已使用选项colorlinks
来hyperref
更清楚地表明您不希望有链接线。)
更新
- 根据 Peter Grill 的说法评论
\SoulOmitMyLink
不再需要该宏。 - 的重定义
\SOUL@@
扫描 的参数,\MyLink
不需要检查参数并调用。如果宏是通过 定义的,\MyLink
它可以直接将参数传递给\MyLink␣code
,即定义的内部宏。xparse
\NewDocumentCommand
更新后的更短的示例文件:
\documentclass{article}
\usepackage{xcolor}
\usepackage{xparse}
\usepackage{soul}
\setulcolor{red}
\usepackage[colorlinks]{hyperref}
\NewDocumentCommand{\MyUl}{%
s% #1 = starred variant
O{}% #2 = options, if any
m% #3 = mandatory param
}{%
\ul{#3}%
}%
\NewDocumentCommand{\MyLink}{%
s% #1 = starred variant (unused as of yet)
O{}% #2 = options, if any (unused as of yet)
m% #3 = link text
m% #4 = link target
}{%
\href{#3}{#4}%
}%
\usepackage{etoolbox}
\makeatletter
\patchcmd\SOUL@docmd{\else\ifx7}{%
\ifx\MyLink#2%
\SOUL@doword
\let\SOUL@@\@undefined
\NewDocumentCommand{\SOUL@@}{sO{}mm}{%
\csname MyLink code\endcsname{##1}{##2}{##3}{##4}%
\SOUL@scan
}%
\fi
\else\ifx7%
}{%
\soulregister{\MyLink}{8}%
}{}
\makeatother
\begin{document}
\tracingmacros=1
\MyUl{abd \soulomit{\MyLink{www.google.com}{The Google}} ghi}
\MyUl{abd \MyLink{www.google.com}{The Google} ghi}% I want this
\end{document}
答案2
该soul
包的工作原理是对输入进行逐个标记的分解,\soulomit
如果它出现在要分解的文本中,则可以绕过它。在您的示例中\soulomit
,不是出现在看到的输入中soul
。发生的事情是soul
提取\SoulOmitMyLink
并尝试在不带参数的情况下使用它,这就是错误出现的地方。底线:你不能隐藏\soulomit
在另一个宏中,因为soul
它将其视为文字而不是正在使用的内容(它实际上并没有做任何事物)。