30 为何自定义的行内高亮命令无法运行?

发布于 2025-07-26 08:25:03

通过ai得到了这样的一个可以控制属性的高亮盒子,但是无法运行,有很多报错,请问是什么原因?

\documentclass{ctexart}
\usepackage{tikz}
\usepackage{xcolor} % 用于定义颜色
\usepackage{xparse} % 用于定义带有可选参数和默认值的命令
\usetikzlibrary{calc} % 用于坐标计算

% 所有 LaTeX3 相关的代码(包括变量声明、键定义和命令内部的 LaTeX3 函数)
% 都必须放置在 \ExplSyntaxOn 和 \ExplSyntaxOff 环境之间。
\ExplSyntaxOn

% --- LaTeX3 变量声明 ---
% 在使用任何 LaTeX3 变量之前,必须先使用相应的 \_new:N 命令声明它们。
% \tl_new:N 用于声明一个“token list”变量,可以存储文本、颜色名、尺寸字符串等。
% \dim_new:N 用于声明一个“dimension”变量,专门存储长度值(如 1pt, 2em)。
\tl_new:N \l_tikzhl_highlight_color_tl
\tl_new:N \l_tikzhl_underline_thickness_tl
\tl_new:N \l_tikzhl_underline_color_tl
\tl_new:N \l_tikzhl_corner_radius_tl

\dim_new:N \l_tikzhl_padding_dim
\dim_new:N \l_tikzhl_underline_offset_dim

