From 25c26f3541092bf37e1e640a0c9907a3e98aaf23 Mon Sep 17 00:00:00 2001 From: Eshel Yaron Date: Fri, 12 Jul 2024 12:43:46 +0200 Subject: [PATCH] More improvements for new search commands --- lisp/minibuffer.el | 17 ++++++++++---- lisp/search.el | 58 +++++++++++++++++++++++++--------------------- 2 files changed, 45 insertions(+), 30 deletions(-) diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index cdd25bdb46a..d4570d36a5a 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -2013,6 +2013,7 @@ Interactively, ARG is the prefix argument, and it defaults to 1." (completion--replace base end cur) (setq end (+ base (length cur))) (completion--done (buffer-substring-no-properties start (point)) 'sole + ;; TODO: Maybe use prompt indicator instead. (propertize (concat "/" (number-to-string (let ((all all) (n 1)) @@ -2027,8 +2028,7 @@ Interactively, ARG is the prefix argument, and it defaults to 1." (setq completion-all-sorted-completions (cdr all))) (set-transient-map (let ((map (make-sparse-keymap))) - (define-key map (vector last-command-event) - #'minibuffer-cycle-completion) + (define-key map (vector last-command-event) this-command) map) (lambda () (member this-command @@ -2036,7 +2036,8 @@ Interactively, ARG is the prefix argument, and it defaults to 1." negative-argument digit-argument minibuffer-cycle-completion - minibuffer-apply-and-cycle-completion))) + minibuffer-apply-and-cycle-completion + minibuffer-cycle-completion-and-apply))) (lambda () (setq completion-all-sorted-completions nil)))))))) @@ -2047,6 +2048,13 @@ Interactively, ARG is the prefix argument, and it defaults to 1." (minibuffer-apply (car input-prefix) (cdr input-prefix))) (minibuffer-cycle-completion n)) +(defun minibuffer-cycle-completion-and-apply (n) + "Cycle N candidates forward and apply minibuffer action to that candidate." + (interactive "p" minibuffer-mode) + (minibuffer-cycle-completion n) + (let ((input-prefix (minibuffer-current-input))) + (minibuffer-apply (car input-prefix) (cdr input-prefix)))) + (defvar minibuffer-confirm-exit-commands '(completion-at-point minibuffer-complete) "List of commands which cause an immediately following @@ -3509,7 +3517,8 @@ The completion method is determined by `completion-at-point-functions'." :parent minibuffer-local-map "TAB" #'minibuffer-complete "C-o" #'minibuffer-cycle-completion - "C-M-o" #'minibuffer-apply-and-cycle-completion + "C-M-o" #'minibuffer-cycle-completion-and-apply + "C-M-S-o" #'minibuffer-apply-and-cycle-completion "C-l" #'minibuffer-restore-completion-input "C-S-a" #'minibuffer-toggle-completion-ignore-case "?" #'minibuffer-completion-help diff --git a/lisp/search.el b/lisp/search.el index 553eb6a9e43..84044cc0b20 100644 --- a/lisp/search.el +++ b/lisp/search.el @@ -27,15 +27,11 @@ ;; - Support multi-buffer `search'. ;; - Add regexp completion style and use it for `search' completion. -;; - Restore initial position on quit. -;; - Place mark at initial position. ;; - Add replace support. ;; - Isearch-to-search and vice versa. ;; - Search non-matches. ;; - Highlight subgroups in matches. ;; - Improve documentation. -;; - In minibuffer, on `C-M-o', cycle forward first and then act. -;; - Pulse final selection. ;;; Code: @@ -45,6 +41,11 @@ '((t :inherit highlight :foreground "black")) "Foo.") +(defun search--go-to (target) + "Go to TARGET." + (let ((pos (string-to-number target))) + (unless (zerop pos) (goto-char pos)))) + (defun search-read-target (&optional beg end re-or-fn) "Prompt for \\[search] target between BEG and END matching RE-OR-FN." (let* ((buffer (current-buffer)) @@ -86,7 +87,7 @@ (cons (lambda (c) (with-selected-window (minibuffer-selected-window) - (search c) + (unless (search--go-to c) (user-error "Invalid search target")) (when (overlayp cur) (overlay-put cur 'face 'lazy-highlight)) (setq cur (seq-some (lambda (ov) (and (overlay-get ov 'search) ov)) @@ -95,21 +96,22 @@ "search")) (let ((hook-fn (lambda (input) - (mapc #'delete-overlay ovz) - (setq ovz nil) - (with-current-buffer buffer - (dolist (ov ovs) - (save-excursion - (goto-char (overlay-start ov)) - (let ((r (regexp-quote input)) - (e (overlay-end ov))) - (while (re-search-forward r e t) - (push (make-overlay (match-beginning 0) - (match-end 0)) - ovz) - (overlay-put (car ovz) 'face 'search-highlight) - (overlay-put (car ovz) 'search-input t) - (overlay-put (car ovz) 'priority '(nil . 10)))))))))) + (unless (string-empty-p input) + (mapc #'delete-overlay ovz) + (setq ovz nil) + (with-current-buffer buffer + (dolist (ov ovs) + (save-excursion + (goto-char (overlay-start ov)) + (let ((r (regexp-quote input)) + (e (overlay-end ov))) + (while (re-search-forward r e t) + (push (make-overlay (match-beginning 0) + (match-end 0)) + ovz) + (overlay-put (car ovz) 'face 'search-highlight) + (overlay-put (car ovz) 'search-input t) + (overlay-put (car ovz) 'priority '(nil . 10))))))))))) (add-hook 'minibuffer-new-completion-input-hook (lambda () (funcall hook-fn (caar completion-history))) nil t) @@ -131,17 +133,21 @@ (defun search (target) "Search for TARGET." (interactive - (list (search-read-target (use-region-beginning) (use-region-end)))) - (let ((pos (string-to-number target))) - (if (zerop pos) - (user-error "Invalid search target") - (goto-char pos)))) + (list + (save-excursion (search-read-target (use-region-beginning) (use-region-end))))) + (push-mark) + (unless (search--go-to target) (user-error "Invalid search target")) + (seq-let (beg end _) (split-string target ":") + (pulse-momentary-highlight-region (string-to-number beg) + (string-to-number end) + 'isearch))) ;;;###autoload (defun search-lines (target) "Search for TARGET line." (interactive - (list (search-read-target (use-region-beginning) (use-region-end) ".*"))) + (list (save-excursion + (search-read-target (use-region-beginning) (use-region-end) ".*")))) (search target)) (provide 'search) -- 2.39.2