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))

Reply via email to