L3 展开提问——定理环境扩展

发布于 2022-12-31 19:21:12

想做一个用户自定义定理环境的接口,下面是只是 MWE ,其他功能尚未写入。本来想用 l3keys 的接口来做的。但是把 interface3 文档看来看去,都觉得 l3keys 做不到用户自定义 key 。所以就换了个思路,用字符串切割的方法模拟 l3keys 的用法。

输出效果只显示最后一个定义环境的中文名,问题不知出在哪(猜测跟 token list 的展开有关?)。期望输出效果是 definition 环境显示“定义 1. 定义测试”。

求教如何解决这个问题。如果有用 l3keys 实现的其他方法也可以。

\documentclass{ctexart}
\usepackage{amsthm}

\ExplSyntaxOn
% 使用方法 \addtheorem{<style>}{<environment name>=<Chinese name>, ...}
\NewDocumentCommand \addtheorem { m m }
  {
    \tl_set:Nn \l_theorem_style_tl { #1 }
    \clist_map_inline:nn { #2 }
      {
        \seq_set_split:Nnn \l_theorem_environment_chinese_seq { = } { ##1 }
        \seq_pop_left:NN \l_theorem_environment_chinese_seq \l_theorem_environment_tl
        \seq_pop_left:NN \l_theorem_environment_chinese_seq \l_theorem_chinese_tl

        \theoremstyle { \l_theorem_style_tl }
        \newtheorem { \l_theorem_environment_tl } { \l_theorem_chinese_tl }
        \newtheorem* { \l_theorem_environment_tl* } { \l_theorem_chinese_tl }
      }
  }
\ExplSyntaxOff

\addtheorem{definition}{
  definition = 定义,
  assume = 假设,
  lemma = 引理,
  question = 问题
}
\addtheorem{remark}{
  remark = 注
}

\begin{document}

\begin{definition}
定义测试
\end{definition}

\begin{remark*}
注释测试
\end{remark*}

\end{document}

微信截图_20221231190556.png

查看更多

关注者
0
被浏览
742
雾月
雾月 2023-01-01
这家伙很懒,什么也没写!

问题出在 \newtheorem 并不会展开第 2 个参数,所以保留的是 \l_theorem_chinese_tl 的最后一个定义。

这里提供使用 \keyval_parse:nnn 的方法,比用 prop 更为简洁、快速。

\ExplSyntaxOn
% 使用方法 \addtheorem{<style>}{<environment name>=<Chinese name>, <environment name>, ...}
\NewDocumentCommand \addtheorem { m m }
  {
    \tl_set:Nn \l_theorem_style_tl {#1}
    \keyval_parse:nnn { \__theorem_new_theorem:nn { } } { \__theorem_new_theorem:nn } {#2}
  }
\cs_new:Npn \__theorem_new_theorem:nn #1#2
  {
    \theoremstyle { \l_theorem_style_tl }
    \tl_if_empty:nTF {#1}
      {
        \exp_last_unbraced:Ne \newtheorem { {#2} { \text_titlecase_first:n {#2} } }
        \exp_last_unbraced:Ne \newtheorem { * {#2*} { \text_titlecase_first:n {#2} } }
      }
      {
        \newtheorem {#1} {#2}
        \newtheorem * {#1*} {#2}
      }
  }
\ExplSyntaxOff

还额外支持没有给出 <chinese name> 的情况,此时把 <environment name> 第一个字母大写作为 <chinese name>。如果不想要这个特性,把 \tl_if_empty:nTF 的 true 分支删掉即可。
比如:

\addtheorem{definition}{
  definition = 定义,
  assume = 假设,
  lemma = 引理,
  question = 问题,
  corollary
}
\addtheorem{remark}{
  remark = 注
}

image.png

如果不知道某一个命令会不会展开它的参数,最好的解决办法是先展开参数(用 \exp_args:N..\exp_last_unbraced:N..),再传递给这个命令。

2 个回答
 個亼滴兲箜
個亼滴兲箜 2022-12-31
这家伙很懒,什么也没写!

经群友提醒,换用 l3prop 模块能实现功能。不过仍想知道原方法失效的原因,多学习学习。

\documentclass{ctexart}
\usepackage{amsthm}

\ExplSyntaxOn
% 使用方法 \addtheorem{<style>}{<environment name>=<Chinese name>, ...}
\NewDocumentCommand \addtheorem { m m }
  {
    \prop_set_from_keyval:Nn \l_theorem_environment_chinese_prop { #2 }
    \prop_map_inline:Nn \l_theorem_environment_chinese_prop
      {
        \theoremstyle { #1 }
        \newtheorem { ##1 } { ##2 }
        \newtheorem* { ##1* } { ##2 }
      }
  }
\ExplSyntaxOff

\addtheorem{definition}{
  definition = 定义,
  assume = 假设,
  lemma = 引理,
  question = 问题
}
\addtheorem{remark}{
  remark = 注
}

\begin{document}

\begin{definition}
定义测试
\end{definition}

\begin{remark*}
注释测试
\end{remark*}

\end{document}

微信截图_20221231195251.png

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览