如果没有对最大工作示例进行简要描述(其中包括以下主要功能),这个问题就很难解释我正在写的一个包,因此在真正进入正题之前,我在下面加上了这段话:
% arara: lualatex
% arara: lualatex
\documentclass{article}
\usepackage{xparse}
\usepackage{expl3}
\usepackage{l3keys2e}
\usepackage{chngcntr}
\setlength\parindent{0pt}
\ExplSyntaxOn
\cs_new:Nn \__teachingtools_print_question: {
\str_clear_new:N \l__teachingtools_question_str
\str_put_left:Nn \l__teachingtools_question_str { Question }
\bool_if:NT \l__teachingtools_numbered_question_bool {
\refstepcounter{question}
\str_put_right:Nn \l__teachingtools_question_str { ~ }
\__teachingtools_print_question_label:
\str_put_right:Nx \l__teachingtools_question_str { \l__teachingtools_question_label_str }
}
\str_put_right:Nx \l__teachingtools_question_str { \l__teachingtools_suffix_character_str }
% Prints format string of label in terminal: how can I use this to change the
% printing of \refl{qu:label}?
% \tl_show:N \l__teachingtools_question_label_format_tl
% It can be used as an argument to `\renewcommand\thequestion`, and appears to work, with the caveat that the redefinition is local to the group created by each environment instance.
\renewcommand\thequestion{ \l__teachingtools_question_label_format_tl }
\par \skip_vertical:N \l__teachingtools_questionbefore_skip
\group_begin:
\bfseries \l__teachingtools_question_str \par\nopagebreak
\group_end:
}
\cs_new:Nn \__teachingtools_print_question_label: {
\str_clear_new:N \l__teachingtools_question_label_str
\tl_clear_new:N \l__teachingtools_question_label_format_tl
\bool_if:NT \l__teachingtools_question_prefix_bool {
\str_put_right:Nx \l__teachingtools_question_label_str { \l__teachingtools_question_prefix_tl }
\str_put_right:Nx \l__teachingtools_question_label_str { \l__teachingtools_prefix_separator_str }
\tl_put_right:NV \l__teachingtools_question_label_format_tl { \l__teachingtools_question_prefix_tl }
\tl_put_right:NV \l__teachingtools_question_label_format_tl { \l__teachingtools_prefix_separator_str }
}
\str_put_right:Nx \l__teachingtools_question_label_str { \l__teachingtools_question_label_tl }
\tl_put_right:NV \l__teachingtools_question_label_format_tl { \l__teachingtools_question_label_tl }
}
\newcounter{question}
\keys_define:nn { teachingtools / question } {
reset .default:n = section,
reset .choices:nn = {
part, chapter, section, subsection, subsubsection, paragraph, subparagraph
}
{
\counterwithin*{question}{ \tl_to_str:N \l_keys_choice_tl }
},
reset / none .code:n = {
\counterwithout*{question}{section}
},
}
\bool_new:N \l__teachingtools_numbered_question_bool
\keys_define:nn { teachingtools } {
question / number .code:n = {
\int_set_eq:NN \l_tmpa_int #1
\int_decr:N \l_tmpa_int
\setcounter{question}{ \int_use:N \l_tmpa_int }
},
}
\str_new:N \l__teachingtools_prefix_separator_str
\keys_define:nn { teachingtools } {
prefix-separator .choice:,
prefix-separator / dash .code:n = {
\str_set:Nn \l__teachingtools_prefix_separator_str { - }
},
prefix-separator / dot .code:n = {
\str_set:Nn \l__teachingtools_prefix_separator_str { . }
},
prefix-separator / colon .code:n = {
\str_set:Nx \l__teachingtools_prefix_separator_str { \c_colon_str }
},
prefix-separator / none .code:n = {
\str_gclear:N \l__teachingtools_prefix_separator_str
},
prefix-separator .default:n = none,
prefix-separator .initial:n = none,
}
\tl_new:N \l__teachingtools_question_prefix_tl
\bool_new:N \l__teachingtools_question_prefix_bool
\keys_define:nn { teachingtools / question } {
prefix .choice:,
prefix / part .code:n = {
\tl_set:Nn \l__teachingtools_question_prefix_tl { \thepart }
\keys_set:nn { teachingtools } {
question / reset = part,
prefix-separator = dash,
}
\bool_set_true:N \l__teachingtools_question_prefix_bool
},
prefix / chapter .code:n = {
\tl_set:Nn \l__teachingtools_question_prefix_tl { \thechapter }
\keys_set:nn { teachingtools } {
question / reset = chapter,
prefix-separator = dash,
}
\bool_set_true:N \l__teachingtools_question_prefix_bool
},
prefix / section .code:n = {
\tl_set:Nn \l__teachingtools_question_prefix_tl { \thesection }
\keys_set:nn { teachingtools } {
question / reset = section,
prefix-separator = dash,
}
\bool_set_true:N \l__teachingtools_question_prefix_bool
},
prefix / subsection .code:n = {
\tl_set:Nn \l__teachingtools_question_prefix_tl { \thesubsection }
\keys_set:nn { teachingtools } {
question / reset = subsection,
prefix-separator = dash,
}
\bool_set_true:N \l__teachingtools_question_prefix_bool
},
prefix / subsubsection .code:n = {
\tl_set:Nn \l__teachingtools_question_prefix_tl { \thesubsubsection }
\keys_set:nn { teachingtools } {
question / reset = subsubsection,
prefix-separator = dash,
}
\bool_set_true:N \l__teachingtools_question_prefix_bool
},
prefix / paragraph .code:n = {
\tl_set:Nn \l__teachingtools_question_prefix_tl { \theparagraph }
\keys_set:nn { teachingtools } {
question / reset = paragraph,
prefix-separator = dash,
}
\bool_set_true:N \l__teachingtools_question_prefix_bool
},
prefix / subparagraph .code:n = {
\tl_set:Nn \l__teachingtools_question_prefix_tl { \thesubparagraph }
\keys_set:nn { teachingtools } {
question / reset = subparagraph,
prefix-separator = dash,
}
\bool_set_true:N \l__teachingtools_question_prefix_bool
},
prefix / none .code:n = {
\tl_gclear:N \l__teachingtools_question_prefix_tl
},
prefix .default:n = none,
prefix .initial:n = none,
}
\tl_new:N \l__teachingtools_question_label_tl
\keys_define:nn { teachingtools / question } {
label .choice:,
label / arabic .code:n = {
\tl_set:Nn \l__teachingtools_question_label_tl { \arabic{question} }
},
label / alph .code:n = {
\tl_set:Nn \l__teachingtools_question_label_tl { \int_to_alph:n { \value{question} } }
},
label / lower-alph .code:n = {
\tl_set:Nn \l__teachingtools_question_label_tl { \int_to_alph:n { \value{question} } }
},
label / upper-alph .code:n = {
\tl_set:Nn \l__teachingtools_question_label_tl { \int_to_Alph:n { \value{question} } }
},
label / roman .code:n = {
\tl_set:Nn \l__teachingtools_question_label_tl { \roman{question} }
},
label / lower-roman .code:n = {
\tl_set:Nn \l__teachingtools_question_label_tl { \roman{question} }
},
label / upper-roman .code:n = {
\tl_set:Nn \l__teachingtools_question_label_tl { \Roman{question} }
},
label .default:n = arabic,
label .initial:n = arabic,
}
\str_new:N \l__teachingtools_suffix_character_str
\keys_define:nn { teachingtools } {
suffix-character .choice:,
suffix-character / dot .code:n = {
\str_set:Nn \l__teachingtools_suffix_character_str { . }
},
suffix-character / colon .code:n = {
\str_set:Nx \l__teachingtools_suffix_character_str { \c_colon_str }
},
suffix-character / bracket .code:n = {
\str_set:Nx \l__teachingtools_suffix_character_str { ) }
},
suffix-character / none .code:n = {
\str_gclear:N \l__teachingtools_suffix_character_str
},
suffix-character .default:n = dot,
suffix-character .initial:n = dot,
}
\skip_new:N \l__teachingtools_questionbefore_skip
\skip_new:N \l__teachingtools_questionafter_skip
\skip_set:Nn \l__teachingtools_questionbefore_skip { 1.0ex plus -1ex minus -0.25ex }
\skip_set:Nn \l__teachingtools_questionafter_skip { 1ex plus 0.25ex }
\NewDocumentEnvironment { question } { s O { } } {
\IfBooleanTF #1
{ \bool_set_false:N \l__teachingtools_numbered_question_bool }
{ \bool_set_true:N \l__teachingtools_numbered_question_bool }
\keys_set:nn { teachingtools / question } {#2}
\__teachingtools_print_question:
\itshape
}
{\par \skip_vertical:N \l__teachingtools_questionafter_skip \thequestion} % The `\thequestion` here is simply to illustrate the changing definition
\NewDocumentCommand \ttsetup { m } {
\keys_set:nn { teachingtools } {#1}
}
\ProcessKeysOptions { teachingtools }
\ExplSyntaxOff
\begin{document}
% Most options set with `\ttsetup` can also be applied on specific instances
% of the `question` environment. Of most use in this scenario is the
% `number` option, which has the same effect as `\setcounter{question}`; the
% others are of limited use but I've made them available anyway.
\ttsetup{
% prefix-separator = dash, % (dash|dot|colon|none)
question / prefix = section, % (part|chapter|section|subsection|subsubsection|paragraph|subparagraph|none)
question / reset = none, % (part|chapter|section|subsection|subsubsection|paragraph|subparagraph|none)
question / label = upper-alph, % (arabic|lower-alph|upper-alph|lower-roman|upper-roman)
suffix-character = bracket, % (dot|colon|bracket|none)
% question / number = 1, % any integer
}
\section{A section}
\begin{question}
The question in a section
\end{question}
\thequestion % Should be 1-A, prints 1 instead
\subsection{A subsection}
\begin{question}
The question in a subsection
\end{question}
\begin{question}[number = 7]
Another question in a subsection
\end{question}
\subsubsection{A subsubsection}
\begin{question}\label{qu:test}
The question in a subsubsection
\end{question}
\begin{question}
Another question in a subsubsection
\end{question}
\section{Another section}
\begin{question}
Another question in another section
\end{question}
See also \ref{qu:test}.
\begin{question}
Another question in another section
\end{question}
\subsection{A subsection}
\begin{question}
The question in a subsection
\end{question}
\begin{question}
Another question in a subsection
\end{question}
\begin{question}
Another question in a subsection
\end{question}
\subsubsection{A subsubsection}
\begin{question}
The question in a subsubsection
\end{question}
\begin{question}
Another question in a subsubsection
\end{question}
\subsubsection{A subsubsection}
\begin{question}
The question in a subsubsection
\end{question}
\begin{question}
Another question in a subsubsection
\end{question}
\end{document}
简而言之,此包将定义环境以排版问题/答案对,以及其他一些内容,用于学术工作表,如教程、教科书、考试、讲义等。为了提供最大的灵活性,这些环境的编号样式可以动态更改,可以使用专用命令或通过将选项传递给环境实例来更改。上面的 MWE 可以执行这些操作,可以通过更改宏中的各种选项来演示\ttsetup
。
我目前的问题是,我还想改变打印标记引用的方式question
,以便如果问题编号为 3-B,则参考资料将打印“3-B”而不是“2”。这可能吗?如果可以,我该怎么做?我一直在研究cleveref
一些提示,但我想我需要在下面的级别进行修改;一旦我开始工作,我总是可以稍后添加补丁cleveref
。
到目前为止,我已经设法让它在终端中打印出正确的标签格式,使用字符串\l__teachingtools_question_label_format_tl
;\renewcommand{\thequestion}
通过 l3→2e 包装器宏将其传递给它,结果以相当奇怪的方式中断,这是可以预料到的。我的直觉是,我已经完成了一部分,但我对 2e 或 l3 的了解还远远不够,无法让接口以合理的方式运行。
答案1
这段代码似乎可以解决问题。\g__teachingtools_question_label_format_tl
需要由单独的函数呈现,然后在文档开头调用一次以生成初始值。之后,每次创建问题环境时都会重新生成它,这样就可以正确设置引用。
% arara: lualatex
% arara: lualatex
\documentclass{article}
\usepackage{xparse}
\usepackage{expl3}
\usepackage{l3keys2e}
\usepackage{chngcntr}
\setlength\parindent{0pt}
\ExplSyntaxOn
\cs_new:Nn \__teachingtools_print_question: {
\teachingtools_generate_question_label_format:
\str_clear_new:N \l__teachingtools_question_str
\str_put_left:Nn \l__teachingtools_question_str { Question }
\bool_if:NT \l__teachingtools_numbered_question_bool {
\refstepcounter{question}
\str_put_right:Nn \l__teachingtools_question_str { ~ }
\__teachingtools_print_question_label:
\str_put_right:Nx \l__teachingtools_question_str { \l__teachingtools_question_label_str }
}
\str_put_right:Nx \l__teachingtools_question_str { \l__teachingtools_suffix_character_str }
% Prints format string of label in terminal: how can I use this to change the
% printing of \refl{qu:label}?
% \tl_show:N \l__teachingtools_question_label_format_tl
% \cs_gset_nopar:cpx { thequestion } { } { \l__teachingtools_question_label_format_tl }
\par \skip_vertical:N \l__teachingtools_questionbefore_skip
\group_begin:
\bfseries \l__teachingtools_question_str \par\nopagebreak
\group_end:
}
\cs_new:Nn \__teachingtools_print_question_label: {
\str_clear_new:N \l__teachingtools_question_label_str
\bool_if:NT \l__teachingtools_question_prefix_bool {
\str_put_right:Nx \l__teachingtools_question_label_str { \l__teachingtools_question_prefix_tl }
\str_put_right:Nx \l__teachingtools_question_label_str { \l__teachingtools_prefix_separator_str }
\tl_gput_right:NV \g__teachingtools_question_label_format_tl { \l__teachingtools_question_prefix_tl }
\tl_gput_right:NV \g__teachingtools_question_label_format_tl { \l__teachingtools_prefix_separator_str }
}
\str_put_right:Nx \l__teachingtools_question_label_str { \l__teachingtools_question_label_tl }
\tl_gput_right:NV \g__teachingtools_question_label_format_tl { \l__teachingtools_question_label_tl }
}
\tl_new:N \g__teachingtools_question_label_format_tl
\cs_new:Nn \teachingtools_generate_question_label_format: {
\tl_gclear:N \g__teachingtools_question_label_format_tl
\bool_if:NT \l__teachingtools_question_prefix_bool {
\tl_gput_right:NV \g__teachingtools_question_label_format_tl { \l__teachingtools_question_prefix_tl }
\tl_gput_right:NV \g__teachingtools_question_label_format_tl { \l__teachingtools_prefix_separator_str }
}
\tl_gput_right:NV \g__teachingtools_question_label_format_tl { \l__teachingtools_question_label_tl }
}
\newcounter{question}
\keys_define:nn { teachingtools / question } {
reset .default:n = section,
reset .choices:nn = {
part, chapter, section, subsection, subsubsection, paragraph, subparagraph
}
{
\counterwithin*{question}{ \tl_to_str:N \l_keys_choice_tl }
},
reset / none .code:n = {
\counterwithout*{question}{section}
},
}
\bool_new:N \l__teachingtools_numbered_question_bool
\keys_define:nn { teachingtools } {
question / number .code:n = {
\int_set_eq:NN \l_tmpa_int #1
\int_decr:N \l_tmpa_int
\setcounter{question}{ \int_use:N \l_tmpa_int }
},
}
\str_new:N \l__teachingtools_prefix_separator_str
\keys_define:nn { teachingtools } {
prefix-separator .choice:,
prefix-separator / dash .code:n = {
\str_set:Nn \l__teachingtools_prefix_separator_str { - }
},
prefix-separator / dot .code:n = {
\str_set:Nn \l__teachingtools_prefix_separator_str { . }
},
prefix-separator / colon .code:n = {
\str_set:Nx \l__teachingtools_prefix_separator_str { \c_colon_str }
},
prefix-separator / none .code:n = {
\str_gclear:N \l__teachingtools_prefix_separator_str
},
prefix-separator .default:n = none,
prefix-separator .initial:n = none,
}
\tl_new:N \l__teachingtools_question_prefix_tl
\bool_new:N \l__teachingtools_question_prefix_bool
\keys_define:nn { teachingtools / question } {
prefix .choice:,
prefix / part .code:n = {
\tl_set:Nn \l__teachingtools_question_prefix_tl { \thepart }
\keys_set:nn { teachingtools } {
question / reset = part,
prefix-separator = dash,
}
\bool_set_true:N \l__teachingtools_question_prefix_bool
},
prefix / chapter .code:n = {
\tl_set:Nn \l__teachingtools_question_prefix_tl { \thechapter }
\keys_set:nn { teachingtools } {
question / reset = chapter,
prefix-separator = dash,
}
\bool_set_true:N \l__teachingtools_question_prefix_bool
},
prefix / section .code:n = {
\tl_set:Nn \l__teachingtools_question_prefix_tl { \thesection }
\keys_set:nn { teachingtools } {
question / reset = section,
prefix-separator = dash,
}
\bool_set_true:N \l__teachingtools_question_prefix_bool
},
prefix / subsection .code:n = {
\tl_set:Nn \l__teachingtools_question_prefix_tl { \thesubsection }
\keys_set:nn { teachingtools } {
question / reset = subsection,
prefix-separator = dash,
}
\bool_set_true:N \l__teachingtools_question_prefix_bool
},
prefix / subsubsection .code:n = {
\tl_set:Nn \l__teachingtools_question_prefix_tl { \thesubsubsection }
\keys_set:nn { teachingtools } {
question / reset = subsubsection,
prefix-separator = dash,
}
\bool_set_true:N \l__teachingtools_question_prefix_bool
},
prefix / paragraph .code:n = {
\tl_set:Nn \l__teachingtools_question_prefix_tl { \theparagraph }
\keys_set:nn { teachingtools } {
question / reset = paragraph,
prefix-separator = dash,
}
\bool_set_true:N \l__teachingtools_question_prefix_bool
},
prefix / subparagraph .code:n = {
\tl_set:Nn \l__teachingtools_question_prefix_tl { \thesubparagraph }
\keys_set:nn { teachingtools } {
question / reset = subparagraph,
prefix-separator = dash,
}
\bool_set_true:N \l__teachingtools_question_prefix_bool
},
prefix / none .code:n = {
\tl_gclear:N \l__teachingtools_question_prefix_tl
},
prefix .default:n = none,
prefix .initial:n = none,
}
\tl_new:N \l__teachingtools_question_label_tl
\keys_define:nn { teachingtools / question } {
label .choice:,
label / arabic .code:n = {
\tl_set:Nn \l__teachingtools_question_label_tl { \arabic{question} }
},
label / alph .code:n = {
\tl_set:Nn \l__teachingtools_question_label_tl { \int_to_alph:n { \value{question} } }
},
label / lower-alph .code:n = {
\tl_set:Nn \l__teachingtools_question_label_tl { \int_to_alph:n { \value{question} } }
},
label / upper-alph .code:n = {
\tl_set:Nn \l__teachingtools_question_label_tl { \int_to_Alph:n { \value{question} } }
},
label / roman .code:n = {
\tl_set:Nn \l__teachingtools_question_label_tl { \roman{question} }
},
label / lower-roman .code:n = {
\tl_set:Nn \l__teachingtools_question_label_tl { \roman{question} }
},
label / upper-roman .code:n = {
\tl_set:Nn \l__teachingtools_question_label_tl { \Roman{question} }
},
label .default:n = arabic,
label .initial:n = arabic,
}
\str_new:N \l__teachingtools_suffix_character_str
\keys_define:nn { teachingtools } {
suffix-character .choice:,
suffix-character / dot .code:n = {
\str_set:Nn \l__teachingtools_suffix_character_str { . }
},
suffix-character / colon .code:n = {
\str_set:Nx \l__teachingtools_suffix_character_str { \c_colon_str }
},
suffix-character / bracket .code:n = {
\str_set:Nx \l__teachingtools_suffix_character_str { ) }
},
suffix-character / none .code:n = {
\str_gclear:N \l__teachingtools_suffix_character_str
},
suffix-character .default:n = dot,
suffix-character .initial:n = dot,
}
\skip_new:N \l__teachingtools_questionbefore_skip
\skip_new:N \l__teachingtools_questionafter_skip
\skip_set:Nn \l__teachingtools_questionbefore_skip { 1.0ex plus -1ex minus -0.25ex }
\skip_set:Nn \l__teachingtools_questionafter_skip { 1ex plus 0.25ex }
\NewDocumentEnvironment { question } { s O { } } {
\IfBooleanTF #1
{ \bool_set_false:N \l__teachingtools_numbered_question_bool }
{ \bool_set_true:N \l__teachingtools_numbered_question_bool }
\keys_set:nn { teachingtools / question } {#2}
\__teachingtools_print_question:
\itshape
}
{\par \skip_vertical:N \l__teachingtools_questionafter_skip }
\cs_new:cpn {question*} {\question*}
\cs_new_eq:cN {endquestion*} \endquestion
\NewDocumentCommand \ttsetup { m } {
\keys_set:nn { teachingtools } {#1}
}
\ProcessKeysOptions { teachingtools }
\renewcommand\thequestion{ \g__teachingtools_question_label_format_tl }
\ExplSyntaxOff
\usepackage{hyperref}
\hypersetup{
colorlinks=false,
hidelinks}
\usepackage[all]{hypcap}
\begin{document}
% Most options set with `\ttsetup` can also be applied on specific instances
% of the `question` environment. Of most use in this scenario is the
% `number` option, which has the same effect as `\setcounter{question}`; the
% others are of limited use but I've made them available anyway.
\ttsetup{
% prefix-separator = dash, % (dash|dot|colon|none)
question / prefix = section, % (part|chapter|section|subsection|subsubsection|paragraph|subparagraph|none)
question / reset = none, % (part|chapter|section|subsection|subsubsection|paragraph|subparagraph|none)
question / label = lower-alph, % (arabic|lower-alph|upper-alph|lower-roman|upper-roman)
suffix-character = dot, % (dot|colon|bracket|none)
% question / number = 1, % any integer
}
\section{A section}
\begin{question}\label{qu:first}
The question in a section
\end{question}
\subsection{A subsection}
\begin{question}
The question in a subsection
\end{question}
\begin{question}[number = 7, label = lower-roman]\label{qu:lowerroman}
Another question in a subsection
\end{question}
\subsubsection{A subsubsection}
\begin{question}\label{qu:test}
The question in a subsubsection
\end{question}
\begin{question}
Another question in a subsubsection
\end{question}
\section{Another section}
\begin{question}
Another question in another section, which refers to
\ref{qu:lowerroman}.
\end{question}
See also \ref{qu:test}, and \ref{qu:first}.
\begin{question}
Another question in another section
\end{question}
\subsection{A subsection}
\begin{question}
The question in a subsection
\end{question}
\begin{question}
Another question in a subsection
\end{question}
\begin{question}
Another question in a subsection
\end{question}
\subsubsection{A subsubsection}
\begin{question}
The question in a subsubsection
\end{question}
\begin{question}
Another question in a subsubsection
\end{question}
\subsubsection{A subsubsection}
\begin{question}
The question in a subsubsection
\end{question}
\begin{question}
Another question in a subsubsection
\end{question}
\end{document}