Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

\section 中有 cs 时的 \tableofcontents 出现报错 #17

Closed
xkwxdyy opened this issue Apr 2, 2024 · 8 comments
Closed

\section 中有 cs 时的 \tableofcontents 出现报错 #17

xkwxdyy opened this issue Apr 2, 2024 · 8 comments

Comments

@xkwxdyy
Copy link
Contributor

xkwxdyy commented Apr 2, 2024

场景

下面可能不是一个最 minimal 的 MWE,但可以复现问题

% !TeX program = xelatex
\documentclass{ctexbook}
\usepackage{cus}
\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 {致谢}
\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
\enablecombinedlist

\begin{document}
\whudefineconstant{
  致谢={
    中文正文=致\quad 谢
  }
}

\tableofcontents

\ExplSyntaxOn
\section{
  \__whu_use_constant:nn{致谢}{中文正文}
}
\ExplSyntaxOff
\end{document}

使用 xelatex 编译后报错

! Missing $ inserted.
<inserted text> 
                $
l.73 
     
? 

尝试

  1. 去掉 \tableofcontents 后不报错
  2. 不去掉 \tableofcontents,但是\section的参数改为正常文本,不报错
@xkwxdyy
Copy link
Contributor Author

xkwxdyy commented Apr 2, 2024

测试期间发现了一个警告

Package hyperref: Token not allowed in a PDF string (Unicode):
(hyperref)	removing `\__whu_use_constant:nn'.

猜测会不会是展开的太晚了?

@Sophanatprime
Copy link
Owner

Sophanatprime commented Apr 2, 2024

在写入目录文件、标签、书签等时,\protected 的宏不会被展开。\__whu_use_constant:nn 不能定义成 \protected
而且在读入目录文件时,不会开启 LaTeX3 语法环境,所以展开之后的内容不能有以 LaTeX3 命名规范命名(包含 _ : 等)的命令。

@xkwxdyy
Copy link
Contributor Author

xkwxdyy commented Apr 2, 2024

在写入目录文件、标签、书签等时,\protected 的宏不会被展开。\__whu_use_constant:nn 不能定义成 \protected

原来如此,感谢提醒。

而且在读入目录文件时,不会开启 LaTeX3 语法环境,所以展开之后的内容不能有以 LaTeX3 命名规范命名(包含 _ : 等)的命令。

请问我这个需求怎么办,能用别的方式解决吗?

@xkwxdyy
Copy link
Contributor Author

xkwxdyy commented Apr 2, 2024

或者把 _ 换成 @

@Sophanatprime
Copy link
Owner

请问我这个需求怎么办,能用别的方式解决吗?

\tl_use:N 是可展的,用 \cs_new:Npn \__whu_use_constant:nn 就可以了,写入目录文件时它会自己展开。

@xkwxdyy
Copy link
Contributor Author

xkwxdyy commented Apr 2, 2024

\tl_use:N 是可展的,用 \cs_new:Npn \__whu_use_constant:nn 就可以了,写入目录文件时它会自己展开。

我可能没表述清楚,我看到您这句话

而且在读入目录文件时,不会开启 LaTeX3 语法环境,所以展开之后的内容不能有以 LaTeX3 命名规范命名(包含 _ ``: 等)的命令。

的时候,我以为是除了 protected 的另外一个问题,我以为除了改成 \cs_new:Npn \__whu_use_constant:nn外 展开的内容里面不能出现 _, 所以我本来打算把 c__whu_constant_ #1/#2 _tl 改成 c@@whu@constant@ #1/#2 @tl 的。

但测试下来改成 \cs_new:Npn \__whu_use_constant:nn 之后 c__whu_constant_ #1/#2 _tlc@@whu@constant@ #1/#2 @tl 都可以行得通,但是 c__whu_constant_ #1/#2 _tl 里面不是也有 _ 吗?这和您上面那个

不能有以 LaTeX3 命名规范命名(包含 _ ``: 等)的命令。

之间好像不太一样?(抱歉,我有点不太懂太深的展开原理)

@Sophanatprime
Copy link
Owner

一个命令能否展开、会不会展开、怎么展开和它所处的上下文有关。
interface3.pdf 里标记 ⋆ 的是可以用于 ef 参数,标记 ✩ 可以用于 e 参数,用在这些参数中它们被完全展开。
写入目录文件、标签、书签等,和用在 e 参数中类似,不过用 \DeclareRobustCommand 定义的命令也不会展开,所以 \textbf 这些可以安全的写入目录文件。

\protected 命令不会在 e 参数中展开,但出现在控制序列的名称中会展开(所以 \__whu_get_constant_csname:nn 能生效)。
所以使用 \cs_new:Npn \__whu_use_constant:nn 会在 e 参数中展开为 \tl_use:c { c__whu_constant_ #1/#2 _tl }\tl_use:c 还可以展开,但它先把后面那个变成一个控制序列,变成了 \tl_use:N <...>\tl_use:N 还可以展开,它的作用是展开为那个 tl 的内容,而这个 tl 的内容并没有 LaTeX3 名称的命令,所以能够正确读取。

@xkwxdyy
Copy link
Contributor Author

xkwxdyy commented Apr 2, 2024

一个命令能否展开、会不会展开、怎么展开和它所处的上下文有关。 interface3.pdf 里标记 ⋆ 的是可以用于 ef 参数,标记 ✩ 可以用于 e 参数,用在这些参数中它们被完全展开。 写入目录文件、标签、书签等,和用在 e 参数中类似,不过用 \DeclareRobustCommand 定义的命令也不会展开,所以 \textbf 这些可以安全的写入目录文件。

\protected 命令不会在 e 参数中展开,但出现在控制序列的名称中会展开(所以 \__whu_get_constant_csname:nn 能生效)。 所以使用 \cs_new:Npn \__whu_use_constant:nn 会在 e 参数中展开为 \tl_use:c { c__whu_constant_ #1/#2 _tl }\tl_use:c 还可以展开,但它先把后面那个变成一个控制序列,变成了 \tl_use:N <...>\tl_use:N 还可以展开,它的作用是展开为那个 tl 的内容,而这个 tl 的内容并没有 LaTeX3 名称的命令,所以能够正确读取。

非常感谢!

@xkwxdyy xkwxdyy closed this as completed Apr 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants