Skip to content

Commit d07901c

Browse files
authored
[2040] 补充语言切换qml弹窗和 later 统一 silent 写值 (#4047)
1 parent 5ff7da6 commit d07901c

10 files changed

Lines changed: 226 additions & 48 deletions

File tree

TeXmacs/plugins/lang/dic/en_US/zh_CN.scm

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,6 @@
118118
("Reasoning" "推理中")
119119
("Rename" "重命名")
120120
("Replace TeXmacs styles with no LaTeX equivalents" "替换没有 LaTeX 等价项的 TeXmacs 样式")
121-
("Requires restarting Mogan STEM to take full effect. Restart now?" "需要重新启动 Mogan STEM 才能完全生效。现在重启吗?")
122-
("Requires restarting Liii STEM to take full effect. Restart now?" "需要重新启动 Liii STEM 才能完全生效。现在重启吗?")
123121
("Restart TeXmacs in order to let changes take effect" "重启TeXmacs以使您的更改生效")
124122
("Restore" "恢复")
125123
("Return::keyboard" "Return")
@@ -2399,6 +2397,7 @@
23992397
("swedish" "瑞典语")
24002398
("swiss" "")
24012399
("switch interface theme" "切换界面主题")
2400+
("switch language" "切换语言")
24022401
("switch keyboard shortcut style" "切换快捷键显示风格")
24032402
("switch look and feel" "切换外观风格")
24042403
("switch preference" "切换首选项")

TeXmacs/progs/kernel/texmacs/tm-preferences.scm

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,16 @@
155155
) ;with
156156
) ;tm-define
157157

