Expl3' tl 变量存储 \seq_map_inline 的结果:在文章标题中可以,但在 beamer 的标题中不行

Expl3' tl 变量存储 \seq_map_inline 的结果:在文章标题中可以,但在 beamer 的标题中不行

正如下面的 MCE 所指出的,一个用于expl3存储结果的标记列表变量\seq_map_inline:\title的参数

  • 就像一个魅力article
  • 不适用于以下beamer课程:

          ! Undefined control sequence.
          <argument> \LaTeX3 error: 
                                    A sequence was misused.
    

您知道为什么以及如何使它与beamer的类一起工作吗?

% \documentclass{article}
\documentclass{beamer}
\usepackage{xparse}
\ExplSyntaxOn
\seq_gset_from_clist:Nn \g_tmpa_seq { foo, bar }
\tl_set:Nn \g_tmpa_tl
{
  \seq_map_inline:Nn \g_tmpa_seq
  {
    #1,\c_space_tl
  }
}
\title{\g_tmpa_tl}
\ExplSyntaxOff
\begin{document}
\maketitle
\end{document}

编辑:目标引导我提出当前的问题(及其简化的 MCE)

对于我开设的一门课程,我会为全班准备一些演示文稿beamer(顺便说一句,以下内容适用于任何课程)。整个课程的内容分为几个主题(每个主题一个文件)\input。可以处理的主题(标题)/相应文件如下:

  • “Foo 1”/foo1.tex
  • “Foo 2”/foo2.tex
  • “Foo 3”/foo3.tex
  • “Foo 4”/foo4.tex
  • “Foo 5”/foo5.tex

演示的内容(选定的主题)根据听众和/或课程进度而有所不同。

重点是,我希望对于给定的演示文稿,所选主题的标题出现在演示文稿的\title

假设当前演示的是“Foo 2”和“Foo 4”。我可以执行以下操作:

\documentclass{beamer}
...
\title{
  % Foo 1,
  Foo 2,
  % Foo 3,
  Foo 4
  % Foo 5,
}
\begin{document}
\maketitle
% \input{foo1}
\input{foo2}
% \input{foo3}
\input{foo4}
% \input{foo5}
\end{document}

但这种方式很痛苦,而且容易出错:每当 ed 文件列表 \input发生变化时,我必须(不要忘记)更改\title的内容。

请注意,在相应的文件中包含主题的标题是没有意义的:它们太晚被读取而无法被放入演示文稿中\title(好吧,另一种方法是将它们写入.aux文件中,然后在下一次编译时读取它们,当\title必须填充,但那是另一个故事)。

因此,我的目标是:

  • 固定的房产清单(比如说\g_subjects_prop)包含所有主题的完整列表,每个主题都有:
    • key:对应文件的名称,
    • 作为值:其标题。此列表可以通过文档命令(例如SubjectFileTitle{⟨filename⟩}{⟨title⟩})填充到配置文件中,
  • A顺序(例如\g_chosen_subjects_seq)包含所选主题的键。此序列可以通过文档命令(例如ChosenSubjects{⟨comma separated list of keys (files)⟩})填充到序言中,
  • 一个标记列表(例如\g_title_tl,而不是\l_tmpa_tl(?)),其中包含与上面选择的键相对应的值,这些值将作为\title的参数传递,
  • 一个文档命令(比如),当使用时,它会插入所选文件\InputChosenSubjects的序列。\input

感谢 egreg 的回答,我使用以下代码进行了处理:

\begin{filecontents*}{foo2}
\begin{frame}
  \frametitle{Foo 2 subject: quite interesting!}
  ...
\end{frame}
\end{filecontents*}

\documentclass{beamer}
\usepackage{xparse}

\ExplSyntaxOn

\prop_new:N \g_subjects_prop
\seq_new:N \g_chosen_subjects_seq
\tl_new:N \g_title_tl

