Skip to content

Commit 37c4fbf

Browse files
da-liiiclaude
andauthored
[1207] 、直接插入顿号,、Tab 进命令模式并自动禁用输入法 (#4343)
Co-authored-by: Claude <noreply@anthropic.com>
1 parent ba11cfc commit 37c4fbf

5 files changed

Lines changed: 157 additions & 8 deletions

File tree

TeXmacs/progs/generic/generic-edit.scm

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2717,6 +2717,13 @@
27172717
) ;with-innermost
27182718
) ;tm-define
27192719

2720+
(tm-define (kbd-dunhao-tab)
2721+
;; 「、 Tab」:组合命中时 try_shortcut 的 mark_cancel 已回滚最近一次按键
2722+
;; 插入的顿号(、、Tab 只吞离 Tab 最近的那个),这里只需进 hybrid
2723+
;; 命令模式(对齐 \ 键的 make-hybrid)
2724+
(if (or (inside? 'hybrid) (in-prog?)) (noop) (make-hybrid))
2725+
) ;tm-define
2726+
27202727
(tm-define (hybrid-kbd-sub) (activate-hybrid #f) (make-script #f #t))
27212728

27222729
(tm-define (hybrid-kbd-sup) (activate-hybrid #f) (make-script #t #t))

TeXmacs/progs/generic/generic-kbd.scm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,8 @@
229229
("std j" (toggle-chat-sidebar))
230230
) ;kbd-map
231231

232-
(utf8-kbd-map ("" (if (or (inside? 'hybrid) (in-prog?)) (insert "<#3001>") (make-hybrid)))
233-
("、 var" "<#3001>")
232+
(utf8-kbd-map ("" "<#3001>")
233+
("、 var" (kbd-dunhao-tab))
234234
("" (make 'math))
235235
("¥ var" "<#FFE5>")
236236
) ;utf8-kbd-map

TeXmacs/tests/1199.scm

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,16 @@
5454
(cons "¥ leaves math"
5555
(lambda () (keyboard-press "<#FFE5>" 0) (check (get-env "mode") => "text"))
5656
) ;cons
57-
(cons "、 enters hybrid"
58-
(lambda () (keyboard-press "<#3001>" 0) (check-true (inside? 'hybrid)))
57+
(cons "、 inserts dunhao"
58+
(lambda () (keyboard-press "<#3001>" 0) (check (before-cursor) => "<#3001>"))
59+
) ;cons
60+
(cons "、 tab enters hybrid"
61+
(lambda ()
62+
(keyboard-press "tab" 0)
63+
(check-true (inside? 'hybrid))
64+
;; 顿号已被消费,不残留在 hybrid 前
65+
(check (before-cursor) => #f)
66+
) ;lambda
5967
) ;cons
6068
(cons "report + quit" (lambda () (check-report) (quit-TeXmacs)))
6169
) ;list

devel/1207.md

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# [1207] 顿号直接插入,`、 Tab` 进命令模式并自动禁用输入法
2+
3+
## 1 相关文档
4+
5+
- [dddd.md](dddd.md)(任务文档模板)
6+
- devel/1199.md
7+
- devel/1167.md
8+
9+
## 2 任务相关的代码文件
10+
11+
- TeXmacs/progs/generic/generic-kbd.scm
12+
- TeXmacs/progs/generic/generic-edit.scm
13+
- src/Plugins/Qt/QTMWidget.cpp
14+
- TeXmacs/tests/1199.scm
15+
16+
## 3 如何测试
17+
18+
### 3.1 环境准备
19+
20+
1. 构建并确认可启动:
21+
```bash
22+
xmake b stem
23+
xmake r stem
24+
```
25+
能正常打开 Mogan STEM 窗口即可。
26+
2. 系统需装有中文输入法(Linux 推荐 fcitx5,任一平台均可)。
27+
3. 启动应用后,新建一个空白文本文档(文件 → 新建)。
28+
4. 用系统输入法切换快捷键(通常是 Ctrl+Space)把输入法切到中文,
29+
确认在系统任意输入框里能弹出候选词窗口。
30+
31+
### 3.2 自动化回归
32+
33+
```bash
34+
xmake r 1199 # headless 冒烟:进程正常退出、无崩溃
35+
MOGAN_TEST_GUI=1 xmake r 1199 # GUI 断言:控制台 check 报告应无失败项
36+
```
37+
38+
### 3.3 手动验证
39+
40+
下面的「命令模式」指按 `\`(或本任务新增的 `` Tab)后在编辑区出现的
41+
带背景色的 `\` 标记状态;输入命令名后按空格即激活并退出该状态。
42+
43+
#### A. 顿号直接插入(核心修复点)
44+
45+
1. 前置:输入法为中文,光标在正文空白处。
46+
2. 操作:按键盘上印有 `\` 的那个键(中文输入法下它输出顿号 ``)。
47+
3. 预期:编辑区插入一个顿号「、」。****出现命令模式的 `\` 标记,
48+
也不弹候选词窗口。
49+
50+
#### B. `` Tab 进入命令模式,顿号被消费
51+
52+
1. 前置:同 A,先按出一个顿号。
53+
2. 操作:紧接着按 Tab。
54+
3. 预期:刚插入的顿号消失,出现命令模式的 `\` 标记,光标在其后。
55+
4. 操作:继续输入 `alpha`,再按空格。
56+
5. 预期:得到希腊字母 α,回到正常文本状态。
57+
6. 操作:连按两个顿号再按 Tab(`、、Tab`)。
58+
7. 预期:**只有离 Tab 最近的一个顿号被吞掉**,前一个顿号保留,
59+
其后出现命令模式的 `\` 标记。
60+
61+
#### C. 命令模式期间输入法自动禁用、退出自动恢复
62+
63+
1. 前置:输入法为中文。
64+
2. 操作:按 `` 再按 Tab 进入命令模式(或直接按 `\`)。
65+
3. 预期:处于命令模式期间,逐个按字母键 a、b、c……屏幕直接出现字母,
66+
**不弹出**中文候选词窗口(输入法被自动禁用)。
67+
4. 操作:输入 `frac` 后按空格激活,光标停在第一个参数框里
68+
(形如 `<frac|arg1|arg2>` 的 arg1 位置)。
69+
5. 预期:此时再按字母键,中文候选词窗口恢复弹出——参数框里允许
70+
输入中文(输入法只应在命令名输入期间禁用)。
71+
72+
#### D. 回归:英文输入法与既有快捷键不受影响
73+
74+
1. 切到英文输入法(无候选词状态)。
75+
2.`\`:进入命令模式;输入 `alpha`+空格得到 α。
76+
3.`$`:进入数学模式;再按 `$`:回到文本模式。
77+
4. 切回中文输入法,按 `` 键(Shift+4 位的全角输出):进入数学模式;
78+
紧接 Tab:应插入全角 ¥ 字符本身(既有 `¥ var` 行为不变)。
79+
80+
#### E. 回归:数学模式下的顿号行为
81+
82+
1. 前置:中文输入法,按 `$` 进入数学模式。
83+
2. 操作:按 ``(同 A 的键)。
84+
3. 预期:数学模式里同样直接插入顿号字符,不进命令模式。
85+
4. 操作:删掉顿号,按 `` 再按 Tab。
86+
5. 预期:进入命令模式,可输入符号命令。
87+
88+
### 3.4 结果记录
89+
90+
- headless 冒烟:通过(2026-08-14,Linux)。
91+
- GUI 断言链完整执行、进程正常 quit;liii check 报告输出待确认。
92+
- 手动验证 A–E:待测试人员按下表勾选。
93+
94+
| 场景 | 结果 |
95+
|------|------|
96+
| A 顿号直接插入 | 待测 |
97+
| B 、Tab 进命令模式 | 待测 |
98+
| C 输入法禁用/恢复 | 待测 |
99+
| D 英文回归 | 待测 |
100+
| E 数学模式回归 | 待测 |
101+
102+
## 4 What
103+
104+
1. 中文输入法下提交 ``(U+3001)不再直接进入 hybrid 命令模式,
105+
而是作为普通文本插入顿号本身。
106+
2. 插入顿号后紧接 Tab(`、 Tab` 序列)才进入 hybrid 命令模式,
107+
刚插入的顿号会被消费(删除)。
108+
3. 进入 hybrid 命令模式期间输入法自动禁用,退出后自动恢复
109+
(复用 1167 的 ImEnabled 机制)。
110+
111+
## 5 Why
112+
113+
顿号是常见中文标点,1199 把 `` 映射到 make-hybrid 后,
114+
中文输入法下打顿号必然误触命令模式,非常不适应。
115+
翻转设计:顿号回归文本输入,`、 Tab` 作为显式进入命令模式的手势。
116+
117+
## 6 How
118+
119+
- `generic-kbd.scm`:utf8-kbd-map 中 `` 的绑定从 make-hybrid 翻转为
120+
插入 `<#3001>``、 var` 从插入顿号翻转为调用 `kbd-dunhao-tab`
121+
C++ try_shortcut 对「完整键 + 前缀」(status=3)先执行完整动作、
122+
再保留 `sh_s` 待续键,两种行为可共存。
123+
- `generic-edit.scm`:新增 `kbd-dunhao-tab`——hybrid/prog 模式下不嵌套、
124+
保持 noop(对齐 `\` 键的守卫条件),其余直接 `make-hybrid`
125+
顿号的消费不在这里做:`、 Tab` 组合命中时 try_shortcut 走
126+
`mark_cancel``edit_keyboard.cpp`),archiver 会回滚自最近一次
127+
`` 按键以来的编辑,刚插入的顿号随之被撤销——`、、Tab` 只吞
128+
离 Tab 最近的一个顿号。初版曾在本函数里 `remove-text` 二次消费,
129+
导致连按顿号时全部被吞,已移除。
130+
- `QTMWidget.cpp``ImEnabled` 查询与 inputMethodEvent 的 preedit 开关
131+
`in-math?` 改为 `in-math-or-hybrid?`。进出 hybrid 光标必动,
132+
SLOT_CURSOR 已有的 `QInputMethod::update(ImEnabled)` 自动覆盖切换。
133+
- `1199.scm`:「、 enters hybrid」步骤更新为新契约(、插入顿号 +
134+
、Tab 进 hybrid 且顿号被消费)。

src/Plugins/Qt/QTMWidget.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -383,8 +383,8 @@ QTMWidget::inputMethodEvent (QInputMethodEvent* event) {
383383
else if (im_preedit_str == "on") {
384384
im_preedit_switch= true;
385385
}
386-
// Disable preedit in math mode to prevent crash in QQPinyin
387-
if (as_bool (call ("in-math?"))) im_preedit_switch= false;
386+
// Disable preedit in math/hybrid mode to prevent crash in QQPinyin
387+
if (as_bool (call ("in-math-or-hybrid?"))) im_preedit_switch= false;
388388

389389
string r= "pre-edit:";
390390
if (im_preedit_switch && !preedit_string.isEmpty ()) {
@@ -434,8 +434,8 @@ QVariant
434434
QTMWidget::inputMethodQuery (Qt::InputMethodQuery query) const {
435435
switch (query) {
436436
case Qt::ImEnabled:
437-
// 数学模式下禁用输入法,按键直接进入公式编辑
438-
return QVariant (!as_bool (call ("in-math?")));
437+
// 数学/hybrid 命令模式下禁用输入法,按键直接进入公式或命令输入
438+
return QVariant (!as_bool (call ("in-math-or-hybrid?")));
439439
#if QT_VERSION < 0x060000
440440
case Qt::ImMicroFocus: {
441441
const QPoint& topleft= cursor_pos - tm_widget ()->backing_pos +

0 commit comments

Comments
 (0)