LaTeX编写宏包时的选项创建

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

LaTeX2e 语法创建宏包选项

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 语法提供了更现代、更安全的编程范式,特别适合复杂的配置系统。