\NewDocumentCommand{\SubjectFileTitle}{mm}
{
  \prop_gput:Nnn \g_subjects_prop {#1} {#2}
}

\cs_new_protected:Npn \__chosen_subjects:n #1
{
  \seq_gset_from_clist:Nn \g_chosen_subjects_seq {
    #1
  }
  \seq_map_inline:Nn \g_chosen_subjects_seq
  {
    \prop_get:NnN \g_subjects_prop {##1} \l_tmpa_tl
    \tl_if_empty:NF \l_tmpa_tl {
      \seq_put_right:Nn \g_tmpa_seq {\prop_item:Nn \g_subjects_prop {##1}}
    }
  }
  \tl_gset:Nx \g_title_tl
  {
    \seq_use:Nn \g_tmpa_seq {,~}
  }
  \title{\g_title_tl}
}

\NewDocumentCommand{\ChosenSubjects}{m}
{
  \__chosen_subjects:n {#1}
}

\cs_new_protected:Npn \__input_chosen_subjects_files:
{
  \seq_map_inline:Nn \g_chosen_subjects_seq
  {
    \par
    \file_if_exist_input:nF {##1}{%
      \begin{frame}
        \frametitle{\alert{File~\texttt{##1.tex}~not~found!}}
      \end{frame}
    }
  }
}

\NewDocumentCommand{\InputChosenSubjects}{}{
  \__input_chosen_subjects_files:
}

\ExplSyntaxOff

\SubjectFileTitle{foo1}{Foo 1}
\SubjectFileTitle{foo2}{Foo 2}
\SubjectFileTitle{foo3}{Foo 3}
\SubjectFileTitle{foo4}{Foo 4}
\SubjectFileTitle{foo5}{Foo 5}

\ChosenSubjects{
  % foo1,
  foo2,
  % foo3,
  foo4,
  % foo5,
}

\begin{document}
\maketitle{}
\InputChosenSubjects
\end{document}

答案1

你要求 TeX\seq_map_inline:Nn在处理 时执行\maketitle。更可能的情况是,你想\maketitle打印用“逗号和空格”分隔的单词列表。为此,请使用\tl_gset:Nx\seq_use:Nn

\documentclass{beamer}
\usepackage{xparse}

\ExplSyntaxOn
\seq_gset_from_clist:Nn \g_tmpa_seq { foo, bar }
\tl_gset:Nx \g_tmpa_tl
{
  \seq_use:Nn \g_tmpa_seq {,~}
}
\exp_args:NV \title \g_tmpa_tl
\ExplSyntaxOff

\begin{document}
\maketitle
\end{document}

我注意到这\g_tmpa_tl不是适合使用的变量,但我相信这只是为了举例子。


这是您代码的编辑版本。我重命名了函数和变量,并赋予了通用前缀。最重要的是,我修复了一个问题:如果变量中不存在某个属性prop,那么

\prop_get:NnN <prop variable> {<property>} <tl variable>

将标记列表变量设置为\q_no_value,而不是“空”。因此要使用的测试是\quark_if_no_value:NF

另外,\title{\g_pres_title_tl}我宁愿

\exp_args:NV \title \g_pres_title_tl

因此变量的内容被传递给\title,而不是容器。

\begin{filecontents*}{foo2}
\begin{frame}
  \frametitle{Foo 2 subject: quite interesting!}
  ...
\end{frame}
\end{filecontents*}

\documentclass{beamer}
\usepackage{xparse}

\ExplSyntaxOn

%% variables
\prop_new:N \g_pres_subjects_prop
\seq_new:N \g_pres_subjects_chosen_seq
\tl_new:N \g_pres_title_tl

%% User level commands
\NewDocumentCommand{\SubjectFileTitle}{mm}
 {
  \prop_gput:Nnn \g_pres_subjects_prop {#1} {#2}
 }

\NewDocumentCommand{\ChosenSubjects}{m}
 {
  \pres_subjects_choose:n {#1}
 }

\NewDocumentCommand{\InputChosenSubjects}{}
 {
  \pres_input_chosen_subjects_files:
 }

%% functions
\cs_new_protected:Npn \pres_subjects_choose:n #1
 {
  \seq_gset_from_clist:Nn \g_pres_subjects_chosen_seq { #1 }
  \seq_map_inline:Nn \g_pres_subjects_chosen_seq
   {
    \prop_get:NnN \g_pres_subjects_prop {##1} \l_tmpa_tl
    \quark_if_no_value:NF \l_tmpa_tl
     {
      \seq_put_right:NV \l_tmpa_seq \l_tmpa_tl
     }
   }
  \tl_gset:Nx \g_pres_title_tl
   {
    \seq_use:Nn \l_tmpa_seq {,~}
   }
  \exp_args:NV \title \g_pres_title_tl
 }

\cs_new_protected:Npn \pres_input_chosen_subjects_files:
 {
  \seq_map_inline:Nn \g_pres_subjects_chosen_seq
   {
    \par
    \file_if_exist_input:nF {##1}
     {
      \begin{frame}
      \frametitle{\alert{File~\texttt{##1.tex}~not~found!}}
      \end{frame}
     }
   }
 }
\ExplSyntaxOff

\SubjectFileTitle{foo1}{Foo 1}
\SubjectFileTitle{foo2}{Foo 2}
\SubjectFileTitle{foo3}{Foo 3}
\SubjectFileTitle{foo4}{Foo 4}
\SubjectFileTitle{foo5}{Foo 5}

\ChosenSubjects{
  % foo1,
  foo2,
  % foo3,
  foo4,
  % foo5,
  blurb % this doesn't exist among the defined files
}

\begin{document}
\maketitle{}
\InputChosenSubjects
\end{document}

答案2

评论太长,如果没有 beamer 也会出现同样的错误

\documentclass{article}
\usepackage{hyperref}
\usepackage{xparse}
\ExplSyntaxOn
\seq_gset_from_clist:Nn \g_tmpa_seq { foo, bar }
\tl_set:Nn \g_tmpa_tl
{
  \seq_map_inline:Nn \g_tmpa_seq
  {
    #1,\c_space_tl
  }
}

\newcommand\test[1]{
  \def\inserttest{#1}
}
\test{\g_tmpa_tl}
\ExplSyntaxOff
\begin{document}
%\maketitle

\hypersetup{pdftitle=\inserttest}

test

\end{document}

答案3

beamer 问题 (在 beamerbasetitle.sty 中)

\hypersetup{pdftitle={\inserttitle\ifx\insertsubtitle\@empty\else\ - \insertsubtitle\fi}}

这意味着 \inserttitle 应该是 hyperref 可以在书签中处理的内容——当涉及到 expl3 命令时:坚持使用文档中带有星号的命令。

您可以使用以下方式避免 beamer 使用 pdftitle 作为标题

\documentclass[usepdftitle=false,hyperref={pdftitle=somethingsafe}]{beamer}

这也会影响作者的 pdf 字段,因此也需要手动设置。

相关内容