Closed xkwxdyy closed 3 months ago
谨防过度工程化。直接手写 \tl_const:Nn
也不怎么麻烦。
所以识别每个 item 有多少个
{}
就是关键。
\tl_count:n
\tl_count:n {abc}
=> 3\tl_count:n {{abc}}
=> 1\tl_count:n {a{bc}}
=> 2看你想如何定义输入里不使用括号时,代码的行为。\whudefineconstant
要提供给用户使用吗?(样式/要求的多样性这么丰富吗?)
% !TeX program = xelatex
\documentclass{ctexart}
\ExplSyntaxOn
\NewDocumentCommand { \whudefineconstant } { m }
{
\clist_map_inline:nn { #1 }
{
\int_case:nnF { \tl_count:n {##1} }
{
{ 2 } { \__whu_define_constant_aux:nn ##1 }
{ 3 } { \__whu_define_constant_aux:nnn ##1 }
% more cases
}
% raise error
{ }
}
}
\cs_new_protected:Nn \__whu_define_constant_aux:nn
{
\tl_const:cn { c__whu_constant_ #1 _tl } {#2}
}
\cs_new_protected:Npn \__whu_define_constant_aux:nnn #1#2#3
{
\tl_const:cn { c__whu_constant_ #1 _tl } {#2}
\tl_const:cn { c__whu_constant_ #1 _en_tl } {#3}
}
\ExplSyntaxOff
\begin{document}
\whudefineconstant{
{acknowledgement}{致\quad 谢}{ACKNOWLEDGEMENT},
{abstract}{摘\qquad 要}
}
\newcommand{\WhuPrintConstant}[1]{%
\par\noindent
Constant ``\textbf{#1}'':
\ifcsname c__whu_constant_#1_tl\endcsname
\\\null\qquad (cn) \UseName{c__whu_constant_#1_tl}
\ifcsname c__whu_constant_#1_en_tl\endcsname
\\\null\qquad (en) \UseName{c__whu_constant_#1_en_tl}
\fi
\else
\\\null\qquad ! Undefined
\fi
\par
}
\WhuPrintConstant{random}
\WhuPrintConstant{acknowledgement}
\WhuPrintConstant{abstract}
\end{document}
参数一多,记忆参数的位置/顺序会带来负担,也许 key-value 形式更好。
```tex % !TeX program = xelatex \documentclass{ctexart} \ExplSyntaxOn \NewDocumentCommand { \whudefineconstant } { m } { \keys_set:nn { whu/constant } {#1} } \cs_new_protected:Nn \__whu_define_constant_family:n { \keys_define:nn { whu/constant } { #1/中文正文 .code:n = { \__whu_set_constant:nnn {#1} { \l_keys_key_str } {##1} } , #1/中文目录 .code:n = { \__whu_set_constant:nnn {#1} { \l_keys_key_str } {##1} } , #1/英文正文 .code:n = { \__whu_set_constant:nnn {#1} { \l_keys_key_str } {##1} } , #1/英文目录 .code:n = { \__whu_set_constant:nnn {#1} { \l_keys_key_str } {##1} } , #1 .code:n = { \keys_set:nn { whu/constant/#1 } { ##1 } \bool_lazy_and:nnT { \__whu_constant_if_exist_p:nn {#1} {中文正文} } { ! \__whu_constant_if_exist_p:nn {#1} {中文目录} } { \__whu_set_constant:nnn {#1} {中文目录} { \__whu_use_constant:nn {#1} {中文正文} } } \bool_lazy_and:nnT { \__whu_constant_if_exist_p:nn {#1} {英文正文} } { ! \__whu_constant_if_exist_p:nn {#1} {英文目录} } { \__whu_set_constant:nnn {#1} {英文目录} { \__whu_use_constant:nn {#1} {英文正文} } } } } } \__whu_define_constant_family:n {致谢} \__whu_define_constant_family:n {摘要} \__whu_define_constant_family:n {啥啥} \cs_new_protected:Nn \__whu_set_constant:nnn { \tl_const:cn { c__whu_constant_ #1/#2 _tl } {#3} } \cs_new_protected:Nn \__whu_use_constant:nn { \tl_use:c { c__whu_constant_ #1/#2 _tl } } \cs_new_protected:Nn \__whu_get_constant_csname:nn { c__whu_constant_ #1/#2 _tl } \prg_new_conditional:Nnn \__whu_constant_if_exist:nn { p , T , F , TF } { \tl_if_exist:cTF { \__whu_get_constant_csname:nn {#1} {#2} } \prg_return_true: \prg_return_false: } \ExplSyntaxOff \begin{document} \whudefineconstant{ 致谢={ 英文正文=ACKNOWLEDGEMENT, 英文目录=Acknowledgement, 中文正文=致\quad 谢, 中文目录=致谢, }, 摘要={ 中文正文=摘\qquad 要, 英文正文=Abstract, }, 啥啥={ 中文正文=啥啥, }, } \ExplSyntaxOn \cs_new_protected:Npn \WhuPrintConstant #1 { \par\noindent \textbf{#1} \__whu_print_constant_aux:nn {#1} {中文正文} \__whu_print_constant_aux:nn {#1} {中文目录} \__whu_print_constant_aux:nn {#1} {英文正文} \__whu_print_constant_aux:nn {#1} {英文目录} \par } \cs_new_protected:Nn \__whu_print_constant_aux:nn { \\\null\qquad (#2):~ \cs_if_exist_use:cF { c__whu_constant_ #1/#2 _tl } { \fbox{未定义} } } \ExplSyntaxOff \WhuPrintConstant{致谢} \WhuPrintConstant{摘要} \WhuPrintConstant{啥啥} \end{document} ```
输入
\whudefineconstant{
致谢={
英文正文=ACKNOWLEDGEMENT,
英文目录=Acknowledgement,
中文正文=致\quad 谢,
中文目录=致谢,
},
摘要={
中文正文=摘\qquad 要,
英文正文=Abstract,
},
啥啥={
中文正文=啥啥,
},
}
存储的信息
我还是觉得,这有过度工程化的嫌疑。把
\addtocontentsline...
\chapter*[...]{...}
暴露给用户不是很坏的方案。
谨防过度工程化。直接手写
\tl_const:Nn
也不怎么麻烦。
我的问题,我没有想过度工程化,只是我不知道(忘记了)还可以用 \tl_count:
来计算 {}
啥的。
\whudefineconstant
要提供给用户使用吗?(样式/要求的多样性这么丰富吗?)
这个命令其实更多情况下都是开发层的使用,但也计划要提供给用户,让用户可以根据一些特殊情形微调,不过可能用的不多。
参数一多,记忆参数的位置/顺序会带来负担,也许 key-value 形式更好。
感谢慕子!这个键值的处理挺不错的,我学习一下。
话说工程化有啥问题吗?不太懂,我写的时候也没想太多。我写模板可能更多只是为了提升自己的水平 hhhh,在写的过程中学一些新东西。
\whudefineconstant
要提供给用户使用吗?(样式/要求的多样性这么丰富吗?)这个命令其实更多情况下都是开发层的使用,但也计划要提供给用户,让用户可以根据一些特殊情形微调,不过可能用的不多。
开发者设置一次、用户在特殊情况下再设置一次,就会修改(已初始化的)常量的值,于是很可能应该按局部或全局变量来命名(\l__whu_...
或 \g__whu_...
)。与 https://github.com/nju-lug/NJUThesis/issues/240 类似。
我后来想到,除了把每一条设置都储存在单独的 tl 里,还可以用 prop/seq 储存(\g__whu_abstract_titles_prop
),虽然它们都是 O(n) 的,但这里 n <= 4。长度确定的情况下,存成 \tl_gset:Nn \g__whu_abstract_titles_tl {{<cn>}{<cn-toc>}{<en>}{<en-toc>}}
的 tuple 形式也可以,然后用 \use_(i|ii|iii|iv):nnnn
取用。
开发者设置一次、用户在特殊情况下再设置一次,就会修改(已初始化的)常量的值,于是很可能应该按局部或全局变量来命名(
\l__whu_...
或\g__whu_...
)。与 nju-lug/NJUThesis#240 类似。
如果在模板里的话,l
和 g
有什么不同的使用场景吗
设计上,声明总是全局的,然后总是局部赋值 \l_xxx_<type>
,如 set
、put_right
、clear
;总是全局赋值\g_xxx_<type>
,如 gset
、gput_right
、gclear
。这么做能避免影响 save stack(可以在 texdoc texbytopic
里直接搜 "save stack")。
实现上,以上只是软性约束,也就是 \tl_gset:Nn \l_tmpa_tl {...}
不会报错。开启 \debug_on:n { check-declarations }
后,对 c/l/g
不匹配的使用会报错(目前覆盖不全,会逐渐补全)。
功能上,如果需要某些设置局部生效,如 {\mysetup{<new settings>} new settings applied} old settings restored
就适合用 l
。反之如果需要在当前分组结束后仍然生效,就适合用 g
。其他时候可以任选。我的印象是,传统的设置项,内部大多用的局部赋值。
好的,感谢。我感觉这个常量还是适合用 g
一些。
检查清单
操作系统
mac os 14
TeX 发行版
TeXLive 2024
描述问题
需求描述
上面定义了一个函数
\whudefineconstant
,作用是批量定义一些常值的tl
,其中\whudefineconstant*
还定义了英文的版本。使用场景为论文模板开发中,定义一些固定的值比如“摘要”,“ABSTRACT”,“致谢”等。
但是有一个需求是需要额外定义这个常值的
toc
版本:具体来说,就是在设置一些章节标题的时候,比如“致谢”,可能样式是致 \quad 谢
,但是在目录中仍然是致谢
。思路是定义两个tl
,\c__whu_constant_acknowledgement_tl
和\c__whu_constant_acknowledgement_toc_tl
分别储存致 \quad 谢
和致谢
,然后通过\chapter[\c__whu_constant_acknowledgement_toc_tl]{\c__whu_constant_acknowledgement_tl}
的方式来实现效果。所以就想能把
\whudefineconstant
继续优化,甚至不需要带*版本。功能设想
\whudefineconstant
依旧支持批量生成,即必选参数是一个clist
,其中每一个 item 是 2-5 个{}
的组合,比如就定义了
\c__whu_constant_acknowledgement_tl
:致\quad谢
\c__whu_constant_acknowledgement_en_tl
:ACKNOWLEDGEMENT
\c__whu_constant_acknowledgement_toc_tl
:致谢
\c__whu_constant_acknowledgement_en_toc_tl
:Acknowledgement
和\c__whu_constant_abstract_tl
:摘\qquad要
\c__whu_constant_abstract_en_tl
:Abstract
\c__whu_constant_abstract_toc_tl
:摘要
\c__whu_constant_abstract_en_toc_tl
: 缺省则表示和\c__whu_constant_abstract_en_tl
相同,为摘要
总结来说就是
{}{name_zh}
定义了中文的 tl,中文 toc tl 和中文 tl 相同{}{name_zh}{name_en}
定义了中文和英文的 tl,中英文的 toc 和对应 tl 相同{}{name_zh}{name_en}{name_zh_toc}
定义了中文和英文的 tl 以及中文的 toc,而英文的 toc tl 和英文 tl 相同{}{name_zh}{name_en}{name_zh_toc}{name_en_toc}
定义了中文和英文的 tl,以及中英文的 toc tl所以识别每个 item 有多少个
{}
就是关键。还考虑到如果某一个
{}
里仍然有{}
,比如{{\kaishu 摘}要}
(虽然可能不太常见),也需要能正确识别数量,可能需要 peek 配对的括号。上述需求超出了我的能力范围,所以请求帮助
最小工作示例(MWE)
链接
No response
其他信息
我只了解到 latex3 中 peek 模块好像是扫描啥的,但是不太会。
附件
No response