expl3-strategy 根据文档内容自动更新文档标题

expl3-strategy 根据文档内容自动更新文档标题

语境

当前的问题出现了:

目的(总结)

我有一个主 ( beamer) 文档,例如main.tex,其内容根据目标受众而变化。为此,main.tex输入一个或多个子文件,例如 5 个子文件:topic1.textopic2.textopic3.textopic4.textopic5.tex

每个主题(文件)都有一个主题标题,我希望主文档的标题自动成为输入的主题标题列表(并且仅是输入的主题)。

为此,我采用了以下策略:

  • 在每个主题文件的开头,通过\topictitle宏指定主题标题。
  • 每次使用时,该宏都会将相应的主题标题附加到\g_topics_seq序列的右侧。
  • 在(主)文档的末尾:
    • 序列的内容\g_topics_seq放在\g_presentation_title_tl标记列表中,
    • (未展开\exp_not:V:) 的内容\g_presentation_title_tlx写入辅助.sbj文件。
  • 在(主要)文档序言的末尾(因此在下一个编译中):
    • 设置临时标记列表x以包含辅助文件的内容,
    • 此临时令牌列表的内容被传递给\title

以下 MCE 是该策略的实现,但我想知道是否expl3 可以提供更好的策略。

\documentclass{beamer}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{filecontents}
\usepackage[check-declarations]{expl3}
\usepackage{xparse}

\begin{filecontents*}{topic1}
\topictitle{% \TeX{},
 \LaTeX{} and café%
}
\begin{frame}
  \TeX{}, \LaTeX{} and café are nice!
\end{frame}
\end{filecontents*}

\begin{filecontents*}{topic2}
\topictitle{Topic 2}
\begin{frame}
  Topic 2 is nice!
\end{frame}
\end{filecontents*}

\begin{filecontents*}{topic3}
\topictitle{Topic 3}
\begin{frame}
  Topic 3 is nice!
\end{frame}
\end{filecontents*}

\begin{filecontents*}{topic4}
\topictitle{Topic 4}
\begin{frame}
  Topic 4 is nice!
\end{frame}
\end{filecontents*}

\begin{filecontents*}{topic5}
\topictitle{Topic 5}
\begin{frame}
  Topic 5 is nice!
\end{frame}
\end{filecontents*}

\ExplSyntaxOn

\seq_new:N \g_topics_seq
\tl_new:N \g_presentation_title_tl
\iow_new:N \g_output_stream