158+
;; 同 set-pretty-preference 但用 cpp-set-preference-silent 写值(不触发 notify),
159+
;; 供需重启字段的「稍后」分支使用:写新值下次启动生效,当前会话不实时切。
160+
(tm-define (set-pretty-preference-silent which pretty-val)
161+
(with val
162+
(ahash-ref preference-decode-table (cons which pretty-val))
163+
(cpp-set-preference-silent which (or val pretty-val))
164+
(save-preferences)
165+
) ;with
166+
) ;tm-define
167+
158168
(tm-define (get-pretty-preference which)
159169
(with val
160170
(get-preference which)

TeXmacs/progs/prog/glue-symbols.scm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
"cpp-has-preference?"
9696
"cpp-get-preference"
9797
"cpp-set-preference"
98+
"cpp-set-preference-silent"
9899
"cpp-reset-preference"
99100
"save-preferences"
100101
"get-default-printing-command"

TeXmacs/progs/texmacs/menus/preferences-menu.scm

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,20 @@
2626
;; Preferred scripting language
2727
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2828

29-
;; 三按钮重启确认的正文(陈述句,无问句——问句由按钮表达)。title 由调用方
30-
;; 按字段给出(如「切换界面主题」),本函数只产出通用的「需重启才生效」说明。
31-
(tm-define (restart-required-message)
32-
(if (community-stem?)
33-
(translate "Requires restarting Mogan STEM to take full effect. Restart now?")
34-
(translate "Requires restarting Liii STEM to take full effect. Restart now?")
35-
) ;if
29+
;; 需重启字段的内部值 -> ConfirmRestart 标题翻译。
30+
(tm-define (restart-preference-title which)
31+
(cond ((== which "look and feel") (translate "Switch look and feel"))
32+
((== which "gui theme") (translate "Switch interface theme"))
33+
((== which "language") (translate "Switch language"))
34+
((== which "keyboard shortcut style")
35+
(translate "Switch keyboard shortcut style")
36+
) ;
37+
(else (translate "Switch preference"))
38+
) ;cond
3639
) ;tm-define
3740

41+
;; 三按钮重启确认的正文(陈述句,无问句——问句由按钮表达)。title 由调用方
42+
;; 按字段给出(如「切换界面主题」),本函数只产出通用的「需重启才生效」说明。
3843
(tm-define (restart-effect-message)
3944
(if (community-stem?)
4045
(translate "This change requires restarting Mogan STEM to take full effect.")
@@ -44,10 +49,11 @@
4449

4550
;; 三按钮重启确认:弹 ConfirmRestart(重启/稍后/取消),按返回值分别
4651
;; restart -> apply-proc + 存盘 + 重启
47-
;; later -> apply-proc(保留新值,不重启
52+
;; later -> later-proc(写新值但不触发实时副作用,下次启动生效
4853
;; cancel -> rollback-proc(回滚旧值)
49-
;; apply-proc / rollback-proc 为零参过程;用户未定义 save-all-buffers 时惰性加载。
50-
(tm-define (confirm-restart-and-act title apply-proc rollback-proc)
54+
;; later-proc 由调用方给出 silent 写值过程(如 set-pretty-preference-silent /
55+
;; cpp-set-preference-silent):需重启字段当前会话不实时切,避免 crash 或状态不一致。
56+
(tm-define (confirm-restart-and-act title apply-proc rollback-proc later-proc)
5157
(with msg
5258
(restart-effect-message)
5359
(with choice
@@ -60,7 +66,7 @@
6066
(save-all-buffers)
6167
(restart-TeXmacs)
6268
) ;
63-
((== choice "later") (apply-proc))
69+
((== choice "later") (later-proc))
6470
(else (rollback-proc))
6571
) ;cond
6672
) ;with
@@ -119,28 +125,18 @@
119125
;; Language settings and restart notifications
120126
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
121127

128+
;; later 用 silent 写值:实时切 language 不重启可能 crash,故当前会话不切,下次启动生效。
129+
;; restart 仍走 set-preference(实时切):紧接重启、进程即将退出,实时副作用无意义。
122130
(tm-define (set-language-and-notify lan)
123131
(let ((old (get-preference "language")))
124132
(if (== lan old)
125133
(set-preference "language" lan)
126-
(let ((msg (restart-required-message)))
127-
(user-confirm msg
128-
#f
129-
(lambda (answ)
130-
(if answ
131-
(begin
132-
(set-preference "language" lan)
133-
(when (not (defined? 'save-all-buffers))
134-
(use-modules (plugin autosave))
135-
) ;when
136-
(save-all-buffers)
137-
(restart-TeXmacs)
138-
) ;begin
139-
(set-preference "language" old)
140-
) ;if
141-
) ;lambda
142-
) ;user-confirm
143-
) ;let
134+
(confirm-restart-and-act (restart-preference-title "language")
135+
(lambda () (set-preference "language" lan))
136+
(lambda () (set-preference "language" old))
137+
;; language 无 pretty 映射,不复用带 decode 的 set-pretty-preference-silent。
138+
(lambda () (cpp-set-preference-silent "language" lan) (save-preferences))
139+
) ;confirm-restart-and-act
144140
) ;if
145141
) ;let
146142
) ;tm-define

TeXmacs/progs/texmacs/menus/preferences-widgets.scm

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,26 +22,14 @@
2222
;; Wrapper
2323
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2424

25-
26-
;; 需重启字段的三按钮确认标题映射(内部值 -> 翻译标题)。
27-
28-
(define (restart-preference-title which)
29-
(cond ((== which "look and feel") (translate "Switch look and feel"))
30-
((== which "gui theme") (translate "Switch interface theme"))
31-
((== which "keyboard shortcut style")
32-
(translate "Switch keyboard shortcut style")
33-
) ;
34-
(else (translate "Switch preference"))
35-
) ;cond
36-
) ;define
37-
3825
(tm-define (set-pretty-preference* which pretty-val)
3926
(let* ((old (get-pretty-preference which)))
4027
(when (!= old pretty-val)
41-
;; 三按钮确认:重启 / 稍后(保留新值)/ 取消(回滚旧值,修复旧 no 不回滚的 bug)。
28+
;; 三按钮确认:重启 / 稍后(silent 写值,下次启动生效)/ 取消(回滚旧值)。
4229
(confirm-restart-and-act (restart-preference-title which)
4330
(lambda () (set-pretty-preference which pretty-val))
4431
(lambda () (set-pretty-preference which old))
32+
(lambda () (set-pretty-preference-silent which pretty-val))
4533
) ;confirm-restart-and-act
4634
) ;when
4735
) ;let*

TeXmacs/tests/2040.scm

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2+
;;
3+
;; MODULE : 2040.scm
4+
;; DESCRIPTION : Test language ConfirmRestart 三按钮(重启/稍后/取消)语义
5+
;; COPYRIGHT : (C) 2026 Mogan STEM
6+
;;
7+
;; 用 MOGAN_TEST_CONFIRM_RESTART 钩子驱动 cpp-confirm-restart 返回值,覆盖:
8+
;; later -> 只写值不实时切(get-preference 已是新值,get-output-language 不变)
9+
;; cancel -> 回滚旧值(get-preference 回到 old)
10+
;; (restart 会触发重启,不在自动化测试覆盖范围)
11+
;;
12+
;; 覆盖缺口:later 的落盘未断言(scheme 侧无 preference 文件路径入口),仅验内存值。
13+
;; 误删 later-proc 的 save-preferences 此测试不会失败;后续可补 glue 读文件验证。
14+
;;
15+
;; 运行:MOGAN_TEST_CONFIRM_RESTART=later xmake r 2040
16+
;; (钩子在 run_qml_dialog 之前 return,headless 可跑,无需 MOGAN_TEST_GUI)
17+
;;
18+
;; This software falls under the GNU general public license version 3 or later.
19+
;; It comes WITHOUT ANY WARRANTY whatsoever. Details see LICENSE.
20+
;;
21+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
22+
23+
(use-modules (texmacs menus preferences-menu))
24+
(import (liii check))
25+
26+
(tm-define (test_2040)
27+
(let ((orig (get-preference "language")) (orig-out (get-output-language)))
28+
;; 统一回到 english 作为起点,避免受历史 preference 影响
29+
(cpp-set-preference "language" "english")
30+
(set-output-language "english")
31+
32+
;; --- later:写值不实时切 ---
33+
(system-setenv "MOGAN_TEST_CONFIRM_RESTART" "later")
34+
(set-language-and-notify "chinese")
35+
;; preference 已写入新值
36+
(check (get-preference "language") => "chinese")
37+
;; 但输出语言未实时切换(later 用 cpp-set-preference-silent 跳过 notify-language)
38+
(check (get-output-language) => "english")
39+
40+
;; --- cancel:回滚旧值 ---
41+
(system-setenv "MOGAN_TEST_CONFIRM_RESTART" "cancel")
42+
(set-language-and-notify "english")
43+
;; cancel 不落定,回滚;此时旧值是 chinese(上一步 later 写入的)
44+
(check (get-preference "language") => "chinese")
45+
46+
;; 还原(空串不命中钩子的 restart/later/cancel,等同取消)
47+
(system-setenv "MOGAN_TEST_CONFIRM_RESTART" "")
48+
(cpp-set-preference "language" orig)
49+
(set-output-language orig-out)
50+
) ;let
51+
) ;tm-define

devel/2040.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,117 @@ xmake b qml_load_test && xmake r qml_load_test
9696
`("this change requires ...)" ...)` ×2 / `("keyboard shortcut style" "快捷键显示风格")`
9797
全部**小写首字母登记**(靠 `translate` 首字母大写折叠命中代码里的大写 key)
9898
-**字母序**插入 `zh_CN.scm` 对应字母段
99+
100+
## 8 补充:切换语言接入 ConfirmRestart 三按钮 + later 统一 silent 写值
101+
102+
2040 合并后,原计划用独立 PR(2041)把切换语言改成不弹窗即时生效,但 2041 暂无法合并。
103+
而 language 切换确实需要重启才生效,故将其从旧 `user-confirm`(两按钮)升级为
104+
ConfirmRestart 三按钮,与 look and feel / gui theme 等需重启字段统一。
105+
106+
### What
107+
1. `set-language-and-notify`:值变化时改走 `confirm-restart-and-act`(重启/稍后/取消),
108+
值未变直接落定不弹窗
109+
2. `confirm-restart-and-act` 加第 4 参 `later-proc`(固定 4 参,非可选——tm-define 下
110+
rest 参数虽可用但固定签名更清晰),later 分支调它
111+
3. **新增 C++ glue `cpp-set-preference-silent`**(绑 `set_user_preference_silent`):
112+
写 preference 值但**不调 `notify_preference`**。later-proc 用它写值,避免当前会话
113+
实时切(实时切换需重启字段可能 crash 或状态不一致),下次启动读 preference 生效
114+
4. **所有需重启字段 later 统一 silent 写值**(不只 language):
115+
- `set-pretty-preference*`(look and feel / gui theme):later-proc 用新增的
116+
`set-pretty-preference-silent`(decode + `cpp-set-preference-silent` + 存盘)
117+
- `set-language-and-notify`:later-proc 用 `cpp-set-preference-silent` + 存盘
118+
5. `restart-preference-title``preferences-widgets.scm` **移到 `preferences-menu.scm`**
119+
新增 `language` 分支(`translate "Switch language"`),改 `tm-define` 导出
120+
(原 widgets 私有 `define` 形成 widgets→menu 反向依赖)
121+
6. 删除被取代的 `restart-required-message`(旧两按钮正文,已无调用方)及字典条目
122+
`Requires restarting ... Restart now?` ×2(死 key)
123+
7. 字典新增 `("switch language" "切换语言")`
124+
125+
### Why
126+
- 三按钮 later 语义统一为「写新值,下次启动生效」——当前会话不实时切。
127+
**根因**`cpp-set-preference`(C++ `set_user_preference`)内部会调 `notify_preference`
128+
触发 `notify-language` 等回调实时切换;实时切 language 不重启可能 crash。故新增
129+
`set_user_preference_silent`(只写值不 notify),later 走它。look and feel / gui theme
130+
一并统一,行为一致且避免各自实时副作用
131+
- restart 仍用 `set-preference`(notify,实时切)+ 存盘 + 重启——马上重启,实时副作用无所谓
132+
- `restart-preference-title` 移到 menu:消除 widgets→menu 反向依赖,menu/widgets 共用
133+
-`restart-required-message`:升级后无调用方,连配套字典 key 一起清理
134+
135+
### How
136+
- `src/System/Config/preferences.cpp` / `.hpp`:新增 `set_user_preference_silent`
137+
(同 `set_user_preference` 但去掉 `notify_preference(var)`
138+
- `src/Scheme/Glue/glue_basic.lua` + `TeXmacs/progs/prog/glue-symbols.scm`:声明并登记
139+
`cpp-set-preference-silent`
140+
- `TeXmacs/progs/kernel/texmacs/tm-preferences.scm`:新增 `set-pretty-preference-silent`
141+
(decode + silent 写值 + 存盘)
142+
- `preferences-menu.scm`
143+
- `restart-preference-title`(tm-define,含 language 分支)
144+
- `confirm-restart-and-act` 固定 4 参 `(title apply-proc rollback-proc later-proc)`
145+
later 走 `later-proc`
146+
- `set-language-and-notify` 传 later-proc = `cpp-set-preference-silent + save-preferences`
147+
- `preferences-widgets.scm``set-pretty-preference*` later-proc 用 `set-pretty-preference-silent`
148+
删本地 `restart-preference-title`
149+
- `zh_CN.scm`:删 `Requires restarting ... Restart now?` ×2,加 `switch language`
150+
151+
### 验证
152+
```bash
153+
gf fmt --changed-since=main
154+
xmake b stem && xmake i stem # 注意:glue 改动需 xmake i stem 更新打包目录
155+
xmake b qml_load_test && xmake r qml_load_test # ConfirmRestart 加载测试
156+
# language 三按钮(用 MOGAN_TEST_CONFIRM_RESTART 钩子驱动,headless 可跑):
157+
MOGAN_TEST_CONFIRM_RESTART=later xmake r 2040 # later 写值不实时切(get-output-language 不变)
158+
# 人工:打开首选项切 Language / gui theme:
159+
# 重启 = 立即生效并重启
160+
# 稍后 = 当前会话不变,下次启动生效(preference 已存新值)
161+
# 取消 = 回滚
162+
```
163+
164+
## 9 preference 写值的 notify 机制与 silent 变体
165+
166+
本 PR 新增 `set_user_preference_silent`(写值不 notify),服务于「稍后」分支。记录
167+
notify 机制,说明 silent 的适用边界。
168+
169+
### 9.1 notify 是「同步进程内派生状态」
170+
171+
`notify_preference`(C++ `preferences.cpp:188` → scheme `notify-preference`
172+
`tm-preferences.scm:103`)按字段名分派到 call-back:
173+
174+
```scheme
175+
(tm-define (notify-preference which)
176+
((get-call-back which) which (get-preference which)))
177+
```
178+
179+
call-back 的职责是**让进程内的派生状态跟上 preference 新值**。以 `language` 为例,
180+
call-back `notify-language``tm-server.scm:51`)调 `set-output-language`,改 scheme
181+
全局 `output_language`——这是「当前生效值」,独立于 preference 文件里的值。
182+
183+
### 9.2 两类字段,silent 的适用面不同
184+
185+
- **纯存储型**(如 `plugin:binary:*``texlive:*` 路径):无 call-back 维护派生状态,
186+
读写只看 preference 值。这类字段 silent 写值无副作用。
187+
- **带派生状态型**(language / gui theme / look and feel):进程内有靠 notify 同步的
188+
「当前生效值」。silent 写值后 preference 已更新,但生效值未变,二者短暂脱节。
189+
190+
脱节在本 PR 是**预期的**:用户选「稍后」即明知当前会话不变、下次启动生效;脱节状态寿命
191+
仅到下次重启。因此 silent 是有适用前提的特化写值(需当前会话能容忍脱节),并非通用 setter。
192+
`.hpp``@note` 标注此约束,避免日后误用于「想立即生效却忘了 notify」的普通字段。
193+
194+
### 9.3 应用:本 PR 的 silent 写值与 restart 分支
195+
196+
- **`set_user_preference_silent`**(later 分支):写新值落盘,下次启动生效,当前会话不
197+
实时切。language 实时切不重启可能 crash(devel 记录的根因),later 用 silent 规避。
198+
- **restart 分支仍走 `set-preference`(notify)**:紧接 `save-all-buffers` +
199+
`restart-TeXmacs`,进程即将退出,实时切与退出间窗口极短,无需 silent。
200+
- silent 调用点目前仅 2 处(language later-proc / `set-pretty-preference-silent`),
201+
均为受控的 later 场景。
202+
203+
### 9.4 顺带的注释/测试补充
204+
205+
- `preferences.hpp`:silent 声明补 Doxygen `@note`(标注适用边界)
206+
- `preferences.cpp`:silent 函数体补一行 Why
207+
- `preferences-menu.scm` `set-language-and-notify`:later / restart 两分支各一行 Why,
208+
later-proc 内联注释说明 language 无 pretty 映射、不复用带 decode 的
209+
`set-pretty-preference-silent`
210+
- `tests/2040.scm`:头部注明 later 落盘未断言(scheme 侧无 preference 文件路径入口),
211+
误删 later-proc 的 `save-preferences` 此测试不会失败;后续可补 glue 读文件验证
212+

src/Scheme/Glue/glue_basic.lua

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,15 @@ function main()
266266
"string"
267267
}
268268
},
269+
{
270+
scm_name = "cpp-set-preference-silent",
271+
cpp_name = "set_user_preference_silent",
272+
ret_type = "void",
273+
arg_list = {
274+
"string",
275+
"string"
276+
}
277+
},
269278
{
270279
scm_name = "cpp-reset-preference",
271280
cpp_name = "reset_user_preference",

src/System/Config/preferences.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,13 @@ set_user_preference (string var, string val) {
103103
notify_preference (var);
104104
}
105105

106+
void
107+
set_user_preference_silent (string var, string val) {
108+
if (val == "default") user_prefs->reset (var);
109+
else user_prefs (var)= val;
110+
user_prefs_modified= true;
111+
}
112+
106113
void
107114
reset_user_preference (string var) {
108115
user_prefs->reset (var);

src/System/Config/preferences.hpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,12 @@ void get_old_settings (string s);
2121
bool has_user_preference (string var);
2222
string get_user_preference (string var, string def= "");
2323
void set_user_preference (string var, string val);
24-
void reset_user_preference (string var);
25-
void load_user_preferences ();
26-
void save_user_preferences ();
24+
/*! @note 只写值不 notify,仅供需重启字段 deferred 写值;勿用于普通字段,
25+
* 不 notify 会使依赖该回调的 UI/内存状态不同步。 */
26+
void set_user_preference_silent (string var, string val);
27+
void reset_user_preference (string var);
28+
void load_user_preferences ();
29+
void save_user_preferences ();
2730

2831
void notify_preferences_booted ();
2932
void set_preference (string var, string val);

0 commit comments

Comments
 (0)