branch: externals/hyperbole commit a1505b449c0ca6285773411a79ec1a588c6719f1 Merge: 2e4857aef4 ef93d6a124 Author: Robert Weiner <r...@gnu.org> Commit: GitHub <nore...@github.com>
Merge pull request #731 from rswgnu/rsw Fix close quote selection around HyWikiWords; hypb:in-string-p - Fix open quote detection --- ChangeLog | 16 +++++++ hui-mouse.el | 36 +++++++-------- hypb.el | 100 +++++++++++++++++++++++------------------ man/hyperbole.texi | 114 +++++++++++++++++++++++------------------------ test/demo-tests.el | 15 ++++--- test/hmouse-drv-tests.el | 4 +- 6 files changed, 158 insertions(+), 127 deletions(-) diff --git a/ChangeLog b/ChangeLog index fa611613d7..02f89582f9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,21 @@ +2025-05-19 Bob Weiner <r...@gnu.org> + +* test/demo-tests.el (fast-demo-elisp-or-env-vars): Fix to move past opening + brace so does not trigger hui-select. + (demo-smart-mouse-keys-ref-test, demo-man-apropos-test): Make similar fixes. + test/hmouse-drv-tests.el (hbut-rfc-test): Make similar fixes. + +* hypb.el (hypb:in-string-p): Fix open quote detection heuristics including + subtracting quoted delimiters from overall counts. + 2025-05-18 Bob Weiner <r...@gnu.org> +* hui-mouse.el (hkey-alist): Move hui-select clauses up before (hbut:at-p) + call so for example, if on the trailing delimiter surrounding a HyWikiWord, + the delimited whole is marked rather than activating the HyWikiWord. + man/hyperbole.texi (Smart Key - Magit Mode, Smart Key - Delimited Things): + Reorder to comde before (Smart Key - Hyperbole Buttons). + * hypb.el (hypb:in-string-p): Make heuristic to optimize performance; search back only until the beginning of the first line prior to point that contains a non-quoted double quote mark. Also add support for 'texinfo-mode' strings diff --git a/hui-mouse.el b/hui-mouse.el index e2f1f762a4..a3f2f5e0ca 100644 --- a/hui-mouse.el +++ b/hui-mouse.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 04-Feb-89 -;; Last-Mod: 8-May-25 at 10:25:38 by Mats Lidell +;; Last-Mod: 19-May-25 at 00:01:18 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -334,6 +334,23 @@ Its default value is `smart-scroll-down'. To disable it, set it to ((string-prefix-p "magit-" (symbol-name major-mode)) . ((smart-magit) . (smart-magit-assist))) ;; + ;; Select or select-and-kill a markup pair (e.g. hmtl tags), list, + ;; array/vector, set, function, comment or string that begins or + ;; ends at point. For markup pairs, point must be at the first + ;; character of the opening or closing tag. + ((hui-select-at-delimited-thing-p) + . ((hui-select-thing) . (progn (hui-select-thing) + (hmouse-kill-region)))) + ;; + ;; If the prior test failed and point is at the start or end of an + ;; sexpression, mark it for editing or kill it (assist key). This + ;; only handles the special case where point is just after the + ;; closing delimiter and not at an end-of-line, so this may be + ;; removed someday. + ((hui-select-at-delimited-sexp-p) + . ((hui-select-mark-delimited-sexp) + . (progn (hui-select-mark-delimited-sexp) (hmouse-kill-region)))) + ;; ;; If on a Hyperbole button, perform action or give help. ((hbut:at-p) . ((hui:hbut-act 'hbut:current) . (hui:hbut-help 'hbut:current))) @@ -381,23 +398,6 @@ Its default value is `smart-scroll-down'. To disable it, set it to (equal br-feature-tags-file (hypb:buffer-file-name)))) . ((smart-element) . (hkey-help))) ;; - ;; Select or select-and-kill a markup pair (e.g. hmtl tags), list, - ;; array/vector, set, function, comment or string that begins or - ;; ends at point. For markup pairs, point must be at the first - ;; character of the opening or closing tag. - ((hui-select-at-delimited-thing-p) - . ((hui-select-thing) . (progn (hui-select-thing) - (hmouse-kill-region)))) - ;; - ;; If the prior test failed and point is at the start or end of an - ;; sexpression, mark it for editing or kill it (assist key). This - ;; only handles the special case where point is just after the - ;; closing delimiter and not at an end-of-line, so this may be - ;; removed someday. - ((hui-select-at-delimited-sexp-p) - . ((hui-select-mark-delimited-sexp) - . (progn (hui-select-mark-delimited-sexp) (hmouse-kill-region)))) - ;; ((eq major-mode 'occur-mode) . ((occur-mode-goto-occurrence) . (occur-mode-goto-occurrence))) ;; diff --git a/hypb.el b/hypb.el index 9e4c837f1d..40b8bea6fd 100644 --- a/hypb.el +++ b/hypb.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 6-Oct-91 at 03:42:38 -;; Last-Mod: 18-May-25 at 17:40:45 by Bob Weiner +;; Last-Mod: 19-May-25 at 01:28:31 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -75,12 +75,13 @@ This should end with a space.") (list (format open-regexp "\"\\|'''\\|\"\"\"\\|'") (format close-regexp "\"\\|'''\\|\"\"\"\\|'"))) ((derived-mode-p 'texinfo-mode) - (list (format open-regexp "\"\\|``") - (format close-regexp "\"\\|''"))) + (list (format open-regexp "``\\|\"") + (format close-regexp "''\\|\""))) (t (list (format open-regexp "\"") (format close-regexp "\""))))) - "Return a list of open/close string delimiter regexps for `hypb:in-string-p'." + "Return a list of open/close string delimiter regexps for `hypb:in-string-p'. +Or clauses in regexps must be arranged from longest match to shortest match." :type 'sexp :group 'hyperbole-commands) @@ -694,47 +695,60 @@ Quoting conventions recognized are: Python triple single-quotes: '''str'''; Python triple double-quotes: \"\"\"str\"\"\"; Texinfo open and close quotes: ``str''." - (save-restriction - (when (integerp max-lines) - (narrow-to-region (line-beginning-position) - (line-end-position max-lines))) - ;; Don't use `syntax-ppss' here as it fails to ignore backquoted - ;; double quote characters in strings and doesn't work in - ;; `change-log-mode' due to its syntax-table. - (let ((opoint (point)) - (start (point-min)) - (open-match-string "")) - (cl-destructuring-bind (open-regexp close-regexp) - (eval hypb:in-string-modes-regexps) - (cond ((derived-mode-p 'python-mode) - (setq open-regexp (format open-regexp "\"\\|'''\\|\"\"\"\\|'") - close-regexp (format close-regexp "\"\\|'''\\|\"\"\"\\|'"))) - ((derived-mode-p 'texinfo-mode) - (setq open-regexp (format open-regexp "\"\\|``") - close-regexp (format close-regexp "\"\\|''"))) - (t - (setq open-regexp (format open-regexp "\"") - close-regexp (format close-regexp "\"")))) - (save-match-data - (when (re-search-backward open-regexp nil t) - (setq open-match-string (match-string 2)) - (forward-line 0) - (setq start (point)) - (goto-char opoint) - (if (and (derived-mode-p 'texinfo-mode) - (string-equal open-match-string texinfo-open-quote)) + (save-excursion + (save-restriction + (when (integerp max-lines) + (narrow-to-region (line-beginning-position) + (line-end-position max-lines))) + ;; Don't use `syntax-ppss' here as it fails to ignore backquoted + ;; double quote characters in strings and doesn't work in + ;; `change-log-mode' due to its syntax-table. + (let ((opoint (point)) + (start (point-min)) + (open-match-string "")) + (cl-destructuring-bind (open-regexp close-regexp) + (eval hypb:in-string-modes-regexps) + (save-match-data + (when (and (re-search-backward open-regexp nil t) + (setq open-match-string (match-string 2)) + ;; If this is the start of a string, it must be + ;; at the start of line, preceded by whitespace + ;; or preceded by another string end sequence. + (save-match-data + (or (string-empty-p (match-string 1)) + (string-search (match-string 1) " \t\n\r\f") + (progn (goto-char (1+ (point))) + (looking-back close-regexp nil))))) + (forward-line 0) + (setq start (point)) + (goto-char opoint) + (if (and (derived-mode-p 'texinfo-mode) + (string-equal open-match-string texinfo-open-quote)) + (and (cl-oddp (- (count-matches (regexp-quote open-match-string) + start (point)) + ;; Subtract any backslash quoted delimiters + (count-matches + (format "[\\]\\(%s\\)" + (regexp-quote open-match-string)) + start (point)) + (count-matches (regexp-quote texinfo-close-quote) + start (point)) + ;; Subtract any backslash quoted delimiters + (count-matches + (format "[\\]\\(%s\\)" + (regexp-quote texinfo-close-quote)) + start (point)))) + (search-forward texinfo-close-quote nil t) + t) (and (cl-oddp (- (count-matches (regexp-quote open-match-string) start (point)) - (count-matches (regexp-quote texinfo-close-quote) - start (point)))) - (save-excursion (search-forward texinfo-close-quote nil t)) - t) - (and (cl-oddp (count-matches - (format "\\(^\\|[^\\]\\)\\(%s\\)" - (regexp-quote open-match-string)) - start (point))) - (save-excursion (re-search-forward close-regexp nil t)) - t)))))))) + ;; Subtract any backslash quoted delimiters + (count-matches + (format "[\\]\\(%s\\)" + (regexp-quote open-match-string)) + start (point)))) + (re-search-forward close-regexp nil t) + t))))))))) (defun hypb:indirect-function (obj) "Return the function at the end of OBJ's function chain. diff --git a/man/hyperbole.texi b/man/hyperbole.texi index 743422a2fd..544202534e 100644 --- a/man/hyperbole.texi +++ b/man/hyperbole.texi @@ -7,7 +7,7 @@ @c Author: Bob Weiner @c @c Orig-Date: 6-Nov-91 at 11:18:03 -@c Last-Mod: 4-May-25 at 10:45:09 by Bob Weiner +@c Last-Mod: 19-May-25 at 00:12:26 by Bob Weiner @c %**start of header (This is for running Texinfo on a region.) @setfilename hyperbole.info @@ -171,7 +171,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.</P> <PRE> Edition 9.0.2pre -Printed May 4, 2025. +Printed May 19, 2025. Published by the Free Software Foundation, Inc. Author: Bob Weiner @@ -213,7 +213,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. @example Edition 9.0.2pre -May 4, 2025 +May 19, 2025 Published by the Free Software Foundation, Inc. Author: Bob Weiner @@ -10888,6 +10888,60 @@ If pressed within a dired-mode (directory editor) buffer: @end group @end format +@node Smart Key - Magit Mode, Smart Key - The OO-Browser, Smart Key - Gomoku Game, Smart Keyboard Keys +@subsection Smart Key - Magit Mode +@cindex git +@cindex magit +@cindex version control +@vindex hpath:display-where +@format +@group +If pressed within a Magit buffer and not on a button: + ACTION KEY + (1) on the last line, quit from the magit mode (@bkbd{q} key binding); + (2) at the end of a line, scroll up a windowful; + (3) in a @code{magit-status-mode} buffer on a merge conflict + marker, keep either the upper, both or the lower version of + the conflict. See also @ref{smerge}. + (4) on an initial read-only header line, cycle visibility of diff sections; + (5) anywhere else, hide/show the thing at point (@bkbd{@key{TAB}} key binding) + unless that does nothing in the mode, then jump to the thing at point + (@bkbd{@key{RET}} key binding) but display based on the value of + @code{hpath:display-where}. + ASSIST KEY + (1) on the last line, quit from the magit mode (@bkbd{q} key binding); + (2) at the end of a line, scroll down a windowful; + (3) on an initial read-only header line, cycle visibility of all sections; + (4) anywhere else, jump to the thing at point (@bkbd{@key{RET}} key binding) + but display based on the value of @code{hpath:display-where}." +@end group +@end format + +@node Smart Key - Delimited Things, Smart Key - Occurrence Matches, Smart Key - ERT Results Mode, Smart Keyboard Keys +@subsection Smart Key - Delimited Things + +@cindex thing +@cindex list +@cindex comment +@cindex string +@cindex array +@cindex vector +@cindex set +@cindex function +@cindex markup pair +@format +@group +In a programming or markup language buffer, when pressed/clicked at +the start or end of a delimited thing (including lists, comments, +strings, arrays/vectors, sets, functions and markup pair tags in a +markup language), and not at the end of a line: + ACTION KEY + Marks the thing for editing. + ASSIST KEY + Marks and kills the thing for yanking elsewhere. +Note that the press must be on the first character of the delimiter of +the thing. + @node Smart Key - Hyperbole Buttons, Smart Key - View Mode, Smart Key - Dired Mode, Smart Keyboard Keys @subsection Smart Key - Hyperbole Buttons @@ -10989,31 +11043,6 @@ When in an Emacs Regression Test (ERT) results buffer: @end group @end format -@node Smart Key - Delimited Things, Smart Key - Occurrence Matches, Smart Key - ERT Results Mode, Smart Keyboard Keys -@subsection Smart Key - Delimited Things - -@cindex thing -@cindex list -@cindex comment -@cindex string -@cindex array -@cindex vector -@cindex set -@cindex function -@cindex markup pair -@format -@group -In a programming or markup language buffer, when pressed/clicked at -the start or end of a delimited thing (including lists, comments, -strings, arrays/vectors, sets, functions and markup pair tags in a -markup language), and not at the end of a line: - ACTION KEY - Marks the thing for editing. - ASSIST KEY - Marks and kills the thing for yanking elsewhere. -Note that the press must be on the first character of the delimiter of -the thing. - @cindex Smart Mouse Key @cindex Action Mouse Key @cindex Assist Mouse Key @@ -11950,35 +11979,6 @@ If pressed within a Gomoku game buffer: @end group @end format -@node Smart Key - Magit Mode, Smart Key - The OO-Browser, Smart Key - Gomoku Game, Smart Keyboard Keys -@subsection Smart Key - Magit Mode -@cindex git -@cindex magit -@cindex version control -@vindex hpath:display-where -@format -@group -If pressed within a Magit buffer and not on a button: - ACTION KEY - (1) on the last line, quit from the magit mode (@bkbd{q} key binding); - (2) at the end of a line, scroll up a windowful; - (3) in a @code{magit-status-mode} buffer on a merge conflict - marker, keep either the upper, both or the lower version of - the conflict. See also @ref{smerge}. - (4) on an initial read-only header line, cycle visibility of diff sections; - (5) anywhere else, hide/show the thing at point (@bkbd{@key{TAB}} key binding) - unless that does nothing in the mode, then jump to the thing at point - (@bkbd{@key{RET}} key binding) but display based on the value of - @code{hpath:display-where}. - ASSIST KEY - (1) on the last line, quit from the magit mode (@bkbd{q} key binding); - (2) at the end of a line, scroll down a windowful; - (3) on an initial read-only header line, cycle visibility of all sections; - (4) anywhere else, jump to the thing at point (@bkbd{@key{RET}} key binding) - but display based on the value of @code{hpath:display-where}." -@end group -@end format - @node Smart Key - The OO-Browser, Smart Key - Todotxt Mode, Smart Key - Magit Mode, Smart Keyboard Keys @subsection Smart Key - The OO-Browser diff --git a/test/demo-tests.el b/test/demo-tests.el index 6d58fe16fc..3366971c05 100644 --- a/test/demo-tests.el +++ b/test/demo-tests.el @@ -3,7 +3,7 @@ ;; Author: Mats Lidell <ma...@gnu.org> ;; ;; Orig-Date: 30-Jan-21 at 12:00:00 -;; Last-Mod: 20-Apr-25 at 14:55:17 by Bob Weiner +;; Last-Mod: 19-May-25 at 22:53:23 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -42,7 +42,8 @@ (let ((enable-local-variables nil)) (hypb:display-file-with-logo "DEMO") (goto-char (point-min)) - (re-search-forward "#Smart Keys") + ;; Omit last char of string from search so ends on a non-quote char + (re-search-forward "#Smart Key") (action-key) (should (bolp)) (should (looking-at "^\\* Smart"))) @@ -387,11 +388,11 @@ (hy-test-helpers:kill-buffer "DEMO") (hy-test-helpers:kill-buffer "*Occur*")))) -;; Man appropos -(ert-deftest demo-man-appropos-test () +;; Man apropos +(ert-deftest demo-man-apropos-test () (with-temp-buffer (insert "rm (1) - remove") - (goto-char 4) + (goto-char 2) (with-mock (mock (man "rm(1)") => t) (action-key)))) @@ -450,10 +451,10 @@ (unwind-protect (with-temp-buffer (insert "\"${hyperb:dir}/HY-NEWS\"") - (goto-char 3) + (goto-char 4) (action-key) (should (string= (buffer-name (current-buffer)) "HY-NEWS"))) - (hy-test-helpers:kill-buffer "HY-NEWS"))) + (hy-test-helpers:kill-buffer "HY-NEWS"))) (ert-deftest fast-demo-elisp-library-in-load-path () "Verify ibut to Elisp library works." diff --git a/test/hmouse-drv-tests.el b/test/hmouse-drv-tests.el index 87728289cd..444bfb8938 100644 --- a/test/hmouse-drv-tests.el +++ b/test/hmouse-drv-tests.el @@ -3,7 +3,7 @@ ;; Author: Mats Lidell <ma...@gnu.org> ;; ;; Orig-Date: 28-Feb-21 at 22:52:00 -;; Last-Mod: 17-May-25 at 16:07:56 by Mats Lidell +;; Last-Mod: 19-May-25 at 22:53:55 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -528,7 +528,7 @@ (ert-deftest hbut-man-apropos-test () (with-temp-buffer (insert "rm (1) - remove") - (goto-char 4) + (goto-char 2) (with-mock (mock (man "rm(1)") => t) (should (action-key))