Implement Qt winner mode toggle

ober

d8f646750f5b163a1395431f6392be37bf19887e

diff --git a/src/jerboa-emacs/qt/commands-core.ss b/src/jerboa-emacs/qt/commands-core.ss
index 2ad0664..08ca85c 100644
--- a/src/jerboa-emacs/qt/commands-core.ss
+++ b/src/jerboa-emacs/qt/commands-core.ss
@@ -36,6 +36,7 @@
 (def *winner-history* [])   ; list of (tree-snapshot . cur-buf-name)
 (def *winner-future* [])    ; redo stack
 (def *winner-max-history* 50)
+(def *winner-mode* #t)
 
 (def (winner-snapshot-tree node)
   "Serialize split tree as an s-expr with buffer names for snapshot."
@@ -69,12 +70,13 @@
           cur-buf)))
 
 (def (winner-save! fr)
-  "Save current window configuration to history."
-  (let ((config (winner-current-config fr)))
-    (set! *winner-history* (cons config *winner-history*))
-    (when (> (length *winner-history*) *winner-max-history*)
-      (set! *winner-history* (take *winner-history* *winner-max-history*)))
-    (set! *winner-future* [])))
+  "Save current window configuration to history when winner-mode is enabled."
+  (when *winner-mode*
+    (let ((config (winner-current-config fr)))
+      (set! *winner-history* (cons config *winner-history*))
+      (when (> (length *winner-history*) *winner-max-history*)
+        (set! *winner-history* (take *winner-history* *winner-max-history*)))
+      (set! *winner-future* []))))
 
 (def (winner-restore-config! app config)
   "Restore a saved window configuration.
diff --git a/src/jerboa-emacs/qt/commands-parity5.ss b/src/jerboa-emacs/qt/commands-parity5.ss
index ba7e602..3ac3c81 100644
--- a/src/jerboa-emacs/qt/commands-parity5.ss
+++ b/src/jerboa-emacs/qt/commands-parity5.ss
@@ -1348,6 +1348,15 @@
   (cmd-toggle-line-numbers app)
   (hash-put! *qt-toggle-states* 'global-display-line-numbers-mode *line-numbers-visible*)
   (hash-put! *qt-toggle-states* 'toggle-global-display-line-numbers *line-numbers-visible*))
+(def (cmd-winner-mode app)
+  "Toggle Qt winner-mode window configuration history."
+  (set! *winner-mode* (not *winner-mode*))
+  (hash-put! *qt-toggle-states* 'winner-mode *winner-mode*)
+  (hash-put! *qt-toggle-states* 'toggle-winner-mode *winner-mode*)
+  (echo-message! (app-state-echo app)
+    (if *winner-mode*
+      "Winner mode ON"
+      "Winner mode OFF")))
 (def *qt-run-with-timer-counter* 0)
 
 (def (next-run-with-timer-name!)
@@ -1455,6 +1464,8 @@
       (cons 'toggle-blink-cursor-mode cmd-blink-cursor-mode)
       (cons 'global-display-line-numbers-mode cmd-global-display-line-numbers-mode)
       (cons 'toggle-global-display-line-numbers cmd-global-display-line-numbers-mode)
+      (cons 'winner-mode cmd-winner-mode)
+      (cons 'toggle-winner-mode cmd-winner-mode)
       (cons 'run-with-timer cmd-run-with-timer)
       (cons 'ibuffer-mark cmd-ibuffer-mark)
       (cons 'ibuffer-delete cmd-ibuffer-delete)
diff --git a/tests/test-qt-part2.ss b/tests/test-qt-part2.ss
index 9bf057a..81f14ff 100644
--- a/tests/test-qt-part2.ss
+++ b/tests/test-qt-part2.ss
@@ -25,7 +25,8 @@
               qt-minibuffer-history-for)
         (jerboa-emacs qt commands)
         (only (jerboa-emacs qt commands-edit) *line-numbers-visible*)
-        (only (jerboa-emacs qt commands-core) *so-long-threshold*)
+        (only (jerboa-emacs qt commands-core)
+              *so-long-threshold* *winner-mode* *winner-history* *winner-future*)
         (only (jerboa-emacs qt commands-parity5) schedule-user-timer!)
         (only (jerboa-emacs async) master-timer-tick!)
         (jerboa-emacs qt keymap)
@@ -107,7 +108,7 @@
       (loop (+ i 1)
             (cons (string-append "line " (number->string i) "\n") acc)))))
 
-(display "\n=== Qt Part2 Groups 44-61 ===\n")
+(display "\n=== Qt Part2 Groups 44-62 ===\n")
 
 (test-case "group44 qt key/mouse fidelity"
   (check (qt-key-event->string QT_KEY_RETURN 0 "") => "C-m")
@@ -310,9 +311,34 @@
           (set! *line-numbers-visible* old)
           (qt-line-number-area-set-visible! (qt-edit-window-line-number-area win) old))))))
 
+(test-case "group62 winner-mode controls window history"
+  (let-values (((ed w app) (make-qt-test-app "part2-62")))
+    (let ((old-mode *winner-mode*)
+          (old-history *winner-history*)
+          (old-future *winner-future*))
+      (dynamic-wind
+        (lambda ()
+          (set! *winner-mode* #t)
+          (set! *winner-history* '())
+          (set! *winner-future* '()))
+        (lambda ()
+          (execute-command! app 'winner-mode)
+          (check *winner-mode* => #f)
+          (check (echo-state-message (app-state-echo app)) => "Winner mode OFF")
+          (execute-command! app 'split-window-right)
+          (check (length *winner-history*) => 0)
+          (execute-command! app 'toggle-winner-mode)
+          (check *winner-mode* => #t)
+          (check (echo-state-message (app-state-echo app)) => "Winner mode ON")
+          (execute-command! app 'split-window-right)
+          (check (length *winner-history*) => 1))
+        (lambda ()
+          (set! *winner-mode* old-mode)
+          (set! *winner-history* old-history)
+          (set! *winner-future* old-future))))))
 (newline)
 (let ([total (+ *pass* *fail*)])
-  (printf "Part2 results: ~a/~a tests passed (groups 44-61)~n" *pass* total)
+  (printf "Part2 results: ~a/~a tests passed (groups 44-62)~n" *pass* total)
   (when (> *fail* 0)
     (printf "FAILED: ~a test(s)~n" *fail*))
   (when (= *fail* 0)