\NewDocumentCommand{\topictitle}{m}
{
  \__topic_title:n {#1}
}

\cs_new_protected:Npn \__topic_title:n #1
{
  \seq_gput_right:Nn \g_topics_seq {#1}
}

\AtEndDocument
{
  \tl_gset:Nx \g_presentation_title_tl
  {
    \seq_use:Nn\g_topics_seq {,~}
  }
  \iow_open:Nn \g_output_stream { \c_sys_jobname_str.sbj }
  \iow_now:Nx \g_output_stream { \exp_not:V\g_presentation_title_tl }
  \iow_close:N \g_output_stream
}

\AtEndPreamble{%
  \file_if_exist:nTF {\c_sys_jobname_str.sbj} {
    \tl_set:Nx \l_tmpa_tl {\file_input:n {\c_sys_jobname_str.sbj}}
    \exp_args:NV \title \l_tmpa_tl
  }{
    \title{No topic!}
  }
}
\ExplSyntaxOff

\begin{document}
\maketitle{}
%
\input{topic1}
% \input{topic2}
\input{topic3}
% \input{topic4}
\input{topic5}
\end{document}

答案1

我只需写入辅助文件:

\documentclass{beamer}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{filecontents}
\usepackage[check-declarations]{expl3}
\usepackage{xparse}

\begin{filecontents*}{topic1}
\topictitle{% \TeX{},
 \LaTeX{} and café%
}
\begin{frame}
  \TeX{}, \LaTeX{} and café are nice!
\end{frame}
\end{filecontents*}

\begin{filecontents*}{topic2}
\topictitle{Topic 2}
\begin{frame}
  Topic 2 is nice!
\end{frame}
\end{filecontents*}

\begin{filecontents*}{topic3}
\topictitle{Topic 3}
\begin{frame}
  Topic 3 is nice!
\end{frame}
\end{filecontents*}

\begin{filecontents*}{topic4}
\topictitle{Topic 4}
\begin{frame}
  Topic 4 is nice!
\end{frame}
\end{filecontents*}

\begin{filecontents*}{topic5}
\topictitle{Topic 5}
\begin{frame}
  Topic 5 is nice!
\end{frame}
\end{filecontents*}

\ExplSyntaxOn

\seq_new:N \g_topics_seq


\NewDocumentCommand\addtopictitle{m}
{
 \seq_gput_right:Nn\g_topics_seq {#1} 
}

\makeatletter
\NewDocumentCommand{\topictitle}{m}
{
  \iow_now:Nx \@mainaux
   {
    \exp_not:n {\addtopictitle{#1}}
   }
}

\title{\seq_use:Nn\g_topics_seq {,~}}

\ExplSyntaxOff

\begin{document}
\maketitle{}
%
\input{topic1}
% \input{topic2}
\input{topic3}
\input{topic4}
\input{topic5}
\end{document}

在此处输入图片描述

答案2

我会按照 Ulrike 的建议去做,写入以\@mainaux避免污染文件流。我还会避免扩展x文本(主要是 -type),因为这可能会给你带来麻烦。

还要注意,在您的代码中\tl_set:Nx \l_tmpa_tl {\file_input:n {\c_sys_jobname_str.sbj}}没有执行任何操作,因为\input不可扩展,所以您最终得到了\title{\input{\jobname.sbj}}

我建议的方法是在文档末尾将 写入\gdef\@input@topics{<stuff>}\@mainaux它将在下次运行中被读取。读取文件后, 就\@input@topics已经知道了,并且可以简单地在标题中使用。写入的定义必须是全局的,因为文件的内容.aux是在组内读取的。

在编写步骤中,我使用了e-type 扩展,\seq_use:Nn因为x-type 扩展太多,并且f-type 会尝试扩展标题的第一个标记,\TeX除非前面有空格,否则它将扩展。一切都是\exp_not:e为了避免x扩展。在以后的运行中,需要\write一个额外的before ,它已经定义了。\exp_not:N\@input@topics

代码如下:

\documentclass{beamer}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{filecontents}
\usepackage[check-declarations]{expl3}
\usepackage{xparse}

\begin{filecontents*}{topic1}
\topictitle{\TeX{},
 \LaTeX{} and café%
}
\begin{frame}
  \TeX{}, \LaTeX{} and café are nice!
\end{frame}
\end{filecontents*}

\begin{filecontents*}{topic2}
\topictitle{Topic 2}
\begin{frame}
  Topic 2 is nice!
\end{frame}
\end{filecontents*}

\begin{filecontents*}{topic3}
\topictitle{Topic 3}
\begin{frame}
  Topic 3 is nice!
\end{frame}
\end{filecontents*}

\begin{filecontents*}{topic4}
\topictitle{Topic 4}
\begin{frame}
  Topic 4 is nice!
\end{frame}
\end{filecontents*}

\begin{filecontents*}{topic5}
\topictitle{Topic 5}
\begin{frame}
  Topic 5 is nice!
\end{frame}
\end{filecontents*}

\ExplSyntaxOn

\seq_new:N \g_topics_seq

\NewDocumentCommand{\topictitle}{m}
  { \__topic_title:n {#1} }
\cs_new_protected:Npn \__topic_title:n #1
  { \seq_gput_right:Nn \g_topics_seq {#1} }

\makeatletter
\AtEndDocument
  {
    \iow_now:Nx \@auxout
      {
        \gdef \exp_not:N \@input@topics
            { \exp_not:e { \seq_use:Nn \g_topics_seq {,~} } }
      }
  }

\AtBeginDocument
  {
    \cs_if_exist:NTF \@input@topics
      { \exp_args:NV \title \@input@topics }
      { \title { No~topic! } }
  }
\makeatother

\ExplSyntaxOff

\begin{document}
\maketitle{}
%
\input{topic1}
% \input{topic2}
\input{topic3}
% \input{topic4}
\input{topic5}
\end{document}

相关内容