Skip to content

[201_35] 修复在 frame、solution 等环境内的公式编号错位的问题#2897

Open
AXeonV wants to merge 1 commit intomainfrom
ty/201_35/3
Open

[201_35] 修复在 frame、solution 等环境内的公式编号错位的问题#2897
AXeonV wants to merge 1 commit intomainfrom
ty/201_35/3

Conversation

@AXeonV
Copy link
Contributor

@AXeonV AXeonV commented Feb 28, 2026

[201_35] align环境编号后 smart-ref 以及 reference 失效

如何测试

打开 TeXmacs\tests\tmu\201_35.tmu ,查看 smart-ref 和 reference 的公式编号是否正确

  • line1 的 label 编号应该都是1(这一次修改的修复样例)
  • line2 的 label 编号应该都是2(这一次修改的修复样例)
  • line3 的 label 编号应该都是3
  • line4 的 label 编号应该都是4
  • line5 的 label 编号应该都是5
  • line6 的 label 编号应该都是6

2026/2/28

What

修复在 frame、solution 等环境内的公式编号错位的问题

Why

之前的实现把 defer-tags=row 放在 table_rep::typeset_row 行入口处,导致所有走 table row 的场景都可能触发延迟绑定

defer-tags 的设计初衷仅是服务多行公式(align/eqnarray/gather 等)中“label 先于 eq-number”的时序修正。像 frame、solution 这类外层环境内部也会进入 typeset_row,从而把本不该延迟重绑的 label 键加入 the-tags,最终在后续 set-binding(1参)时被错误覆盖,表现为编号错位

How

typeset_rowdefer-tags/the-tags 的行级作用域从“无条件开启”改为“仅在多行显示公式场景开启”:

  1. hyphen == "y":仅处理可按行拆分的数学表格(多行公式结构信号)
  2. mode == "math":仅在数学语义环境生效
  3. math-display == "true":仅在陈列公式模式生效

满足三条件时才 local_begin ("defer-tags", "row")local_begin ("the-tags", tuple);否则不进入 defer 逻辑。exec_set_binding 中已有的 defer-tags=="row" 判定逻辑保持不变,因此修复后既保留 align 场景的正确重绑,也避免 frame/solution 等环境误触发

2025/12/12

What

之前的修改会导致 equation 环境中 label 被下一行覆盖绑定,导致编号出错

Why

table_rep::typeset_row 只用 local_begin/end the-tags 的隔离设置在 equation 环境下不会进入 table 行,导致 the-tags 没被隔离好,因此会被下一个 equation 覆盖绑定

How

在表格行入口打标记 defer-tags=row,并在 2 参 set-binding(label, <value|the-label>) 时判断只有存在 defer-tags=="row" 标记时才把键加入 the-tags

if (is_func (t[1], VALUE, 1) && t[1][0] == THE_LABEL) {
  tree defer_tag= read ("defer-tags");
  tree old_tags = read ("the-tags");
  if (is_tuple (old_tags) && is_atomic (defer_tag) && defer_tag == "row") {
    tree new_tags= old_tags * tuple (key);
    assign (string ("the-tags"), new_tags);
    refined= true;
  }
}

这么做还能删除前一个实现中不必要的打补丁,因为列表环境的覆盖绑定也是因为 the-tags 没被隔离好:

// if refined but new value is not atomic, skip (only for 1-arg set-binding)
if (N (t) == 1 && !is_atomic (value) && is_func (old_value, TUPLE) && N (old_value) >= 1 && is_atomic (old_value[0])) continue;

2025/11/30

What

在 align 环境中,若 <label|id> 出现在 <eq-number> 之前,则 <reference|id><smart-ref|id> 会"错位",即显示上一行的编号或“?”。

Why

这是一个执行时序问题,排版器按从左到右的顺序处理公式/表格时:

  • <label|id> 实际展开是 <set-binding|id|<value|the-label>>(二参形式),然后立即用当前the-label 值绑定
  • <eq-number> 内部调用 <next-equation>,然后执行 <set-binding|<the-equation>>(一参形式),更新计数器并设置 the-label

<label|id> 出现在 <eq-number> 之前时,在执行 <set-binding|id|<value|the-label>>the-label 尚未更新,所以就绑定了错误的值

How

  1. edit_env_rep::exec_set_binding 中,当处理到 <label|id> 的二参形式的 set-binding 时,若值来自 <value|the-label>,则将这个键加入 the-tags。这样当后续处理到 <eq-number> 的一参形式的 set-binding 时,the-tags 能读取这些键,就会用正确的编号值去覆盖绑定它们。如下:
if (is_func (t[1], VALUE, 1) && t[1][0] == THE_LABEL) {
  tree old_tags= read ("the-tags");
  if (is_tuple (old_tags)) {
    tree new_tags= old_tags * tuple (key);
    assign (string ("the-tags"), new_tags);
  }
}
  1. table_rep::typeset_row 中,在每行开始时隔离 the-tags,这样确保行与行之间的 the-tags 互不干扰,避免 <label|id> 如果打在 <eq-number> 之后,会被下一行的 <eq-number> 错误覆盖。如下:
tree old_tags= env->local_begin ("the-tags", tree (TUPLE));
// ...
env->local_end ("the-tags", old_tags);

FIX

  1. 以上修改实测会触发覆盖绑定的警告。故在处理一参和二参形式时,当涉及延迟绑定时都设置 refined= true ,在后面需要流入 redefined 时检测 refined 并跳过即可

  2. 在列表等环境下,如果新值并不符合可读要求(不是atomic结构)则跳过覆盖绑定

// if refined but new value is not atomic, skip (only for 1-arg set-binding)
if (N (t) == 1 && !is_atomic (value) && is_func (old_value, TUPLE) && N (old_value) >= 1 && is_atomic (old_value[0])) continue;

Copilot AI review requested due to automatic review settings February 28, 2026 08:41
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes equation label/reference numbering misalignment that could occur when frame, solution, and similar outer environments internally route through table_rep::typeset_row, unintentionally triggering the “deferred tag rebinding” mechanism intended for multi-line display math (e.g., align).

Changes:

  • Restrict row-scoped defer-tags=row and the-tags isolation in table_rep::typeset_row to multi-line display math tables only (table-hyphen=y, mode=math, math-display=true).
  • Update the developer note (devel/201_35.md) with the new regression context and expected numbering outcomes.
  • Expand the regression test TMU to cover the frame + equation scenario alongside the existing align/equation checks.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
src/Typeset/Table/table.cpp Gates defer-tags/the-tags row scoping to multi-line display math tables to prevent accidental deferred rebinding in non-target environments.
devel/201_35.md Documents the new failure mode (frame/solution) and updated verification steps.
TeXmacs/tests/tmu/201_35.tmu Adds a frame test case and updates expected reference/smart-ref associations to validate the fix.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants