LaTeX3 l3msg 最佳实践

LaTeX3 l3msg 最佳实践

LaTeX3 模块l3msg提供了一些不错的消息传递、错误、警告等功能,并且非常灵活。工作流程与我们之前使用的工作流程不同LaTex2e软件包不同。这方面的最佳实践是什么?

在我看来,一些好的做法(也用于其他计算机语言)是:

  1. 在 l3msg 之上包装您自己的错误、警告函数等。
  2. 创建一些布尔值来表示错误和警告(即使您没有使用它们)。
  3. 不确定如何最好地安排国际化信息,一种方法是汇总\msg_new文件中的所有内容,并根据语言切换加载它们。这将类似于gettext。第二种想法是将它们存储为标记列表(字符串),并使用translator类型机制来翻译它们。首选方法是使用更高的层次结构函数:

例如不要这样写:

    \msg_set:nnnn {mypackage} { old-version }
            { LaTeX~source~files~more~than~5~year~old.~ Is~dated~
    (year:#1~date:#2-#3)

字符串应该在翻译文件中,在目录中标记en等,格式如下

   __str{old-version}{en}{LaTeX~source~files~more~than~5~year~old.} 

在德语文件中可能类似如下内容:

   __str{old-version}{LaTeX olde ...}}

然后\msg_set可以修改该函数来调用:

    \msg_set:nnnn {mypackage} { old-version }
            {__translate{old-version}} 

下面显示部分 MWE(仅用于实验)。

    \documentclass{article}
    \usepackage{expl3}
    \parindent0pt
    \begin{document}
    % Error message example
    %
    % simulate LaTeX2e \fmversion
    \def\fmversion{2000/11/12}
    \makeatletter
    \ExplSyntaxOn 

    % create error boolean
      \bool_new:N \l_mypackage_error_bool

    % redirect package errors here
      \cs_new_protected:Npn \mypackage_warning:nxx #1#2#3 {
          \bool_set_true:N \l_mypackage_error_bool
          \msg_info:nnxx { mypackage } {#1} {#2} {#3}
      }


    % define some error messages     
       \msg_set:nnnn {mypackage} { old-version }
       { LaTeX~source~files~more~than~5~year~old.~ Is~dated~(year:#1~date:#2-#3) }
       { Please~update~your~distribution~visit~ctan } %(*@\label{test}@*)


    % check version number          
        \cs_new:Npn \mypackage_check_version:n #1 {
           \exp_after:wN \l_mypackage_check_version_aux:w #1\q_stop
        }

    % check version number auxiliary                        
        \cs_new:Npn \l_mypackage_check_version_aux:w #1/#2/#3\q_stop {
            \int_compare:nNnTF  { (\tex_year:D-#1)*12 + (\tex_month:D-#2) } > { 65 }
                { FAIL\\ \mypackage_warning:nxx {old-version} {#1} {#1/#2/#3} }
                { PASS\\ } 
        }

      \mypackage_check_version:n \fmversion 
      \mypackage_check_version:n \fmtversion 
    \ExplSyntaxOff
    \end{document}

答案1

正如您所注意到的,l3msg其设计与 LaTeX2e 消息系统截然不同。其背后有两个关键的设计理念

  • 信息文本在使用消息的地方不需要。这主要是因为我们今天在 TeX 中有很多可用的“空间”,而 LaTeX2e 编写时却没有。因此,expl3通常鼓励使用大量小函数/变量而不是单片代码。对于消息来说,如果一个函数有“在这里使用消息 X”的概念,而不是所有文本,那么它会更有意义。这会产生一些负面效果,例如本地化的可能性,以及每条消息都有一个定义的名称。

  • 消息的数量/性质应该由最终用户控制。并不是每个人都希望收到关于他们不关心的内容的警告,ETC。,所以这是一项重要的能力,确实需要培养。

就最佳实践而言,只要牢记上述内容,就应该没问题。关于包装器的想法,我认为这取决于程序员。直接使用内核级代码

\msg_error:nn { mymodule } { drat }

对于一次性来说很好,而且一目了然,但对于较大的模块来说,保持代码简短更有优势

\mymod_error:n { drat } % Or \@@_error:n { draft } using l3docstrip

设置布尔返回值很大程度上取决于错误/警告/...在所涉及代码上下文中的含义:这是我们没有添加“通用”机制的原因之一。这里要注意的一点是关于消息过滤的要点:仅仅因为您将其作为错误处理并不意味着用户不会将其关闭。如果您使用布尔返回系统,那么当然,您可能还需要一个包装器。

关于消息的语言,虽然这是拥有命名消息系统的明显好处,但这并不是其主要原因。因此,这个领域尚未得到充分探索,因此以下内容有些推测。我认为类似机制translator可能不是这里的出路。消息本地化应该适用于整个运行,因此不需要动态更改它们。因此,可以想象一组消息在不同的文件或类似文件中(每种语言一个),其中文本使用设置\msg_set:nnn(n)。例如,这可能看起来像

% Core messages always in English
\msg_new:nnn { mymodule } { drat } { Drat! }
...
\file_input:n { mymodule-messages- \l_interface_language_tl }

...

% mymodule-messages-de

\msg_set:nnn { mymodule } { drat } { Achje! }

% mymodule-messages-fr

\msg_set:nnn { mymodule } { drat } { Zut! }

重要的是,改变消息的全部内容不仅仅意味着交换单词(这就是它的作用translator):语法变化等等使生活变得更加复杂。

长期目标是,消息应该被记录下来,以便实现本地化和自动解析(可以完全关闭“用户”文本,只返回消息名称和参数)。我认为理想的做法是列出消息的名称、消息使用的上下文以及消息所采用的参数的含义。然后可以将其用于各种目的。

问题中未提及但需要考虑的一个领域是“跟踪”代码。最初我们提供了一个trace消息类,但已将其删除。这里的逻辑是,对于非常低级的跟踪,相当“丰富”的消息重定向系统是l3msg错误的方法(存在性能成本)。因此,如果您确实希望提供非常详细的跟踪数据,则应该使用低级\iow_log:n和合适的包装器

% If not tracing
\cs_new_eq:NN \mymodule_trace:n \use_none:n
% If tracing
\cs_new_eq:NN \mymodule_trace:n \iow_log:n

相关内容