Sophanatprime / cus

CusTeX
8 stars 4 forks source link

需求:开发一个类似于 `\CUSLibraryDelayedUntil` 的命令 #24

Closed xkwxdyy closed 1 month ago

xkwxdyy commented 1 month ago

场景

希望能开发一个类似于 \CUSLibraryDelayedUntil 用于日常使用的延迟加载命令,比如 hyperref 宏包一般是比较晚加载的,比如可能在 \AtEndPreamble 时才加载。但是我在前期根据文档选项的不同会进行一些设置,比如如果要打印,就会把 hyperref 的 link 去掉,但这部分命令需要在 hyperref 宏包使用,而这些设置一般和 \AtEndPreamble{\RequirePackage{hyperref}} 不在同一处,甚至不在同一个文件中。

想法

我第一反应是 \CUSLibraryDelayedUntil,但是发现这个只能是把库移动到后面,有点“大”了,我的需求偏向于小的,精准的定位。 然后我看了一下 \CUSLibraryDelayedUntil 的源码: https://github.com/Sophanatprime/cus/blob/dd143f406d628a41863a13d71f9264d8767133fc/cus.sty#L236-L262

发现本质上也是用钩子 \hook_gput_code:nnn { package/#2/after },钩在 package 的后面,但是这个操作还是有点底层了,不仅用于开发,日常在 2e 层可能也会有这个需求。

所以希望能开发一个这样的命令。

xkwxdyy commented 1 month ago

尝试

我试了一下,如果这个 hook 和 \RequirePackage{hyperref} 在同一个文件中是可以的:

\documentclass{ctexart}
\usepackage{etoolbox}
\AddToHook{package/hyperref/after}{\hypersetup{hidelinks}}
\AtEndPreamble
  {
    \RequirePackage{hyperref}
  }

\begin{document}

\tableofcontents

\section{test}
test

\end{document}

但是我在项目中处理的时候发现失效了。主要是我的 hook 是在一个库里面设置的,然后通过 cus 加载库,而 \RequirePackage{hyperref} cls 文件中

xkwxdyy commented 1 month ago
\AtEndPreamble
  {
    \AddToHook { package / hyperref / after }
      { \hypersetup { allcolors = black } }
    \RequirePackage { hyperref }
    \hypersetup
      { 
        pdfencoding = auto,
        citecolor   = magenta,
        linkcolor   = blue,
        hidelinks
      }
  }

行不通,而

\AtEndPreamble
  {
    \RequirePackage { hyperref }
    \hypersetup
      { 
        pdfencoding = auto,
        citecolor   = magenta,
        linkcolor   = blue,
        hidelinks
      }
    \AddToHook { package / hyperref / after }
      { \hypersetup { allcolors = black } }
  }

可以。应该是因为前者相当于

\AtEndPreamble
  {
    \RequirePackage { hyperref }
    \hypersetup { allcolors = black }
    \hypersetup
      { 
        pdfencoding = auto,
        citecolor   = magenta,
        linkcolor   = blue,
        hidelinks
      }
  }

导致前面的 black 被覆盖了。这么看的话,即使能把 \hypersetup { allcolors = black } 延迟到 hyperref 后面加载,好像我本身的问题也没解决。

为了防止出现 X-Y 问题,我说一下我最初的需求:

\AtEndPreamble
  {
    \RequirePackage { hyperref }
    \hypersetup
      { 
        pdfencoding = auto,
        citecolor   = magenta,
        linkcolor   = blue,
        hidelinks
      }
  }

是默认的配置,然后在文档是 for-printfor-library 的时候,需要把颜色设置为 black。然后这个设置是放在了另一个库里。 这么看的话好像只能把 \RequirePackage { hyperref } 和设置放在库里处理了。

xkwxdyy commented 1 month ago

目前我想到的唯一办法,就是把 hyperref 的加载放在库里面进行

% -------- %
% 超链接设置 %
% -------- %
\AtEndPreamble
  {
    \RequirePackage { hyperref }
    \hypersetup
      { 
        pdfencoding = auto,
        citecolor   = magenta,
        linkcolor   = blue,
        hidelinks
      }
  }

% ----------------- %
% 不同文档类型下的设置 %
% ----------------- %
\cs_set:Nn \__whu_type_for_print_additional_setting: 
  {
    \AtEndPreamble { \hypersetup { allcolors = black } }
  }
\cs_set:Nn \__whu_type_for_library_additional_setting: 
  {
    \AtEndPreamble { \hypersetup { allcolors = black } }
  }

然后由于 cls

\seq_put_right:Nx \l_file_search_path_seq { ./module }
\seq_put_right:Nx \l_file_search_path_seq { ./library }
\seq_put_right:Nx \l_file_search_path_seq { ./library-cus }
\RequirePackage { whu }

\PassOptionsToClass{ \g__whu_to_book_clist }{ book }
\LoadClass { book }

\str_case:Vn \g__whu_type_str
  {
    { electronic } { \__whu_type_electronic_setting: }
    { for-print } { \__whu_type_for_print_setting: }
    { for-library } { \__whu_type_for_library_setting: }
  }

\str_case:Vn \g__whu_type_str
  {
    { electronic } { \__whu_type_electronic_setting: }
    { for-print } { \__whu_type_for_print_setting: }
    { for-library } { \__whu_type_for_library_setting: }
  }

是在宏包加载之后的,也就会在库调用之后,所以

\cs_set:Nn \__whu_type_for_print_additional_setting: 
  {
    \AtEndPreamble { \hypersetup { allcolors = black } }
  }
\cs_set:Nn \__whu_type_for_library_additional_setting: 
  {
    \AtEndPreamble { \hypersetup { allcolors = black } }
  }

部分的 \AtEndPreamble 会在

\AtEndPreamble
  {
    \RequirePackage { hyperref }
    \hypersetup
      { 
        pdfencoding = auto,
        citecolor   = magenta,
        linkcolor   = blue,
        hidelinks
      }
  }

的后面,从而生效。

Sophanatprime commented 1 month ago

\begin{document} 除了会执行通用的环境钩子:env/document/before env/document/begin 还会执行 begindocument/before begindocument begindocument/end 这三个钩子。执行顺序就是这里列出的顺序。 \AtEndPreamble 使用的是 begindocument/before\AtBeginDocument 用的是 begindocument。 可以用的钩子有很多,感觉 cus 可做的不多了。

比如,这个问题就可以用 \AtBeginDocument 解决。

xkwxdyy commented 1 month ago

好的,感谢!用 \AtBeginDocument 解决了