branch: externals/hyperbole
commit 583db9cd54845fbcc19af2015b249eaf5163e1c9
Merge: 9ef5fb795c a703503c48
Author: Robert Weiner <[email protected]>
Commit: GitHub <[email protected]>

    Merge pull request #966 from rswgnu/rsw
    
    hyrolo-edit - Ensure matches to whole line and not a substring
---
 ChangeLog            | 19 ++++++++++++++++
 hyrolo.el            | 64 +++++++++++++++++++++++++++-------------------------
 test/hyrolo-tests.el | 32 +++++++++++++++++++++++++-
 3 files changed, 83 insertions(+), 32 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index c9349c52ea..2a4a7485cf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2026-06-01  Bob Weiner  <[email protected]>
+
+2026-05-31  Bob Weiner  <[email protected]>
+
+* hyrolo.el (hyrolo-edit, hyrolo-name-at-p): Rename 'hyrolo-line-entry to
+    :hyrolo-line-entry-column.
+            (hyrolo-name-at-p): Rename :hyrolo-name-entry to
+    :hyrolo-name-entry-column and make its value be just the column number.
+    And change return of entry-name to entry-line to prevent partial string
+    match when jumping to an entry to edit.
+            (hyrolo-to, hyrolo-name-at-p): Adjust to handle
+    :hyrolo-name-entry-column value change.
+            (hyrolo-to): When searching for a full-line do a regexp search
+    matching the full line so do not match substrings of the line.
+            (hyrolo-name-at-p): Change return from a cons to a list.
+  test/hyrolo-tests.el (hyrolo-tests--edit-entry-edits-the-selected-match):
+    Add to test that 'hyrolo-to' does not match to a substring of the line
+    selected.
+
 2026-05-28  Mats Lidell  <[email protected]>
 
 * test/hyrolo-tests.el (hyrolo-tests--edit-entry-updates-the-date): Add
diff --git a/hyrolo.el b/hyrolo.el
index 47d644a030..ed80ea9769 100644
--- a/hyrolo.el
+++ b/hyrolo.el
@@ -3,7 +3,7 @@
 ;; Author:       Bob Weiner
 ;;
 ;; Orig-Date:     7-Jun-89 at 22:08:29
-;; Last-Mod:     25-May-26 at 01:07:05 by Bob Weiner
+;; Last-Mod:      1-Jun-26 at 01:14:32 by Bob Weiner
 ;;
 ;; SPDX-License-Identifier: GPL-3.0-or-later
 ;;
@@ -629,7 +629,7 @@ a parent entry which begins with the parent string."
                           name))
     (setq file-or-buf (expand-file-name (match-string 1 name))
          name (substring name (match-end 0)))
