我想编写一个 LaTeX 文件,其中每个字符都是彩虹的下一种颜色,但我不知道如何在新命令中对其进行编程。
因此,如果我想写文本“Hello World”,我希望“H”为红色,“e”为橙色,“l”为黄色,等等。
先感谢您!
答案1
欢迎来到 TeX.SX!以下是从“复杂示例”改编而来的方法之一这里, 用一个来自 egreg 的技巧处理空间:
\documentclass{article}
\usepackage[svgnames]{xcolor}
\usepackage{xparse}
\ExplSyntaxOn
\msg_new:nnn { myrainbowtext } { not-enough-elements-in-color-vector }
{ Not~enough~elements~in~color~vector. }
\seq_new:N \l_my_color_vector_seq
% We are going to copy \g__my_saved_color_vector_seq to this one before
% starting a set of color operations, then from pop from it as we need to get
% each next color.
\seq_new:N \g__my_work_color_vector_seq
\seq_new:N \g__my_saved_color_vector_seq
\cs_new_protected:Npn \my_set_local_color_vector:n #1
{
\seq_set_from_clist:Nn \l_my_color_vector_seq {#1}
}
\cs_new_protected:Nn \my_use_current_color_vector:
{
\seq_gset_eq:NN \g__my_work_color_vector_seq \l_my_color_vector_seq
\seq_gset_eq:NN \g__my_saved_color_vector_seq \l_my_color_vector_seq
}
\cs_new_protected:Npn \my_set_color_vector:n #1
{
\my_set_local_color_vector:n {#1}
\my_use_current_color_vector:
}
\cs_generate_variant:Nn \my_set_color_vector:n { x }
\NewDocumentCommand \myUseCurrentColorVector { }
{
\my_use_current_color_vector:
}
\NewDocumentCommand \mySetColorVector { m }
{
\my_set_color_vector:n {#1}
}
% #1: a token (typically a control sequence)
\cs_new_protected:Npn \my_apply_current_vector_color:N #1
{
\seq_gpop_left:NN \g__my_work_color_vector_seq \l_tmpa_tl
\tl_if_eq:NNTF \l_tmpa_tl \q_no_value
{
\msg_error:nn { myrainbowtext }
{ not-enough-elements-in-color-vector }
}
% Apply command #1 to the color contained in \l_tmpa_tl
{ \exp_args:NV #1 \l_tmpa_tl }
}
% #1: a <boolean expression> indicating whether looping is enabled
% #2: a token (typically a control sequence) passed to
% \my_apply_current_vector_color:N
\cs_new_protected:Npn \my_apply_current_vector_color:nN #1#2
{
\bool_if:nT {#1}
{ % looping allowed -> restore the work vector
\seq_if_empty:NT \g__my_work_color_vector_seq
{
\seq_gset_eq:NN \g__my_work_color_vector_seq
\g__my_saved_color_vector_seq
}
}
\my_apply_current_vector_color:N #2
}
\prg_generate_conditional_variant:Nnn \tl_if_blank:n { x } { TF }
% #1: <boolean expression> indicating whether to loop
% #2: command to apply to each element of #3 (e.g., \textcolor)
% #3: token list
\cs_new_protected:Npn \my_tl_map_colorize:nNn #1#2#3
{
\tl_set:Nn \l_tmpa_tl {#3}
% Trick from egreg <https://tex.stackexchange.com/a/491669/73317>
\tl_replace_all:Nnn \l_tmpa_tl { ~ } { \c_space_tl }
\tl_map_inline:Nn \l_tmpa_tl
{
\tl_if_blank:xTF {##1}
{ ~ } % don't use any color for spaces
{ \my_apply_current_vector_color:nN {#1} #2 {##1} }
}
}
\NewDocumentCommand \myColorize { s m }
{
\my_use_current_color_vector:
\exp_args:Nx \my_tl_map_colorize:nNn
{ \IfBooleanTF {#1} { \c_true_bool } { \c_false_bool } }
\textcolor {#2}
}
% #1: color model
% #2: stem for color names
% #3: color specs (seq)
\cs_new_protected:Npn \my_define_color_series:nnN #1#2#3
{
\seq_set_eq:NN \l_tmpa_seq #3
\int_step_inline:nnn { 1 } { \seq_count:N #3 }
{
\seq_gpop_left:NN \l_tmpa_seq \l_tmpa_tl
\exp_args:Nnnx
\definecolor { #2 ##1 } {#1} { \tl_use:N \l_tmpa_tl }
}
}
\seq_new:N \l__my_batch_define_colors_seq
% #1: color model
% #2: stem for color names
% #3: color specs (clist)
\cs_new_protected:Npn \my_batch_define_colors:nnn #1#2#3
{
\seq_set_from_clist:Nn \l__my_batch_define_colors_seq {#3}
\my_define_color_series:nnN {#1} {#2} \l__my_batch_define_colors_seq
}
\NewDocumentCommand \myBatchDefineColors { m m m }
{
\my_batch_define_colors:nnn {#1} {#2} {#3}
}
% #1: first color index (default: 1)
% #2: last color index
% #3: stem for color names
\cs_new_protected:Npn \my_batch_set_color_vector:nnn #1#2#3
{
\seq_clear:N \l_tmpa_seq
\int_step_inline:nnn {#1} {#2}
{ \seq_gput_right:Nn \l_tmpa_seq { #3 ##1 } }
\my_set_color_vector:x { \seq_use:Nn \l_tmpa_seq { , } }
}
\NewDocumentCommand \myBatchSetColorVector { O{1} m m }
{
\my_batch_set_color_vector:nnn {#1} {#2} {#3}
}
\ExplSyntaxOff
% Define MyColor1, MyColor2, MyColor3, MyColor4, MyColor5 and MyColor6 in one
% go.
\myBatchDefineColors{rgb}{MyColor}{%
{0.4,0.2,0.6},
{0.2,1.0,0.1},
{0.3,0.5,0.8},
{0.9,0.4,0.5},
{1.0,0.9,0.1},
{0.1,0.8,0.7}
}
\begin{document}
% Simplest way to define the current color vector:
\mySetColorVector{gray!60, DarkSlateBlue, MediumVioletRed, DarkCyan}%
% The unstarred version wouldn't loop over the color vector, and thus would
% need at least as many elements in said vector as there are characters in the
% argument of \myColorize (not the case here).
\myColorize*{This is a test.}
{% The notion of “current color vector” respects grouping, as we are about to
% demonstrate.
%
\myBatchSetColorVector{6}{MyColor}% this is a shortcut for
% \mySetColorVector{MyColor1,MyColor2,MyColor3,MyColor4,MyColor5,MyColor6}%
%
\myColorize*{Once upon a time in a galaxy far, far away...}%
}
\myColorize*{Back to the first color vector.}
\end{document}