Sophanatprime / cus

CusTeX
8 stars 4 forks source link

`\CUSLibraryDelayedUntil` 的“失效”问题 #27

Closed xkwxdyy closed 1 month ago

xkwxdyy commented 1 month ago

cus 版本:main 分支的非最新版本:dd143f406d628a41863a13d71f9264d8767133fc

MWE

\documentclass{ctexbook}
\makeatletter
\@ifundefined{input@path}{\let\input@path\@empty}{}
\g@addto@macro\input@path{{./module}{./library}{./lt3ekeys}{./cus-doc}{./cus-doc-aux}}
\makeatother
\usepackage[
  library={
    math.theorem
  }
]{cus}
\usepackage{amsmath}

\begin{document}
\begin{proof}
  test
\end{proof}
\end{document}

其中 math.theorem 库的内容为

\CUSLibraryDelayedUntil* { amsmath }
% \CUSDependency{ package = { amsthm } }
\CUSProvideExplLibrary{math.theorem}{2024-04-07}{v0.0.1}{define math theorem environment}

% \RequirePackage{amsmath}
\RequirePackage{amsthm}

% 重定义 proof 环境的样式
\RenewDocumentEnvironment { proof } { O{\proofname} +b }
  {
    \par
    \pushQED { \qed }
    \normalfont \topsep6 \p@ \@plus6 \p@ \relax
    \trivlist
    \item \relax
    \group_begin:
      \hspace*{2em}
      \heiti #1
    \group_end:
    \hspace{1em} \ignorespaces
    #2
  }
  {
    \popQED \endtrivlist \@endpefalse
  }

使用 xelatex 编译后报错

! LaTeX Error: Environment proof undefined.

See the LaTeX manual or LaTeX Companion for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.14 \begin{proof}

? 

需求和场景

math.theorem 库用来写一些数学环境的定义,其中用到了 amsthmthmtools 包,一开始本来把这两个包写进 dependency 的。

但是发现 proof 环境的 \qedhere 异常,搜索发现需要把 amsthm 放在 amsmath 包后面载入,然后我加了 \CUSLibraryDelayedUntil* { amsmath }

但是我想到 #25 里好像说 dependency 是在那一刻去加载,这样的话amsthmthmtools 包还是会在 amsmath 后面,所以我把 dependency 改成了显式的 requirepackage,然后在 tex 里加入 amsmath 发现报错,这个库并不是像我想的那样,在 amsmath 后才载入。甚至改成

\usepackage{amsmath}
\usepackage[
  library={
    math.theorem
  }
]{cus}

这个顺序,依旧说 proof undefine。

目前测试下来的可行办法是:tex 文件去掉 amsmath 的载入,math.theorem 库的开头改成

% \CUSLibraryDelayedUntil* { amsmath }
% \CUSDependency{ package = { amsthm } }
\CUSProvideExplLibrary{math.theorem}{2024-04-07}{v0.0.1}{define math theorem environment}

\RequirePackage{amsmath}
\RequirePackage{amsthm}

这样就没有报错了。不知道上面的问题在哪。

为什么要这么弄,是因为 amsmath 本不应该在这个库载入,因为没有用到里面的命令,需求只是要把这个库依赖的 amsthm 放在 amsmath 后面。

总结:

  1. 为什么会出现上面的问题?
  2. 我这个问题有什么建议的解决办法吗?
Sophanatprime commented 1 month ago

\CUSLibraryDelayedUntil 不在 LaTeX3 环境,参数不能有多余的空格。

xkwxdyy commented 1 month ago

感谢,不过在更新之后:

\documentclass{ctexbook}
\makeatletter
\@ifundefined{input@path}{\let\input@path\@empty}{}
\g@addto@macro\input@path{{./module}{./library}{./lt3ekeys}{./cus-doc}{./cus-doc-aux}}
\makeatother
\usepackage[
  library={
    math.theorem
  }
]{cus}
\usepackage{amsmath}

\begin{document}
\begin{theorem}
  测试
\end{theorem}
\end{document}

↑上面是主文件,↓是 math.theorem 库更新:

% https://tex.stackexchange.com/a/130655/246645
% amsthm 要在 amsmath 后面载入,否则 \qedhere 会在 align* 中失效
\CUSLibraryDelayedUntil*{amsmath}
\CUSDependency { package = { thmtools } }
\CUSProvideExplLibrary{math.theorem}{\cus@d@te}{\cus@versi@n}{define math theorem environment}

\declaretheorem{theorem}

使用 xelatex 编译后出现报错:

! Extra \else.
\reserved@a ...fter}\UseHook {package/after}\else 
                                                  \ifx \@currext \@clsextens...
l.12 

? 

这个 package 的 hook 感觉是 cus 的行为?

Sophanatprime commented 1 month ago

https://github.com/Sophanatprime/cus/commit/3bb230a79a4f0de7603a2a9cf3e84b54584463cc 已经修复了该问题。

xkwxdyy commented 1 month ago

我测试了这个问题没有被修复,仍然是上面的代码,同样的报错

xkwxdyy commented 1 month ago

已经 pull 了最新的代码。

\documentclass{ctexbook}
\makeatletter
\@ifundefined{input@path}{\let\input@path\@empty}{}
\g@addto@macro\input@path{{./module}{./library}{./lt3ekeys}{./cus-doc}{./cus-doc-aux}}
\makeatother
\usepackage[
  library={
    math.theorem
  }
]{cus}
\usepackage{amsmath}

\begin{document}
\begin{theorem}
  测试
\end{theorem}
\end{document}
% https://tex.stackexchange.com/a/130655/246645
% amsthm 要在 amsmath 后面载入,否则 \qedhere 会在 align* 中失效
\CUSLibraryDelayedUntil*{amsmath}
\CUSDependency { package = { thmtools } }
\CUSProvideExplLibrary{math.theorem}{\cus@d@te}{\cus@versi@n}{define math theorem environment}