-    (put-text-property 0 1 'hyrolo-line-entry 0 name))
+    (put-text-property 0 1 :hyrolo-line-entry-column 0 name))
 
   (let* ((found-point)
         (all-files-or-bufs (hyrolo-get-file-list))
@@ -672,7 +672,7 @@ a parent entry which begins with the parent string."
        (hmouse-pulse-line))
       (when (derived-mode-p 'kotl-mode)
        (kotl-mode:to-valid-position))
-      (unless (get-text-property 0 'hyrolo-line-entry name)
+      (unless (get-text-property 0 :hyrolo-line-entry-column name)
        ;; Run hooks like adding a date only when handling a
        ;; delimited (rather than single-line) entry.
        (run-hooks 'hyrolo-edit-hook)))))
@@ -683,9 +683,8 @@ Return entry name, if any, otherwise, trigger an error."
   (interactive)
   (hyrolo-funcall-match
    (lambda ()
-     (let* ((name-and-src (hyrolo-name-at-p))
-           (name (car name-and-src))
-           (src (cdr name-and-src)))
+     (cl-destructuring-bind (name src)
+         (hyrolo-name-at-p)
        (if name
           (progn (cond ((and (boundp 'bbdb-file) (stringp bbdb-file) (equal 
src (expand-file-name bbdb-file)))
                         ;; For now, can't edit an entry from the bbdb 
database, signal an error.
@@ -2836,18 +2835,18 @@ begins or nil if not found."
                    ;; must be a buffer
                    file-or-buf))
       (let ((case-fold-search t) (real-name name) (parent "") (level)
-           col-num end line line-and-col)
+           col-num end line name-column)
        (hyrolo-widen)
        (goto-char (point-min))
-       (if (setq col-num (get-text-property 0 'hyrolo-line-entry name))
+       (if (setq col-num (get-text-property 0 :hyrolo-line-entry-column name))
            ;; this is a whole line to find without any entry delimiters
-           (when (search-forward name nil t)
+           (when (re-search-forward (concat (regexp-quote name) "$") nil t)
              (move-to-column col-num)
              (setq found (point)))
          ;; If this is the first line of an entry, then don't treat
          ;; '/' characters as parent/child delimiters but just as
          ;; part of the entry first line text.
-         (unless (setq line-and-col (get-text-property 0 :hyrolo-name-entry 
name))
+         (unless (setq name-column (get-text-property 0 
:hyrolo-name-entry-column name))
            ;; Otherwise, navigate through parent-child records.
            (while (string-match "\\`[^\]\[<>{}\"]*/" name)
              (setq end (1- (match-end 0))
@@ -2874,7 +2873,10 @@ begins or nil if not found."
          (goto-char (point-min))
          (while (and
                  ;; Search for just the leaf part of a name
-                 (search-forward name nil t)
+                  (if name-column
+                      ;; Then searching for a whole line
+                      (re-search-forward (concat (regexp-quote name) "$") nil 
t)
+                   (search-forward name nil t))
                  (not (save-excursion
                         (forward-line 0)
                         (setq found
@@ -2882,14 +2884,16 @@ begins or nil if not found."
                                                      'outline-regexp
                                                      (current-buffer)))
                                         ;; Jump to non-first line within an 
entry
-                                        (progn (back-to-indentation)
+                                        (progn (unless name-column
+                                                  (back-to-indentation))
                                                (looking-at (regexp-quote 
name))))
-                                (when (or line-and-col
-                                          (setq line-and-col 
(get-text-property 0 :hyrolo-name-entry name)))
+                                (when (or name-column
+                                          (setq name-column (get-text-property 
0 :hyrolo-name-entry-column name)))
                                   ;; this is a whole line to find except for 
leading whitespace
-                                  (setq line (car line-and-col)
-                                        col-num (cdr line-and-col))
-                                  (when (search-forward line nil t)
+                                  (setq line name
+                                        col-num name-column)
+                                  (when (re-search-forward
+                                          (concat (regexp-quote line) "$") nil 
t)
                                     (move-to-column col-num)))
                                 (when (derived-mode-p 'kotl-mode)
                                   (kotl-mode:to-valid-position))
@@ -3289,7 +3293,7 @@ Name is returned as `last, first-and-middle'."
 
 (defun hyrolo-name-at-p ()
   "Iff point is at or within an entry in `hyrolo-display-buffer', return 
non-nil.
-Any non-nil value returned is a cons of (<entry-name> . <entry-source>)."
+Any non-nil value returned is a list of (<entry-line> <entry-source>)."
   (when (eq (current-buffer) (get-buffer hyrolo-display-buffer))
     (let ((entry-source (hbut:get-key-src t))
          (col-num (current-column))
@@ -3299,8 +3303,7 @@ Any non-nil value returned is a cons of (<entry-name> . 
<entry-source>)."
        (save-excursion
          (forward-line 0)
          (let (case-fold-search
-               entry-line
-               entry-name)
+               entry-line)
            (if (and (or (looking-at hyrolo-hdr-and-entry-regexp)
                         (re-search-backward hyrolo-hdr-and-entry-regexp nil t))
                     (save-match-data (not (looking-at hyrolo-hdr-regexp))))
@@ -3308,21 +3311,20 @@ Any non-nil value returned is a cons of (<entry-name> . 
<entry-source>)."
                       (skip-chars-forward " \t")
                       (when (or (looking-at "[^ \t\n\r]+ ?, ?[^ \t\n\r]+")
                                 (looking-at "\\( ?[^ \t\n\r]+\\)+"))
-                        (setq entry-name (match-string-no-properties 0)
-                              entry-line (buffer-substring-no-properties 
line-start line-end))
-                        ;; Add a text-property of :hyrolo-name-entry with
-                        ;; value of (entry-line . current-column) to 
entry-name.
-                        (put-text-property 0 1 :hyrolo-name-entry
-                                           (cons entry-line col-num)
-                                           entry-name)
-                        (cons entry-name entry-source)))
+                        (setq entry-line (buffer-substring-no-properties 
line-start line-end))
+                        ;; Add a text-property of :hyrolo-name-entry-column
+                         ;; with value of (current-column)
+                        (put-text-property 0 1 :hyrolo-name-entry-column
+                                           col-num entry-line)
+                        (list entry-line entry-source)))
              ;; If not blank, return the current line as the name with
-             ;; a text-property of 'hyrolo-line-entry with value of 
(current-column).
+             ;; a text-property of :hyrolo-line-entry-column with value of
+              ;; (current-column).
              (goto-char line-start)
              (when (not (looking-at "[ \t\f]*$"))
                (setq entry-line (buffer-substring-no-properties line-start 
line-end))
-               (put-text-property 0 1 'hyrolo-line-entry col-num entry-line)
-               (cons entry-line entry-source)))))))))
+               (put-text-property 0 1 :hyrolo-line-entry-column col-num 
entry-line)
+               (list entry-line entry-source)))))))))
 
 (define-derived-mode hyrolo-org-mode outline-mode "HyRoloOrg"
   "Basic Org mode for use in HyRolo display match searches."
diff --git a/test/hyrolo-tests.el b/test/hyrolo-tests.el
index 544600da75..90defd8a0c 100644
--- a/test/hyrolo-tests.el
+++ b/test/hyrolo-tests.el
@@ -3,7 +3,7 @@
 ;; Author:       Mats Lidell <[email protected]>
 ;;
 ;; Orig-Date:    19-Jun-21 at 22:42:00
-;; Last-Mod:     17-May-26 at 12:15:26 by Bob Weiner
+;; Last-Mod:      1-Jun-26 at 00:09:22 by Bob Weiner
 ;;
 ;; SPDX-License-Identifier: GPL-3.0-or-later
 ;;
@@ -2144,6 +2144,36 @@ Dependencies on the consult package are mocked."
             (should (looking-at-p "old-file"))))
       (hy-delete-files-and-buffers (list old-file old-file-backup new-file 
new-file-backup)))))
 
+(ert-deftest hyrolo-tests--edit-entry-edits-the-selected-match ()
+  "Verify `hyrolo-edit-entry' moves to the selected match and not a substring."
+  (let* ((org-file (make-temp-file "hypb" nil ".org"
+                                   "\
+* heading long
+body 1
+* heading
+body 2
+"))
+         (hyrolo-file-list (list org-file)))
+    (unwind-protect
+        (progn
+          (should (= 2 (hyrolo-grep "heading")))
+          (should (string= hyrolo-display-buffer (buffer-name)))
+
+          ;; Search Down
+          (should (looking-at-p "==="))
+          (hyrolo-next-match)
+          (should (looking-at-p (rx "heading long" eol)))
+
+          ;; Edit next record
+          (hyrolo-next-match)
+          (should (looking-at-p (rx "heading" eol)))
+          (hyrolo-edit-entry)
+          (should (string= (buffer-name) (file-name-nondirectory org-file)))
+          (should (looking-at-p (rx "heading" eol)))
+          )
+      (kill-buffer hyrolo-display-buffer)
+      (hy-delete-files-and-buffers hyrolo-file-list))))
+
 (provide 'hyrolo-tests)
 
 ;; This file can't be byte-compiled without the `el-mock' package

Reply via email to