我想在 LaTeX2e 中编写一个宏\textcolor
,它可以传递嵌入在另一个宏中的颜色模型 gray、rgb 或 cmyk 的值。指定的参数数量表示要使用的颜色模型;1 个参数表示 gray,3 个参数表示 rgb,4 个参数表示 cmyk 模型。我能够编写一个宏来执行我想要的操作,但参数以标准方式括在括号中。这是我通过修改答案编写的代码这里。
\makeatletter
\def\setmycolour#1{%
\@ifnextchar\bgroup%
{\docolour{#1}}
{\dogray{#1}}
}
\def\dogray#1{This is gray hue #1.}
\def\docolour#1#2#3{%
\@ifnextchar\bgroup%
{\docmyk{#1}{#2}{#3}}
{\dorgb{#1}{#2}{#3}}
}
\def\dorgb#1#2#3{This is rgb colour #1,#2,#3.}
\def\docmyk#1#2#3#4{This is cmyk colour #1,#2,#3,#4.}
\makeatother
我使用宏作为
\setmycolour{0.85}\\
\setmycolour{1}{0}{0}\\
\setmycolour{1}{0}{0}{0}\
我想使用宏,例如,as\setmycolour{1,0,0}
或\setmycolour{0.85}
。如何解析宏定义中的参数来执行此操作?上面的代码是获得我想要的效果的最佳方法吗?
答案1
我们对此颜色的评论仅用于演示。
\documentclass{article}
\usepackage[T1]{fontenc}
\makeatletter
\def\setmycolour#1{\expandafter\setmycolour@i#1,,,,\@nil}
\def\setmycolour@i#1,#2,#3,#4,#5\@nil{%
\ifx$#2$ we have gray => #1 \else
\ifx$#3$ we have a wrong color setting \else
\ifx $#4$ we have a rgb setting => #1,#2,#3\else
we have a cmyk setting =>#1,#2,#3,#4
\fi
\fi
\fi
}
\makeatother
\begin{document}
\setmycolour{0.5}\par
\setmycolour{0.5,0.6}\par
\setmycolour{0.5,0.6,0.7}\par
\setmycolour{0.5,0.6,0.7,0.8}\par
\end{document}
答案2
LaTeX3 解决方案:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\setmycolour}{ m }
{
\prg_case_int:nnn { \clist_length:n { #1 } }
{
{1}{ \dogray{#1} }
{3}{ \dorgb{#1} }
{4}{ \docmyk{#1} }
}
{OOPS}
}
\ExplSyntaxOff
\def\dogray#1{This is gray hue #1.}
\def\dorgb#1{This is rgb colour #1.}
\def\docmyk#1{This is cmyk colour #1.}
\begin{document}
\setmycolour{0.85}\\
\setmycolour{1,0,0}\\
\setmycolour{1,0,0,0}
\end{document}
当然,在可接受的情况下执行的命令可以进行定制。
重要变更
由于expl3
2012 年夏季所做的更改,功能
\prg_case_int:nnn
\clist_length:n
应该改为
\int_case:nnn
\clist_count:n
使用相同的语法。
答案3
\documentclass{minimal}
\makeatletter
\def \setmycolour #1{
\newcount \n
\n = 0
\setmycolour@ #1,\stopmarker ,
\ifnum \n = 1
This is gray hue (#1).
\else \ifnum \n = 3
This is rgb colour (#1).
\else \ifnum \n = 4
This is cmyk colour (#1).
\else
\message{Wrong number of values.}
\fi\fi\fi
}
\def \stopmarker{EOV}
\def \setmycolour@ #1,{
\edef \colorvalue{#1}
\ifx \colorvalue \stopmarker
\let \next = \relax
\else
\advance \n by 1
\let \next = \setmycolour@
\fi
\next
}
\makeatother
\begin{document}
\setmycolour{0.5}\par
\setmycolour{0.5,0.6}\par
\setmycolour{0.5,0.6,0.7}\par
\setmycolour{0.5,0.6,0.7,0.8}\par
\end{document}
答案4
只是为了好玩,lpeg
其中包含一个解析器的解决方案luaTeX
。
\documentclass{standalone}
\usepackage{luacode}
\begin{luacode*}
lpeg = require('lpeg')
digit = lpeg.R('09')
dot = lpeg.P('.')
number = (digit^1 * dot * digit^1) + digit^1
comma = lpeg.P(',')
csv = lpeg.Ct(lpeg.C(number) * (comma * lpeg.C(number))^0) / function (t)
if #t == 1 then
return '\\dogray{' .. tostring(t[1]) .. '}'
else if #t == 3 then
return '\\dorgb{' .. tostring(t[1]) .. '}{' .. tostring(t[2]) .. '}{' .. tostring(t[3]) .. '}'
else if #t == 4 then
return '\\docmyk{' .. tostring(t[1]) .. '}{' .. tostring(t[2]) .. '}{' .. tostring(t[3]) .. '}{' .. tostring(t[4]) .. '}'
end
end
end
end
function parse_and_make(s)
tex.sprint(lpeg.match(csv,s))
end
\end{luacode*}
\def\dogray#1{This is gray hue #1.}
\def\dorgb#1#2#3{This is rgb colour #1,#2,#3.}
\def\docmyk#1#2#3#4{This is cmyk colour #1,#2,#3,#4.}
\def\setmycolor#1{%
\directlua{parse_and_make("#1")}}
\begin{document}
\setmycolor{0.85}\\
\setmycolor{1,0,0}\\
\setmycolor{1,0,0,0}\
\end{document}