我希望能够使用排队 逐字具有以下特征的文本:
- 换行符,例如由包
spverbatim
、命令提供\spverb
; - 彩色字体,由包裹提供
color
; - 突出显示(带有彩色背景的文字),类似于
soul
的包\hl
命令。
我所说的“内联”是指逐字部分在普通文本中(而不是具有自己段落的环境),而“逐字”是指诸如 等特殊符号\
不能_
被 LaTeX 解释。
我想要实现的效果是这样的(使用蓝色作为字体颜色,使用灰色作为突出显示颜色),但如果逐字部分需要换行,它应该允许换行。
我尝试过color
、 newverbs
和 spverbatim
等软件包soul
,但无法将上述所有功能结合起来。我最接近的方法是:
调整
spverbatim
的定义以spverb
包含彩色字体。这样我得到了特征 1 和 2,但没有得到特征 3:\gdef\myVerb{% \bgroup \color{fgColor}% \let\spverb@ve=\verb@egroup \def\verb@egroup{\spverb@ve\egroup}% \def\@xobeysp{\mbox{}\space}% \verb }
显然,
\myVerb
这种方式不能与soul
的包链接hl
使用\hl{\myVerb{verbatim text}}
(LaTeX 抱怨LaTeX Error: \verb illegal in command argument.
)。有什么办法可以将它们结合起来吗?例如,是否有类似于 的东西可以在上面的代码\hl
后面添加以实现突出显示?\color{fgColor}
使用
newverbs
包来定义\newverbcommand{\myVerb} {\color{fgColor}\begin{lrbox}{\verbbox}} {\end{lrbox}\colorbox{bgColor}{\usebox{\verbbox}}}
这会使字体变色
fgColor
并用 突出显示bgColor
,因此我得到 2 和 3;但不是 1:它不允许换行。我猜那是因为lrbox
或\colorbox
,但我不知道如何修改它以允许换行。有什么办法吗?我当然可以使用
\newcommand{\myVerb}[1]{{\ttfamily\color{fgcolor}{\hl{#1}}}}
按照包
hl
进行soul
操作。这样我得到了 1、2 和 3,但这不是逐字的,所以我必须转义所有特殊字符。
那么,有什么方法可以实现我想要的吗?是解决上述任何一种方法中缺少的内容,还是使用其他方法?也许有一个现成的软件包可以支持我想要的所有功能?
答案1
虽然不完全符合原作者的要求,但可能已经足够了。首先,它使用\detokenize
,而不是verbatim
,这意味着 1) 括号{}
必须匹配,2) 符号%
仍被解释为注释,3) 在所有去标记化的宏名称后插入一个空格,4) 井号的#
数量加倍。
另外,我只是\allowbreak
在单词之间,使用\fboxsep
颜色框来创建单词间空间。
已编辑以用于\ttfamily
宏\mytokens
。
\strut
已编辑以修复行高,因为和的组合\fboxsep
超出了允许的基线跳过预算。
最初,我没有使用单词间空格,而是允许\fboxsep
就足够了。但这会导致边距问题,因为没有东西可以拉伸。因此,在重新编辑时,我在0pt minus \fboxsep
单词之间插入了一个 的空格,这似乎允许足够的压缩来解决边距问题,同时仍在单词之间留出足够的空间(否则2\fboxsep
)。
在重新编辑时,我还重新排列了\grayspace
和,以便在尾随标点符号之前不会出现换行符。allowbreak
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{xcolor}
\newcommand\mytokens[1]{\mytokenshelp#1 \relax\relax}
\def\mytokenshelp#1 #2\relax{\allowbreak\grayspace\tokenscolor{#1}\ifx\relax#2\else
\mytokenshelp#2\relax\fi}
\newcommand\tokenscolor[1]{\colorbox{gray!20}{\textcolor{blue}{%
\ttfamily\mystrut\smash{\detokenize{#1}}}}}
\def\mystrut{\rule[\dimexpr-\dp\strutbox+\fboxsep]{0pt}{%
\dimexpr\normalbaselineskip-2\fboxsep}}
\def\grayspace{\hspace{0pt minus \fboxsep}}
\begin{document}
Here is my leading text
\mytokens{Fie Fi Fo Fum, I smell the $#@*& blood of an \Englishman.
I will continue this text to observe the margins.
Fie Fi Fo Fum, I smell the \textbf{blood} of an Englishman.}
and my trailing text. And here is more text to find where the margin end
really should be.
Standard MATLAB formats are allowed, such as \mytokens{1.2}, \mytokens{-.2i},
\mytokens{1.}, \mytokens{-1.2e3}, \mytokens{+.2E-3j}. \mytokens{i} and
\mytokens{j} denote...
\end{document}
补充
为了响应评论请求,这里有一个将背景颜色作为可选参数的版本。
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{xcolor}
\newcommand\mytokens[2][gray!20]{\mytokenshelp{#1}#2 \relax\relax}
\def\mytokenshelp#1#2 #3\relax{\allowbreak\grayspace\tokenscolor[#1]{#2}\ifx\relax#3\else
\mytokenshelp{#1}#3\relax\fi}
\newcommand\tokenscolor[2][gray!20]{\colorbox{#1}{\textcolor{blue}{%
\ttfamily\mystrut\smash{\detokenize{#2}}}}}
\def\mystrut{\rule[\dimexpr-\dp\strutbox+\fboxsep]{0pt}{%
\dimexpr\normalbaselineskip-2\fboxsep}}
\def\grayspace{\hspace{0pt minus \fboxsep}}
\begin{document}
Here is my leading text
\mytokens{Fie Fi Fo Fum, I smell the $#@*& blood of an \Englishman.
I will continue this text to observe the margins.
Fie Fi Fo Fum, I smell the \textbf{blood} of an Englishman.}
and my trailing text. And here is more text to find where the margin end
really should be.
Standard MATLAB formats are allowed, such as \mytokens{1.2},
\mytokens{-.2i}, \mytokens[red!40]{1.}, \mytokens{-1.2e3},
\mytokens{+.2E-3j}. \mytokens[cyan!30]{i} and
\mytokens[green!20]{j} denote...
\end{document}
答案2
正如我在评论中提到的那样史蒂文的回答,我最终编写了一个 Matlab 函数来转换例如
\myVerb+abc$\+
进入
\myVerb{abc\$\textbackslash }
即转义字符并用作{}
分隔符。这样我就可以处理verbatim
并使用
\newcommand{\myVerb}[1]{{\ttfamily\color{fgcolor}{\hl{#1}}}}
即我的问题中的第三个“解决方案”。它并不理想,但它有效;我只需要在 tex 文件上运行我的 Matlab 函数进行转换,然后再使用 LaTeX 进行编译。
这是我使用的 Matlab 函数。
function convert_myVerb(fileName)
% Converts \myVerb+...+ or \myVerb|...| into: \myVerb{...} with escaped characters
fid = fopen(fileName);
s = fread(fid);
fclose(fid);
s = char(s.');
ind = regexp(s, '(?<=\\myVerb).');
unique(s(ind)); % characters found after "\myVerb", as a check. I only used + and |
[ini, fin] = regexp(s, '\\myVerb([+|]).*?\1'); % all matching substrings
if isempty(ini)
disp('Nothing needs to be converted. Converted file not written')
else
disp([num2str(numel(fin)) ' substrings identified for conversion'])
y = s(1:ini(1)-1); % output. Initiallize
% \# \$ \% \& \textbackslash{} \textasciicircum {}\_ \{ \} \textasciitilde{}
ini(end+1) = numel(s)+1;
for n = 1:numel(fin)
t = regexprep(s(ini(n)+6:fin(n)-1), '\\', '\\textbackslash '); % This has
% to go first, so that it won't convert \ introduced to escape other
% characters. No {} here, because they would get converted into \{\} later
t = regexprep(t, '[#$%&_{}]', '\\$0');
t = regexprep(t, '\^', '\\textasciicircum{}');
t = regexprep(t, '~', '\\textasciitilde{}');
t = ['\myVerb{' t '}'];
y = [y t s(fin(n)+1:ini(n+1)-1)];
end
fid = fopen(fileName, 'w');
count = fwrite(fid, y);
fclose(fid);
if count
disp('Converted file successfully written')
end
end