当前部分使用的 LaTeX 输出自定义命令

当前部分使用的 LaTeX 输出自定义命令

我正在使用 LaTeX 排版戏剧剧本。每个角色都有一个自制的命令\<charactername>x,该命令接受一个参数并将该文本输出为该角色的语音。例如,\tomx{Hi, I'm Tom}表示汤姆说“嗨,我是汤姆”。

在每个场景的开头,我都需要一个出现在这个场景中的角色列表。目前,我正在手动完成这项工作,但要跟踪哪些角色在该场景中说了些什么,这是一个容易出错的任务,尤其是在角色拥挤的情况下。经常会有人被遗忘,我需要再三检查是否将每个人都包括在角色列表中。

我想知道是否可以稍微调整一下我的自定义语音命令,以便每个场景都有一个变量来保存该场景中出现的角色列表,并且每次\<charactername>x调用其中一个命令时,如果角色名称不在列表中,它们会将该角色的名称附加到该列表中。如何解决这个问题?MWE 可能看起来像这样:

\documentclass{scrartcl}

\newcommand{\tomx}[1]{
% Alter this command (maybe?) to append "Tom" to the list of
% characters of the scene this command is used in if "Tom" is not yet present.
\textsc{Tom:} #1
}

\begin{document}
\section{In the supermarket}
% Call command here that lists characters in this scene, in this case only tom.
\tomx{Hi, I'm Tom!}
\end{document}

无需快速或花哨。任何帮助都非常感谢,提前致谢!

答案1

这里的困难在于知道哪些人会在后面出现,但人物列表必须先完成。

我在这里使用这种\label方法并检查是否给出了标签,否则不会列出该人。

用 定义了一个新的人\NewPerson{foo},它自动定义\foox并添加代码来检查标签是否存在等。

现在,命令\DisplayPersons循环遍历所有定义的人员并存储本地人员,再次循环遍历这个较小的人员列表并应用\displayindividualperson可以根据个人喜好进行更改的人员。

\PostPersonlist可以\personlistheader配置为提供其他样式。

注意:与任何\label基于方法一样,至少需要运行两次编译

\documentclass{scrartcl}

\usepackage{refcount}
\usepackage{xparse}

\ExplSyntaxOn
\seq_new:N \g_luke_listofpersons_seq
\seq_new:N \l_luke_listofpersons_seq 


\NewDocumentCommand{\addperson}{m}{%
  \seq_gput_right:Nn \g_luke_listofpersons_seq {#1}
  \seq_gremove_duplicates:N \g_luke_listofpersons_seq
}


\NewDocumentCommand{\addpersonlocal}{m}{%
  \seq_gput_right:Nn \l_luke_listofpersons_seq {#1}
}

\cs_new:Npn \IfPersonCalledAlreadyF #1#2 {%
  \seq_if_in:NnF \l_luke_listofpersons_seq {#1} {#2}
}

\NewDocumentCommand{\DisplayPersons}{}{%
  \seq_clear:N \l_luke_listofpersons_seq
  \group_begin:
  \seq_clear:N \l_tmpa_seq
  \seq_map_inline:Nn \g_luke_listofpersons_seq {%
    \IfRefUndefinedExpandable{##1\thesection}{}{
      \seq_put_right:Nn \l_tmpa_seq {\displayindividualperson{##1}}
     }
   }
   \seq_if_empty:NF \l_tmpa_seq {
     \PrePersonList
     \seq_use:Nn \l_tmpa_seq {,~} 
     \PostPersonList
   }
   \group_end:

}
\ExplSyntaxOff

\NewDocumentCommand{\PostPersonList}{}{%
  \bigskip%

}

\NewDocumentCommand{\displayindividualperson}{m}{%
  \textbf{#1}%
}

\NewDocumentCommand{\PrePersonList}{}{%
  {\large \bfseries Persons in Section \thesection}

}

\makeatletter
\NewDocumentCommand{\NewPerson}{m}{%
  % Add this person to the global list
  \addperson{#1}%
  % Now define the personal \...x command 
  \expandafter\NewDocumentCommand\csname #1x\endcsname{+m}{%
    %Check if the person has been called in the local section already
    \IfPersonCalledAlreadyF{#1}{%
      \addpersonlocal{#1}
      % Add the personal to the local list, i.e. per section
      % Check whether the label has been defined already
        \protected@edef\@currentlabel{\thesection.#1}\label{#1\thesection}
    }%
    \textsc{#1:} ##1%
  }% End of the \...x command
}% End of \NewPerson
\makeatother


\NewPerson{tom}
\NewPerson{frodo}
\NewPerson{Gandalf}



\begin{document}
\section{In the supermarket}
\DisplayPersons
\tomx{Hi, I'm Tom!}

\frodox{Hi, I'm Frodo!}

\section{At TeX.SE}

\DisplayPersons

\frodox{Hi, I'm Frodo!}

\frodox{I am going to Mordor}

\Gandalfx{Cast the ring into the fire!}

\tomx{Waiting for Godot}
\end{document}

在此处输入图片描述

更新并突出显示

\documentclass{scrartcl}

\usepackage{xcolor}
\usepackage{refcount}
\usepackage{xparse}

\ExplSyntaxOn
\seq_new:N \g_luke_listofpersons_seq
\seq_new:N \l_luke_listofpersons_seq 


\NewDocumentCommand{\addperson}{m}{%
  \seq_gput_right:Nn \g_luke_listofpersons_seq {#1}
  \seq_gremove_duplicates:N \g_luke_listofpersons_seq
}


\NewDocumentCommand{\addpersonlocal}{m}{%
  \seq_gput_right:Nn \l_luke_listofpersons_seq {#1}
}

\cs_new:Npn \IfPersonCalledAlreadyF #1#2 {%
  \seq_if_in:NnF \l_luke_listofpersons_seq {#1} {#2}
}

\NewDocumentCommand{\DisplayPersons}{}{%
  \seq_clear:N \l_luke_listofpersons_seq
  \group_begin:
  \seq_clear:N \l_tmpa_seq
  \seq_map_inline:Nn \g_luke_listofpersons_seq {%
    \IfRefUndefinedExpandable{##1\thesection}{}{
      \seq_put_right:Nn \l_tmpa_seq {\use:c{##1h}}
     }
   }
   \seq_if_empty:NF \l_tmpa_seq {
     \PrePersonList
     \seq_use:Nn \l_tmpa_seq {,~} 
     \PostPersonList
   }
   \group_end:

}
\ExplSyntaxOff

\NewDocumentCommand{\PostPersonList}{}{%
  \bigskip%

}

\NewDocumentCommand{\displayindividualperson}{m}{%
  \textbf{#1}%
}

\NewDocumentCommand{\PrePersonList}{}{%
  {\large \bfseries Persons in Section \thesection}

}

\makeatletter
\NewDocumentCommand{\NewPerson}{m+m}{%
  % Add this person to the global list
  \addperson{#1}%
  % Now define the personal \...x command 
  \expandafter\NewDocumentCommand\csname #1x\endcsname{+m}{%
    %Check if the person has been called in the local section already
    \IfPersonCalledAlreadyF{#1}{%
      \addpersonlocal{#1}
      % Add the personal to the local list, i.e. per section
      % Check whether the label has been defined already
        \protected@edef\@currentlabel{\thesection.#1}\label{#1\thesection}
    }%
    \textsc{#1:} ##1%
  }% End of the \...x command
  \expandafter\NewDocumentCommand\csname #1h\endcsname{}{%
    #2{#1}%
  }
}% End of \NewPerson
\makeatother


\NewPerson{tom}{\colorbox{green}}
\NewPerson{frodo}{\colorbox{yellow}}
\NewPerson{Gandalf}{\fcolorbox{yellow}{yellow!60!blue}}



\begin{document}
\section{In the supermarket}
\DisplayPersons
\tomx{Hi, I'm Tom!}

\frodox{Hi, I'm Frodo!}

\section{At TeX.SE}

\DisplayPersons

\frodox{Hi, I'm Frodo!}

\frodox{I am going to Mordor}

\Gandalfx{Cast the ring into the fire!}

\tomx{Waiting for Godot}
\end{document}

在此处输入图片描述

相关内容