% --- 键定义 (Key Definition) ---
% 使用 \keys_define:nn 定义一组键,它们可以被 \tikzhl 命令识别。
% .initial:n 设置键的默认值。
% .meta:n 用于定义别名或将一个键的值映射到另一个键。
\keys_define:nn { tikzhl }
{
  highlight-color .initial:n = yellow!30, % 默认高亮背景颜色
  underline-thickness .initial:n = 1.5pt, % 默认下划线粗细
  underline-color .initial:n = blue,      % 默认下划线颜色
  corner-radius .initial:n = 0pt,         % 默认圆角半径
  % 定义短名称作为别名,方便用户调用
  color .meta:n = { highlight-color = #1 },
  thickness .meta:n = { underline-thickness = #1 },
  ulcolor .meta:n = { underline-color = #1 },
  radius .meta:n = { corner-radius = #1 },
}

% --- 命令定义 ---
% \NewDocumentCommand 定义了用户可以调用的 \tikzhl 命令。
% O{}: 第一个参数是可选的键值对列表,默认为空。
% m: 第二个参数是强制的文本内容。
\NewDocumentCommand{\tikzhl}{ O{} m }{%
  % 开始一个 TikZ 绘图环境。
  % baseline=(current bounding box.base) 确保 TikZ 图片的基线与周围文本的基线对齐。
  \tikz[baseline=(current bounding box.base)] {
    % 设置内部维度变量的值。
    % \dim_set:Nn 用于给维度变量赋值。
    \dim_set:Nn \l_tikzhl_padding_dim { 1pt }           % 文本与高亮框的内边距
    \dim_set:Nn \l_tikzhl_underline_offset_dim { 1pt }     % 下划线距离文本的垂直偏移

    % 处理用户通过可选参数 #1 提供的键值对。
    % \keys_set:nn 会将用户提供的键值对应用到 'tikzhl' 键族中,
    % 从而覆盖之前定义的默认值。
    \keys_set:nn { tikzhl } { #1 }

    % 从键中获取最终的值,并存储到已声明的 token list 变量中。
    % 关键点:这里使用 \tl_set:Nx 而不是 \tl_set:Nn。
    % \tl_set:Nx 会对第二个参数(即 \keys_value:nn {tikzhl}{...})进行一次“x-expansion”。
    % 这意味着 \keys_value:nn 命令会被执行,并将其结果(例如 "yellow!30")存储到变量中,
    % 而不是存储 \keys_value:nn 命令本身。
    \tl_set:Nx \l_tikzhl_highlight_color_tl { \keys_value:nn { tikzhl } { highlight-color } }
    \tl_set:Nx \l_tikzhl_underline_thickness_tl { \keys_value:nn { tikzhl } { underline-thickness } }
    \tl_set:Nx \l_tikzhl_underline_color_tl { \keys_value:nn { tikzhl } { underline-color } }
    \tl_set:Nx \l_tikzhl_corner_radius_tl { \keys_value:nn { tikzhl } { corner-radius } }

    % 1. 绘制文本节点,并应用高亮背景和圆角。
    \node[
      % 在 TikZ 选项中使用 LaTeX3 变量时,必须使用 \dim_use:N 或 \tl_use:N
      % 来“展开”变量,使其值被 TikZ 识别。
      inner sep=\dim_use:N \l_tikzhl_padding_dim,       % 文本与高亮框之间的内边距
      fill=\tl_use:N \l_tikzhl_highlight_color_tl,      % 高亮背景颜色
      text=black,                                        % 确保文本颜色是黑色
      anchor=base,                                       % 确保节点的基线与文本的基线对齐
      rounded corners=\tl_use:N \l_tikzhl_corner_radius_tl, % 圆角半径
    ] (textnode) {#2}; % 节点内容为 #2 (强制参数)

    % 2. 绘制加粗下划线。
    \draw[
      draw=\tl_use:N \l_tikzhl_underline_color_tl,      % 下划线颜色
      line width=\tl_use:N \l_tikzhl_underline_thickness_tl % 下划线粗细
    ] ($(textnode.south west) + (0,-\dim_use:N \l_tikzhl_underline_offset_dim)$) -- ($(textnode.south east) + (0,-\dim_use:N \l_tikzhl_underline_offset_dim)$);
  }%
}

\ExplSyntaxOff % 关闭 LaTeX3 语法环境。所有 LaTeX3 特有的命令在此之后将不可用。

\begin{document}

这是一个示例文本,其中包含一些 \tikzhl{需要高亮} 的内容。
你可以看到它和周围的文本在同一行,并且带有加粗的下划线。

% --- 正确的调用方式示例 (使用键值对) ---

% 1. 仅改变高亮背景颜色
\tikzhl[color=green!20]{这是绿色高亮}。

% 2. 仅改变下划线粗细
\tikzhl[thickness=2pt]{这是粗下划线}。

% 3. 仅改变下划线颜色
\tikzhl[ulcolor=red]{这是红色下划线}。

% 4. 设置圆角半径
\tikzhl[radius=3pt]{这个是圆角高亮}。

% 5. 组合使用:紫色高亮,3pt下划线,紫色下划线,3pt圆角
\tikzhl[color=violet!20, thickness=3pt, ulcolor=purple, radius=3pt]{复杂组合示例}。

% 6. 所有参数都使用默认值
默认样式:\tikzhl{默认样式}。

\end{document}

Plus:

假若上述代码可以修复,请问是否可以增加绘制外部框线的属性,包括可以调节外部框线的粗细,圆角和颜色?

查看更多

关注者
1
被浏览
111
Sagittarius Rover
Sagittarius Rover 15小时前
我要成为Typst糕手/(ㄒoㄒ)/~~
改不动了....一定不会有后续了...Happy LaTeX3!

我食言了。

我还是觉得作为一名开发者,不能对latex3在七窍通了六窍的情况下就开始造轮子

过分使用AI只会陷入vibe coding这种「复制链接大脑,粘贴代替思考」的境地,事实上,对于\keys_value:nn查无此命令的幻觉应该是很容易通过texdoc interface3发觉的。

我删掉了大部分注释,也不打算做介绍了...

Claim:我没太注意ai给的tikz绘制细节,只是把l3keys的错误用法做了修改...

如果我没理解错.meta:n创建的是「元键」是用来创建多层级键值对的,也并不是「定义短名称作为别名,方便用户调用」,这 似乎 又是一个幻觉...

当一些错误混杂在基本正确的逻辑中,挺难debug的,遇到这种情况还是应该自己从最简单的「l3keys」例子开始,一步步测试,不要每次复制粘贴上百行代码...

  • 先实现tikz的绘图逻辑
  • 再学会如何用l3keys控制键值对
  • 最后封装tikzhl命令

一个不基于.initial:n的做法如下:

\documentclass{ctexart}
\usepackage{tikz}
\usetikzlibrary{calc}
\ExplSyntaxOn
\tl_new:N \l_tikzhl_highlight_color_tl
\tl_new:N \l_tikzhl_underline_thickness_tl
\tl_new:N \l_tikzhl_underline_color_tl
\tl_new:N \l_tikzhl_corner_radius_tl
\dim_new:N \l_tikzhl_padding_dim
\dim_new:N \l_tikzhl_underline_offset_dim
\keys_define:nn { tikzhl } {
  hlcolor .tl_set:N = \l_tikzhl_highlight_color_tl,
  ulcolor .tl_set:N =\l_tikzhl_underline_color_tl,
  thickness .tl_set:N = \l_tikzhl_underline_thickness_tl,
  radius .tl_set:N = \l_tikzhl_corner_radius_tl,
}
\keys_set:nn { tikzhl } {
  hlcolor = yellow!30,
  ulcolor= blue,      
  thickness = 1.5pt,
  radius = 0pt,
}
\NewDocumentCommand{\tikzhl}{ O{} m }{%
  \tikz[baseline=(current~bounding~box.base)]{
    % 设置内部维度变量的值。
    \dim_set:Nn \l_tikzhl_padding_dim { 1pt }% 文本与高亮框的内边距
    \dim_set:Nn \l_tikzhl_underline_offset_dim { 1pt }% 下划线距离文本的垂直偏移
    \keys_set:nn { tikzhl } { #1 }
    % 1. 绘制文本节点,并应用高亮背景和圆角。
    \node[
      inner~sep=\l_tikzhl_padding_dim,
      fill=\l_tikzhl_highlight_color_tl,
      text=black,
      anchor=base,
      rounded~corners=\l_tikzhl_corner_radius_tl,
    ] (textnode) {#2};% 节点内容为 #2 (强制参数)
    % 2. 绘制加粗下划线。
    \draw[
      draw=\l_tikzhl_underline_color_tl,
      line~width=\l_tikzhl_underline_thickness_tl
     ] ($(textnode.south~west) + (0,-\dim_use:N \l_tikzhl_underline_offset_dim)$) 
    -- ($(textnode.south~east) + (0,-\dim_use:N \l_tikzhl_underline_offset_dim)$);
  }%
}
\ExplSyntaxOff

\begin{document}

这是一个示例文本,其中包含一些 \tikzhl{需要高亮} 的内容。
你可以看到它和周围的文本在同一行,并且带有加粗的下划线。

% --- 正确的调用方式示例 (使用键值对) ---

% 1. 仅改变高亮背景颜色
\tikzhl[hlcolor=green!20]{这是绿色高亮}。

% 2. 仅改变下划线粗细
\tikzhl[thickness=2pt]{这是粗下划线}。

% 3. 仅改变下划线颜色
\tikzhl[ulcolor=red]{这是红色下划线}。

% 4. 设置圆角半径
\tikzhl[radius=3pt]{这个是圆角高亮}。

% 5. 组合使用:紫色高亮,3pt下划线,紫色下划线,3pt圆角
\tikzhl[hlcolor=violet!20, thickness=3pt, ulcolor=purple, radius=3pt]{复杂组合示例}。

% 6. 所有参数都使用默认值
默认样式:\tikzhl{默认样式}。

\end{document}

image.png

希望下次不要直接把ai的代码丢上来,要注意到这个问题其实不是集中在一个关键点上,而是泛泛而谈「但是无法运行,有很多报错,请问是什么原因?」,后来者看到这个页面的时候很难反应过来这是在「改l3keys的不正确语法」。

请问是否可以增加绘制外部框线的属性,包括可以调节外部框线的粗细,圆角和颜色?

没看太明白,上面好像已经实现了控制(?)...tikz您是高手,应该可以自己搞定...

2 个回答
Sagittarius Rover
Sagittarius Rover 22小时前
我要成为Typst糕手/(ㄒoㄒ)/~~

这个问题太长了,目测OP在原问题上花的时间和精力并不多。

没有细看,但是AI在一个如此庞大的和精细的需求里是不给力的

但是无法运行,有很多报错

那理应贴出来报错信息。

side-notes:

\usepackage{xcolor} % 用于定义颜色
\usepackage{xparse} % 用于定义带有可选参数和默认值的命令

这两行都是不需要的,tikz内部调用了xcolor;且xparse早已进入内核,因此都不需要显式调用。


第一个报错是:

! Undefined control sequence.
<argument> ..._highlight_color_tl {\keys_value:nn
                                                  {tikzhl}{highlight-color}}
l.91 ...其中包含一些 \tikzhl{需要高亮}
                                                   的内容。
?

很显然,在interface3.pdf中并不能搜索到\keys_value:nn这个API...

\tl_set:Nx \l_tikzhl_highlight_color_tl { \keys_value:nn { tikzhl } { highlight-color } }
\tl_set:Nx \l_tikzhl_underline_thickness_tl { \keys_value:nn { tikzhl } { underline-thickness } }
\tl_set:Nx \l_tikzhl_underline_color_tl { \keys_value:nn { tikzhl } { underline-color } }
\tl_set:Nx \l_tikzhl_corner_radius_tl { \keys_value:nn { tikzhl } { corner-radius } }

上面几行都显然是是错的...

一般来说,l3keys里类似的需求也许会这么写:

\keys_define:nn { foo / blockstyle } {
    bordercolor .tl_set:N = \l_foo_border_color_tl,
    backgroundcolor .tl_set:N = \l_foo_background_color_tl,
    textcolor .tl_set:N = \l_foo_text_color_tl,
    textstyle .tl_set:N = \l_foo_text_style_tl,
}

但这基本上要重写代码,而且需要别人先理解你的原始需求,再理解ai的实现过程,我不喜欢读ai生产的垃圾....


第二个错误:

! Package pgfkeys Error: I do not know the key '/tikz/innersep', to which you p
assed '\dim_use:N \l_tikzhl_padding_dim ', and I am going to ignore it. Perhaps
 you misspelled it.

See the pgfkeys package documentation for explanation.
Type  H <return>  for immediate help.
 ...

l.91 ...其中包含一些 \tikzhl{需要高亮}
                                                   的内容。
?

另一个很显然的问题是,在\ExplSyntaxOn/Off对里,空格均会被忽略,因此带空格的rounded cornersline width都应该加上~.....

改不动了....一定不会有后续了...Happy LaTeX3!

撰写答案

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

发布
问题

分享
好友

手机
浏览

扫码手机浏览