diff --git a/etc/NEWS b/etc/NEWS index ffe2f508a89..bde9b89c468 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -141,11 +141,6 @@ regular expression was previously invalid, but is now accepted: * Editing Changes in Emacs 27.1 -+++ -** New isearch bindings. -'C-M-w' in isearch changed from isearch-del-char to the new function -isearch-yank-symbol-or-char. isearch-del-char is now bound to 'C-M-d'. - --- ** New variable 'x-wait-for-event-timeout'. This controls how long Emacs will wait for updates to the graphical @@ -169,6 +164,10 @@ for abbrevs that have them. `text-property-search-backward' have been added. These provide an interface that's more like functions like @code{search-forward}. +--- +** More commands support noncontiguous rectangular regions, namely +‘upcase-dwim’, ‘downcase-dwim’, ‘replace-string’, ‘replace-regexp’. + * Changes in Specialized Modes and Packages in Emacs 27.1 @@ -292,6 +291,11 @@ can now be searched via 'C-s'. ** Search and Replace ++++ +*** New isearch bindings. +'C-M-w' in isearch changed from isearch-del-char to the new function +isearch-yank-symbol-or-char. isearch-del-char is now bound to 'C-M-d'. + +++ *** 'search-exit-option' provides new options 'move' and 'shift-move' to extend the search string by yanking text that ends at the new @@ -299,6 +303,10 @@ position after moving point in the current buffer. 'shift-move' extends the search string by motion commands while holding down the shift key. +--- +*** Isearch now remembers the regexp-based search mode for words/symbols +and case-sensitivity together with search strings in the search ring. + ** Edebug +++ diff --git a/lisp/info.el b/lisp/info.el index 0db84fb3dab..bbce55f6216 100644 --- a/lisp/info.el +++ b/lisp/info.el @@ -2017,7 +2017,7 @@ If DIRECTION is `backward', search in the reverse direction." Info-isearch-initial-node bound (and found (> found opoint-min) (< found opoint-max))) - (signal 'user-search-failed (list regexp "(end of node)"))) + (signal 'user-search-failed (list regexp "end of node"))) ;; If no subfiles, give error now. (unless (or found Info-current-subfile) diff --git a/lisp/isearch.el b/lisp/isearch.el index db196e00efb..5cbb4c941a5 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -1143,10 +1143,10 @@ REGEXP if non-nil says use the regexp search ring." (defun isearch-update-from-string-properties (string) "Update isearch properties from the isearch string" - (when (memq 'isearch-case-fold-search (text-properties-at 0 string)) + (when (plist-member (text-properties-at 0 string) 'isearch-case-fold-search) (setq isearch-case-fold-search (get-text-property 0 'isearch-case-fold-search string))) - (when (memq 'isearch-regexp-function (text-properties-at 0 string)) + (when (plist-member (text-properties-at 0 string) 'isearch-regexp-function) (setq isearch-regexp-function (get-text-property 0 'isearch-regexp-function string)))) @@ -1602,10 +1602,10 @@ Turning on character-folding turns off regexp mode.") (defun isearch--momentary-message (string) "Print STRING at the end of the isearch prompt for 1 second" (let ((message-log-max nil)) - (message "%s%s [%s]" + (message "%s%s%s" (isearch-message-prefix nil isearch-nonincremental) isearch-message - string)) + (propertize (format " [%s]" string) 'face 'minibuffer-prompt))) (sit-for 1)) (isearch-define-mode-toggle lax-whitespace " " nil @@ -2693,12 +2693,16 @@ the word mode." (cond ;; 1. Do not use a description on the default search mode, ;; but only if the default search mode is non-nil. - ((or (and search-default-mode - (equal search-default-mode regexp-function)) - ;; Special case where `search-default-mode' is t - ;; (defaults to regexp searches). - (and (eq search-default-mode t) - (eq search-default-mode isearch-regexp))) "") + ((and (or (and search-default-mode + (equal search-default-mode regexp-function)) + ;; Special case where `search-default-mode' is t + ;; (defaults to regexp searches). + (and (eq search-default-mode t) + (eq search-default-mode isearch-regexp))) + ;; Also do not omit description in case of error + ;; in default non-literal search. + (or isearch-success (not (or regexp-function isearch-regexp)))) + "") ;; 2. Use the `isearch-message-prefix' set for ;; `regexp-function' if available. (regexp-function @@ -2741,6 +2745,8 @@ the word mode." (< (point) isearch-opoint))) "over") (if isearch-wrapped "wrapped ") + (if (and (not isearch-success) (not isearch-case-fold-search)) + "case-sensitive ") (let ((prefix "")) (advice-function-mapc (lambda (_ props) @@ -2768,11 +2774,12 @@ the word mode." 'face 'minibuffer-prompt))) (defun isearch-message-suffix (&optional c-q-hack) - (concat (if c-q-hack "^Q" "") - (if isearch-error - (concat " [" isearch-error "]") - "") - (or isearch-message-suffix-add ""))) + (propertize (concat (if c-q-hack "^Q" "") + (if isearch-error + (concat " [" isearch-error "]") + "") + (or isearch-message-suffix-add "")) + 'face 'minibuffer-prompt)) ;; Searching @@ -2808,25 +2815,18 @@ Can be changed via `isearch-search-fun-function' for special needs." (isearch-regexp isearch-regexp-lax-whitespace) (t isearch-lax-whitespace)) search-whitespace-regexp))) - (condition-case er - (funcall - (if isearch-forward #'re-search-forward #'re-search-backward) - (cond (isearch-regexp-function - (let ((lax (and (not bound) (isearch--lax-regexp-function-p)))) - (when lax - (setq isearch-adjusted t)) - (if (functionp isearch-regexp-function) - (funcall isearch-regexp-function string lax) - (word-search-regexp string lax)))) - (isearch-regexp string) - (t (regexp-quote string))) - bound noerror count) - (search-failed - (signal (car er) - (let ((prefix (get isearch-regexp-function 'isearch-message-prefix))) - (if (and isearch-regexp-function (stringp prefix)) - (list (format "%s [using %ssearch]" string prefix)) - (cdr er))))))))) + (funcall + (if isearch-forward #'re-search-forward #'re-search-backward) + (cond (isearch-regexp-function + (let ((lax (and (not bound) (isearch--lax-regexp-function-p)))) + (when lax + (setq isearch-adjusted t)) + (if (functionp isearch-regexp-function) + (funcall isearch-regexp-function string lax) + (word-search-regexp string lax)))) + (isearch-regexp string) + (t (regexp-quote string))) + bound noerror count)))) (defun isearch-search-string (string bound noerror) "Search for the first occurrence of STRING or its translation. diff --git a/lisp/replace.el b/lisp/replace.el index d5d34f652ab..3503b656d9c 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -314,7 +314,7 @@ the original string if not." (query-replace-read-to from prompt regexp-flag)))) (list from to (or (and current-prefix-arg (not (eq current-prefix-arg '-))) - (and (memq 'isearch-regexp-function (text-properties-at 0 from)) + (and (plist-member (text-properties-at 0 from) 'isearch-regexp-function) (get-text-property 0 'isearch-regexp-function from))) (and current-prefix-arg (eq current-prefix-arg '-))))) diff --git a/lisp/vc/add-log.el b/lisp/vc/add-log.el index 41a99916994..4c64ae1f60b 100644 --- a/lisp/vc/add-log.el +++ b/lisp/vc/add-log.el @@ -1099,9 +1099,17 @@ file were isearch was started." ;; If there are no files that match the default pattern ChangeLog.[0-9], ;; return the current buffer to force isearch wrapping to its beginning. ;; If file is nil, multi-isearch-search-fun will signal "end of multi". - (if (and file (file-exists-p file)) - (find-file-noselect file) - (current-buffer)))) + (cond + ;; Wrapping doesn't catch errors from the nil arg of file-exists-p, + ;; so handle it explicitly. + ((and wrap (null file)) + (current-buffer)) + ;; When there is no next file, file-exists-p raises the error to be + ;; catched by the search function that displays the error message. + ((file-exists-p file) + (find-file-noselect file)) + (t + (current-buffer))))) (defun change-log-fill-forward-paragraph (n) "Cut paragraphs so filling preserves open parentheses at beginning of lines."