我正在写一份包含如下酶图像的报告:
\caption
我想在其中添加颜色指南,以便可以用颜色描述关键组件/原子(此报告未发布,因此对于色盲来说这不是问题)。我目前正在使用如下命令:
\newcommand\ColourGuide{%
Colour code: \textcolor{violet}{metal ion}, \textcolor{Green3}{residue}, \textcolor{teal}{ligand}, \textcolor{Yellow3}{substrate}, \textcolor{DarkOrange1}{phosphorus}, \textcolor{red}{oxygen} and \textcolor{RoyalBlue4}{nitrogen}%
}
但是,有些图像中并非所有颜色成分都存在,因此包含多余的颜色代码并不好。如何根据输入创建句子?例如:
\ColourGuide{M}{R}{S}{O}{N}
将产生:
颜色代码:金属离子、残留物、底物、氧气和氮气。
在指定的颜色中。我正在使用lualatex
并查看使用lua
(这很好),但我不知道如何正确(或有效地)交互这两者,如何提取参数,例如像在 Python 中使用input[0]
?我将不胜感激任何建议或解决方案,但lua
这样我就可以开始学习它并将其应用于我lualatex
经常使用的其他命令。
梅威瑟:
\documentclass{book}
\usepackage[x11names]{xcolor}
\newcommand\ColourGuide{%
Colour code: \textcolor{violet}{metal ion}, \textcolor{Green3}{residue}, \textcolor{teal}{ligand}, \textcolor{Yellow3}{substrate}, \textcolor{DarkOrange1}{phosphorus}, \textcolor{red}{oxygen} and \textcolor{RoyalBlue4}{nitrogen}%
}
\begin{document}
\ColourGuide{}
\end{document}
外观:
(我不确定该给这个贴什么标签)
答案1
您的回答很好,但是……
\documentclass{book}
\usepackage[x11names]{xcolor}
\ExplSyntaxOn
\NewDocumentCommand{\ColourGuide}{m}
{
Color~code:~\jamest_colourguide:n { #1 }
}
\seq_new:N \l__jamest_colourguide_seq
\cs_new_protected:Nn \jamest_colourguide:n
{
\seq_clear:N \l__jamest_colourguide_seq
\tl_map_function:nN { #1 } \__jamest_colourguide_add:n
\seq_use:Nnnn \l__jamest_colourguide_seq { ~and~ } { ,~ } { ~and~}
}
\cs_new_protected:Nn \__jamest_colourguide_add:n
{
\seq_put_right:Nx \l__jamest_colourguide_seq
{
\str_case:nn { #1 }
{
{a}{\textcolor{red}{oxygen},~\textcolor{DarkOrange1}{phosphorus},~
\textcolor{Yellow3}{substrate},~\textcolor{Green3}{residue},~
\textcolor{RoyalBlue4}{nitrogen},~\textcolor{teal}{ligand}~
and~\textcolor{violet}{metal~ion}.}
{M}{\textcolor{violet}{metal~ion}}
{R}{\textcolor{Green3}{residue}}
{S}{\textcolor{Yellow3}{substrate}}
{O}{\textcolor{red}{oxygen}}
{N}{\textcolor{RoyalBlue4}{nitrogen}}
{L}{\textcolor{teal}{ligand}}
{P}{\textcolor{DarkOrange1}{phosphorus}}
}
}
}
\ExplSyntaxOff
\begin{document}
\noindent\ColourGuide{MRSON}
\noindent\ColourGuide{LPON}
\noindent\ColourGuide{a}
\end{document}
不需要计数:参数逐个字符映射,并将相关代码添加到序列中,然后可与合适的分隔符一起使用。
也许更好的方法是,如果您想要完整列表,则将参数留空,以避免代码重复。
\documentclass{book}
\usepackage[x11names]{xcolor}
\ExplSyntaxOn
\NewDocumentCommand{\ColourGuide}{m}
{
Color~code:~
\jamest_colourguide:n { #1 }
}
\seq_new:N \l__jamest_colourguide_seq
\cs_new_protected:Nn \jamest_colourguide:n
{
\tl_if_empty:nTF { #1 }
{
\jamest_colourguide:n { OPSRNLM }
}
{
\seq_clear:N \l__jamest_colourguide_seq
\tl_map_function:nN { #1 } \__jamest_colourguide_add:n
\seq_use:Nnnn \l__jamest_colourguide_seq { ~and~ } { ,~ } { ~and~}
}
}
\cs_new_protected:Nn \__jamest_colourguide_add:n
{
\seq_put_right:Nx \l__jamest_colourguide_seq
{
\str_case:nn { #1 }
{
{M}{\textcolor{violet}{metal~ion}}
{R}{\textcolor{Green3}{residue}}
{S}{\textcolor{Yellow3}{substrate}}
{O}{\textcolor{red}{oxygen}}
{N}{\textcolor{RoyalBlue4}{nitrogen}}
{L}{\textcolor{teal}{ligand}}
{P}{\textcolor{DarkOrange1}{phosphorus}}
}
}
}
\ExplSyntaxOff
\begin{document}
\noindent\ColourGuide{MRSON}
\noindent\ColourGuide{LPON}
\noindent\ColourGuide{}
\end{document}
输出是一样的。
答案2
感谢大家的评论,我终于找到了一个解决方案,虽然不是很漂亮,但可以满足要求。将 @egreg 的回答添加到如何确定命令参数中的字符数以及链接的答案@John Kormylo评论给出这个:
\documentclass{book}
\usepackage[x11names]{xcolor}
\usepackage{xstring}
\usepackage{xparse} % loads expl3
\ExplSyntaxOn
\newcounter{Chars}
\newcounter{CharsConstant}
\def\CharsCount#1{%
\setcounter{Chars}{\tl_count:n { #1 }}%
\setcounter{CharsConstant}{\tl_count:n { #1 }}%
}
\NewDocumentCommand{\punctOrAnd}{mm}
{
\int_compare:nTF { #1 > 1 }
{
\int_compare:nTF { #1 = \value{CharsConstant} }
{
#2
}
{
,~#2
}
}
{
\space and~#2.
}
}
\def\ColourGuide#1{\CharsCount{#1}Colour~code:~\scanA#1\end}
\def\scanA#1{%
\ifx\end#1\else
\IfStrEq{#1}{a}{\textcolor{red}{oxygen},~\textcolor{DarkOrange1}{phosphorus},~\textcolor{Yellow3}{substrate},~\textcolor{Green3}{residue},~\textcolor{RoyalBlue4}{nitrogen},~\textcolor{teal}{ligand}~and~\textcolor{violet}{metal~ion}.}{}%
%
\IfStrEq{#1}{M}{\punctOrAnd{\value{Chars}}{\textcolor{violet}{metal~ion}}}{}%
\IfStrEq{#1}{R}{\punctOrAnd{\value{Chars}}{\textcolor{Green3}{residue}}}{}%
\IfStrEq{#1}{S}{\punctOrAnd{\value{Chars}}{\textcolor{Yellow3}{substrate}}}{}%
\IfStrEq{#1}{O}{\punctOrAnd{\value{Chars}}{\textcolor{red}{oxygen}}}{}%
\IfStrEq{#1}{N}{\punctOrAnd{\value{Chars}}{\textcolor{RoyalBlue4}{nitrogen}}}{}%
\IfStrEq{#1}{L}{\punctOrAnd{\value{Chars}}{\textcolor{teal}{ligand}}}{}%
\IfStrEq{#1}{P}{\punctOrAnd{\value{Chars}}{\textcolor{DarkOrange1}{phosphorus}}}{}%
%
\addtocounter{Chars}{-1}%
\expandafter \scanA \fi
}
\ExplSyntaxOff
\begin{document}
\noindent\ColourGuide{MRSON}
\noindent\ColourGuide{LPON}
\noindent\ColourGuide{a}
\end{document}
答案3
这使用分号作为终止符。 \def\CGparse#1#2;
将把第一个标记(字母)放入 中,#1
并将分号之前的所有内容放入 中#2
。它会递归调用自身,#2
直到\empty
。
\documentclass{book}
\usepackage[x11names]{xcolor}
\newcommand\ColourGuide[1]{Colour code:{\count1=0\relax\CGparse#1;}}
\def\CGparse#1#2;{\def\A{#1}%
\def\B{#2}%
\ifnum\count1=0\relax
\space
\else
\ifx\B\empty\relax
{ and }%
\else
{, }%
\fi
\fi
\advance\count1 by 1
\def\C{M}\ifx\A\C\relax\textcolor{violet}{metal ion}\fi
\def\C{R}\ifx\A\C\relax\textcolor{Green3}{residue}\fi
\def\C{L}\ifx\A\C\relax\textcolor{teal}{ligand}\fi
\def\C{S}\ifx\A\C\relax\textcolor{Yellow3}{substrate}\fi
\def\C{P}\ifx\A\C\relax\textcolor{DarkOrange1}{phosphorus}\fi
\def\C{O}\ifx\A\C\relax\textcolor{red}{oxygen}\fi
\def\C{N}\ifx\A\C\relax\textcolor{RoyalBlue4}{nitrogen}\fi
\ifx\B\empty\relax
{. }%
\else
\CGparse#2;
\fi}
\begin{document}
\ColourGuide{MRSON}
\end{document}
答案4
已经有很多好的答案了,可能我的使用pgfkeys
过于复杂和繁琐,但这就是我想出的。
- 不需要
lualatex
(这里明确要求,但也许有人可以在其他地方使用它)。 - 不管你写成
\ColourGuide[ligand,residue]
或,原子总是以相同的顺序排列\ColourGuide[residue,ligand]
。这可能是你想要的,也可能不是,但我认为保持相同的顺序是一种好的风格。
\ColourGuide[L,R]
当然,可选参数/键可以几乎毫不费力地缩短为例如。
\documentclass{article}
% create 'if's for each atom
\newif\ifmetalion
\newif\ifresidue
\newif\ifligand
\newif\ifsubstrate
\newif\ifphosphorus
\newif\ifoxygen
\newif\ifnitrogen
% create two counters
\newcounter{numtrue} % total number of 'if's which are true
\newcounter{currval} % counter (for correctly putting 'and' at the last atom)
% colors
\usepackage[x11names]{xcolor}
% create pgfkeys
\usepackage{pgfkeys,xcolor}
\pgfkeys{
/colourguide/.is family, /colourguide/.cd,
default/.style={
metalion=false,
residue=false,
ligand=false,
substrate=false,
phosphorus=false,
oxygen=false,
nitrogen=false,
},
metalion/.is if=metalion,
residue/.is if=residue,
ligand/.is if=ligand,
substrate/.is if=substrate,
phosphorus/.is if=phosphorus,
oxygen/.is if=oxygen,
nitrogen/.is if=nitrogen
}
% this will produce the adequate delimiter between different atoms
\def\chooseDelimiter{%
\stepcounter{currval}% increment counter
\ifnum\value{currval}<\value{numtrue}\relax% if more than one atom remains ...
,\ % ... put ',' ...
\else%
\ifnum\value{currval}=\value{numtrue}\relax% ... if only one atom remains ...
\ and\ % ... put 'and' ...
\else% ... if no atom remains ...
.% ... put '.'
\fi%
\fi%
}
% main command: \ColorGuide
\newcommand\ColourGuide[1][]{%
% do pgfkeys magic
\pgfkeys{/colourguide, default, #1}%
% get number of requested atoms
\setcounter{currval}{1}%
\setcounter{numtrue}{0}%
\ifmetalion \stepcounter{numtrue}\fi%
\ifresidue \stepcounter{numtrue}\fi%
\ifligand \stepcounter{numtrue}\fi%
\ifsubstrate \stepcounter{numtrue}\fi%
\ifphosphorus\stepcounter{numtrue}\fi%
\ifoxygen \stepcounter{numtrue}\fi%
\ifnitrogen \stepcounter{numtrue}\fi%
% build sentence
Colour code:\ %
\ifmetalion\textcolor{violet}{metal ion}\chooseDelimiter\fi%
\ifresidue\textcolor{Green3}{residue}\chooseDelimiter\fi%
\ifligand\textcolor{teal}{ligand}\chooseDelimiter\fi%
\ifsubstrate\textcolor{Yellow3}{substrate}\chooseDelimiter\fi%
\ifphosphorus\textcolor{DarkOrange1}{phosphorus}\chooseDelimiter\fi%
\ifoxygen\textcolor{red}{oxygen}\chooseDelimiter\fi%
\ifnitrogen\textcolor{RoyalBlue4}{nitrogen}\chooseDelimiter\fi%
}
\begin{document}
\paragraph{Works with one atom:}
\ColourGuide[metalion]
\paragraph{Works with two atoms:}
\noindent\ColourGuide[residue,ligand]\\ % two atoms
\paragraph{Works with many atoms:}
\ColourGuide[metalion,residue,ligand,substrate,phosphorus,oxygen,nitrogen]\\ % many atoms
\paragraph{Keeps the given order, no matter what is the order in brackets:}
\ColourGuide[ligand, residue]
\end{document}