|
1 | 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | 2 | ;; |
3 | 3 | ;; MODULE : 2014.scm |
4 | | -;; DESCRIPTION : GUI 复现:切换 tab 时观察 menu 缓存是否命中 |
| 4 | +;; DESCRIPTION : GUI 复现:切换/新建/关闭/拖拽 tab 时观察 menu 缓存命中与重建 |
5 | 5 | ;; COPYRIGHT : (C) 2026 Mogan STEM |
6 | 6 | ;; |
7 | 7 | ;; PURPOSE |
8 | | -;; 排查"切 tab 仍触发 SLOT_TAB_PAGES 整条重建"。配合 get_menu_widget 里 |
9 | | -;; which==4 的 [tabpage] menu cache HIT/MISS 日志,在真实 GUI 里切换两个 |
10 | | -;; 文档,看每次切换是 HIT(不重建)还是 MISS(重建)。 |
| 8 | +;; 排查"切 tab / 增删 / 排序 tab 触发 SLOT_TAB_PAGES 整条重建"。配合 |
| 9 | +;; get_menu_widget 里 which==4 的 [tabpage] menu cache HIT/MISS 日志与 |
| 10 | +;; QTMTabPageContainer 的 [tabpage] rebuild/active 计数日志,在真实 GUI 里 |
| 11 | +;; 驱动四种动作,看每次是 HIT(不重建)还是 MISS(重建)。 |
11 | 12 | ;; |
12 | | -;; 夹具从 $TEXMACS_PATH/tests/tmu 复制到 /tmp,避免 save/编辑污染检入副本。 |
13 | | -;; 带 stem-doc-id 以排除 auto-backup 标脏干扰(见 1106)。 |
| 13 | +;; 覆盖动作: |
| 14 | +;; 1. 切换 active(switch-to-view-index)—— 应只 active、零 rebuild。 |
| 15 | +;; 2. 点 + 新建(new-document)—— 增 tab,签名变 → 1 次 rebuild。 |
| 16 | +;; 3. 关闭一个 tab(safely-kill-tabpage)—— 减 tab,签名变 → 1 次 rebuild。 |
| 17 | +;; 4. 拖拽排序(move-buffer-to-index)—— 集合不变、仅顺序变,签名按 |
| 18 | +;; tabpage-list 顺序拼接 → 顺序变也算签名变 → 1 次 rebuild(但指针复用)。 |
14 | 19 | ;; |
| 20 | +;; 夹具从 $TEXMACS_PATH/tests/tmu 复制到 /tmp,避免 save/编辑污染检入副本。 |
15 | 21 | ;; 用 exec-delayed-at 串异步链,不阻塞 Qt 事件循环;链尾自己 quit。 |
16 | 22 | ;; |
17 | 23 | ;; USAGE |
|
22 | 28 |
|
23 | 29 | (texmacs-module (texmacs tests 2014)) |
24 | 30 |
|
| 31 | +(import (only (srfi srfi-1) list-index)) |
| 32 | + |
25 | 33 | (define (tmp-name name) |
26 | 34 | (string->url (string-append "/tmp/" name)) |
27 | 35 | ) ;define |
|
34 | 42 | ) ;let |
35 | 43 | ) ;define |
36 | 44 |
|
| 45 | +;; 步骤间隔:给 Qt 事件循环 + typeset 足够时间,避免异步事件叠加。 |
| 46 | + |
37 | 47 | (define step-delay-ms 4000) |
38 | 48 |
|
| 49 | +;; 打印当前 tab 数与 buffer 列表,便于把 [tabpage] 日志和动作对齐。 |
| 50 | + |
| 51 | +(define (log-state label) |
| 52 | + (let ((n (length (tabpage-list #t)))) |
| 53 | + (display "[2014-step] ") |
| 54 | + (display label) |
| 55 | + (display " tabs=") |
| 56 | + (display n) |
| 57 | + (newline) |
| 58 | + ) ;let |
| 59 | +) ;define |
| 60 | + |
| 61 | +;; 串异步链:每步在 exec-delayed-at 触发,步间隔 step-delay-ms。 |
| 62 | +;; 每个元素是 (label . action-thunk)。 |
| 63 | + |
39 | 64 | (define (run-chain steps) |
40 | 65 | (let loop |
41 | 66 | ((rest steps) (t (+ (texmacs-time) step-delay-ms))) |
|
46 | 71 | (display label) |
47 | 72 | (newline) |
48 | 73 | (act) |
| 74 | + (log-state (string-append "after " label)) |
49 | 75 | (loop (cdr rest) (+ (texmacs-time) step-delay-ms)) |
50 | 76 | ) ;lambda |
51 | 77 | t |
|
59 | 85 | (refresh-fixture "2014_a.tmu") |
60 | 86 | (refresh-fixture "2014_b.tmu") |
61 | 87 | (let* ((path-a (tmp-name "2014_a.tmu")) (path-b (tmp-name "2014_b.tmu"))) |
62 | | - (let ((steps (list (cons "load a" (lambda () (load-buffer path-a))) |
63 | | - (cons "load b" (lambda () (load-buffer path-b))) |
64 | | - ) ;list |
| 88 | + ;; 动作链: |
| 89 | + ;; - 载入 a、b(建 tab) |
| 90 | + ;; - 1. 来回切 5 轮(应零 rebuild,全部 menu cache HIT) |
| 91 | + ;; - 2. 新建 1 个 tab(+,应 1 次 MISS + 1 次 rebuild,added 仅 +1) |
| 92 | + ;; - 3. 关闭当前 tab(应 1 次 MISS + 1 次 rebuild,removed 仅 +1) |
| 93 | + ;; - 4. 排序:把当前 buffer 移到首位(应 1 次 MISS + 1 次 rebuild,added/removed 均为 0) |
| 94 | + ;; - 结束退出 |
| 95 | + ;; |
| 96 | + ;; 关闭/排序的可预测性要点: |
| 97 | + ;; - new-document 建的是脏 buffer,safely-kill-tabpage 会命中 buffer-modified? |
| 98 | + ;; 分支弹确认框、卡住异步链。故新建后立即 buffer-pretend-saved 去脏。 |
| 99 | + ;; - 排序用 move-buffer-to-index 移到 index 0(首位),顺序必变。 |
| 100 | + (let ((steps (append (list (cons "load a" (lambda () (load-buffer path-a))) |
| 101 | + (cons "load b" (lambda () (load-buffer path-b))) |
| 102 | + ) ;list |
| 103 | + ;; 1) 切换 active:5 轮来回切 view 1 / view 2 |
| 104 | + (let loop |
| 105 | + ((i 0) (acc '())) |
| 106 | + (if (>= i 5) |
| 107 | + (reverse acc) |
| 108 | + (loop (+ i 1) |
| 109 | + (append (list (cons (string-append "round " (number->string i) ": -> a") |
| 110 | + (lambda () (switch-to-view-index 1)) |
| 111 | + ) ;cons |
| 112 | + (cons (string-append "round " (number->string i) ": -> b") |
| 113 | + (lambda () (switch-to-view-index 2)) |
| 114 | + ) ;cons |
| 115 | + ) ;list |
| 116 | + acc |
| 117 | + ) ;append |
| 118 | + ) ;loop |
| 119 | + ) ;if |
| 120 | + ) ;let |
| 121 | + ;; 2) 新建 tab(+)并去脏,便于后续安全关闭 |
| 122 | + (list (cons "new-document (+)" (lambda () (new-document)))) |
| 123 | + (list (cons "buffer-pretend-saved" |
| 124 | + (lambda () (buffer-pretend-saved (current-buffer))) |
| 125 | + ) ;cons |
| 126 | + ) ;list |
| 127 | + ;; 3) 关闭当前 tab(新建的那个,已去脏,不弹框) |
| 128 | + (list (cons "safely-kill-tabpage" (lambda () (safely-kill-tabpage)))) |
| 129 | + ;; 4) 排序:当前 buffer 移到首位(index 0) |
| 130 | + (list (cons "move-buffer-to-index (reorder to 0)" |
| 131 | + (lambda () |
| 132 | + (let ((buf (current-buffer))) |
| 133 | + (when buf |
| 134 | + (move-buffer-to-index buf 0) |
| 135 | + ) ;when |
| 136 | + ) ;let |
| 137 | + ) ;lambda |
| 138 | + ) ;cons |
| 139 | + ) ;list |
| 140 | + ;; 结束 |
| 141 | + (list (cons "done; quitting" (lambda () (quit-TeXmacs)))) |
| 142 | + ) ;append |
65 | 143 | ) ;steps |
66 | 144 | ) ; |
67 | | - ;; 在两个 tab 间来回切 5 轮。 |
68 | | - (let loop |
69 | | - ((i 0) (acc steps)) |
70 | | - (if (>= i 5) |
71 | | - (set! steps |
72 | | - (append acc (list (cons "done; quitting" (lambda () (quit-TeXmacs))))) |
73 | | - ) ;set! |
74 | | - (loop (+ i 1) |
75 | | - (append acc |
76 | | - (list (cons (string-append "round " (number->string i) ": -> a") |
77 | | - (lambda () (switch-to-view-index 1)) |
78 | | - ) ;cons |
79 | | - (cons (string-append "round " (number->string i) ": -> b") |
80 | | - (lambda () (switch-to-view-index 2)) |
81 | | - ) ;cons |
82 | | - ) ;list |
83 | | - ) ;append |
84 | | - ) ;loop |
85 | | - ) ;if |
86 | | - ) ;let |
87 | 145 | (display "[2014-step] starting delayed chain\n") |
88 | 146 | (run-chain steps) |
89 | 147 | ) ;let |
|
0 commit comments