关于 \seq_set_split 的扩展

关于 \seq_set_split 的扩展

如图所示,如果我使用键值,那么我的 MWE 就无法正常工作。

在此处输入图片描述

我的 MWE 出了什么问题?

\documentclass{article}

\usepackage{keyval}
\usepackage{expl3}
\usepackage{xparse}

\makeatletter
\def\BUPTthesiscntitlepage#1{\setkeys{cntitle}{#1}}
\define@key{cntitle}{title}{\long\def\BUPT@value@title{#1}}
\makeatother

\makeatletter\ExplSyntaxOn
\seq_new:N \l_@@_title_seq
\NewDocumentCommand \settitle {m}
{ \seq_set_split:Nnn \l_@@_title_seq { \\ } {#1} }

\dim_new:N \l_@@_title_width_dim
\NewDocumentCommand \printtitle {}
{
    \group_begin:
    \@@_title_name_format:
    \tl_use:N \c_@@_title_name_tl
    \group_end:
    \group_begin:
    \@@_title_format:
    \@@_get_max_width:NN \l_@@_title_width_dim \l_@@_title_seq
    \dim_add:Nn \l_@@_title_width_dim { 10\p@ }
    \dim_log:N \l_@@_title_width_dim
    \parbox [t] { \l_@@_title_width_dim }
    {
        \seq_map_inline:Nn \l_@@_title_seq
        { \@@_underline:Nn \l_@@_title_width_dim {##1} \\ }
    }
    \group_end:
}

\cs_new_protected:Npn \@@_get_max_width:NN #1#2
{
    \group_begin:
    \dim_zero:N #1
    \bool_until_do:nn { \seq_if_empty_p:N #2 }
    {
        \seq_pop:NN #2 \l_tmpa_tl
        \exp_args:NNV \@@_get_width:Nn \l_tmpa_dim \l_tmpa_tl
        \dim_gset:Nn #1 { \dim_max:nn { \dim_use:N #1 } { \l_tmpa_dim } }
    }
    \group_end:
}
\cs_new_protected:Npn \@@_get_width:Nn #1#2
{
    \hbox_set:Nn \l_tmpa_box {#2}
    \dim_set:Nn #1 { \box_wd:N \l_tmpa_box }
}

\cs_new_protected:Npn \@@_underline:Nn #1#2
{ \underline { \hbox_to_wd:nn { \dim_use:N #1 } { \hss #2 \hss } } }

\tl_const:Nn \c_@@_title_name_tl    { Title: }
\cs_new:Npn  \@@_title_name_format: { \Large \bfseries }
\cs_new:Npn  \@@_title_format:      { \Large \bfseries }

\ExplSyntaxOff\makeatother

\BUPTthesiscntitlepage{%
    title = {AAAA \\ BBB\LaTeX B}}

\begin{document}
\settitle{AAAA \\ BBB\LaTeX BB}
\printtitle

\makeatletter
\long\def\BUPTtitletemp{\BUPT@value@title}
\makeatother

\settitle{\BUPTtitletemp}
\printtitle
\end{document}

答案1

当您设置标题(如)时\settitle{\BUPTtitletemp}\BUPTtitletemp宏不会展开。因此拆分\\失败。仅当您实际在 中排版行时才会发生扩展\hbox(其中不能有换行符)。

在这种情况下,一个简单的解决方法是确保传递给的内容\settitle至少扩展到在其开头出现不可扩展的标记的程度:

\exp_args_generate:n { Nnf }
\NewDocumentCommand \settitle {m}
{ \exp_args:NNnf \seq_set_split:Nnn \l_@@_title_seq { \\ } {#1} }

结果正如预期

在此处输入图片描述

答案2

最重要的是:@@是文件中使用的内部约定,.dtx用于表示函数和变量中的通用前缀,并且应该不是用于生产代码。

解决您的问题最简单的方法是避免keyval并使用更强大的功能expl3

您可以将标题存储为一个序列,并在处进行拆分\\,而不必稍后再进行拆分。

而且 atabular比 更容易\parbox,因为它不需要测量物品。

\documentclass{article}

\usepackage{expl3}
\usepackage{xparse}

\ExplSyntaxOn

\keys_define:nn { danger/BUPT }
 {
  title .code:n = { \seq_set_split:Nnn \l_danger_title_seq { \\ } { #1 } },
 }
\seq_new:N \l_danger_title_seq

\NewDocumentCommand{\BUPTthesiscntitlepage}{m}
 {
  \keys_set:nn { danger/BUPT } { #1 }
 }


\NewDocumentCommand \printtitle {}
 {
  \group_begin:
  \danger_title_name_format:
  \tl_use:N \c_danger_title_name_tl
  \c_space_tl
  \group_end:
  \group_begin:
  \danger_title_format:
  \begin{tabular}[t]{@{} l @{}}
  \seq_map_function:NN \l_danger_title_seq \__danger_underline_endline:n 
  \end{tabular}
  \group_end:
 }

\cs_new_protected:Npn \__danger_underline_endline:n #1
 {
  \underline { #1 } \\
 }

\tl_const:Nn \c_danger_title_name_tl    { Title: }
\cs_new_protected:Npn  \danger_title_name_format: { \Large \bfseries }
\cs_new_protected:Npn  \danger_title_format:      { \Large \bfseries }

\ExplSyntaxOff

\BUPTthesiscntitlepage{
  title = {AAAA \\ BBB\LaTeX B},
}

\begin{document}

\printtitle

\end{document}

在此处输入图片描述

答案3

注意\settitle定义为

\seq_set_split:Nnn \l_@@_title_seq { \\ } {#1}

这意味着它的论点应该是括号中给出的一组标记。 所以

\settitle{AAAA \\ BBB\LaTeX BB}

AAAA \\ BBB\LaTeX BB作为参数,然后在 处将其拆分\\并将AAAABBB\LaTeX BB\l_@@_title_seq

然而,当使用

\settitle{\BUPTtitletemp}

参数只是\BUPTtitletemp(不是它的值),没有\\明确说明。因此,整个标题AAAA \\ BBB\LaTeX B将作为单个项目推送\l_@@_title_seq。这将导致错误,因为以下函数\@@_get_max_width:NN不允许\\在其参数中出现。

相关内容