\declaretheorem{theorem}

报错:

! Extra \else.
\reserved@a ...fter}\UseHook {package/after}\else 
                                                  \ifx \@currext \@clsextens...
l.12 

? 
Sophanatprime commented 1 month ago

cus 无关,或者说问题的根源不在 cus

旧的 \ifx.. \else ..\fi 写法有严重问题,直接把内容放在 \ifx \else \fi 中间可能有不易发现的重大错误,上面这个问题就是该写法导致。

  1. 把 LaTeX 内核 \load@onefile@withoptions 里的上述写法全部替换为 LaTeX3 的 ..TF 写法则不会有此错误。
  2. \declaretheorem 的实现也必然有类似的问题,只有 \load@onefile@withoptions 不会出现错误。

因此 cus 没法解决这个问题。 可以先把定义定理的代码保存起来,然后在 begindocument 等钩子中执行。

xkwxdyy commented 1 month ago

可以先把定义定理的代码保存起来

您的意思是把 \declaretheorem 的定义 copy 过来重新 new 一个 cs,并把里面出现的 \ifx \else \fi 换成 LaTeX3 的 ..TF 写法?

然后在 begindocument 等钩子中执行

为什么要在钩子中执行呢?上面定义完之后我把 math.theorem 库里的 \declaretheorem 换成改过的新的 cs,然后就正常定义新定理命题。之后还需要做其它操作?

xkwxdyy commented 1 month ago

把 LaTeX 内核 \load@onefile@withoptions 里的上述写法全部替换为 LaTeX3 的 ..TF 写法则不会有此错误。

请问是换成 \cs_if_eq:NNTF 吗?

xkwxdyy commented 1 month ago

我改成了

% https://tex.stackexchange.com/a/130655/246645
% amsthm 要在 amsmath 后面载入,否则 \qedhere 会在 align* 中失效
\CUSLibraryDelayedUntil*{amsmath}
\CUSDependency { package = { thmtools } }
\CUSProvideExplLibrary{math.theorem}{\cus@d@te}{\cus@versi@n}{define math theorem environment}

% \AtBeginDocument
% \AddToHook{begindocument/end}
\AddToHook{env/document/begin}
  {
    \def\load@onefile@withoptions#1
      {
        \let\CurrentOption\@empty
        \@reset@ptions
        \def\reserved@a
          {
            \@pass@ptions\@currext{#1}{\@currname}
            \expandafter\let
              \csname opt@\@currpkg@reqd\expandafter\endcsname
              \csname opt@\@currname.\@currext\endcsname
            \expandafter\let
              \csname @raw@opt@\@currpkg@reqd\expandafter\endcsname
              \csname @raw@opt@\@currname.\@currext\endcsname
            \global\expandafter
            \let\csname ver@\@currname.\@currext\endcsname\@empty
            \expandafter\let\csname\@currname.\@currext-h@@k\endcsname\@empty
            \cs_if_eq:NNTF \@currext \@pkgextension
              {
                \UseHook{package/before}
                \UseOneTimeHook{package/\@currname/before}
              }
              {
                \cs_if_eq:NNT \@currext \@clsextension
                  {
                    \UseHook{class/before}
                    \UseOneTimeHook{class/\@currname/before}
                  }
              }
            \InputIfFileExists{\@currpath\@currpkg@reqd}{}
              {\@latex@error
                {The \@cls@pkg\space\@currpkg@reqd\space failed to load}\@ehd}
            \expandafter\let\csname unprocessedoptions-\@currname.\@currext\endcsname
                            \@@unprocessedoptions
            \csname\@currname.\@currext-h@@k\endcsname
            \expandafter\let\csname\@currname.\@currext-h@@k\endcsname
                      \@undefined
            \cs_if_eq:NNTF \@unprocessedoptions \relax
              { \let\@unprocessedoptions\@undefined }
              { \csname unprocessedoptions-\@currname.\@currext\endcsname }
            \expandafter\let
                \csname unprocessedoptions-\@currname.\@currext\endcsname
              \@undefined
            \cs_if_eq:NNTF \@currext\@pkgextension
              {
                \UseOneTimeHook{package/\@currname/after}
                \UseHook{package/after}
              }
              {
                \cs_if_eq:NNT \@currext\@clsextension
                  {
                    \UseOneTimeHook{class/\@currname/after}
                    \UseHook{class/after}
                  }
              }
          }
        \@ifl@aded\@currext\@currname{}{\reserved@a}
      }
  }
\declaretheorem{theorem}

但是还是一样的报错,不知道该 hook 到哪里才行

xkwxdyy commented 1 month ago

我整理不出 MWE,因为平时不用 cus 我都是那样定义定理的,不过 cls 都很简单,也没遇到过问题。 我感觉从根源上解决比较好,重定义感觉只是临时之举而且我看了 thmtools 关于 declaretheorem 的源码,有很多个 \ifx,感觉修改起来也很麻烦。我看了一下 thmtools 目前的维护者是 @muzimuzhi,可能麻烦 muzi 看一下这个问题了

Sophanatprime commented 1 month ago

重定义 \load@onefile@withoptions 要在放在 cus.sty 最开始,而且任然会存在问题。

经过我的测试,目前问题是由于 \thmt@newtheoremiv 在执行前后的 \currentiflevel 不一致,但是在正常的情况下是一致的,还没有定位到准确原因(应该是发生在 \thmt@newtheorem@predefinition 之中)。

Sophanatprime commented 1 month ago

问题找到了,原来是 struct 模块 patch thmtools 出现了错误,马上修复。不必麻烦 muzi 了。