我做了一些实验expl3
,我想创建一个命令,允许我为每种被引用的对象创建不同类型的引用。此外,我想创建一种简单的方法来为列表中的练习创建超链接。所以我想出了代码:
\documentclass{article}
\usepackage{amsmath}
\usepackage{hyperref}
\usepackage{expl3}
% For the \exc command ----------------------------------------------
\newcounter{exercises}
\setcounter{exercises}{0}
\newcounter{letter}[exercises]
\ExplSyntaxOn
\tl_new:N \l_exc_arg_tl
\seq_new:N \l_exc_args_seq
\tl_new:N \l_exc_first_arg_tl
\tl_new:N \l_exc_second_arg_tl
\newcommand{\exc}[1]{
\tl_set:Nn \l_exc_arg_tl {#1}
\tl_if_in:NnTF \l_exc_arg_tl {.} {% Used between the number and the letter of the exercise
\seq_set_split:Nnn \l_exc_args_seq {.} {#1}
\exc_write_number_letter:N \l_exc_args_seq
}{
\exc_write_letter:V \l_exc_arg_tl
}
}
\cs_new:Npn \exc_write_number_letter:N #1 {
\seq_get_left:NN \l_exc_args_seq \l_exc_first_arg_tl
\seq_get_right:NN \l_exc_args_seq \l_exc_second_arg_tl
\exc_write_exercise:VV \l_exc_first_arg_tl \l_exc_second_arg_tl
}
\cs_new:Npn \exc_write_exercise:VV #1#2 {
\stepcounter{exercises}
\setcounter{exercises}{#1}
\refstepcounter{letter}
\exc_write_label:VV {#1} {#2}
\writeExercise{#1}\space\writeItem{#2}
}
\cs_new:Npn \exc_write_letter:V #1 {
\refstepcounter{letter}
\exc_write_label:VV {\theexercises} {#1}
\writeItem{#1}
}
\cs_new:Npn \exc_write_label:VV #1#2 {
\label{exc:#1.#2}
}
\ExplSyntaxOff
\newcommand*{\writeExercise}[1]{%
\textbf{#1.}%
}%
\newcommand*{\writeItem}[1]{%
\textbf{#1)}%
}%
% -------------------------------------------------------------------
% New definition for \Ref -------------------------------------------
\ExplSyntaxOn
\tl_new:N \l_label_type_tl
\tl_new:N \l_label_name_tl
\seq_new:N \l_separated_arg_seq
\seq_new:N \g_supported_types_seq
\seq_gput_right:Nn \g_supported_types_seq {eq}
\seq_gput_right:Nn \g_supported_types_seq {exc}
\renewcommand{\Ref}[1]{
\seq_set_split:NnV \l_separated_arg_seq {:} {#1}
\seq_get_left:NN \l_separated_arg_seq \l_label_type_tl
\seq_get_right:NN \l_separated_arg_seq \l_label_name_tl
\seq_if_in:NVTF \g_supported_types_seq {\l_label_type_tl} {
\tl_if_in:NnT \l_label_type_tl {eq} {
\rf_eq_ref:V \l_label_name_tl
}
\tl_if_eq:NnT \l_label_type_tl {exc} {
\rf_exc_ref:V \l_label_name_tl
}
}{
\rf_ref:VV \l_label_type_tl \l_label_name_tl
}
}
\cs_new:Npn \rf_ref:VV #1#2 {
\ref{#1:#2}
}
\cs_new:Npn \rf_eq_ref:V #1 {
\eqref{eq:#1}
}
\cs_new:Npn \rf_exc_ref:V #1 {
\seq_clear:N \l_exc_args_seq
\tl_set:Nn \l_exc_arg_tl {#1}
\tl_if_in:NnTF \l_exc_arg_tl {.} {
\seq_set_split:Nnn \l_exc_args_seq {.} {#1}
\seq_get_left:NN \l_exc_args_seq \l_exc_first_arg_tl
\seq_get_right:NN \l_exc_args_seq \l_exc_second_arg_tl
\rf_write_exc_ref:VV \l_exc_first_arg_tl \l_exc_second_arg_tl
}{
\tl_set: \l_exc_fisrt_arg {\theexercises}
\rf_write_exc_ref:VV \l_exc_first_arg_tl {#1}
}
}
\cs_new:Npn \rf_write_exc_ref:VV #1#2 {
\hyperref[exc:#1.#2]{\textbf{#1.}\space\textbf{#2)}}
}
\ExplSyntaxOff
% -------------------------------------------------------------------
\begin{document}
\exc{1. a}
\begin{equation} \label{eq:equation}
a^2 + b^2 = c^2
\end{equation}
\exc{b}
\Ref{eq:equation}
\Ref{exc:b}
\exc{2. a}
\Ref{exc:2.a}
\end{document}
很抱歉造成了混乱,但我希望你能理解。
第四、第五和第七行的输出应该是可点击的。
问题是它无法编译。在给出的示例中,错误消息为:“您不能在 \the 后使用‘字母 e’”。无论哪个字符最终成为 的参数中的第一个字符,都会发生相同的错误\Ref
,例如,代码\Ref{fig:figure}
将生成错误“您不能在 \the 后使用‘字母 f’”。
如果我将 定义中的第一行改为\Ref
,\seq_set_split:Nnn \l_separated_arg_seq {:} {#1}
它将能够编译,但代码将无法识别字符 ':',因此不会拆分参数。如果我将其改为\seq_set_split:NnV \l_separated_arg_seq {:} #1
,它只会将第一个字符作为参数。
你知道如何解决这个问题吗?