diff --git a/TeXmacs/progs/generic/generic-edit.scm b/TeXmacs/progs/generic/generic-edit.scm index b5eef67813..3aeb285574 100644 --- a/TeXmacs/progs/generic/generic-edit.scm +++ b/TeXmacs/progs/generic/generic-edit.scm @@ -166,6 +166,122 @@ (set-message `(concat "Use " ,sh " in order to insert a tab") "tab")))) +;; 辅助函数:定义 enumerate-tag-list +(define (enumerate-tag-list) + '(enumerate enumerate-1 enumerate-2 enumerate-3 enumerate-4)) + +;; 辅助函数:检查是否在有序列表环境中 +(define (in-enumerate-context?) + (not (not (tree-search-upwards (focus-tree) (lambda (node) (tree-in? node (enumerate-tag-list))))))) + +;; 辅助函数:查找包含 item 的 concat 包装和真正的 item list +(define (find-item-wrapper-and-list item) + (let ((wrapper #f) + (item-list #f)) + (let loop ((current (tree-outer item))) + (if (tree-is? current 'concat) + (begin + (set! wrapper current) + (loop (tree-outer current)) + ) + (set! item-list current) + ) + ) + (values wrapper item-list) + ) +) + +;; 辅助函数:提取 item 内容(处理 concat 包装) +(define (extract-item-content item wrapper) + (if (and item (> (tree-arity item) 0)) + (tree-copy (tree-ref item 0)) + (if (and wrapper (> (tree-arity wrapper) 1)) + (let ((content #f)) + (do ((i 1 (+ i 1))) + ((or content (>= i (tree-arity wrapper)))) + (let ((child (tree-ref wrapper i))) + (if (not (tree-is? child 'item)) + (set! content (tree-copy child)) + #f + ) + ) + ) + content + ) + #f + ) + ) +) + +;; 辅助函数:在列表中移除 item(处理 concat 包装) +(define (remove-item-from-list item wrapper item-list) + (if wrapper + ;; 如果有 wrapper,移除整个 wrapper + (let ((wrapper-index (tree-index wrapper))) + (tree-remove! item-list wrapper-index 1) + ) + ;; 否则移除单个 item + (let ((item-index (tree-index item))) + (tree-remove! item-list item-index 1) + ) + ) +) + +;; 在有序列表中实现缩进功能 +(tm-define (kbd-variant t forwards?) + (:require (and in-enumerate-context? (tree-is? (focus-tree) 'item))) + "在有序列表中按Tab键创建子列表" + + (let ((item (focus-tree))) + + ;; 步骤 1: 查找包装和列表 + (call-with-values (lambda () (find-item-wrapper-and-list item)) + (lambda (wrapper item-list) + + (if (and item item-list) + (let ((item-index (if wrapper (tree-index wrapper) (tree-index item)))) + + (if (> item-index 0) + (let ((prev-item (tree-ref item-list (- item-index 1)))) + + ;; 步骤 2: 提取内容 + (let ((item-content (extract-item-content item wrapper))) + + ;; 步骤 3: 创建子列表并移动内容 + (tree-go-to prev-item :end) + (insert-return) + (make-tmlist 'enumerate) + + (if item-content + (let ((new-item (focus-tree))) + (let ((content-stree (tree->stree item-content))) + (tree-set! new-item `(concat (item), content-stree)) + (tree-go-to new-item) + ) + ) + #f + ) + + ;; 步骤 4: 从原列表中移除 + (remove-item-from-list item wrapper item-list) + ) + ) + (begin + (noop) + ) + ) + ) + (begin + (and-with p (tree-outer t) + (kbd-variant p forwards?) + ) + ) + ) + ) + ) + ) +) + (tm-define (kbd-variant t forwards?) (:require (and (tree-in? t '(label reference pageref eqref smart-ref)) (cursor-inside? t))) diff --git a/devel/201_84.md b/devel/201_84.md new file mode 100644 index 0000000000..3e4ad36715 --- /dev/null +++ b/devel/201_84.md @@ -0,0 +1,49 @@ +# 201_84 有序列表中实现Tab键缩进功能 + +## 如何测试 +- 创建一个有序列表(enumerate环境) +- 在列表中添加多个item +- 将光标放在第二个或后续item上 +- 按Tab键,观察当前item是否缩进成为前一个item的子列表项 +- 测试带concat包装的item是否也能正常缩进 +- 测试第一个item按Tab键是否无反应(因为没有前一个item可以缩进) + +## 2026/02/13 新增有序列表Tab键缩进功能 + +### What +在TeXmacs/progs/generic/generic-edit.scm中新增了有序列表的Tab键缩进功能。当用户在有序列表的item上按Tab键时,该item会缩进成为前一个item的子列表项。 + +### Why +在LaTeX等文档编辑器中,有序列表支持通过Tab键将列表项缩进为子列表,这是常见的编辑功能。TeXmacs此前缺少这一功能,用户体验不够友好。通过添加此功能,用户可以更方便地创建嵌套的有序列表结构。 + +### How +在generic-edit.scm中新增了以下内容: + +1. **辅助函数**: + - `enumerate-tag-list`: 定义有序列表的标签列表(enumerate, enumerate-1, enumerate-2, enumerate-3, enumerate-4) + - `in-enumerate-context?`: 检查当前是否在有序列表环境中 + - `find-item-wrapper-and-list`: 查找包含item的concat包装和真正的item list + - `extract-item-content`: 提取item内容,处理concat包装的情况 + - `remove-item-from-list`: 从列表中移除item,处理concat包装的情况 + +2. **kbd-variant函数重载**: + - 新增了kbd-variant函数的特定版本,专门处理在有序列表中按Tab键的场景 + - 该函数会检查当前是否在有序列表环境中,并且光标是否在item上 + - 当条件满足时,执行以下操作: + a. 查找item的包装和所属列表 + b. 检查是否有前一个item + c. 提取当前item的内容 + d. 在前一个item末尾创建子列表 + e. 将提取的内容移动到新创建的子列表item中 + f. 从原列表中移除当前item + +### 涉及的功能模块 +- 文档编辑功能(generic-edit.scm) +- 列表环境处理(enumerate环境) +- 键盘快捷键处理(kbd-variant) +- 树结构操作(tree操作相关函数) + +### 解决的问题 +- 解决了有序列表中无法通过Tab键创建子列表的问题 +- 提升了用户在编辑有序列表时的效率 +- 使TeXmacs的列表编辑功能更符合主流文档编辑器的使用习惯