From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Augusto Stoffel Newsgroups: gmane.emacs.devel Subject: [WIP PATCH] Controlling Isearch from the minibuffer Date: Sat, 08 May 2021 12:13:52 +0200 Message-ID: <87zgx5cz33.fsf@gmail.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="31219"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sat May 08 12:14:55 2021 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lfJz4-000803-TO for ged-emacs-devel@m.gmane-mx.org; Sat, 08 May 2021 12:14:55 +0200 Original-Received: from localhost ([::1]:60614 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lfJz3-0006rf-JQ for ged-emacs-devel@m.gmane-mx.org; Sat, 08 May 2021 06:14:53 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:54582) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lfJyC-0005wQ-Fk for emacs-devel@gnu.org; Sat, 08 May 2021 06:14:00 -0400 Original-Received: from mail-ed1-x535.google.com ([2a00:1450:4864:20::535]:39863) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1lfJy8-0006lH-Lu for emacs-devel@gnu.org; Sat, 08 May 2021 06:14:00 -0400 Original-Received: by mail-ed1-x535.google.com with SMTP id g14so13123845edy.6 for ; Sat, 08 May 2021 03:13:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:user-agent:mime-version; bh=pBKP5cKq/DFFQEsi7h6XONilW8k8h9UgjgG3Pr0Rzcs=; b=ctd8Zg8tLqjET65f9DszrldalarSlqJ+66SwytC6AkAu8LM+FJ1D0Xr9BvTXieXv17 vfOb/8raqynHUQD/TKGmpL9xZDnB81W524y4v9vtxReu97hZJ8TAiNjNO7IEra4GQjgk qc3q/umjH0J9ZF3/GH/w4J9uZdSBDwVMBoYr+HGws1kW8ZJdBcC+FUdgfe4KZvfSC6fq NweL6HBzw26K2ACIy9O0AeMftpy6EDdHIQD9JWDYYjjUjl8FukzrdrP8Vhgbxwv354nj CMCmdd8ddDVr+1LzAEAD0gEB0AKxWSn2NPt/6A5oGvvE8EkYiTr+OeRwXONsobjNagwI smBw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:user-agent :mime-version; bh=pBKP5cKq/DFFQEsi7h6XONilW8k8h9UgjgG3Pr0Rzcs=; b=MpW5jUHuSxPJgrMHIVCER8M6avzwY5L731j9L535b9o6/uZpM3mWjH4fKgMMZRy9aa jo6chURTqcgu+f7dkSOdiJnjq676LlGmqIrryyS4PG2Wjq6/q7zAsEYJDg130Xh1hfky D3o5P36EH5DDPx65QLr+EyTWQcwxaJKgTo/vWP4b0kPDge7YYEPdLwceMFVkWEcVyVlX NPzdmZJlR5GCquQC0JpEqQgCrZYc2uA76/E5+I4tC8fiwobpNXlnSaXa1v3k9geo1VKz gS5TcTvYFZ5CrCgRenRAGjf6giQicszLdZt7SPQIfklLlHcW4CI0vICf+95dTzFxwng5 e/KA== X-Gm-Message-State: AOAM533gmJqMa6cPXxAmAGKdYMOPBgLwGRlDIldDCLiSPZVxPX8z3aj/ Zi1Xhs8+TCa1/W1b5jYdGM0NInW5W0Y= X-Google-Smtp-Source: ABdhPJwUxQOAijpkN1YQa+O1WJM2jEIw0lV9UPLwOpqn4Z0gPbXuslVzNCfZF61196kZzl7bLpZgQw== X-Received: by 2002:a50:da88:: with SMTP id q8mr17456478edj.256.1620468834416; Sat, 08 May 2021 03:13:54 -0700 (PDT) Original-Received: from ars3 ([2a02:908:2211:8540::68a]) by smtp.gmail.com with ESMTPSA id ck4sm6003768edb.56.2021.05.08.03.13.52 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 May 2021 03:13:53 -0700 (PDT) Received-SPF: pass client-ip=2a00:1450:4864:20::535; envelope-from=arstoffel@gmail.com; helo=mail-ed1-x535.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:269036 Archived-At: --=-=-= Content-Type: text/plain I've attached a draft implementation of a minibuffer-controlled mode for Isearch, as described for instance in https://lists.gnu.org/archive/html/emacs-devel/2020-01/msg00447.html To enable the feature, set `isearch-from-minibuffer' to t. The basic trade-off is that this makes it easier to edit the search string, and harder to quit the search. It also drops some of the eccentricities of regular Isearch. For instance, DEL deletes and C-g quits. I'm sharing this preliminary version because two important questions can already be answered: - Does the approach taken here seem sufficiently robust? Note in particular the `with-isearch-window' macro, which is now needed around several functions, as well as the somewhat hacky `run-with-idle-timer' call inside the `isearch-mode' function. - Are the slightly backwards incompatible keybinding changes in `isearch-edit-string' acceptable? If any of these answers is no, then I would provide a package for the same feature. But I think the feature is interesting enough to be built in isearch.el. Moreover, it would benefit from being official because many third-party extensions to Isearch will need to take into account the possibility that the search is being controlled remotely from a minibuffer. Some further remarks: - The minibuffer-controlled mode is supposed to depend on the proposed `isearch-buffer-local' feature. This will make the hack used to deactivate the `overriding-terminal-local-map' unnecessary. - It seems necessary to let-bind `inhibit-redisplay' to nil in `with-isearch-window' in order to avoid flicker in the cursor. This seems related to the recent thread "Temporarily select-window, without updating mode-line face and cursor fill?" in this list. Any better solutions? - I don't like the `with-isearch-window-quitting-edit' macro, but I don't see a different way of achieving the necessary effect. - I don't use/know of all Isearch features, so let me know if you spot some incompatibility. What do you think? --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=0001-Control-Isearch-from-minibuffer-draft.patch >From d623ea3e00f07688a4b1cff8dd758c3bea45519c Mon Sep 17 00:00:00 2001 From: Augusto Stoffel Date: Sat, 8 May 2021 10:24:20 +0200 Subject: [PATCH] Control Isearch from minibuffer (draft) --- lisp/isearch.el | 272 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 215 insertions(+), 57 deletions(-) diff --git a/lisp/isearch.el b/lisp/isearch.el index 9f3cfd70fb..c2a46f7690 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -821,15 +821,32 @@ isearch-tool-bar-map :image '(isearch-tool-bar-image "left-arrow"))) map)) +;; WIP for debugging +(makunbound 'minibuffer-local-isearch-map) + (defvar minibuffer-local-isearch-map (let ((map (make-sparse-keymap))) (set-keymap-parent map minibuffer-local-map) - (define-key map "\r" 'exit-minibuffer) + (define-key map "\C-j" 'newline) (define-key map "\M-\t" 'isearch-complete-edit) - (define-key map "\C-s" 'isearch-forward-exit-minibuffer) - (define-key map "\C-r" 'isearch-reverse-exit-minibuffer) - (define-key map "\C-f" 'isearch-yank-char-in-minibuffer) - (define-key map [right] 'isearch-yank-char-in-minibuffer) + (define-key map "\C-s" 'isearch-repeat-forward) + (define-key map [down] 'isearch-repeat-forward) + (define-key map "\C-r" 'isearch-repeat-backward) + (define-key map [up] 'isearch-repeat-backward) + (define-key map "\M-%" 'isearch-query-replace) + (define-key map [?\C-\M-%] 'isearch-query-replace-regexp) + (define-key map "\M-<" 'isearch-beginning-of-buffer) + (define-key map "\M->" 'isearch-end-of-buffer) + (define-key map "\M-s'" 'isearch-toggle-char-fold) + (define-key map "\M-s " 'isearch-toggle-lax-whitespace) + (define-key map "\M-s_" 'isearch-toggle-symbol) + (define-key map "\M-sc" 'isearch-toggle-case-fold) + (define-key map "\M-shr" 'isearch-highlight-regexp) + (define-key map "\M-shl" 'isearch-highlight-lines-matching-regexp) + (define-key map "\M-si" 'isearch-toggle-invisible) + (define-key map "\M-so" 'isearch-occur) + (define-key map "\M-sr" 'isearch-toggle-regexp) + (define-key map "\M-sw" 'isearch-toggle-word) map) "Keymap for editing Isearch strings in the minibuffer.") @@ -980,6 +997,32 @@ search-map (define-key search-map "." 'isearch-forward-symbol-at-point) (define-key search-map "\M-." 'isearch-forward-thing-at-point) +;;; Minibuffer-based interface + +(defcustom isearch-from-minibuffer nil + "If non-nil, control Isearch from the minibuffer." + :type 'boolean) + +(defmacro with-isearch-window (&rest body) + "Execute BODY in the Isearch window." + `(if (and (minibufferp) + (not (eq isearch--current-buffer (current-buffer)))) + (let ((inhibit-redisplay t)) + (with-minibuffer-selected-window + ,@body)) + ,@body)) + +(defmacro with-isearch-window-quitting-edit (&rest body) + "Execute BODY in the Isearch window. + +Like `with-isearch-window', but quit editing the search string +first if applicable. In this case, control is returned to the +caller of `isearch-edit-string'. This must be used if BODY exits +the search and uses the minibuffer." + `(if (and (minibufferp) (not (eq isearch--current-buffer (current-buffer)))) + (throw 'isearch-edit--continue (lambda () ,@body)) + ,@body)) + ;; Entry points to isearch-mode. (defun isearch-forward (&optional regexp-p no-recursive-edit) @@ -1316,9 +1359,16 @@ isearch-mode ;; isearch-mode can be made modal (in the sense of not returning to ;; the calling function until searching is completed) by entering ;; a recursive-edit and exiting it when done isearching. - (if recursive-edit + (if (and isearch-from-minibuffer (not (minibufferp))) + (if recursive-edit + (isearch-edit-string t) + ;; WIP: This timer hack is used e.g. for + ;; `isearch-forward-symbol-at-point' as well as third party + ;; packages which prepare a special isearch state. + (run-with-idle-timer 0 nil #'isearch-edit-string t)) + (when recursive-edit (let ((isearch-recursive-edit t)) - (recursive-edit))) + (recursive-edit)))) isearch-success) @@ -1518,6 +1568,21 @@ isearch-update-from-string-properties (setq isearch-regexp-function (get-text-property 0 'isearch-regexp-function string)))) +(defun isearch-set-string (string &optional properties) + "Set the current search string. + +Return STRING. If PROPERTIES is non-nil, also update the search +mode from the text properties of STRING." + (when properties (isearch-update-from-string-properties string)) + (when isearch-edit--minibuffer + (with-current-buffer isearch-edit--minibuffer + (let ((inhibit-modification-hooks t)) + (delete-minibuffer-contents) + (insert string)) + (end-of-buffer))) + (setq isearch-message (mapconcat 'isearch-text-char-description string "") + isearch-string string)) + ;; The search status structure and stack. @@ -1783,41 +1848,111 @@ with-isearch-suspended (defvar minibuffer-history-symbol) ;; from external package gmhist.el -(defun isearch-edit-string () +(defun isearch-edit--post-command-hook () + "Hook to run from the minibuffer to update the Isearch state." + (set-text-properties (minibuffer-prompt-end) (point-max) nil) + (when-let ((fail-pos (isearch-fail-pos))) + (add-text-properties (+ (minibuffer-prompt-end) fail-pos) + (point-max) + '(face isearch-fail))) + (when isearch-error + (isearch--momentary-message isearch-error))) + +(defun isearch-edit--after-change (_ _ _) + "Hook to run from the minibuffer to update the Isearch state." + (let ((string (minibuffer-contents))) + (with-isearch-window + (setq isearch-string (substring-no-properties string)) + (isearch-update-from-string-properties string) + ;; Backtrack to barrier and search, unless the `this-command' + ;; is special or the search regexp is invalid. + (if (or (and (symbolp this-command) + (get this-command 'isearch-edit-string--no-search)) + (and isearch-regexp + (condition-case err + (prog1 nil (string-match-p isearch-string "")) + (invalid-regexp + (prog1 t (isearch--momentary-message (cadr err))))))) + (isearch-update) + (goto-char isearch-barrier) + (setq isearch-adjusted t isearch-success t) + (isearch-search-and-update))))) + +(put 'next-history-element 'isearch-edit-string--no-search t) +(put 'previous-history-element 'isearch-edit-string--no-search t) + +(defvar-local isearch-edit--prompt-overlay nil + "Overlay to display the Isearch status in `isearch-edit-string'.") + +(defvar-local isearch-edit--minibuffer nil + "Pointer to the minibuffer controlling the search. +Local to the search buffer. Non-nil only during an +`isearch-edit-string' session.") + +(defun isearch-edit-string (&optional exit) "Edit the search string in the minibuffer. + +When EXIT is nil, exiting the minibuffer or repeating the search +resumes Isearch with the edited string. When EXIT is non-nil, +exiting the minibuffer also ends the search. + The following additional command keys are active while editing. -\\ -\\[exit-minibuffer] to resume incremental searching with the edited string. -\\[isearch-forward-exit-minibuffer] to resume isearching forward. -\\[isearch-reverse-exit-minibuffer] to resume isearching backward. -\\[isearch-complete-edit] to complete the search string using the search ring." +\\{minibuffer-local-isearch-map}" (interactive) - (with-isearch-suspended - (let* ((message-log-max nil) - ;; Don't add a new search string to the search ring here - ;; in `read-from-minibuffer'. It should be added only - ;; by `isearch-update-ring' called from `isearch-done'. - (history-add-new-input nil) - ;; Binding minibuffer-history-symbol to nil is a work-around - ;; for some incompatibility with gmhist. - (minibuffer-history-symbol) - ;; Search string might have meta information on text properties. - (minibuffer-allow-text-properties t)) - (setq isearch-new-string - (read-from-minibuffer - (isearch-message-prefix nil isearch-nonincremental) - (cons isearch-string (1+ (or (isearch-fail-pos) - (length isearch-string)))) - minibuffer-local-isearch-map nil - (if isearch-regexp - (cons 'regexp-search-ring - (1+ (or regexp-search-ring-yank-pointer -1))) - (cons 'search-ring - (1+ (or search-ring-yank-pointer -1)))) - nil t) - isearch-new-message - (mapconcat 'isearch-text-char-description - isearch-new-string ""))))) + (condition-case nil + (funcall + (catch 'isearch-edit--continue + (let (;; WIP: This is a hack that can be removed when isearch + ;; local mode is available. + (overriding-terminal-local-map nil) + ;; We need to set `inhibit-redisplay' in `with-isearch-window' to + ;; avoid flicker. As a side effect, window-start/end in + ;; `isearch-lazy-highlight-update' will have incorrect values, + ;; so we need to lazy-highlight the whole buffer. + (lazy-highlight-buffer (not (null isearch-lazy-highlight)))) + (minibuffer-with-setup-hook + (lambda () + (add-hook 'after-change-functions 'isearch-edit--after-change nil t) + (add-hook 'post-command-hook 'isearch-edit--post-command-hook nil t) + (setq-local isearch-edit--prompt-overlay + (make-overlay (point-min) (point-min) (current-buffer) t t)) + (let ((inhibit-modification-hooks t) + (mb (current-buffer)) + (buf (window-buffer (minibuffer-selected-window)))) + (insert (buffer-local-value 'isearch-string buf)) + (with-current-buffer buf + (setq-local isearch-edit--minibuffer mb) + (isearch-message))) + (when isearch-error (isearch--momentary-message isearch-error))) + (unwind-protect + (read-from-minibuffer + "I-search: " + nil + (if exit + minibuffer-local-isearch-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map minibuffer-local-isearch-map) + (define-key map + [remap isearch-repeat-forward] 'isearch-forward-exit-minibuffer) + (define-key map + [remap isearch-repeat-backward] 'isearch-reverse-exit-minibuffer) + map)) + nil + (if isearch-regexp + (cons 'regexp-search-ring + (1+ (or regexp-search-ring-yank-pointer -1))) + (cons 'search-ring + (1+ (or search-ring-yank-pointer -1)))) + (thread-last isearch-forward-thing-at-point + ;; WIP: The above variable can be renamed + (mapcar 'thing-at-point) + (delq nil) + (delete-dups) + (mapcar (if isearch-regexp 'regexp-quote 'identity))) + t) + (setq-local isearch-edit--minibuffer nil))) +(if (and exit isearch-mode) 'isearch-done 'ignore)))) + (quit (if (and exit isearch-mode) (isearch-cancel) (signal 'quit nil))))) (defun isearch-nonincremental-exit-minibuffer () (interactive) @@ -1879,13 +2014,8 @@ isearch-repeat ;; If search string is empty, use last one. (if (null (if isearch-regexp regexp-search-ring search-ring)) (setq isearch-error "No previous search string") - (setq isearch-string - (car (if isearch-regexp regexp-search-ring search-ring)) - isearch-message - (mapconcat 'isearch-text-char-description - isearch-string "") - isearch-case-fold-search isearch-last-case-fold-search) - ;; After taking the last element, adjust ring to previous one. + (isearch-set-string (car (if isearch-regexp regexp-search-ring search-ring)) t) + ;; After taking the last element, adjust ring to previous one. (isearch-ring-adjust1 nil)) ;; If already have what to search for, repeat it. (unless (or isearch-success (null isearch-wrap-pause)) @@ -1955,6 +2085,7 @@ isearch-repeat-forward search string. To find the absolute occurrence from the beginning of the buffer, type \\[isearch-beginning-of-buffer] with a numeric argument." (interactive "P") +(with-isearch-window (if arg (let ((count (prefix-numeric-value arg))) (cond ((< count 0) @@ -1968,6 +2099,7 @@ isearch-repeat-forward (when (not isearch-forward) (setq count (1+ count)))) (isearch-repeat 'forward count)))) (isearch-repeat 'forward))) +) (defun isearch-repeat-backward (&optional arg) "Repeat incremental search backwards. @@ -1978,6 +2110,7 @@ isearch-repeat-backward search string. To find the absolute occurrence from the end of the buffer, type \\[isearch-end-of-buffer] with a numeric argument." (interactive "P") +(with-isearch-window (if arg (let ((count (prefix-numeric-value arg))) (cond ((< count 0) @@ -1991,6 +2124,7 @@ isearch-repeat-backward (when isearch-forward (setq count (1+ count)))) (isearch-repeat 'backward count)))) (isearch-repeat 'backward))) +) (defun isearch-beginning-of-buffer (&optional arg) "Go to the first occurrence of the current search string. @@ -2000,6 +2134,7 @@ isearch-beginning-of-buffer the beginning of the buffer. To find the next relative occurrence forwards, type \\[isearch-repeat-forward] with a numeric argument." (interactive "p") +(with-isearch-window (if (and arg (< arg 0)) (isearch-end-of-buffer (abs arg)) ;; For the case when the match is at bobp, @@ -2007,6 +2142,7 @@ isearch-beginning-of-buffer (setq isearch-just-started t) (goto-char (point-min)) (isearch-repeat 'forward arg))) +) (defun isearch-end-of-buffer (&optional arg) "Go to the last occurrence of the current search string. @@ -2016,11 +2152,13 @@ isearch-end-of-buffer the end of the buffer. To find the next relative occurrence backwards, type \\[isearch-repeat-backward] with a numeric argument." (interactive "p") +(with-isearch-window (if (and arg (< arg 0)) (isearch-beginning-of-buffer (abs arg)) (setq isearch-just-started t) (goto-char (point-max)) (isearch-repeat 'backward arg))) +) ;;; Toggles for `isearch-regexp-function' and `search-default-mode'. @@ -2040,6 +2178,7 @@ isearch-define-mode-toggle ,(format "Toggle %s searching on or off.%s" mode (if docstring (concat "\n" docstring) "")) (interactive) +(with-isearch-window (unless isearch-mode (isearch-mode t)) ,@(when function `((setq isearch-regexp-function @@ -2049,6 +2188,7 @@ isearch-define-mode-toggle ,@body (setq isearch-success t isearch-adjusted t) (isearch-update)) +) (define-key isearch-mode-map ,key #',command-name) ,@(when (and function (symbolp function)) `((put ',function 'isearch-message-prefix ,(format "%s " mode)) @@ -2075,6 +2215,9 @@ isearch-message-properties (defun isearch--momentary-message (string &optional seconds) "Print STRING at the end of the isearch prompt for 1 second. The optional argument SECONDS overrides the number of seconds." + (if isearch-edit--minibuffer + (message (propertize (concat " [" string "]") + 'face 'minibuffer-prompt)) (let ((message-log-max nil)) (message "%s%s%s" (isearch-message-prefix nil isearch-nonincremental) @@ -2082,6 +2225,7 @@ isearch--momentary-message (apply #'propertize (format " [%s]" string) isearch-message-properties))) (sit-for (or seconds 1))) +) (isearch-define-mode-toggle lax-whitespace " " nil "In ordinary search, toggles the value of the variable @@ -2311,6 +2455,7 @@ isearch-query-replace replacements from Isearch is `M-s w ... M-%'." (interactive (list current-prefix-arg)) +(with-isearch-window-quitting-edit (barf-if-buffer-read-only) (if regexp-flag (setq isearch-regexp t)) (let ((case-fold-search isearch-case-fold-search) @@ -2359,6 +2504,7 @@ isearch-query-replace (if (use-region-p) (region-end)) backward)) (and isearch-recursive-edit (exit-recursive-edit))) +) (defun isearch-query-replace-regexp (&optional arg) "Start `query-replace-regexp' with string to replace from last search string. @@ -2379,6 +2525,7 @@ isearch-occur for a literal string, REGEXP is constructed by quoting all the special characters in that string." (interactive +(with-isearch-window (let* ((perform-collect (consp current-prefix-arg)) (regexp (cond ((functionp isearch-regexp-function) @@ -2404,6 +2551,8 @@ isearch-occur ;; Otherwise normal occur takes numerical prefix argument. (when current-prefix-arg (prefix-numeric-value current-prefix-arg)))))) +) +(with-isearch-window (let ((case-fold-search isearch-case-fold-search) ;; Set `search-upper-case' to nil to not call ;; `isearch-no-upper-case-p' in `occur-1'. @@ -2421,6 +2570,7 @@ isearch-occur regexp) nlines (if (use-region-p) (region-bounds))))) +) (declare-function hi-lock-read-face-name "hi-lock" ()) @@ -2461,18 +2611,22 @@ isearch-highlight-regexp The arguments passed to `highlight-regexp' are the regexp from the last search and the face from `hi-lock-read-face-name'." (interactive) +(with-isearch-window-quitting-edit (isearch--highlight-regexp-or-lines #'(lambda (regexp face lighter) (highlight-regexp regexp face nil lighter)))) +) (defun isearch-highlight-lines-matching-regexp () "Exit Isearch mode and call `highlight-lines-matching-regexp'. The arguments passed to `highlight-lines-matching-regexp' are the regexp from the last search and the face from `hi-lock-read-face-name'." (interactive) +(with-isearch-window-quitting-edit (isearch--highlight-regexp-or-lines #'(lambda (regexp face _lighter) (highlight-lines-matching-regexp regexp face)))) +) (defun isearch-delete-char () @@ -3227,7 +3381,7 @@ isearch-complete1 (all-completions isearch-string ring)))) t) (and completion - (setq isearch-string completion)))) + (isearch-set-string completion)))) (t (message "No completion") ; waits a second if in minibuffer nil)))) @@ -3238,22 +3392,14 @@ isearch-complete If there is no completion possible, say so and continue searching." (interactive) (if (isearch-complete1) - (progn (setq isearch-message - (mapconcat 'isearch-text-char-description - isearch-string "")) - (isearch-edit-string)) - ;; else + (isearch-edit-string) (sit-for 1) (isearch-update))) (defun isearch-complete-edit () "Same as `isearch-complete' except in the minibuffer." (interactive) - (setq isearch-string (field-string)) - (if (isearch-complete1) - (progn - (delete-field) - (insert isearch-string)))) + (with-isearch-window (isearch-complete1))) ;; Message string @@ -3267,6 +3413,17 @@ isearch-message ;; circumstances are when follow-mode is active, the search string ;; spans two (or several) windows, and the message about to be ;; displayed will cause the echo area to expand. + (if isearch-from-minibuffer + (when-let ((mb isearch-edit--minibuffer) + (ov (buffer-local-value 'isearch-edit--prompt-overlay mb))) + (overlay-put ov + 'before-string + (concat + (when isearch-lazy-count + (format "%-6s" (isearch-lazy-count-format))) + (capitalize + (isearch--describe-regexp-mode + isearch-regexp-function))))) (let ((cursor-in-echo-area ellipsis) (m isearch-message) (fail-pos (isearch-fail-pos t))) @@ -3283,6 +3440,7 @@ isearch-message m (isearch-message-suffix c-q-hack))) (if c-q-hack m (let ((message-log-max nil)) (message "%s" m))))) +) (defun isearch--describe-regexp-mode (regexp-function &optional space-before) "Make a string for describing REGEXP-FUNCTION. -- 2.30.2 --=-=-=--