branch: externals/hyperbole commit 335f128c105930bf4c8ae18b4808b4ae6dac0035 Author: bw <r...@gnu.org> Commit: bw <r...@gnu.org>
hui.el - Add more context types to hui:kill/copy cmds when no region (hui:selectable-thing-priority-list): Add this defcustom; if nil, disables both delimited and non-delimited regional thing selection in `hyperbole-mode' when no region is active. hpath.el (hpath:url-at-p, hpath:url-p, hpath:www-at-p, hpath:www-p): Clarify in doc string whether leading protocol string is necessary for recognition. hmouse-drv.el (hkey-throw): Change so selects the window thrown to. Use new 'hkey-throw-and-stay' for old behavior. --- ChangeLog | 54 +++++++++++ hact.el | 9 +- hbut.el | 4 +- hmouse-drv.el | 38 +++++++- hpath.el | 11 ++- hui-select.el | 125 ++++++++++++++------------ hui-window.el | 10 +-- hui.el | 260 ++++++++++++++++++++++++++++++++++++----------------- hypb.el | 9 +- hyperbole.el | 10 +-- kotl/kotl-mode.el | 71 +++++++-------- kotl/kview.el | 8 +- man/hyperbole.texi | 10 +-- test/hui-tests.el | 109 +++++++++++----------- 14 files changed, 462 insertions(+), 266 deletions(-) diff --git a/ChangeLog b/ChangeLog index 777d78ab8d..d4741b3b6d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,57 @@ +2025-06-20 Bob Weiner <r...@gnu.org> + +* kotl/kotl-mode.el (kotl-mode:kill-region): + hui.el (hui:copy-to-register, hui:kill-ring-save): Test that a mark is set + in the buffer before calling 'indicate-copied-region' or it will error. + +* kotl/kotl-mode.el (kotl-mode:kill-region): Add 'kill-ring-save' to + 'kill-commands'. + +* test/hui-tests.el (hui--kill-highlighted-region): Update to only error when + on whitespace. + +* hypb.el (hypb:in-string-p): Fix bug where point was on the end delimiter and + the search forward for it skips over it because it requires a non-backslash + character ahead of it. Update doc to note that this returns nil if point + is on the closing quote(s). + +* hmouse-drv.el (hkey-throw): Change so selects the window thrown to. Use new + 'hkey-throw-and-stay' for old behavior. + +* hui-select.el (hui-select-get-region-boundaries): Set syntax-table so <> and {} + work as balanced pairs. + (hui-select-string-p): Rewrite to use string start and end values + returned by (hypb:in-string-p nil t) and to use 'hargs:delimited' to simplify + the implementation. + hui.el (hui:delimited-selectable-thing): Replace call of 'hui-select-get-thing' + with (hui-select-delimited-thing-call #'hui-select-thing) so does not select + multiple lines due to sexpressions when point is at the start of: + <a...@abc.com> + "www.google.com". + +* hpath.el (hpath:url-at-p, hpath:url-p, hpath:www-at-p, hpath:www-p): Clarify + in doc string whether leading protocol string is necessary for recognition. + +* hui.el (hui:kill-region): Rename to 'hui:kill-region-internal' for consistency. + (hui-copy-to-register): Rename to 'hui:copy-to-register'. + (hui-kill-region): Rename to 'hui:kill-region'. + (hui-kill-ring-save): Rename to 'hui:kill-ring-save'. + (hui:selectable-thing-priority-list): Add this defcustom; if nil, disables + both delimited and non-delimited regional thing selection in 'hyperbole-mode' + when no region is active. + (hui:non-delimited-selectable-symbol-and-bounds): Add and select + a customizable set of non-delimitable symbols using {M-w} and {C-w}. + (hui:copy-to-register, hui:kill-region, hui:kill-ring-save): Call above + added function. + (hui:delimited-selectable-thing-and-bounds): Add <thing-type> to beginning + of list returned to match 'hui:non-delimited-selectable-symbol-and-bounds'. + (hui:selectable-thing-and-bounds): Add to call both delimited and non-delim + thing-and-bounds functions and to include any delimiters. + +2025-06-19 Bob Weiner <r...@gnu.org> + +* hui-window.el (hmouse-dired-readin-hook): Fix where to find associated doc. + 2025-06-16 Bob Weiner <r...@gnu.org> * test/hyrolo-tests.el (hyrolo-tests--forward-same-level-all-file-types-level1): diff --git a/hact.el b/hact.el index 1bcd8106cc..f456b53ed6 100644 --- a/hact.el +++ b/hact.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 18-Sep-91 at 02:57:09 -;; Last-Mod: 19-Apr-25 at 19:03:44 by Bob Weiner +;; Last-Mod: 19-Jun-25 at 10:24:53 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -393,10 +393,9 @@ Autoloads action function if need be to get the parameter list." (defun hact (&rest args) "Perform action formed from rest of ARGS and return the result. The value of `hrule:action' determines what effect this has. The -default for `hrule:action' is `actype:act' which returns the -result of the action unless it is nil, in which case t is -returned instead, to ensure that implicit button types register -the performance of the action. +default for `hrule:action' is `actype:act' which returns the result of +the action unless it is nil, in which case t is returned instead, to +ensure that implicit button types register the performance of the action. Alternatively act as a no-op when testing implicit button type contexts. First arg may be a symbol or symbol name for either an action type or a diff --git a/hbut.el b/hbut.el index d7258ea3c6..ab85b9c9be 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: 26-Apr-25 at 10:12:23 by Bob Weiner +;; Last-Mod: 20-Jun-25 at 16:39:53 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -1632,7 +1632,7 @@ Modify `hbut:syntax-table' and `help-mode-syntax-table' to include <> and {}. Modify `text-mode-syntax-table' and `fundamental-mode's syntax table to include {} only. For use with implicit button activations." ;; Treat angle brackets and braces as opening and closing delimiters - ;; for ease of matching. + ;; for ease of matching. (mapc (lambda (syntax-table) (modify-syntax-entry ?\< "(>" syntax-table) (modify-syntax-entry ?\> ")<" syntax-table) diff --git a/hmouse-drv.el b/hmouse-drv.el index 9349967698..1bdba28299 100644 --- a/hmouse-drv.el +++ b/hmouse-drv.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 04-Feb-90 -;; Last-Mod: 10-May-25 at 00:19:45 by Mats Lidell +;; Last-Mod: 20-Jun-25 at 15:22:16 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -627,6 +627,40 @@ Throw one of: - a displayable item at point or - the current buffer. With optional prefix arg THROW-REGION-FLAG, throw the current region +even if not active. After the throw, the RELEASE-WINDOW becomes the +selected window." + (interactive (list (ace-window nil) current-prefix-arg)) + (let ((depress-frame (selected-frame)) + (display-delay (if (boundp 'temp-display-delay) + temp-display-delay + 0.5))) + ;; Throw either the region or the item at point and keep selected-window + (let ((action-key-depress-window (selected-window)) + (action-key-release-window release-window) + (action-key-depress-args)) + (unless (hkey-insert-region action-key-depress-window release-window throw-region-flag display-delay) + (if (cadr (assq major-mode hmouse-drag-item-mode-forms)) + (hmouse-item-to-window) + (set-window-buffer release-window (current-buffer)))) + (unless (eq depress-frame (window-frame release-window)) + ;; Force redisplay or item buffer won't be displayed here. + (redisplay t) + ;; Show the frame thrown to before it is covered when + ;; input-focus is returned to the depress-frame. + (raise-frame (window-frame release-window)) + (select-frame-set-input-focus (window-frame release-window)) + ;; Don't use sit-for here because it can be interrupted early. + (sleep-for display-delay)) + (select-window release-window)))) + +;;;###autoload +(defun hkey-throw-and-stay (release-window &optional throw-region-flag) + "Throw a thing to display in RELEASE-WINDOW. +Throw one of: + - the active (highlighted) region, + - a displayable item at point or + - the current buffer. +With optional prefix arg THROW-REGION-FLAG, throw the current region even if not active. The selected window does not change." (interactive (list (ace-window nil) current-prefix-arg)) @@ -798,7 +832,7 @@ Leave the end window selected." Throw either a displayable item at start window's point or its current buffer to the end window. The selected window does not change." (interactive) - (hmouse-choose-windows #'hkey-throw)) + (hmouse-choose-windows #'hkey-throw-and-stay)) (defun hmouse-choose-link-and-referent-windows () "Select and return a list of (link-button-window referent-window)." diff --git a/hpath.el b/hpath.el index b05aa1dde3..0bb15bbfee 100644 --- a/hpath.el +++ b/hpath.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 1-Nov-91 at 00:44:23 -;; Last-Mod: 15-Jun-25 at 12:03:03 by Bob Weiner +;; Last-Mod: 20-Jun-25 at 09:41:06 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -2399,7 +2399,7 @@ off otherwise." #'hpath:disable-find-file-urls))) (defun hpath:url-at-p () - "Return an url that point immediately precedes or nil. + "Return a url with an initial protocol that point immediately precedes or nil. Url is a world-wide-web universal resource locator. See the documentation for `hpath:url-regexp' for `match-string' groupings." (if (or (looking-at hpath:url-regexp) (looking-at hpath:url-regexp2) @@ -2410,8 +2410,9 @@ See the documentation for `hpath:url-regexp' for `match-string' groupings." (buffer-substring-no-properties (match-beginning hpath:url-grpn) (point))))) (defun hpath:url-p (obj) - "Return t if OBJ is an url, else nil. + "Return t if OBJ is a url, else nil. Url is a world-wide-web universal resource locator. +The url may lack a leading protocol; it will be inferred. See the documentation for `hpath:url-regexp' for match groupings to use with `string-match'." (and (stringp obj) @@ -2422,6 +2423,7 @@ use with `string-match'." (defun hpath:www-at-p (&optional include-start-and-end-p) "Return a world-wide-web link reference that point is within or nil. +The url may lack a leading protocol; it will be inferred. With optional INCLUDE-START-AND-END-P non-nil, returns list of: (link-string begin-position end-position)." (save-excursion @@ -2437,7 +2439,8 @@ With optional INCLUDE-START-AND-END-P non-nil, returns list of: (point)))))) (defun hpath:www-p (path) - "Return PATH iff PATH is a world-wide-web link reference, else nil." + "Return PATH iff PATH is a world-wide-web link reference, else nil. +The PATH may lack a leading protocol; it will be inferred." (and (stringp path) (hpath:url-p path) path)) ;;; ************************************************************************ diff --git a/hui-select.el b/hui-select.el index 13f678acfe..e241f48897 100644 --- a/hui-select.el +++ b/hui-select.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 19-Oct-96 at 02:25:27 -;; Last-Mod: 14-Apr-25 at 15:53:22 by Mats Lidell +;; Last-Mod: 21-Jun-25 at 13:29:32 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -541,9 +541,13 @@ Also, add language-specific syntax setups to aid in thing selection." (defun hui-select-get-region-boundaries () "Return the (START . END) boundaries of region for `hui-select-thing'." - (or (hui-select-boundaries (point)) - (when (eq hui-select-previous 'punctuation) - (hui-select-word (point))))) + (with-syntax-table + (if (memq major-mode hui-select-ignore-quoted-sexp-modes) + (syntax-table) + hui-select-syntax-table) + (or (hui-select-boundaries (point)) + (when (eq hui-select-previous 'punctuation) + (hui-select-word (point)))))) ;;;###autoload (defun hui-select-get-thing () @@ -1040,63 +1044,66 @@ Return the updated cons cell." hui-select-region)) (defun hui-select-string-p (&optional start-delim end-delim) - "Return (start . end) of a string. -Works when on a delim or on the first line with point in the -string or directly before it. Positions include delimiters. -String is delimited by double quotes unless optional START-DELIM -and END-DELIM (strings) are given. Returns nil if not within a -string." + "Return (start . end) positions of a string, including delimiters. +This works when point is immediately before the opening or closing +delimiter or within the text of the string. The string is delimited +by double quotes, unless optional START-DELIM and END-DELIM (strings) +are given. Return nil if not at a string." (unless start-delim (setq start-delim "\"")) (unless end-delim (setq end-delim "\"")) + (let (string-start-end) (with-syntax-table hbut:syntax-table - (or (and (equal start-delim "\"") (equal end-delim "\"") - (ignore-errors - (cond ((and (= (or (char-after) 0) ?\") - (/= (or (char-before) 0) ?\\)) - (if (hypb:in-string-p) - (hui-select-set-region (1+ (point)) - (scan-sexps (1+ (point)) -1)) - (hui-select-set-region (point) (scan-sexps (point) 1)))) - ((and (= (or (char-before) 0) ?\") - (/= (or (char-before (1- (point))) 0) ?\\)) - (if (hypb:in-string-p) - (hui-select-set-region (1- (point)) (scan-sexps (1- (point)) 1)) - (hui-select-set-region (point) (scan-sexps (point) -1))))))) - (let ((opoint (point)) - (count 0) - bol start delim-regexp start-regexp end-regexp) - ;; Special case for the empty string. - (if (looking-at (concat (regexp-quote start-delim) - (regexp-quote end-delim))) - (hui-select-set-region (point) (match-end 0)) - (setq start-regexp (concat "\\(^\\|[^\\]\\)\\(" - (regexp-quote start-delim) "\\)") - end-regexp (concat "[^\\]\\(" (regexp-quote end-delim) "\\)") - delim-regexp (concat start-regexp "\\|" end-regexp)) - (save-excursion - (beginning-of-line) - (setq bol (point)) - (while (re-search-forward delim-regexp opoint t) - (setq count (1+ count)) - ;; This is so we don't miss the closing delimiter of an empty - ;; string. - (if (and (= (point) (1+ bol)) - (looking-at (regexp-quote end-delim))) - (setq count (1+ count)) - (unless (bobp) - (backward-char 1)))) - (goto-char opoint) - ;; If found an even # of starting and ending delimiters before - ;; opoint, then opoint is at the start of a string, where we want it. - (if (zerop (mod count 2)) - (unless (bobp) - (backward-char 1)) - (re-search-backward start-regexp nil t)) - ;; Point is now before the start of the string. - (when (re-search-forward start-regexp nil t) - (setq start (match-beginning 2)) - (when (re-search-forward end-regexp nil t) - (hui-select-set-region start (point)))))))))) + (or + ;; On or before double quote delimiters + (and (equal start-delim "\"") (equal end-delim "\"") + (cond ((and (= (or (char-after) 0) ?\") + (/= (or (char-before) 0) ?\\)) + (if (setq string-start-end (hypb:in-string-p nil t)) + ;; Add double quote delimiters to the region returned + (hui-select-set-region (1- (nth 1 string-start-end)) + (1+ (nth 2 string-start-end))) + ;; May be on the closing double quote of a string in + ;; which case this first scan-sexps will fail but + ;; the second will succeed. + (when (setq string-start-end + (or (ignore-errors (hui-select-set-region (point) (scan-sexps (point) 1))) + (ignore-errors (hui-select-set-region + (scan-sexps (1+ (point)) -1) + (1+ (point)))))) + (hui-select-set-region + (min (car string-start-end) (cdr string-start-end)) + (max (car string-start-end) (cdr string-start-end)))))) + ((and (= (or (char-before) 0) ?\") + (/= (or (char-before (1- (point))) 0) ?\\)) + (if (setq string-start-end (hypb:in-string-p nil t)) + ;; Add double quote delimiters to the region returned + (hui-select-set-region (1- (nth 1 string-start-end)) + (1+ (nth 2 string-start-end))) + ;; Either there are no matching string delimiters + ;; (only an open delimiter) or (point) is immediately + ;; after the end of the string in which case the + ;; following scan-sexps will succeed. + (when (setq string-start-end + (ignore-errors (hui-select-set-region (point) (scan-sexps (point) -1)))) + (hui-select-set-region + (min (car string-start-end) (cdr string-start-end)) + (max (car string-start-end) (cdr string-start-end)))))))) + + ;; Non-double quote delimiters + (let ((opoint (point)) + (count 0) + bol start delim-regexp start-regexp end-regexp) + (save-excursion + (when (looking-at (regexp-quote start-delim)) + (goto-char (match-end 0))) + (when (setq string-start-end + (hargs:delimited start-delim end-delim nil nil t)) + ;; Include delimiters + (hui-select-set-region (- (nth 1 string-start-end) + (length start-delim)) + (+ (nth 2 string-start-end) + (length end-delim)))))))))) + ;;; ;;; Code selections ;;; @@ -1445,7 +1452,7 @@ The region includes sexpressions before and after POS" (hui-select-set-region (point) end)))))) (defun hui-select-string (pos) - "Return (start . end) of string at POS or nil. Pos include delimiters. + "Return (start . end) of string including delimiters at POS, or nil. Delimiters may be single, double or open and close quotes." (setq hui-select-previous 'string) (save-excursion diff --git a/hui-window.el b/hui-window.el index 71bd190756..abf08a955f 100644 --- a/hui-window.el +++ b/hui-window.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 21-Sep-92 -;; Last-Mod: 11-Nov-24 at 00:20:41 by Bob Weiner +;; Last-Mod: 19-Jun-25 at 11:44:26 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -387,18 +387,18 @@ part of InfoDock and not a part of Hyperbole)." (defun hmouse-dired-readin-hook () "Remove local `hpath:display-where' setting whenever re-read a Dired directory. -See `hmouse-dired-item-dragged' for use." +See the `hmouse-dired-display-here-mode' function for use." (hmouse-dired-display-here-mode 0)) (define-minor-mode hmouse-dired-display-here-mode "Display item here on key press after Dired item drag. Once a Dired buffer item has been dragged, make next Action Key -press on an item display it in the same Dired window. +press on an item display it in the current Dired window. By default an Action Key press on a Dired item displays it in another window. But once a Dired item is dragged to another window, the next -Action Key press should display it in the Dired window so that the -behavior matches that of Buffer Menu and allows for setting what is +Action Key press should display it in the current Dired window so that +the behavior matches that of Buffer Menu and allows for setting what is displayed in all windows on screen, including the Dired window. If the directory is re-read into the Dired buffer with {g}, then Action diff --git a/hui.el b/hui.el index e1af82cca2..0f7c23e33e 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: 20-Apr-25 at 15:15:12 by Bob Weiner +;; Last-Mod: 21-Jun-25 at 13:26:46 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -19,6 +19,7 @@ ;;; Other required Elisp libraries ;;; ************************************************************************ +(require 'cl-macs) ;; For `cl-do*' (require 'hversion) (require 'hargs) ;; Avoid any potential library name conflict by giving the load directory. @@ -49,16 +50,26 @@ ;;; Public variables ;;; ************************************************************************ -(defcustom hui:hbut-delete-confirm-flag t - "*Non-nil means prompt before interactively deleting explicit buttons." +(defcustom hui:ebut-prompt-for-action nil + "*Non-nil prompts for a button-specific action on explicit button creation." :type 'boolean :group 'hyperbole-buttons) -(defcustom hui:ebut-prompt-for-action nil - "*Non-nil prompts for a button-specific action on explicit button creation." +(defcustom hui:hbut-delete-confirm-flag t + "*Non-nil means prompt before interactively deleting explicit buttons." :type 'boolean :group 'hyperbole-buttons) +(defcustom hui:selectable-thing-priority-list '(uuid email filename symbol word) + "List of priority ordered symbols recognized by `thing-at-point'. +Either a 'url matches or the first match from this list is used when +`hui:non-delimited-selectable-thing-and-bounds' is called during region +copy and kills. Set this list to nil to disable both delimited and +non-delimited thing recognition in copy and kill commands when +`hyperbole-mode' is enabled." + :type '(list symbol) + :group 'hyperbole) + ;;; ************************************************************************ ;;; Private variables ;;; ************************************************************************ @@ -76,7 +87,7 @@ At other times, value must be nil.") ;; Derived from copy-to-register of "register.el" ;;;###autoload -(defun hui-copy-to-register (register start end &optional delete-flag region-flag) +(defun hui:copy-to-register (register start end &optional delete-flag region-flag) "Copy region or thing into REGISTER. With prefix arg, delete as well. Called from program, takes five args: REGISTER, START, END, DELETE-FLAG, and REGION-FLAG. START and END are buffer positions indicating what to copy. @@ -109,10 +120,11 @@ point; see `hui:delimited-selectable-thing'." ((and (called-interactively-p 'interactive) transient-mark-mode (not (use-region-p)) - (prog1 (setq thing-and-bounds (hui:delimited-selectable-thing-and-bounds) - start (nth 1 thing-and-bounds) - end (nth 2 thing-and-bounds) - thing (nth 0 thing-and-bounds)) + (prog1 (setq thing-and-bounds + (hui:selectable-thing-and-bounds) + thing (nth 1 thing-and-bounds) + start (nth 2 thing-and-bounds) + end (nth 3 thing-and-bounds)) (when (and delete-flag start end) (delete-region start end)))) thing) @@ -126,16 +138,17 @@ point; see `hui:delimited-selectable-thing'." (setq deactivate-mark t) (cond (delete-flag) ((called-interactively-p 'interactive) - (if thing - (message "Saved selectable thing: %s" thing) - (indicate-copied-region))))))) + (cond (thing + (message "Saved selectable thing: %s" thing)) + ((mark t) + (indicate-copied-region)))))))) ;; In "hyperbole.el", use this to override the {C-w} command from ;; either "completion.el" or "simple.el" when hyperbole-mode is active ;; to allow killing kcell references, active regions and delimited ;; areas (like sexpressions). ;;;###autoload -(defun hui-kill-region (beg end &optional region interactive-flag) +(defun hui:kill-region (beg end &optional region interactive-flag) "Kill (\"cut\") between point and mark. The text is deleted but saved in the kill ring. The command \\[yank] can retrieve it from there. @@ -153,37 +166,34 @@ Patched to remove the most recent completion." ;; calling `kill-append'. (interactive (list (when mark-active (mark)) (when mark-active (point)) - 'region (prefix-numeric-value current-prefix-arg))) - (cond ((and transient-mark-mode - (or (use-region-p) - (not interactive-flag))) - (unless (and beg end) - (setq beg (region-beginning) - end (region-end)))) - ((and transient-mark-mode - (let* ((major-mode 'fundamental-mode) - ;; Setting the major mode prevents hui-select from - ;; suppressing use of `hui-select-syntax-table' - ;; if in one of `hui-select-ignore-quoted-sexp-modes'. - (sel-func (hui-select-at-delimited-thing-p)) - beg-end) - (when sel-func - (setq beg-end (funcall sel-func (point)) - beg (car beg-end) - end (cdr beg-end) - region nil) - t)))) - (interactive-flag (setq beg (mark) - end (point)))) + 'region t)) + (when transient-mark-mode + (cond ((or (use-region-p) + (not interactive-flag)) + (unless (and beg end) + (setq beg (region-beginning) + end (region-end)))) + ;; Setting the major mode prevents hui-select from + ;; suppressing use of `hui-select-syntax-table' + ;; if in one of `hui-select-ignore-quoted-sexp-modes'. + ((let* ((major-mode 'fundamental-mode) + thing-and-bounds) + (when (setq thing-and-bounds (hui:selectable-thing-and-bounds)) + (setq beg (nth 2 thing-and-bounds) + end (nth 3 thing-and-bounds) + region nil) + t))))) ;; If there is no mark, this call should trigger an error - (hui:kill-region beg end region)) + (if (and (null beg) (null end) (eq (mark t) (point))) + (hui:kill-region-internal (mark t) (point) region) + (hui:kill-region-internal beg end region))) ;; In "hyperbole.el", use this to override the {M-w} command from ;; "simple.el" when hyperbole-mode is active to allow copying kcell ;; references, active regions and delimited areas (like sexpressions). ;;;###autoload -(defun hui-kill-ring-save (beg end &optional region) +(defun hui:kill-ring-save (beg end &optional region) "Save the active region as if killed, but don't kill it. In Transient Mark mode, deactivate the mark. If `interprogram-cut-function' is non-nil, also save the text for a window @@ -225,22 +235,29 @@ visual feedback indicating the extent of the region being copied." end (point))) (hui:validate-region beg end region) (copy-region-as-kill beg end region)) - (setq thing (hui:delimited-selectable-thing)) - (if (stringp thing) - (progn (kill-new thing) - (setq deactivate-mark t)) - (when (and (called-interactively-p 'interactive) - (or (null beg) (null end))) - (setq beg (mark) - end (point))) - (hui:validate-region beg end region) - (copy-region-as-kill beg end region))) + (if (derived-mode-p 'kotl-mode) + (kotl-mode:copy-region-as-kill beg end) + ;; Setting the major mode prevents hui-select from + ;; suppressing use of `hui-select-syntax-table' + ;; if in one of `hui-select-ignore-quoted-sexp-modes'. + (let ((major-mode 'fundamental-mode)) + (setq thing (nth 1 (hui:selectable-thing-and-bounds)))) + (if (stringp thing) + (progn (kill-new thing) + (setq deactivate-mark t)) + (when (and (called-interactively-p 'interactive) + (or (null beg) (null end))) + (setq beg (mark) + end (point))) + (hui:validate-region beg end region) + (copy-region-as-kill beg end region)))) ;; This use of `called-interactively-p' is correct because the ;; code it controls just gives the user visual feedback. (when (called-interactively-p 'interactive) - (if thing - (message "Saved selectable thing: %s" thing) - (indicate-copied-region))))) + (cond (thing + (message "Saved selectable thing: %s" thing)) + ((mark t) + (indicate-copied-region)))))) ;;; ************************************************************************ ;;; Public functions @@ -307,6 +324,7 @@ binding." (defun hui:delimited-selectable-thing () "Return any delimited selectable thing at point as a string or nil if none. +Return nil if `hui:selectable-thing-priority-list' is nil. With point: in a Koutline klink, copy the klink; @@ -315,41 +333,115 @@ With point: on a Hyperbole button, copy the text of the button excluding delimiters; at the start of a paired delimiter, copy the text including the delimiters." - (cond ((klink:absolute (klink:at-p))) - ((derived-mode-p 'kotl-mode) - (kcell-view:absolute-reference)) - ((and (not (hyperb:stack-frame '(hui-kill-ring-save hbut:at-p ibut:at-p ebut:at-p))) - (let* ((hbut (hbut:at-p)) - (start (when hbut (hattr:get hbut 'lbl-start))) - (end (when hbut (hattr:get hbut 'lbl-end)))) - (and start end - (buffer-substring-no-properties start end))))) - ((hui-select-at-delimited-thing-p) - (hui-select-get-thing)))) + (when hui:selectable-thing-priority-list + (cond ((klink:absolute (klink:at-p))) + ((derived-mode-p 'kotl-mode) + (kcell-view:absolute-reference)) + ((and (not (hyperb:stack-frame '(hui:kill-ring-save hbut:at-p ibut:at-p ebut:at-p))) + (let* ((hbut (hbut:at-p)) + (start (when hbut (hattr:get hbut 'lbl-start))) + (end (when hbut (hattr:get hbut 'lbl-end)))) + (and start end + (buffer-substring-no-properties start end))))) + ((hui-select-at-delimited-thing-p) + (hui-select-get-thing))))) (defun hui:delimited-selectable-thing-and-bounds () "Return a list of any delimited selectable thing at point. -The list is (<thing-string> <thing-start> <thing-end>) -or nil if none. Start and end may be nil if the thing -was generated rather than extracted from a region." - (let (thing-and-bounds thing start end) - (cond ((setq thing-and-bounds (klink:at-p)) - (when thing-and-bounds - (setcar thing-and-bounds (klink:absolute thing-and-bounds)) - thing-and-bounds)) - ((derived-mode-p 'kotl-mode) - (list (kcell-view:absolute-reference))) - ((and (not (hyperb:stack-frame '(hui-kill-ring-save hbut:at-p ibut:at-p ebut:at-p))) - (setq thing (hbut:at-p) - start (when thing (hattr:get thing 'lbl-start)) - end (when thing (hattr:get thing 'lbl-end)))) - (and start end - (list (buffer-substring-no-properties start end) start end))) - ((hui-select-at-delimited-thing-p) - (when (setq thing-and-bounds (hui-select-get-region-boundaries)) - (list (buffer-substring-no-properties (car thing-and-bounds) (cdr thing-and-bounds)) - (car thing-and-bounds) - (cdr thing-and-bounds))))))) +The list returned is (<thing-type> <thing-string> <thing-start> <thing-end>) +or nil if none or if `hui:selectable-thing-priority-list' is nil. +Start and end may be nil if the thing was generated rather than +extracted from a region." + (when (and hui:selectable-thing-priority-list + (not (looking-at "[ \t\n\r\f]"))) + (let (thing-and-bounds thing start end) + (cond ((setq thing-and-bounds (klink:at-p)) + (when thing-and-bounds + (setcar thing-and-bounds (klink:absolute thing-and-bounds)) + (cons 'klink thing-and-bounds))) + ((hui-select-at-delimited-thing-p) + (when (setq thing-and-bounds (hui-select-get-region-boundaries)) + (list hui-select-previous + (buffer-substring-no-properties + (car thing-and-bounds) (cdr thing-and-bounds)) + (car thing-and-bounds) + (cdr thing-and-bounds)))) + ((and (not (hyperb:stack-frame '(hui:kill-ring-save hbut:at-p ibut:at-p ebut:at-p))) + (setq thing (hbut:at-p) + start (when thing (hattr:get thing 'lbl-start)) + end (when thing (hattr:get thing 'lbl-end)))) + (and start end + (list (hattr:get thing 'categ) + (buffer-substring-no-properties start end) start end))))))) + +(defun hui:non-delimited-selectable-thing-and-bounds () + "Return a list of properties for any non-delimited thing at point. +The list returned is (<thing-type> <thing-string> <thing-start> <thing-end>) +or nil if none. + +The prioritized types of things tested is 'url plus the list of types +in `hui:selectable-thing-priority-list' if that variable is non-nil." + (when (and hui:selectable-thing-priority-list + (not (looking-at "[ \t\n\r\f]"))) + (with-syntax-table + (if (memq major-mode hui-select-ignore-quoted-sexp-modes) + (syntax-table) + hui-select-syntax-table) + (let* ((types hui:selectable-thing-priority-list) + thing-and-bounds type thing start-end start end) + ;; Can't use thing-at-point here since it won't recognize URLs + ;; without a protocol prefix, e.g. www.google.com. + (when types + (setq thing-and-bounds (hpath:www-at-p t))) + (if thing-and-bounds + (cons 'url thing-and-bounds) + (while (and types (not thing)) + (setq type (car types) + types (cdr types) + thing (thing-at-point type t)) + (when thing + (cond ((eq type 'filename) + (unless (file-exists-p thing) + (setq thing nil))) + ((eq type 'email) + (unless (string-match "@.+\\." thing) + (setq thing nil))))) + (when thing + (setq start-end (bounds-of-thing-at-point type) + start (car start-end) + end (cdr start-end)))) + (when thing (list type thing start end))))))) + +(defun hui:selectable-thing-and-bounds () + "Return a list of any selectable thing at point. +The list returned is (<thing-type> <thing-string> <thing-start> <thing-end>) +or nil if none or if `hui:selectable-thing-priority-list' is nil. +Start and end may be nil if the thing was generated rather than +extracted from a region." + (let* (thing-and-bounds type thing start end) + (when (setq thing-and-bounds + (or (hui:delimited-selectable-thing-and-bounds) + (hui:non-delimited-selectable-thing-and-bounds))) + (setq type (nth 0 thing-and-bounds) + thing (nth 1 thing-and-bounds) + start (nth 2 thing-and-bounds) + end (nth 3 thing-and-bounds)) + (unless + ;; Already enclosed in delimiters + (or (and (= (char-syntax (char-after start)) ?\() + (= (char-syntax (char-before end)) ?\))) + (and (= (char-syntax (char-after start)) ?\") + (= (char-syntax (char-before end)) ?\"))) + ;; Surrounded by delimiters to add to the thing + (when (or (and (= (if (char-before start) (char-syntax (char-before start)) 0) ?\() + (= (if (char-after end) (char-syntax (char-after end)) 0) ?\))) + (and (= (if (char-before start) (char-syntax (char-before start)) 0) ?\") + (= (if (char-after end) (char-syntax (char-after end)) 0) ?\"))) + ;; Include delimiters in return value + (setq start (1- start) + end (1+ end) + thing (buffer-substring-no-properties start end))))) + (when thing (list type thing start end)))) (defun hui:ebut-act (&optional but) "Activate optional explicit button symbol BUT in current buffer. @@ -1881,7 +1973,7 @@ string arguments." (ibut:operate)) (ibut:operate)))) -(defun hui:kill-region (beg end &optional region) +(defun hui:kill-region-internal (beg end &optional region) "Invoke context-sensitive kill-region command over BEG and END. Third optional arg, REGION, when non-nil is sent to any call of `kill-region' and used to invoke the `region-extract-function' diff --git a/hypb.el b/hypb.el index 3f0749f4de..9e151e82f1 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: 27-May-25 at 22:00:10 by Bob Weiner +;; Last-Mod: 20-Jun-25 at 17:53:08 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -681,7 +681,7 @@ This will this install the Emacs helm package when needed." help-file)))))) (defun hypb:in-string-p (&optional max-lines range-flag) - "Return non-nil iff point is within a string. + "Return non-nil iff point is within a string and not on the closing quote. With optional MAX-LINES, an integer, match only within that many lines from point. With optional RANGE-FLAG, return list @@ -760,6 +760,11 @@ Quoting conventions recognized are: (format "[\\]\\(%s\\)" (regexp-quote open-match-string)) start (point)))) + ;; Move back one char in case point is on a + ;; closing delimiter char to ensure it is not + ;; backslash quoted and so the right delimiter is matched. + (unless (= (1- (point)) (line-beginning-position)) + (goto-char (1- (point)))) (re-search-forward close-regexp nil t) (if range-flag (progn diff --git a/hyperbole.el b/hyperbole.el index cad1f61861..753ead4c58 100644 --- a/hyperbole.el +++ b/hyperbole.el @@ -9,7 +9,7 @@ ;; Maintainer: Robert Weiner <r...@gnu.org> ;; Maintainers: Robert Weiner <r...@gnu.org>, Mats Lidell <ma...@gnu.org> ;; Created: 06-Oct-92 at 11:52:51 -;; Last-Mod: 16-Mar-25 at 10:11:31 by Bob Weiner +;; Last-Mod: 20-Jun-25 at 00:21:49 by Bob Weiner ;; Released: 10-Mar-24 ;; Version: 9.0.2pre ;; Keywords: comm, convenience, files, frames, hypermedia, languages, mail, matching, mouse, multimedia, outlines, tools, wp @@ -310,17 +310,17 @@ of the commands." ;; "simple.el" when hyperbole-mode is active to allow killing ;; kcell references, active regions and delimited areas (like ;; sexpressions). - (hkey-set-key [remap completion-kill-region] #'hui-kill-region) - (hkey-set-key [remap kill-region] #'hui-kill-region) + (hkey-set-key [remap completion-kill-region] #'hui:kill-region) + (hkey-set-key [remap kill-region] #'hui:kill-region) ;; ;; Override the {M-w} command from "simple.el" when hyperbole-mode ;; is active to allow copying delimited things, kcell references ;; or regions to the kill ring. - (hkey-set-key [remap kill-ring-save] #'hui-kill-ring-save) + (hkey-set-key [remap kill-ring-save] #'hui:kill-ring-save) ;; ;; Override the {C-x r s} command from "register.el" when hyperbole-mode is active ;; to allow copying delimited things, kcell references or regions to a register. - (hkey-set-key "\C-xrs" #'hui-copy-to-register) + (hkey-set-key "\C-xrs" #'hui:copy-to-register) ;; ;; Bind {C-c @} to create a user-specified sized grid of windows ;; displaying different buffers. diff --git a/kotl/kotl-mode.el b/kotl/kotl-mode.el index 337c8f0471..d938dc22be 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: 18-Jun-25 at 00:36:26 by Mats Lidell +;; Last-Mod: 20-Jun-25 at 20:08:20 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -740,17 +740,17 @@ With optional prefix argument TOP-P non-nil, refill all cells in the outline." (let ((kill-whole-line t)) (kotl-mode:kill-line arg))) -(defun kotl-mode:kill-region (start end &optional copy-p) +(defun kotl-mode:kill-region (start end &optional copy-flag) "Kill region between START and END within a single kcell. -With optional COPY-P equal to t, copy region to kill ring but does not -kill it. With COPY-P any other non-nil value, return region as a +With optional COPY-FLAG equal to t, copy region to kill ring but does not +kill it. With COPY-FLAG any other non-nil value, return region as a string without affecting kill ring. If called interactively, `transient-mark-mode' is non-nil, and there is no active region, copy any delimited selectable thing at point; see `hui:delimited-selectable-thing'. -If the buffer is read-only and COPY-P is nil, the region will not be deleted +If the buffer is read-only and COPY-FLAG is nil, the region will not be deleted but it will be copied to the kill ring and then an error will be signaled. If a completion is active, this aborts the completion only." @@ -758,13 +758,13 @@ If a completion is active, this aborts the completion only." (progn (barf-if-buffer-read-only) (list (when mark-active (region-beginning)) (when mark-active (region-end))))) - (let ((read-only (and (not copy-p) buffer-read-only)) - (kill-commands '(kill-region kotl-mode:completion-kill-region + (let ((read-only (and (not copy-flag) buffer-read-only)) + (kill-commands '(kill-region kill-ring-save kotl-mode:completion-kill-region kotl-mode:kill-region kotl-mode:copy-region-as-kill)) thing-and-bounds thing) (when read-only - (setq copy-p t)) + (setq copy-flag t)) (prog1 (cond ((eq last-command 'complete) (delete-region (point) cmpl-last-insert-location) @@ -774,14 +774,14 @@ If a completion is active, this aborts the completion only." ((and (memq this-command kill-commands) transient-mark-mode (not (use-region-p)) - (setq thing-and-bounds (hui:delimited-selectable-thing-and-bounds) - start (nth 1 thing-and-bounds) - end (nth 2 thing-and-bounds) - thing (nth 0 thing-and-bounds))) - (if (and copy-p (not (eq copy-p t))) + (setq thing-and-bounds (hui:selectable-thing-and-bounds) + thing (nth 1 thing-and-bounds) + start (nth 2 thing-and-bounds) + end (nth 3 thing-and-bounds))) + (if (and copy-flag (not (eq copy-flag t))) ;; Return thing as a string thing - (kotl-mode:kill-or-copy-region start end copy-p thing))) + (kotl-mode:kill-or-copy-region start end copy-flag thing))) ;; If no thing to process, copy region whether active or not ((and (number-or-marker-p start) (number-or-marker-p end) @@ -789,14 +789,15 @@ If a completion is active, this aborts the completion only." (kcell-view:cell end))) (save-excursion (goto-char start) - (kotl-mode:kill-or-copy-region start end copy-p))) + (kotl-mode:kill-or-copy-region start end copy-flag))) (t (error "(kotl-mode:kill-region): Bad region or not within a single Koutline cell"))) - (when (and copy-p (memq this-command kill-commands)) - (if thing - (message "Saved selectable thing: %s" thing) - (indicate-copied-region)))))) + (when (and copy-flag (memq this-command kill-commands)) + (cond (thing + (message "Saved selectable thing: %s" thing)) + ((mark t) + (indicate-copied-region))))))) -(defun kotl-mode:kill-or-copy-region (start end copy-p &optional kill-str) +(defun kotl-mode:kill-or-copy-region (start end copy-flag &optional kill-str) (when (and start end) (let ((indent (kcell-view:indent)) subst-str) @@ -808,7 +809,7 @@ If a completion is active, this aborts the completion only." kill-str (replace-regexp-in-string subst-str "\\1" (buffer-substring start end))) - (unless copy-p + (unless copy-flag ;; If last char of region is a newline, then delete indent in ;; following line. (delete-region @@ -816,7 +817,7 @@ If a completion is active, this aborts the completion only." '(?\n ?\r)) indent 0)))))) - (cond ((and copy-p (not (eq copy-p t))) + (cond ((and copy-flag (not (eq copy-flag t))) ;; Return killed region as a string. kill-str) ((not (and start end)) @@ -826,7 +827,7 @@ If a completion is active, this aborts the completion only." (kill-new kill-str)) (setq this-command 'kill-region) (setq deactivate-mark t) - (when (and (not copy-p) buffer-read-only) + (when (and (not copy-flag) buffer-read-only) (barf-if-buffer-read-only)) nil))) @@ -1182,11 +1183,11 @@ Leave point at the start of the root cell of the new tree." kotl-kview)) (defun kotl-mode:move-after (from-cell-ref to-cell-ref child-p - &optional copy-p fill-p) + &optional copy-flag fill-p) "Move tree rooted at FROM-CELL-REF to follow tree rooted at TO-CELL-REF. If prefix arg CHILD-P is non-nil, make FROM-CELL-REF the first child of TO-CELL-REF, otherwise make it the sibling following TO-CELL-REF. -With optional COPY-P, copies tree rather than moving it. +With optional COPY-FLAG, copies tree rather than moving it. Leave point at original location but return the tree's new start point." (interactive @@ -1199,7 +1200,7 @@ Leave point at original location but return the tree's new start point." (if current-prefix-arg "child" "sibling"))) (list label label)) (list current-prefix-arg)))) - (if (and (not copy-p) (equal from-cell-ref to-cell-ref)) + (if (and (not copy-flag) (equal from-cell-ref to-cell-ref)) (error "(kotl-mode:move-after): Can't move tree after itself")) (let* ((lbl-sep-len (kview:label-separator-length kotl-kview)) (move-to-point (set-marker @@ -1219,7 +1220,7 @@ Leave point at original location but return the tree's new start point." ;; ;; We can't move a tree to a point within itself, so if that is the case ;; and this is not a copy operation, signal an error. - (when (and (not copy-p) (>= move-to-point start) (<= move-to-point end)) + (when (and (not copy-flag) (>= move-to-point start) (<= move-to-point end)) (error "(kotl-mode:move-after): Can't move tree <%s> to within itself" from-label)) ;; @@ -1248,7 +1249,7 @@ Leave point at original location but return the tree's new start point." ;; ;; Insert tree-to-move at new location ;; - (kview:move start end (point) from-indent to-indent copy-p + (kview:move start end (point) from-indent to-indent copy-flag (or fill-p kotl-mode:refill-flag)) ;; ;; Ensure that point is within editable region of cell with to-label. @@ -1258,7 +1259,7 @@ Leave point at original location but return the tree's new start point." ;; Update current cell and new siblings' labels within view. (klabel-type:update-labels to-label) ;; - (unless copy-p + (unless copy-flag ;; ;; Move to sibling of tree-to-move within view and update labels within ;; view of tree-to-move's original siblings. @@ -1279,11 +1280,11 @@ Leave point at original location but return the tree's new start point." new-tree-start)) (defun kotl-mode:move-before (from-cell-ref to-cell-ref parent-p - &optional copy-p fill-p) + &optional copy-flag fill-p) "Move tree rooted at FROM-CELL-REF to precede tree rooted at TO-CELL-REF. If prefix arg PARENT-P is non-nil, make FROM-CELL-REF the first child of TO-CELL-REF's parent, otherwise make it the preceding sibling of TO-CELL-REF. -With optional COPY-P, copies tree rather than moving it. +With optional COPY-FLAG, copies tree rather than moving it. Leave point at original location but return the tree's new start point." (interactive @@ -1296,7 +1297,7 @@ Leave point at original location but return the tree's new start point." "preceding sibling"))) (list label label)) (list current-prefix-arg)))) - (when (and (not copy-p) (equal from-cell-ref to-cell-ref)) + (when (and (not copy-flag) (equal from-cell-ref to-cell-ref)) (error "(kotl-mode:move-before): Can't move tree before itself")) (let* ((lbl-sep-len (kview:label-separator-length kotl-kview)) (move-to-point (set-marker @@ -1315,7 +1316,7 @@ Leave point at original location but return the tree's new start point." ;; ;; We can't move a tree to a point within itself, so if that is the case ;; and this is not a copy operation, signal an error. - (when (and (not copy-p) (>= move-to-point start) (<= move-to-point end)) + (when (and (not copy-flag) (>= move-to-point start) (<= move-to-point end)) (error "(kotl-mode:move-before): Can't move tree <%s> to within itself" from-label)) ;; @@ -1342,7 +1343,7 @@ Leave point at original location but return the tree's new start point." ;; ;; Insert tree-to-move at new location ;; - (kview:move start end (point) from-indent to-indent copy-p + (kview:move start end (point) from-indent to-indent copy-flag (or fill-p kotl-mode:refill-flag)) ;; ;; Ensure that point is within editable region of root of tree just moved. @@ -1352,7 +1353,7 @@ Leave point at original location but return the tree's new start point." ;; Update current cell and new siblings' labels within view. (klabel-type:update-labels to-label) ;; - (unless copy-p + (unless copy-flag ;; ;; Move to sibling of tree-to-move within view and update labels within ;; view of tree-to-move's original siblings. diff --git a/kotl/kview.el b/kotl/kview.el index 5bd9fdf72a..c4a960fe7f 100644 --- a/kotl/kview.el +++ b/kotl/kview.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 6/30/93 -;; Last-Mod: 29-Jan-25 at 19:07:24 by Mats Lidell +;; Last-Mod: 20-Jun-25 at 00:40:40 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -1169,10 +1169,10 @@ See also `kview:map-region', `kview:map-branch' and `kview:map-siblings'." (nreverse results))))) (defun kview:move (from-start from-end to-start from-indent to-indent - &optional copy-p fill-p) + &optional copy-flag fill-p) "Move tree between FROM-START and FROM-END to TO-START. Also change indentation from FROM-INDENT to TO-INDENT. -Copy tree if optional COPY-P is non-nil. Refill cells if optional +Copy tree if optional COPY-FLAG is non-nil. Refill cells if optional FILL-P is non-nil. Leave point at TO-START." (let ((region (buffer-substring from-start from-end)) (new-start (set-marker (make-marker) to-start)) @@ -1181,7 +1181,7 @@ FILL-P is non-nil. Leave point at TO-START." ;; ;; Move or copy tree region to new location. - (or copy-p (delete-region from-start from-end)) + (or copy-flag (delete-region from-start from-end)) (goto-char new-start) (insert region) (setq new-end (point)) diff --git a/man/hyperbole.texi b/man/hyperbole.texi index 323271e8c3..9c05daa6e7 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: 15-Jun-25 at 22:44:41 by Bob Weiner +@c Last-Mod: 20-Jun-25 at 00:10:17 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 June 15, 2025. +Printed June 20, 2025. Published by the Free Software Foundation, Inc. Author: Bob Weiner @@ -9439,12 +9439,12 @@ binding. @xref{Smart Key Thing Selection}, for more information. @cindex key binding, M-w @vindex mark-even-if-inactive -@findex hui-kill-ring-save +@findex hui:kill-ring-save @kitem M-w @cindex copying things to kill ring Delimited Thing, Koutline Cell Reference or Region Copy: While Hyperbole is active, it sets @code{mark-even-if-inactive} to @code{nil} and overrides -@bkbd{M-w} with its own command, @code{hui-kill-ring-save}, which copies the +@bkbd{M-w} with its own command, @code{hui:kill-ring-save}, which copies the region only when it is active/highlighted. When there is no active region, @bkbd{M-w} does one of the following: @@ -9461,7 +9461,7 @@ region only when it is active/highlighted. When there is no active region, Delimited Thing, Koutline Cell Reference or Region Save to Register: This does the same thing as @bkbd{M-w} except it copies to an Emacs register given by a letter or number rather than the kill ring. While Hyperbole is active, -it overrides @bkbd{C-x r s} with its own command, @code{hui-copy-to-register}. +it overrides @bkbd{C-x r s} with its own command, @code{hui:copy-to-register}. which copies the region only when it is active/highlighted. @end table diff --git a/test/hui-tests.el b/test/hui-tests.el index 7a8a68bf5a..1e93d10134 100644 --- a/test/hui-tests.el +++ b/test/hui-tests.el @@ -3,7 +3,7 @@ ;; Author: Mats Lidell <ma...@gnu.org> ;; ;; Orig-Date: 30-Jan-21 at 12:00:00 -;; Last-Mod: 25-Apr-25 at 19:50:39 by Mats Lidell +;; Last-Mod: 20-Jun-25 at 19:37:43 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -410,7 +410,7 @@ Ensure modifying the button but keeping the label does not create a double label (kotl-mode:beginning-of-cell) (forward-char 1) - (call-interactively #'hui-kill-ring-save) + (call-interactively #'hui:kill-ring-save) (kotl-mode:add-cell) (yank) @@ -432,7 +432,7 @@ Ensure modifying the button but keeping the label does not create a double label (kotl-mode:beginning-of-cell) (forward-char 1) - (call-interactively #'hui-kill-ring-save) + (call-interactively #'hui:kill-ring-save) (find-file other-file) (yank) @@ -455,7 +455,7 @@ Ensure modifying the button but keeping the label does not create a double label (kotl-mode:beginning-of-cell) (forward-char 1) - (call-interactively #'hui-kill-ring-save) + (call-interactively #'hui:kill-ring-save) (find-file other-file) (yank) @@ -479,7 +479,7 @@ Ensure modifying the button but keeping the label does not create a double label (kotl-mode:beginning-of-cell) (forward-char 1) - (call-interactively #'hui-kill-ring-save) + (call-interactively #'hui:kill-ring-save) (find-file other-file) (yank) @@ -505,7 +505,7 @@ Ensure modifying the button but keeping the label does not create a double label (forward-char 1) (with-mock (mock (register-read-with-preview "Copy to register: ") => ?a) - (call-interactively #'hui-copy-to-register)) + (call-interactively #'hui:copy-to-register)) (kotl-mode:add-cell) (insert-register ?a) @@ -530,7 +530,7 @@ Ensure modifying the button but keeping the label does not create a double label (forward-char 1) (with-mock (mock (register-read-with-preview "Copy to register: ") => ?a) - (call-interactively #'hui-copy-to-register)) + (call-interactively #'hui:copy-to-register)) (find-file other-file) (insert-register ?a) @@ -555,7 +555,7 @@ Ensure modifying the button but keeping the label does not create a double label (forward-char 1) (with-mock (mock (register-read-with-preview "Copy to register: ") => ?a) - (call-interactively #'hui-copy-to-register)) + (call-interactively #'hui:copy-to-register)) (find-file other-file) (insert-register ?a) @@ -581,7 +581,7 @@ Ensure modifying the button but keeping the label does not create a double label (forward-char 1) (with-mock (mock (register-read-with-preview "Copy to register: ") => ?a) - (call-interactively #'hui-copy-to-register)) + (call-interactively #'hui:copy-to-register)) (find-file other-file) (insert-register ?a) @@ -605,7 +605,7 @@ Ensure modifying the button but keeping the label does not create a double label (kotl-mode:newline 1) (insert "b") (setq last-command #'ignore) - (hui-kill-ring-save (region-beginning) (region-end)) + (hui:kill-ring-save (region-beginning) (region-end)) (should (string= (current-kill 0 t) "a\nb"))) (hy-delete-file-and-buffer kotl-file)))) @@ -619,7 +619,7 @@ Ensure modifying the button but keeping the label does not create a double label (insert "a") (kotl-mode:add-cell) (insert "b") - (should-error (hui-kill-ring-save (region-beginning) (region-end)) :type 'error)) + (should-error (hui:kill-ring-save (region-beginning) (region-end)) :type 'error)) (hy-delete-file-and-buffer kotl-file)))) (ert-deftest hui--ibut-create-interactive () @@ -764,7 +764,7 @@ With point on label suggest that ibut for rename." (with-temp-buffer (ebut:program "label" 'link-to-directory "/tmp") (end-of-line) - (hui-kill-ring-save (point-min) (point)) + (hui:kill-ring-save (point-min) (point)) (yank) (goto-char (point-min)) (should (looking-at-p "<(label)><(label)>")) @@ -1174,7 +1174,7 @@ With point on label suggest that ibut for rename." (hy-delete-file-and-buffer global-but-file)))) (ert-deftest hui--kill-highlighted-region-default-settings () - "Verify `hui-kill-region'. + "Verify `hui:kill-region'. The Emacs default settings are used, i.e. both `transient-mark-mode' and `mark-even-if-inactive' are enabled." (with-temp-buffer @@ -1185,17 +1185,14 @@ The Emacs default settings are used, i.e. both `transient-mark-mode' and (set-mark nil) ;; No mark set - (condition-case err - (call-interactively #'hui-kill-region) - (error - (progn - (should (memq (car err) (list 'error 'user-error))) - (should (string-match "The mark is not set now, so there is no region" (cadr err)))))) + (call-interactively #'hui:kill-region) + (should (string= "{def}ghi" (buffer-string))) (set-mark (point)) + (activate-mark) (goto-char 4) - (call-interactively #'hui-kill-region) - (should (string= "{def}ghi" (buffer-string))) + (call-interactively #'hui:kill-region) + (should (string= "f}ghi" (buffer-string))) (erase-buffer) (insert "abc{def}hig") @@ -1203,7 +1200,7 @@ The Emacs default settings are used, i.e. both `transient-mark-mode' and (set-mark (point)) (goto-char 4) (deactivate-mark) - (call-interactively #'hui-kill-region) + (call-interactively #'hui:kill-region) (should (string= "abchig" (buffer-string))) (erase-buffer) @@ -1212,7 +1209,7 @@ The Emacs default settings are used, i.e. both `transient-mark-mode' and (set-mark (point)) (goto-char 4) (activate-mark) - (call-interactively #'hui-kill-region) + (call-interactively #'hui:kill-region) (should (string= "{def}igh" (buffer-string))) (erase-buffer) @@ -1221,8 +1218,8 @@ The Emacs default settings are used, i.e. both `transient-mark-mode' and (set-mark (point)) (goto-char 5) (deactivate-mark) - (call-interactively #'hui-kill-region) - (should (string= "def}ghi" (buffer-string))) + (call-interactively #'hui:kill-region) + (should (string= "bcaghi" (buffer-string))) ;; Not interactive (erase-buffer) @@ -1231,7 +1228,7 @@ The Emacs default settings are used, i.e. both `transient-mark-mode' and (set-mark (point)) (goto-char 4) (activate-mark) - (hui-kill-region (mark t) (point)) + (hui:kill-region (mark t) (point)) (should (string= "{efd}ghi" (buffer-string))) ;; Pick up region if beg or end is not set. @@ -1241,27 +1238,28 @@ The Emacs default settings are used, i.e. both `transient-mark-mode' and (set-mark (point)) (goto-char 4) (deactivate-mark) - (hui-kill-region nil nil) + (hui:kill-region nil nil) (should (string= "{def}ghi" (buffer-string)))))) (ert-deftest hui--kill-highlighted-region () - "Verify `hui-kill-region'. + "Verify `hui:kill-region'. `transient-mark-mode' is enabled and `mark-even-if-inactive' is disabled." (with-temp-buffer (let ((transient-mark-mode t) (mark-even-if-inactive nil)) - (insert "abc{def}ghi") + (insert " abc{def}ghi") (goto-char 1) (set-mark nil) - ;; No mark set - (should-error (call-interactively #'hui-kill-region) :type 'error) + ;; No mark set and on whitespace + (should-error (call-interactively #'hui:kill-region) :type 'error) + (delete-char 1) (set-mark (point)) (goto-char 4) - (call-interactively #'hui-kill-region) + (call-interactively #'hui:kill-region) (should (string= "{def}ghi" (buffer-string))) (erase-buffer) @@ -1270,7 +1268,7 @@ disabled." (set-mark (point)) (goto-char 4) (deactivate-mark) - (call-interactively #'hui-kill-region) + (call-interactively #'hui:kill-region) (should (string= "abchig" (buffer-string))) (erase-buffer) @@ -1279,7 +1277,7 @@ disabled." (set-mark (point)) (goto-char 4) (activate-mark) - (call-interactively #'hui-kill-region) + (call-interactively #'hui:kill-region) (should (string= "{def}igh" (buffer-string))) (erase-buffer) @@ -1288,7 +1286,8 @@ disabled." (set-mark (point)) (goto-char 5) (deactivate-mark) - (should-error (call-interactively #'hui-kill-region) :type 'error) + (call-interactively #'hui:kill-region) + (should (string= "bcaghi" (buffer-string))) ;; Not interactive (erase-buffer) @@ -1297,7 +1296,7 @@ disabled." (set-mark (point)) (goto-char 4) (activate-mark) - (hui-kill-region (mark t) (point)) + (hui:kill-region (mark t) (point)) (should (string= "{efd}ghi" (buffer-string))) (erase-buffer) @@ -1306,10 +1305,11 @@ disabled." (set-mark (point)) (goto-char 4) (deactivate-mark) - (should-error (hui-kill-region nil (point)) :type 'error)))) + (call-interactively #'hui:kill-region) + (should (string= "bacghi" (buffer-string)))))) (ert-deftest hui--kill-non-highlighted-region () - "Verify `hui-kill-region'. + "Verify `hui:kill-region'. `transient-mark-mode' is disabled and `mark-even-if-inactive' is enabled." (with-temp-buffer @@ -1321,11 +1321,11 @@ enabled." (set-mark nil) ;; No mark set - (should-error (call-interactively #'hui-kill-region) :type 'error) + (should-error (call-interactively #'hui:kill-region) :type 'error) (set-mark (point)) (goto-char 4) - (call-interactively #'hui-kill-region) + (call-interactively #'hui:kill-region) (should (string= "{def}ghi" (buffer-string))) (erase-buffer) @@ -1333,7 +1333,7 @@ enabled." (goto-char 1) (set-mark (point)) (goto-char 4) - (call-interactively #'hui-kill-region) + (call-interactively #'hui:kill-region) (should (string= "{def}hig" (buffer-string))) (erase-buffer) @@ -1341,7 +1341,7 @@ enabled." (goto-char 1) (set-mark (point)) (goto-char 5) - (call-interactively #'hui-kill-region) + (call-interactively #'hui:kill-region) (should (string= "def}igh" (buffer-string))) ;; Not interactive @@ -1351,7 +1351,7 @@ enabled." (goto-char 1) (set-mark (point)) (goto-char 4) - (hui-kill-region (mark t) (point)) + (hui:kill-region (mark t) (point)) (should (string= "{def}gih" (buffer-string))) (erase-buffer) @@ -1359,17 +1359,17 @@ enabled." (goto-char 1) (set-mark nil) (goto-char 4) - (should-error (hui-kill-region nil (point)) :type 'error) + (should-error (hui:kill-region nil (point)) :type 'error) (erase-buffer) (insert "bca{def}hig") (goto-char 1) (set-mark (point)) (goto-char 5) - (hui-kill-region (mark t) (point)) + (hui:kill-region (mark t) (point)) (should (string= "def}hig" (buffer-string))) - (hui-kill-region (mark t) (point)) + (hui:kill-region (mark t) (point)) (should (string= "def}hig" (buffer-string)))))) (ert-deftest hui--kill-empty-region-twice () @@ -1382,15 +1382,16 @@ Mimics the test case of setting a mark and hitting `C-w' twice." (insert "foo bar") (goto-char 4) (set-mark (point)) - (call-interactively #'hui-kill-region) + (activate-mark) + (call-interactively #'hui:kill-region) ;; Prepare second call to be setup as kill-region would leave ;; the state when calling it using C-w. (setq mark-active nil) (setq last-command #'kill-region) - (call-interactively #'hui-kill-region)))) + (call-interactively #'hui:kill-region)))) (ert-deftest hui--kill-region-multiple-kill () - "Verify `hui-kill-region' saves to the yank ring on multiple kills. + "Verify `hui:kill-region' saves to the yank ring on multiple kills. See test case `kill-whole-line-after-other-kill' and others in simple-tests.el for prior art of forcing values on `last-command'." ;; Two regions @@ -1401,12 +1402,12 @@ simple-tests.el for prior art of forcing values on `last-command'." (goto-char 2) (set-mark (point)) (goto-char 4) - (call-interactively #'hui-kill-region) + (call-interactively #'hui:kill-region) (goto-char 2) (set-mark (point)) (goto-char 4) (setq last-command #'kill-region) - (call-interactively #'hui-kill-region) + (call-interactively #'hui:kill-region) (should (string= "16" (buffer-string))) (should (string= "2345" (car kill-ring))))) @@ -1425,7 +1426,7 @@ line 1 (set-mark (point)) (goto-char 4) (setq last-command #'kill-region) - (call-interactively #'hui-kill-region) + (call-interactively #'hui:kill-region) (should (string= "14" (buffer-string))) (should (string= "line 1\n23" (car kill-ring))))) @@ -1439,9 +1440,9 @@ line 1 (goto-char 4) (deactivate-mark) (setq last-command #'ignore) - (call-interactively #'hui-kill-region) + (call-interactively #'hui:kill-region) (setq last-command #'kill-region) - (call-interactively #'hui-kill-region) + (call-interactively #'hui:kill-region) (should (string= "abcjkl" (buffer-string))) (should (string= "{def}{ghi}" (car kill-ring))))))