branch: externals/hyperbole commit 1b8fb059c66a794d1ac29945b9f5d92a4e1b85a9 Author: Bob Weiner <r...@gnu.org> Commit: Bob Weiner <r...@gnu.org>
Fix HyRolo {f} and {b} commands and tests smart-hyrolo - extend to edit source files from anywhere in header --- ChangeLog | 36 ++++++++++++ hui-mouse.el | 17 ++++-- hyrolo.el | 163 ++++++++++++++++++++++++++++++++++----------------- kotl/kotl-mode.el | 4 +- man/hkey-help.txt | 2 +- man/hyperbole.texi | 7 ++- test/hyrolo-tests.el | 8 +-- 7 files changed, 168 insertions(+), 69 deletions(-) diff --git a/ChangeLog b/ChangeLog index 61f4713b19..feedb4d0cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,39 @@ +2024-01-15 Bob Weiner <r...@gnu.org> + +* test/hyrolo-tests.el (hyrolo-tests--forward-same-level-all-file-types-level1): + Fix test error by removing last forward list element so does not move past. + +* hyrolo.el (hyrolo-map-matches, hyrolo-funcall-match): Disable 'orgtbl-mode' + only if enabled. + +* man/hkey-help.txt: Add ref to Org Meta Return. + +* hui-mouse.el (smart-hyrolo): Extend to edit source location from any line + within the header, not just the @loc> line. + man/hyperbole.texi (Smart Key - HyRolo Match Buffers): Document above change. + +* kotl/kotl-mode.el (kotl-mode): Set 'outline-level' to 'hyrolo-outline-level' + which works for all HyRolo supported modes. + +* hyrolo.el (hyrolo-mode-map): Change {b} to 'hyrolo-outline-backward-same-level'. + Change {f} to 'hyrolo-outline-forward-same-level' and rewrite. + (hyrolo-outline-get-last-sibling, hyrolo-outline-get-next-sibling): + Add to support {f} and {b} commands. + (hyrolo-mode): Add set of buffer read-only to ensure no editing. Any + commands that change text therein need to also update the buffer caches. + (hyrolo-forward-same-level, hyrolo-backward-same-level): Remove, + duplicates of above hyrolo-outline-* functions. + (hyrolo-outline-next-visible-heading): Change to return whether any + next heading/header is found. + (hyrolo-outline-forward-same-level, hyrolo-outline-backward-same-level): + Rewrite based on 'hyrolo-outline-next-visible-heading'. + (hyrolo-outline-get-level): Add and call from above 2 functions. + (hyrolo-markdown-outline-level): Remove and use 'hyrolo-outline-level'. + (hyrolo-outline-level): Fix to handle kotl-mode properly. + (hyrolo-outline-move-subtree-up, hyrolo-outline-move-subtree-down, + hyrolo-outline-insert-heading, hyrolo-outline-demote, + hyrolo-outline-promote): Barf if buffer is read-only for these cmds. + 2024-01-15 Mats Lidell <ma...@gnu.org> * test/hyrolo-tests.el (hyrolo-tests--forward-same-level-all-file-types-level1) diff --git a/hui-mouse.el b/hui-mouse.el index b1ffa16509..8d1af80747 100644 --- a/hui-mouse.el +++ b/hui-mouse.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 04-Feb-89 -;; Last-Mod: 10-Jan-24 at 21:26:33 by Bob Weiner +;; Last-Mod: 15-Jan-24 at 18:18:37 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -89,7 +89,10 @@ (defvar helm-selection-point) -;; Functions from Hyperbole's Koutliner +;; Functions from Hyperbole's HyRolo and Koutliner +(declare-function hyrolo-edit-entry "hyrolo") +(declare-function hyrolo-hdr-in-p "hyrolo") +(declare-function hyrolo-hdr-to-first-line-p "hyrolo") (declare-function kotl-mode:eobp "kotl-mode") (declare-function kotl-mode:eolp "kotl-mode") @@ -99,7 +102,6 @@ (declare-function tar-extract-other-window "tar") (declare-function tar-expunge "tar") (declare-function outline-invisible-in-p "hyperbole") -(declare-function hyrolo-edit-entry "hyrolo") (declare-function Custom-newline "cus-edit") (declare-function Custom-buffer-done "cus-edit") @@ -1437,13 +1439,18 @@ If assist key is pressed within: (defun smart-hyrolo () "In hyrolo match buffer, edit current entry. -Uses one key or mouse key. +If on a file header, edit the file. Uses one key or mouse key. Invoked via a key press when in the `hyrolo-display-buffer'. Assume that its caller has already checked that the key was pressed in an appropriate buffer and has moved the cursor to the selected buffer." (interactive) - (hyrolo-edit-entry)) + (if (hyrolo-hdr-in-p) + (hact 'hyp-source (save-excursion + (hyrolo-hdr-to-first-line-p) + (when (search-forward hbut:source-prefix nil t) + (hbut:source t)))) + (hyrolo-edit-entry))) (defalias 'smart-hyrolo-assist #'smart-hyrolo) diff --git a/hyrolo.el b/hyrolo.el index a199de2a88..cdde8cccce 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: 13-Jan-24 at 20:04:26 by Bob Weiner +;; Last-Mod: 15-Jan-24 at 21:27:59 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -218,7 +218,7 @@ This pattern must match the beginning of a line.") ;; trailing-space grouping below hyrolo-entry-trailing-space-group-number 2 outline-regexp (concat hyrolo-hdr-prefix-regexp markdown-regex-header) - outline-level #'hyrolo-markdown-outline-level))) + outline-level #'hyrolo-outline-level))) ;; Support hyrolo searches in Emacs outline files (add-hook 'outline-mode-hook @@ -1547,12 +1547,6 @@ returned to the number given." ;; (goto-char (previous-single-char-property-change (point) 'invisible)))) (goto-char (1- (point))))) -(defun hyrolo-backward-same-level (arg) - "Move backward to the ARG'th subheading at same level as this one. -Stop at the first and last subheadings of a superior heading." - (interactive "p") - (hyrolo-move-backward #'hyrolo-outline-backward-same-level arg)) - ;;;###autoload (defun hyrolo-consult-grep (&optional regexp max-matches) "Interactively search `hyrolo-file-list' with a consult package grep command. @@ -1608,12 +1602,6 @@ only (first line of entries), rather than entire entries. Return number of matching entries found." (hyrolo-grep-file hyrolo-file-or-buf (regexp-quote string) max-matches count-only headline-only)) -(defun hyrolo-forward-same-level (arg) - "Move forward to the ARG'th subheading at same level as this one. -Stop at the first and last subheadings of a superior heading." - (interactive "p") - (hyrolo-move-forward #'outline-forward-same-level arg)) - (defun hyrolo-hdr-to-first-line-p () "If point is within a file header, go to its first line. Return t in such cases. Otherwise, don't move and return nil. @@ -1937,6 +1925,8 @@ Calls the functions given by `hyrolo-mode-hook'. (setq major-mode 'hyrolo-mode mode-name "HyRolo") + (setq buffer-read-only t) + (run-mode-hooks 'hyrolo-mode-hook)) (defun hyrolo-next-regexp-match (regexp headline-only) @@ -1960,7 +1950,19 @@ Only visible heading lines are considered, unless INVISIBLE-OK is non-nil." "Move backward to the ARG'th subheading at same level as this one. Stop at the first and last subheadings of a superior heading." (interactive "p") - (hyrolo-funcall-match (lambda () (outline-backward-same-level arg)))) + (hyrolo-funcall-match + (lambda () + (outline-back-to-heading) + (while (> arg 0) + (let ((point-to-move-to (save-excursion + (hyrolo-outline-get-last-sibling)))) + (if point-to-move-to + (progn + (goto-char point-to-move-to) + (setq arg (1- arg))) + (setq arg 0) + (error "No previous same-level heading/header"))))) + nil t)) (defun hyrolo-outline-demote (&optional which) "Demote headings lower down the tree. @@ -1971,16 +1973,68 @@ subtree (from a Lisp program, pass `subtree' for WHICH); with prefix argument, demote just the current heading (from a Lisp program, pass nil for WHICH, or do not pass any argument)." (interactive - (list (if (and transient-mark-mode mark-active) 'region - (outline-back-to-heading) - (if current-prefix-arg nil 'subtree)))) + (progn + (barf-if-buffer-read-only) + (list (if (and transient-mark-mode mark-active) 'region + (outline-back-to-heading) + (if current-prefix-arg nil 'subtree))))) (hyrolo-funcall-match (lambda () (outline-demote which)) t)) (defun hyrolo-outline-forward-same-level (arg) "Move forward to the ARG'th subheading at same level as this one. Stop at the first and last subheadings of a superior heading." (interactive "p") - (hyrolo-funcall-match (lambda () (outline-forward-same-level arg)))) + (hyrolo-funcall-match + (lambda () + (outline-back-to-heading) + (while (> arg 0) + (let ((point-to-move-to (save-excursion + (hyrolo-outline-get-next-sibling)))) + (if point-to-move-to + (progn + (goto-char point-to-move-to) + (setq arg (1- arg))) + (setq arg 0) + (error "No following same-level heading/header"))))))) + +(defun hyrolo-outline-get-last-sibling () + "Move to previous heading of the same level, and return point. +If there is no such heading, return nil." + (let ((opoint (point)) + (level (funcall outline-level))) + (hyrolo-outline-previous-visible-heading 1) + (when (and (/= (point) opoint) (outline-on-heading-p)) + (while (and (> (funcall outline-level) level) + (not (bobp))) + (hyrolo-outline-previous-visible-heading 1)) + (if (< (funcall outline-level) level) + nil + (point))))) + +(defun hyrolo-outline-get-level (backward-flag) + "Return the outline level at point. +Return 0 if not on an `outline-regexp' line. +BACKWARD-FLAG is non-nil if moving backward, else nil when moving +forward through the buffer." + (save-excursion + (beginning-of-line) + (hyrolo-funcall-match + (lambda () + (if (looking-at outline-regexp) + (hyrolo-outline-level) + 0)) + backward-flag))) + +(defun hyrolo-outline-get-next-sibling () + "Move to next heading/header of the same level, and return point. +If there is no such heading/header, return nil." + (let ((level (funcall outline-level))) + (hyrolo-outline-next-visible-heading 1) + (while (and (not (eobp)) (> (funcall outline-level) level)) + (hyrolo-outline-next-visible-heading 1)) + (if (or (eobp) (< (funcall outline-level) level)) + nil + (point)))) (defun hyrolo-outline-hide-body () "Hide all body lines in buffer, leaving all headings visible. @@ -2048,7 +2102,7 @@ only if on the heading line of the subtree." (defun hyrolo-outline-insert-heading () "Insert a new heading at same depth at point." - (interactive) + (interactive "*") (hyrolo-funcall-match #'outline-insert-heading t)) (defun hyrolo-outline-mark-subtree () @@ -2059,27 +2113,28 @@ This puts point at the start of the current subtree, and mark at the end." (defun hyrolo-outline-move-subtree-down (&optional arg) "Move the current subtree down past ARG headlines of the same level." - (interactive "p") + (interactive "*p") (hyrolo-funcall-match (lambda () (outline-move-subtree-down arg)) t)) (defun hyrolo-outline-move-subtree-up (&optional arg) "Move the current subtree up past ARG headlines of the same level." - (interactive "p") + (interactive "*p") (hyrolo-funcall-match (lambda () (outline-move-subtree-up arg)) t)) (defun hyrolo-outline-next-visible-heading (arg) - "Move to the next visible heading or match buffer header. + "Move to next visible heading or match buffer header. With ARG, repeats or can move backward if negative. +Return t if find any matching next heading/header, nil otherwise. A heading is one that starts with an `outline-regexp' match. A match buffer header is one that starts with `hyrolo-hdr-regexp'." (interactive "p") - (condition-case nil - (progn - (if (< arg 0) - (beginning-of-line) - (end-of-line)) - (let ((found-heading-p)) + (let ((found-heading-p)) + (condition-case nil + (progn + (if (< arg 0) + (beginning-of-line) + (end-of-line)) (while (and (not (bobp)) (< arg 0)) (while (and (not (bobp)) (progn (hyrolo-hdr-to-first-line-p) @@ -2104,13 +2159,13 @@ A match buffer header is one that starts with `hyrolo-hdr-regexp'." nil 'move))))) (outline-invisible-p (match-beginning 0)))) (setq arg (1- arg))) - (if found-heading-p (beginning-of-line)))) - ;; Prevent error and move to start or end of file header at point, - ;; if any - (error (if (>= arg 0) - (hyrolo-hdr-move-after-p) - (hyrolo-hdr-to-first-line-p)))) - (point)) + (if found-heading-p (beginning-of-line))) + ;; Prevent error and move to start or end of file header at point, + ;; if any + (error (if (>= arg 0) + (hyrolo-hdr-move-after-p) + (hyrolo-hdr-to-first-line-p)))) + (when found-heading-p t))) (defun hyrolo-outline-previous-heading () "Move to the previous (possibly invisible) heading line." @@ -2135,9 +2190,11 @@ subtree (from a Lisp program, pass `subtree' for WHICH); with prefix argument, promote just the current heading (from a Lisp program, pass nil for WHICH, or do not pass any argument)." (interactive - (list (if (and transient-mark-mode mark-active) 'region - (outline-back-to-heading) - (if current-prefix-arg nil 'subtree)))) + (progn + (barf-if-buffer-read-only) + (list (if (and transient-mark-mode mark-active) 'region + (outline-back-to-heading) + (if current-prefix-arg nil 'subtree))))) (hyrolo-funcall-match (lambda () (outline-promote which)) t)) ;;; Don't need to override but alias them for completeness @@ -2531,10 +2588,6 @@ HYROLO-BUF is optional; the default is the current buffer." (and hyrolo-kill-buffers-after-use (not (buffer-modified-p hyrolo-buf)) (kill-buffer hyrolo-buf))) -(defun hyrolo-markdown-outline-level () - "Fix markdown `outline-level' function to always return a non-nil level." - (or (markdown-outline-level) 1)) - (defun hyrolo-name-and-email () "If point is in a mail message, return list of (name email-addr) of sender. Name is returned as `last, first-and-middle'." @@ -2799,9 +2852,12 @@ trailing periods and whitespace. Point must be at the beginning of a heading line and a regexp match to `outline-regexp' must have been done prior to calling this." (or (cdr (assoc (match-string-no-properties 0) outline-heading-alist)) - (when (looking-at-p hyrolo-hdr-regexp) 1) - (when (looking-at-p hbut:source-prefix) 1) - (1- (- (match-end 0) (match-beginning 0))))) + (when (hyrolo-hdr-in-p) 1) + (cond ((derived-mode-p 'kotl-mode) + (kcell-view:level)) + ((looking-at hyrolo-hdr-and-entry-regexp) + (1- (- (match-end 0) (match-beginning 0)))) + (t 0)))) ;;; ************************************************************************ ;;; Caching of buffer major-modes for use in HyRolo display match buffer @@ -2847,7 +2903,8 @@ prior to applying FUNC." (error "(hryolo-map-matches): No HyRolo matches in current buffer")) (let ((display-buf (get-buffer hyrolo-display-buffer))) (if (eq (current-buffer) display-buf) - (let ((bounds hyrolo--cache-loc-match-bounds) + (let ((outline-regexp hyrolo-hdr-and-entry-regexp) + (bounds hyrolo--cache-loc-match-bounds) (ofont-lock font-lock-mode) (omode major-mode) (ostart (point-min)) @@ -2873,7 +2930,7 @@ prior to applying FUNC." ;; Restore original mode and font-locking (funcall omode) (font-lock-mode (if ofont-lock 1 0)) - (when (fboundp 'orgtbl-mode) + (when (and (fboundp 'orgtbl-mode) orgtbl-mode) ;; Disable as overrides single letter keys (orgtbl-mode 0)) ;; This pause forces a window redisplay that maximizes the @@ -2900,7 +2957,7 @@ on a file boundary, move point back a character to select the proper major mode." (let ((display-buf (get-buffer hyrolo-display-buffer))) (if (eq (current-buffer) display-buf) - (progn + (let ((outline-regexp hyrolo-hdr-and-entry-regexp)) (when (< (length hyrolo--cache-loc-match-bounds) 1) (error "(hryolo-funcall-match): No HyRolo matches in display buffer")) (let ((ofont-lock font-lock-mode) @@ -2930,7 +2987,7 @@ proper major mode." ;; Restore original mode and font-locking (funcall omode) (font-lock-mode (if ofont-lock 1 0)) - (when (fboundp 'orgtbl-mode) + (when (and (fboundp 'orgtbl-mode) orgtbl-mode) ;; Disable as overrides single letter keys (orgtbl-mode 0)) ;; This pause forces a window redisplay that maximizes the @@ -3025,7 +3082,7 @@ Add `hyrolo-hdr-regexp' to `hyrolo-hdr-and-entry-regexp' and `outline-regexp'." (unless (string-prefix-p hyrolo-hdr-regexp outline-regexp) (setq-local outline-regexp (concat hyrolo-hdr-prefix-regexp outline-regexp))) (when (eq outline-level #'markdown-outline-level) - (setq-local outline-level #'hyrolo-markdown-outline-level))) + (setq-local outline-level #'hyrolo-outline-level))) ;;; ************************************************************************ ;;; hyrolo-mode key bindings - set after all library functions have @@ -3049,9 +3106,9 @@ Add `hyrolo-hdr-regexp' to `hyrolo-hdr-and-entry-regexp' and `outline-regexp'." (define-key hyrolo-mode-map "\177" 'scroll-down) (define-key hyrolo-mode-map " " 'scroll-up) (define-key hyrolo-mode-map "a" 'outline-show-all) - (define-key hyrolo-mode-map "b" 'hyrolo-backward-same-level) + (define-key hyrolo-mode-map "b" 'hyrolo-outline-backward-same-level) (define-key hyrolo-mode-map "e" 'hyrolo-edit-entry) - (define-key hyrolo-mode-map "f" 'hyrolo-forward-same-level) + (define-key hyrolo-mode-map "f" 'hyrolo-outline-forward-same-level) (define-key hyrolo-mode-map "h" 'hyrolo-outline-hide-subtree) (define-key hyrolo-mode-map "l" 'hyrolo-locate) (define-key hyrolo-mode-map "m" 'hyrolo-mail-to) diff --git a/kotl/kotl-mode.el b/kotl/kotl-mode.el index 8292b2071e..91a41ed1e3 100644 --- a/kotl/kotl-mode.el +++ b/kotl/kotl-mode.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 6/30/93 -;; Last-Mod: 29-Dec-23 at 02:05:41 by Bob Weiner +;; Last-Mod: 15-Jan-24 at 17:21:47 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -183,7 +183,7 @@ It provides the following keys: ;; Remove indication that buffer is narrowed. mode-line-format (copy-sequence mode-line-format) mode-line-format (set:remove "%n" mode-line-format) - outline-level #'kcell-view:level + outline-level #'hyrolo-outline-level outline-regexp hyrolo-hdr-and-entry-regexp)) ;; (when (fboundp 'add-to-invisibility-spec) diff --git a/man/hkey-help.txt b/man/hkey-help.txt index 4af3803640..44bf67e102 100644 --- a/man/hkey-help.txt +++ b/man/hkey-help.txt @@ -105,7 +105,7 @@ Hyperbole Key Press/Click in Special Modes Menu Item or node hdr Jumps to Texinfo referent Button help Include file Jumps to Texinfo referent Button help code/var reference Displays doc for referent Button help - Org Mode Follows links and cycles outline views + Org Mode Follows links, cycles headings and Org Meta Return Org/Roam ID Jumps to ID referent Button help Outline Major/Minor Modes Collapses, expands, and moves outline entries Man Apropos Displays man page entry <- same diff --git a/man/hyperbole.texi b/man/hyperbole.texi index 46da3d6620..e4d4e28700 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: 6-Jan-24 at 01:18:32 by Bob Weiner +@c Last-Mod: 15-Jan-24 at 18:26:44 by Bob Weiner @c %**start of header (This is for running Texinfo on a region.) @setfilename hyperbole.info @@ -11229,9 +11229,10 @@ If pressed on a World-Wide Web universal resource locator (URL): @cindex hyrolo matches @format @group -If pressed within an entry in the HyRolo search results buffer: +If pressed within the HyRolo search results buffer: ACTION KEY or ASSIST KEY - The entry is edited in the other window. + On an entry, the entry is displayed for editing in its source buffer. + On a file header, the file location is displayed for editing. @end group @end format diff --git a/test/hyrolo-tests.el b/test/hyrolo-tests.el index 3c4ae188d1..89e2974540 100644 --- a/test/hyrolo-tests.el +++ b/test/hyrolo-tests.el @@ -3,7 +3,7 @@ ;; Author: Mats Lidell <ma...@gnu.org> ;; ;; Orig-Date: 19-Jun-21 at 22:42:00 -;; Last-Mod: 15-Jan-24 at 00:38:13 by Mats Lidell +;; Last-Mod: 15-Jan-24 at 21:40:51 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -906,7 +906,6 @@ Make cell start with HEADING and follow by next line BODY." (ert-deftest hyrolo-tests--forward-same-level-all-file-types-level1 () "Verify forward and backward to first level headers and section lines. All files types are present." - :expected-result :failed (let* ((org-file1 (make-temp-file "hypb" nil ".org" (hyrolo-tests--gen-outline ?* "heading-org" 1 "body-org" 1))) (md-file1 (make-temp-file "hypb" nil ".md" @@ -922,7 +921,7 @@ All files types are present." ;; Move forward (dolist (v '("===" "^\\* heading-org 1$" "===" "^# heading-md 1$" - "===" "^\\* heading-otl 1$" "===" "^ +1\\. heading-kotl$")) + "===" "^\\* heading-otl 1$" "===")) (should (and (looking-at-p v) (hact 'kbd-key "f")))) (should (looking-at-p "^ +1\\. heading-kotl$")) ; When on last match do not move further @@ -968,8 +967,7 @@ body (should (and (hact 'kbd-key "f") (looking-at-p "^\\*\\* h-org 1\\.2"))) ;; Multiple times does not move point when there are no more headers at the same level - (should (and (hact 'kbd-key "f") (looking-at-p "^\\*\\* h-org 1\\.2"))) - (should (and (hact 'kbd-key "f") (looking-at-p "^\\*\\* h-org 1\\.2"))) + (should-error (and (hact 'kbd-key "f") (looking-at-p "^\\*\\* h-org 1\\.2"))) ;; Move back on same level (should (and (hact 'kbd-key "b") (looking-at-p "\\*\\* h-org 1\\.1")))