]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix tabbing between widgets (bug#70594)
authorStephen Berman <stephen.berman@gmx.net>
Tue, 25 Jun 2024 10:38:03 +0000 (12:38 +0200)
committerEshel Yaron <me@eshelyaron.com>
Wed, 26 Jun 2024 13:34:10 +0000 (15:34 +0200)
* lisp/wid-edit.el (widget-move): Don't error when tabbing in a
buffer with only one active widget and 'widget-skip-inactive'
enabled.  Improve code by handling forward and backward movement
in a single loop.

(cherry picked from commit 2f18929319a4883575acb7440c920ad059a84105)

lisp/wid-edit.el

index 3b467434d29f230847b46921d7577b0635c12493..b599aa680a4d09f57d970636f70e61eb83e60cdd 100644 (file)
@@ -1276,42 +1276,40 @@ This is much faster.")
 ARG may be negative to move backward.
 When the second optional argument is non-nil,
 nothing is shown in the echo area."
-  (let ((wrapped 0)
-       (number arg)
-       (old (widget-tabable-at)))
-    ;; Forward.
-    (while (> arg 0)
-      (cond ((eobp)
-            (goto-char (point-min))
-            (setq wrapped (1+ wrapped)))
-           (widget-use-overlay-change
-            (goto-char (next-overlay-change (point))))
-           (t
-            (forward-char 1)))
-      (and (= wrapped 2)
-          (eq arg number)
-          (error "No buttons or fields found"))
-      (let ((new (widget-tabable-at)))
-       (when new
-         (unless (eq new old)
-           (setq arg (1- arg))
-           (setq old new)))))
-    ;; Backward.
-    (while (< arg 0)
-      (cond ((bobp)
-            (goto-char (point-max))
-            (setq wrapped (1+ wrapped)))
-           (widget-use-overlay-change
-            (goto-char (previous-overlay-change (point))))
-           (t
-            (backward-char 1)))
-      (and (= wrapped 2)
-          (eq arg number)
-          (error "No buttons or fields found"))
-      (let ((new (widget-tabable-at)))
-       (when new
-         (unless (eq new old)
-           (setq arg (1+ arg))))))
+  (let* ((wrapped 0)
+        (number arg)
+         (fwd (> arg 0))                ; widget-forward is caller.
+         (bwd (< arg 0))                ; widget-backward is caller.
+        (old (widget-tabable-at))
+         (tabable (if old 1 0))
+         pos)
+    (catch 'one
+      (while (> (abs arg) 0)
+        (cond ((or (and fwd (eobp)) (and bwd (bobp)))
+              (goto-char (cond (fwd (point-min))
+                                (bwd (point-max))))
+              (setq wrapped (1+ wrapped)))
+             (widget-use-overlay-change
+              (goto-char (cond (fwd (next-overlay-change (point)))
+                                (bwd (previous-overlay-change (point))))))
+             (t
+              (cond (fwd (forward-char 1))
+                     (bwd (backward-char 1)))))
+        (and (= wrapped 2)
+            (eq arg number)
+             (if (= tabable 1)
+                 (progn
+                   (goto-char pos)
+                   (throw 'one (message "Only one tabable widget")))
+              (error "No buttons or fields found")))
+        (let ((new (widget-tabable-at)))
+         (when new
+           (if (eq new old)
+                (setq pos (point))
+              (cl-incf tabable)
+             (setq arg (cond (fwd (1- arg))
+                              (bwd (1+ arg))))
+             (setq old new))))))
     (let ((new (widget-tabable-at)))
       (while (and (eq (widget-tabable-at) new) (not (bobp)))
        (backward-char)))