如图所示,如果我使用键值,那么我的 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
答案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
作为参数,然后在 处将其拆分\\
并将AAAA
推BBB\LaTeX BB
入\l_@@_title_seq
。
然而,当使用
\settitle{\BUPTtitletemp}
参数只是\BUPTtitletemp
(不是它的值),没有\\
明确说明。因此,整个标题AAAA \\ BBB\LaTeX B
将作为单个项目推送\l_@@_title_seq
。这将导致错误,因为以下函数\@@_get_max_width:NN
不允许\\
在其参数中出现。