这是我上一个问题的补充对单词的第 n 个字符应用命令,我需要为这样的一系列字符着色,\ColorRgChar{2-5}{examination}
即为单词的第二个字符到第五个字符着色。
如果第一个数字大于单词的长度,则不进行着色。
字符着色应该用一个命令一次性完成,\textcolor
而不是\textcolor
每个字符都用一个命令。@David Carlisle
\documentclass{article}
\usepackage{xcolor}
\begin{document}
\makeatletter
\def\ColorRgChar#1#2{\xColorRgChar{#1}#2\@empty}
\def\xColorRgChar#1#2{\ifnum\ifx\@empty#21\else#1\fi=1 \textcolor{red}{#2}\expandafter\@gobbletwo
\else#2\fi\xColorRgChar{\numexpr#1-1\relax}}
\makeatother
\ColorRgChar{2}{examination}
%\ColorRgChar{2-5}{examination} % desired macro
\end{document}
答案1
代码的主要部分是管理输入。第二个参数可以是
- 一个数字,表示只有一个字符需要着色;
-
,意思是给一切事物涂上颜色;m-
,表示从第m个字符到末尾的颜色;-n
,表示从开始到第 n 个字符的颜色;m-n
,表示从第 m 个字符到第 n 个字符的颜色。
\documentclass{article}
\usepackage{xparse,xcolor}
\ExplSyntaxOn
\NewDocumentCommand{\colorrange}{>{\SplitArgument{1}{-}}mm}
{
% #1 is passed as two braced arguments
\salim_colorrange:nnn #1 { #2 }
}
\cs_new_protected:Nn \salim_colorrange:nnn
{
% let's analyze the first two args
\tl_if_novalue:nTF { #2 }
{% no hyphen in the argument
\__salim_colorrange:nnn { #1 } { #1 } { #3 }
}
{
\bool_lazy_or:nnTF { \tl_if_blank_p:n { #1 } } { \tl_if_blank_p:n { #2 } }
{% argument is -n or m- or -
\tl_if_blank:nTF { #1 }
{
\tl_if_blank:nTF { #2 }
{% argument is -
\textcolor{red}{#3}
}
{% argument is -n
\__salim_colorrange:nnn { 1 } { #2 } { #3 }
}
}
{% argument is m-
\__salim_colorrange:nnn { #1 } { -1 } { #3 }
}
}
{% argument is m-n
\__salim_colorrange:nnn { #1 } { #2 } { #3 }
}
}
}
\cs_new_protected:Nn \__salim_colorrange:nnn
{
\int_compare:nTF { #1 > #2 > 0 }
{
#3
}
{
\tl_range:nnn { #3 } { 1 } { #1 - 1 }
\textcolor{red}{ \tl_range:nnn { #3 } { #1 } { #2 } }
\tl_range:nnn { #3 } { #2 + 1 } { -1 }
}
}
\ExplSyntaxOff
\begin{document}
\colorrange{4}{examination} (4)
\colorrange{4-6}{examination} (4-6)
\colorrange{1-3}{examination} (1-3)
\colorrange{-3}{examination} (-3)
\colorrange{4-11}{examination} (4-11)
\colorrange{4-}{examination} (4-)
\colorrange{-}{examination} (-)
\colorrange{5-4}{examination} (5-4)
\colorrange{12-4}{examination} (12-4)
\colorrange{12-}{examination} (12-)
\colorrange{-15}{examination} (-15)
\end{document}
允许输入错误。可以轻松添加使用可选参数更改颜色。
答案2
\documentclass{article}
\usepackage{xcolor}
\newcounter{pft}
\begin{document}
\makeatletter
\def\pft#1-#2;{\edef\lower@pft{\the\numexpr#1-1}\edef\upper@pft{\the\numexpr#2+1}}%
\def\ColorRgChar#1#2{\pft#1;%
\setcounter{pft}{0}%
\@tfor\next:=#2\do{\stepcounter{pft}%
\ifnum\value{pft}>\lower@pft
\ifnum\value{pft}<\upper@pft
\textcolor{red}{\next}%
\else
\next
\fi
\else
\next
\fi
}}%
\makeatother
\ColorRgChar{2-5}{examination} \ColorRgChar{4-7}{hibernation} \ColorRgChar{1-3}{catcode}
\end{document}
或者没有明确的反驳。
\documentclass{article}
\usepackage{xcolor}
\colorlet{SalimBouColor}{red}
\begin{document}
\makeatletter
\def\pft#1-#2;{\edef\lower@pft{\the\numexpr#1-1}\edef\upper@pft{\the\numexpr#2+1}}%
\def\ColorRgChar#1#2{\pft#1;%
\edef\n@pft{0}%
\@tfor\next:=#2\do{\edef\n@pft{\the\numexpr\n@pft+1}%
\ifnum\n@pft>\lower@pft
\ifnum\n@pft<\upper@pft
\textcolor{SalimBouColor}{\next}%
\else
\next
\fi
\else
\next
\fi
}}%
\makeatother
\ColorRgChar{2-5}{examination} \ColorRgChar{4-7}{hibernation} \ColorRgChar{1-3}{catcode}
This includes, of course, your case of just coloring one character: \ColorRgChar{3-3}{examination}
\colorlet{SalimBouColor}{blue}%
\ColorRgChar{2-5}{examination}
\end{document}
或者不将单个字符换行到\textcolor
。
\documentclass{article}
\usepackage{xcolor}
\colorlet{SalimBouColor}{red}
\begin{document}
\makeatletter
\def\pft#1-#2-#3;{\edef\lower@pft{#1}\edef\upper@pft{#2}}%
\def\ColorRgChar#1#2{\pft#1-0-0;%
\ifnum\upper@pft=0
\edef\upper@pft{\lower@pft}%
\fi
\colorlet{orig@color}{.}%
\edef\n@pft{0}%
\@tfor\next:=#2\do{\edef\n@pft{\the\numexpr\n@pft+1}%
\edef\tmp@pft{}%
\ifnum\n@pft=\lower@pft
\color{SalimBouColor}%
\fi
\next
\ifnum\n@pft=\upper@pft
\color{orig@color}%
\fi
}}%
\makeatother
\ColorRgChar{2-5}{examination} \ColorRgChar{4-7}{hibernation} \ColorRgChar{1-3}{catcode}
This includes, of course, your case of just coloring one character: \ColorRgChar{3}{examination}
\colorlet{SalimBouColor}{blue}%
\ColorRgChar{2-5}{examination}
\end{document}
答案3
这是一个基于 LuaLaTeX 的解决方案。它提供了一个执行实际工作的 Lua 函数和一个名为 的 LaTeX 实用程序宏\ColorRangeChar
,该宏将其三个参数传递给 Lua 函数。这三个参数是 (a) 和 (b) 整数,它们指示要着色的第一个和最后一个字符的位置,以及 (c) 单词本身。
此解决方案满足了 OP 的要求,即“应使用单个命令一次性完成字符着色\textcolor
”。 Lua 函数设置为处理非 ASCII 字符,例如öäüßÖÄÜ
。 当然,如果第一个数字超出单词中的字符数,则不会进行着色。
% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{xcolor}
%% set up the Lua function that does the actual work:
\directlua{
function color_range_char ( m , n , s )
local t
t = unicode.utf8.sub(s,1,m-1) ..
"\string\\textcolor{red}{" .. unicode.utf8.sub(s,m,n) .. "}" ..
unicode.utf8.sub(s,n+1)
tex.sprint ( t )
end
}
%% set up a LaTeX macro that invokes the Lua function:
\newcommand\ColorRangeChar[3]{\directlua{color_range_char(#1,#2,"#3")}}
\begin{document}
\ColorRangeChar{3}{5}{examination}
\ColorRangeChar{2}{4}{öäüßÖÄÜ}
\end{document}
答案4
以下是 egreg 第一个代码的扩展这个答案支持以下形式的范围分钟-最大限度, 在哪里分钟如果没有给出,则表示“开始”,并且最大限度如果没有提供,则表示“结束”。我的代码用于l3regex
解析范围表达式。
\documentclass{article}
\usepackage{xcolor}
\usepackage{xparse}
\ExplSyntaxOn
\msg_new:nnn { salim } { invalid-range-expression }
{ Invalid~range~expression:~'\exp_not:n {#1}'. }
\msg_new:nnn { salim } { zero-bound-in-range-expression }
{ Range~expression~contains~zero~bound:~'\exp_not:n {#1}'. }
\tl_new:N \l__salim_startexpr_tl
\tl_new:N \l__salim_endexpr_tl
\int_new:N \l__salim_start_int
\int_new:N \l__salim_end_int
\regex_const:Nn \l__salim_range_regex { \A (\d*) \- (\d*) \Z }
% Internal function that handles non-degenerate, ready-to-use input
\cs_new_protected:Npn \__salim_colorrange:nnn #1#2#3
{
% Deliver all characters before the chosen range
\tl_range:nnn { #3 } { 1 } { \l__salim_start_int - 1 }
% Deliver the characters in the chosen range with the desired color
\textcolor {#1}
{ \tl_range:nnn { #3 } { \l__salim_start_int } { \l__salim_end_int } }
% Deliver all characters after the chosen range
\tl_range:nnn { #3 } { \l__salim_end_int + 1 } { -1 }
}
\cs_new_protected:Npn \salim_colorrange:nnn #1#2#3
{
\regex_extract_once:NnNTF \l__salim_range_regex {#2} \l_tmpa_seq
{
\tl_set:Nx \l__salim_startexpr_tl { \seq_item:Nn \l_tmpa_seq { 2 } }
\tl_set:Nx \l__salim_endexpr_tl { \seq_item:Nn \l_tmpa_seq { 3 } }
\int_set:Nn \l__salim_start_int
{
\tl_if_empty:NTF \l__salim_startexpr_tl { 1 }
{ \l__salim_startexpr_tl }
}
\int_set:Nn \l__salim_end_int
{
\tl_if_empty:NTF \l__salim_endexpr_tl { -1 }
{ \l__salim_endexpr_tl }
}
\bool_lazy_any:nTF
{
{ \int_compare_p:nNn { \l__salim_start_int } = { 0 } }
{ \int_compare_p:nNn { \l__salim_end_int } = { 0 } }
}
{ \msg_error:nnn { salim } { zero-bound-in-range-expression } {#2} }
{
\bool_if:nTF
{
\int_compare_p:nNn
{ \l__salim_start_int } > { \tl_count:n {#3} }
||
! \int_compare_p:nNn { \l__salim_end_int } = { -1 }
&& \int_compare_p:nNn { \l__salim_start_int } >
{ \l__salim_end_int }
}
{#3}
{ \__salim_colorrange:nnn {#1} {#2} {#3} }
}
}
{ \msg_error:nnn { salim } { invalid-range-expression } {#2} }
}
\NewDocumentCommand \colorrange { O{red} m m }
{% #1 = color to use, #2 = range, #3 = word
\salim_colorrange:nnn {#1} {#2} {#3}
}
\ExplSyntaxOff
\begin{document}
\colorrange{4-6}{examination}
\colorrange[blue]{1-3}{examination}
\colorrange[blue]{-3}{examination}
\colorrange[green!50!black]{4-11}{examination}
\colorrange[green!50!black]{4-}{examination}
\colorrange{-}{examination}
\bigskip
% Cases with degenerate input
\colorrange{5-4}{examination}
\colorrange{12-4}{examination}
\colorrange{12-}{examination}
\colorrange{-15}{examination}
\end{document}