branch: externals/hyperbole commit ae4fba3980af300e558ad37004a106bb00c8aef7 Author: bw <r...@gnu.org> Commit: bw <r...@gnu.org>
hmouse-drv.el - Improve ibtype pred error handling when move point hui:hbut-operate - Fix improper movement of point in source buffer with an unwind-protect. --- ChangeLog | 16 ++++++++++ hbut.el | 21 +++++++------ hmouse-drv.el | 78 +++++++++++++++++++++++++++++++------------------ hui.el | 5 ++-- test/hui-mouse-tests.el | 54 ++++++++++++++++++++++++++++++++++ 5 files changed, 132 insertions(+), 42 deletions(-) diff --git a/ChangeLog b/ChangeLog index 479762bb6b..a44d873914 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2025-04-14 Bob Weiner <r...@gnu.org> + +* test/hui-mouse-tests.el (hui-mouse-tests--hkey-alist): Update with new + vertico hkey-actions. + +* hui.el (hui:hbut-operate): Add an unwind-protect to code that restores + point in cases where calling the `operation' triggers an error. Fixes + improper point movement in hywiki-display-page with a #section ref + where the section is not found and an error is raised. + +* hbut.el (ibut:create): + hmouse-drv.el (hkey-execute, hkey-actions, hkey-help): Change so point + moved error is thrown for any ibtype predicate tested, not just the + one selected; this will simplify tracking down bad ibtypes. Also + ensure pred-point marker is always set to nil after use. + 2025-04-13 Bob Weiner <r...@gnu.org> * test/hsys-org-tests.el (hsys-org--meta-return-on-end-of-line): Add diff --git a/hbut.el b/hbut.el index c314e023c5..b17c051acd 100644 --- a/hbut.el +++ b/hbut.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 18-Sep-91 at 02:57:09 -;; Last-Mod: 13-Apr-25 at 14:34:35 by Bob Weiner +;; Last-Mod: 14-Apr-25 at 23:07:21 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -2021,22 +2021,23 @@ If a new button is created, store its attributes in the symbol, ;; Move to text of ibut before trying to activate it ;; (may be on name) (goto-char (+ (or text-start (point)) 2)))) - (setq ibtype-point (point)) + (setq ibtype-point (point-marker)) (while (and (not is-type) types) (setq itype (car types)) + ;; Any implicit button type check should leave point + ;; unchanged. Trigger an error if not. + (unless (equal (point-marker) ibtype-point) + (hypb:error "(Hyperbole): ibtype %s improperly moved point from %s to %s" + itype opoint (point))) (when (condition-case err (and itype (setq args (funcall itype))) (error (progn (message "%S: %S" itype err) (switch-to-buffer "*Messages*") ;; Show full stack trace (debug)))) - (setq is-type itype) - ;; Any implicit button type check should leave point - ;; unchanged. Trigger an error if not. - (unless (equal (point) ibtype-point) - (hypb:error "(Hyperbole): `%s' at-p test improperly moved point from %s to %s" - is-type opoint (point-marker)))) + (setq is-type itype)) (setq types (cdr types)))) + (set-marker ibtype-point nil) (goto-char opoint))) (set-marker opoint nil)) @@ -3037,9 +3038,7 @@ type for ibtype is presently undefined." (at-func-symbols (flatten-tree at-func))) (progn (unless (or (member 'ibut:label-set at-func-symbols) (member 'hsys-org-set-ibut-label at-func-symbols)) - (error "(defib): %s `at-p' argument must include a call to `ibut:label-set'" type)) - ;; (unless (member 'hact at-func-symbols) - ;; (error "(defib): %s `at-p' argument must include a call to `hact'" type)) + (error "(defib): `at-p' argument for %s must include a call to `ibut:label-set'" type)) `(progn (symtable:add ',type symtable:ibtypes) (htype:create ,type ibtypes ,doc nil ,at-func '(to-p ,to-func style ,style))))))) diff --git a/hmouse-drv.el b/hmouse-drv.el index c2ea344f78..6a418b3426 100644 --- a/hmouse-drv.el +++ b/hmouse-drv.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 04-Feb-90 -;; Last-Mod: 12-Apr-25 at 15:47:32 by Bob Weiner +;; Last-Mod: 14-Apr-25 at 22:57:56 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -996,14 +996,21 @@ frame instead." "Return the cons of the Action and Assist Key actions at point. Useful in testing Smart Key contexts." (let ((hkey-forms hkey-alist) + (pred-point (point-marker)) pred-value hkey-actions hkey-form pred) - (while (and (null pred-value) (setq hkey-form (car hkey-forms))) - (if (setq hkey-actions (cdr hkey-form) - pred (car hkey-form) - pred-value (hypb:eval-debug pred)) - nil - (setq hkey-forms (cdr hkey-forms)))) - hkey-actions)) + (unwind-protect + (progn + (while (and (null pred-value) (setq hkey-form (car hkey-forms))) + (setq hkey-actions (cdr hkey-form) + pred (car hkey-form) + pred-value (hypb:eval-debug pred)) + (unless (equal (point-marker) pred-point) + (hypb:error "(Hyperbole): predicate %s improperly moved point from %s to %s" + pred (point) pred-point)) + (unless pred-value + (setq hkey-forms (cdr hkey-forms)))) + hkey-actions) + (set-marker pred-point nil)))) (defun hkey-debug (pred pred-value hkey-action) "Display a message with the context and values from Smart Key activation." @@ -1044,25 +1051,30 @@ predicate is found." (assist-flag assisting) (pred-point (point-marker)) pred-value hkey-action hkey-form pred) - (while (and (null pred-value) (setq hkey-form (car hkey-forms))) - (if (setq hkey-action (if assisting (cddr hkey-form) (cadr hkey-form)) - pred (car hkey-form) - pred-value (hypb:eval-debug pred)) - (progn + (unwind-protect + (progn + (while (and (null pred-value) (setq hkey-form (car hkey-forms))) + (setq hkey-action (if assisting (cddr hkey-form) (cadr hkey-form)) + pred (car hkey-form) + pred-value (hypb:eval-debug pred)) ;; Any Smart Key predicate should leave point unchanged. ;; Trigger an error if not. (unless (equal (point-marker) pred-point) - (hypb:error "(Hyperbole): `%s' predicate failed to restore point to %s" pred pred-point)) - (set-marker pred-point nil) - ;; Conditionally debug after Smart Key release and evaluation - ;; of matching predicate but before hkey-action is executed. - (when hkey-debug - (hkey-debug pred pred-value hkey-action)) - (if hkey-debug - (hypb:eval-debug hkey-action) - (eval hkey-action))) - (setq hkey-forms (cdr hkey-forms)))) - pred-value)) + (hypb:error "(Hyperbole): predicate %s improperly moved point from %s to %s" + pred (point) pred-point)) + (if pred-value + ;; Found the ibtype for the current context + (progn + ;; Conditionally debug after Smart Key release and evaluation + ;; of matching predicate but before hkey-action is executed. + (when hkey-debug + (hkey-debug pred pred-value hkey-action)) + (if hkey-debug + (hypb:eval-debug hkey-action) + (eval hkey-action))) + (setq hkey-forms (cdr hkey-forms)))) + pred-value) + (set-marker pred-point nil)))) (defun hkey-help (&optional assisting) "Display help for the Action Key command in current context. @@ -1077,11 +1089,19 @@ documentation is found." (hkey-forms (if mouse-flag hmouse-alist hkey-alist)) (hrule:action #'actype:identity) (assist-flag assisting) - hkey-form pred-value call calls cmd-sym doc) - (while (and (null pred-value) (setq hkey-form (car hkey-forms))) - (or (setq pred-value (hypb:eval-debug (car hkey-form))) - (setq hkey-forms (cdr hkey-forms)))) - (if pred-value + (pred-point (point-marker)) + hkey-form pred pred-value call calls cmd-sym doc) + (unwind-protect + (while (and (null pred-value) (setq hkey-form (car hkey-forms))) + (or (setq pred (car hkey-form) + pred-value (hypb:eval-debug pred)) + (setq hkey-forms (cdr hkey-forms))) + ;; Any Smart Key predicate should leave point unchanged. + ;; Trigger an error if not. + (unless (equal (point-marker) pred-point) + (hypb:error "(Hyperbole): `%s' predicate left point at %s and failed to restore it to %s" pred (point) pred-point))) + (set-marker pred-point nil)) + (if pred-value (setq call (if assisting (cdr (cdr hkey-form)) (cadr hkey-form)) cmd-sym (if (eq (car call) #'funcall) diff --git a/hui.el b/hui.el index 85eb4bd033..d7285acd9a 100644 --- a/hui.el +++ b/hui.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 19-Sep-91 at 21:42:03 -;; Last-Mod: 2-Feb-25 at 12:40:26 by Bob Weiner +;; Last-Mod: 14-Apr-25 at 23:27:50 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -1643,7 +1643,8 @@ completion of all labeled buttons within the current buffer." (ibut:to-text (hattr:get but 'lbl-key))) (setq text-start (point-marker)) (hui:but-flash) - (prog1 (apply hrule:action operation `(',but)) + (unwind-protect + (apply hrule:action operation `(',but)) ;; Restore point as it was prior to `text-start' move ;; if the action switched buffers or did not move point ;; within the current buffer. diff --git a/test/hui-mouse-tests.el b/test/hui-mouse-tests.el new file mode 100644 index 0000000000..0112cf57e1 --- /dev/null +++ b/test/hui-mouse-tests.el @@ -0,0 +1,54 @@ +;;; hui-mouse-tests.el --- unit tests for hui-mouse -*- lexical-binding: t; -*- +;; +;; Author: Mats Lidell +;; +;; Orig-Date: 15-Mar-25 at 22:39:37 +;; Last-Mod: 12-Apr-25 at 17:30:33 by Bob Weiner +;; +;; SPDX-License-Identifier: GPL-3.0-or-later +;; +;; Copyright (C) 2025 Free Software Foundation, Inc. +;; See the "HY-COPY" file for license information. +;; +;; This file is part of GNU Hyperbole. + +;;; Commentary: +;; +;; Unit tests for "../hui-mouse.el". + +;;; Code: + +(require 'ert) +(require 'el-mock) + +;; !! FIXME: Add more predicate cases from hkey-alist. +(ert-deftest hui-mouse-tests--hkey-alist () + "Verify that given predicate values triggers the proper action." + ;; Treemacs + (let ((major-mode 'treemacs-mode)) + (should (equal (hkey-actions) + (cons '(smart-treemacs) '(smart-treemacs))))) + + ;; dired-sidebar-mode + (let ((major-mode 'dired-sidebar-mode)) + (should (equal (hkey-actions) + (cons '(smart-dired-sidebar) '(smart-dired-sidebar))))) + + ;; Vertico + (let ((ivy-mode nil) + (vertico-mode t)) + (mocklet ((vertico--command-p => t)) + (should (equal (hkey-actions) + (cons '(funcall (lookup-key vertico-map (kbd "M-RET"))) + '(funcall (lookup-key vertico-map (kbd "M-RET"))))))))) + +(provide 'hui-mouse-tests) + +;; This file can't be byte-compiled without the `el-mock' package +;; which is not a dependency of Hyperbole. +;; +;; Local Variables: +;; no-byte-compile: t +;; End: + +;;; hui-mouse-tests.el ends here