如何根据命令输入改变句子?

如何根据命令输入改变句子?

我正在写一份包含如下酶图像的报告:

在此处输入图片描述

\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}

相关内容