LaTeX编写宏包时的选项创建

编写LaTeX宏包实现适合自己工作的特殊功能是一项极其重要的工作,在创建宏包时使用LaTeX2e语法和LaTeX3语法的风格并不相同,本文介绍两种语法。

LaTeX2e 语法创建宏包选项

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{mypackage}[2024/01/01 v1.0 My Package]

% 布尔选项
\newif\ifmypackage@draft
\newif\ifmypackage@final

% 键值选项
\newcommand\mypackage@size{10pt}
\newcommand\mypackage@font{times}

% 声明选项
\DeclareOption{draft}{\mypackage@drafttrue}
\DeclareOption{final}{\mypackage@finaltrue}
\DeclareOption{11pt}{\renewcommand\mypackage@size{11pt}}
\DeclareOption{12pt}{\renewcommand\mypackage@size{12pt}}
\DeclareOption{times}{\renewcommand\mypackage@font{times}}
\DeclareOption{helvet}{\renewcommand\mypackage@font{helvet}}

% 未知选项传递给 article 类
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}

% 处理选项
\ProcessOptions\relax

% 加载基础类
\LoadClass[\mypackage@size]{article}

% 根据选项执行操作
\ifmypackage@draft
  \usepackage{draftwatermark}
\fi

LaTeX3 语法创建宏包选项

使用 l3keys 模块

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
\RequirePackage{expl3}
\ProvidesExplPackage{mypackage}{2024/01/01}{1.0}{My Package}

% 定义键
\keys_define:nn { mypackage }
{
  draft .bool_set:N = \l_mypackage_draft_bool,
  draft .initial:n  = false,
  draft .default:n  = false,
  
  size .choices:nn =
    { 10pt, 11pt, 12pt }
    { \tl_set:Nn \l_mypackage_size_tl {#1} },
  size .initial:n = 10pt,
  
  font .tl_set:N = \l_mypackage_font_tl,
  font .initial:n = times,
  
  % 带代码的键
  fancy .code:n = 
    { \bool_set_true:N \l_mypackage_fancy_bool },
  
  % 未知选项处理
  unknown .code:n = 
    { \msg_warning:nnn { mypackage } { unknown-option } { \l_keys_key_str } },
}

% 处理包选项
\ProcessKeysOptions { mypackage }

% 使用选项值
\bool_if:NT \l_mypackage_draft_bool
{
  \RequirePackage{draftwatermark}
}

\tl_case:Nn \l_mypackage_font_tl
{
  {times}   { \RequirePackage{times} }
  {helvet}  { \RequirePackage{helvet} }
}

复杂键的定义

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
\keys_define:nn { mypackage }
{
  % 布尔键
  show-answers .bool_set:N = \l_mypackage_show_answers_bool,
  show-answers .initial:n = false,
  
  % 选择键
  mode .choice:,
  mode / draft .code:n = 
    { \bool_set_true:N \l_mypackage_draft_bool },
  mode / final .code:n = 
    { \bool_set_false:N \l_mypackage_draft_bool },
  mode .initial:n = final,
  
  % 带参数的键
  width .dim_set:N = \l_mypackage_width_dim,
  width .initial:n = 5cm,
  width .min_dim_set:N = \c_zero_dim,
  width .max_dim_set:N = \c_max_dim,
  
  % 元键(meta key)
  setup .meta:nn = { mypackage } 
    { draft = true, width = 3cm },
}
% 处理类选项
\keys_define:nn { mypackage }
{
  % 类选项传递
  unknown .code:n = 
    { \PassOptionsToClass { \l_keys_key_str } { article } },
}

\ProcessKeysPackageOptions { mypackage }

混合使用两种语法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
\RequirePackage{expl3}
\RequirePackage{xparse}

\ProvidesPackage{mypackage}[2024/01/01 v1.0]

\ExplSyntaxOn
% LaTeX3 键值定义
\keys_define:nn { mypackage }
{
  option1 .bool_set:N = \l_mypackage_opt_one_bool,
  option2 .tl_set:N   = \l_mypackage_opt_two_tl,
}

% 处理选项
\ProcessKeysOptions { mypackage }
\ExplSyntaxOff

% 传统 LaTeX2e 代码
\ifdefined\l_mypackage_opt_one_bool
  % 使用 LaTeX3 变量
\fi

注意:混合使用时需要调用expl3宏包,即

1
2
3
4
5
6
% 在导言区加载 expl3
\RequirePackage{expl3}
\ExplSyntaxOn
% LaTeX3 代码
\ExplSyntaxOff
% 传统 LaTeX2e 代码

说明

两种语法都可以有效处理宏包选项,选择哪种取决于项目需求和个人偏好。LaTeX3 语法提供了更现代、更安全的编程范式,特别适合复杂的配置系统。