]> git.eshelyaron.com Git - emacs.git/commitdiff
* search.el: Support changing search context regex
authorEshel Yaron <me@eshelyaron.com>
Sat, 9 Nov 2024 15:06:28 +0000 (16:06 +0100)
committerEshel Yaron <me@eshelyaron.com>
Sat, 9 Nov 2024 15:06:28 +0000 (16:06 +0100)
lisp/search.el

index 498a9a3adb2341ad4f38bedee7a55434ae676d33..e8ac2130ca9822c209b288acf57987ef1a4f627f 100644 (file)
@@ -20,8 +20,8 @@
 
 ;;; Commentary:
 
-;; Library search.el provides advanced text searching commands, inspired
-;; by Icicles search (https://www.emacswiki.org/emacs/Icicles).
+;; This library provides advanced text searching commands, inspired by
+;; Icicles search (https://www.emacswiki.org/emacs/Icicles).
 
 ;;; Todo:
 
   '((t :inherit highlight :foreground "black"))
   "Face for highlighting matches for current input during \\[search].")
 
-(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))
-         (beg (or beg (point-min)))
-         (end (or end (point-max)))
-         (reg nil)
-         (sfn (if (functionp re-or-fn)
-                  (prog1 re-or-fn (setq reg "match"))
-                (setq reg (or re-or-fn (read-regexp "Search regular expression")))
-                (lambda () (re-search-forward reg end t))))
-         (ovs nil)
-         (ovz nil)
-         (cur nil)
-         (trs nil)
-         (tab (make-hash-table))
-         (ind 0)
-         (rep nil))
-    (deactivate-mark)
+(defun search-change ()
+  "Change the current `search' context."
+  (interactive)
+  (throw 'search-change (minibuffer-contents)))
+
+(defun search-read-target-mode-p (_symbol buffer)
+  "Check whether `search-read-target-mode' is enabled in BUFFER."
+  (buffer-local-value 'search-read-target-mode buffer))
+
+(put 'search-change 'completion-predicate #'search-read-target-mode-p)
+
+(defvar-keymap search-read-target-mode-map
+  :doc "Keymap for `search-read-target-mode'."
+  "M-s M-s" #'search-change)
+
+(define-minor-mode search-read-target-mode
+  "Minor mode for `search-read-target' minibuffer.")
+
+(defun search--read-target (buffer beg end reg sfn init)
+  "Prompt for search target in BUFFER between BEG and END matching REG.
+
+SFN is the search function to use for finding matches.  INIT is the
+initial minibuffer input."
+  (let ((tab (make-hash-table)) (ind 0) ovs ovz cur trs rep)
     (save-excursion
       (goto-char beg)
       (let ((pos beg) done)
@@ -82,6 +88,7 @@
     (unwind-protect
         (minibuffer-with-setup-hook
             (lambda ()
+              (search-read-target-mode)
               (setq minibuffer-action
                     (cons
                      (lambda (c)
                          . ,(lambda (string &optional transform)
                               (when transform
                                 (substring string (1+ (string-search ":" string))))))))
-                     nil t nil t))
+                     nil t init t))
                    tab))
       (mapc #'delete-overlay ovs)
       (mapc #'delete-overlay ovz))))
 
+(defun search-read-target (&optional beg end re-or-fn)
+  "Prompt for \\[search] target between BEG and END matching RE-OR-FN."
+  (let* ((buf (current-buffer))
+         (beg (or beg (point-min)))
+         (end (or end (point-max)))
+         reg res
+         (sfn (if (functionp re-or-fn)
+                  (prog1 re-or-fn (setq reg "match"))
+                (setq reg (or re-or-fn (read-regexp "Search regular expression")))
+                (lambda () (re-search-forward reg end t)))))
+    (deactivate-mark)
+    (while (stringp (setq res (catch 'search-change
+                                (search--read-target buf beg end reg sfn res))))
+      (setq reg (read-regexp "Search regular expression")
+            sfn (lambda () (re-search-forward reg end t))))
+    res))
+
 ;;;###autoload
 (defun search (beg end)
   "Go to and pulse region starting at BEG and ending at END."
   (interactive
-   (save-excursion (search-read-target (use-region-beginning) (use-region-end))))
+   (save-excursion
+     (search-read-target (use-region-beginning) (use-region-end))))
   (push-mark)
   (goto-char beg)
   (pulse-momentary-highlight-region beg end 'isearch))
 
 ;;;###autoload
 (defun search-from-isearch (beg end)
+  "Pivot to `search' between BEG and END from `isearch'."
   (interactive
    (if isearch-mode
        (save-excursion
 (defun search-lines (beg end)
   "Go to and pulse line starting at BEG and ending at END."
   (interactive
-   (save-excursion (search-read-target (use-region-beginning) (use-region-end) ".*")))
+   (save-excursion
+     (search-read-target (use-region-beginning) (use-region-end) ".*")))
   (search beg end))
 
 (provide 'search)
-;;; refactor.el ends here
+;;; search.el ends here