X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/118a01c922c8f0e6bad337fd3780392519395e8a..a5743acc05a500b9746f8815dd4d3c6bddf2c931:/lisp/replace.el diff --git a/lisp/replace.el b/lisp/replace.el index 3bfa33f1e2..eb947fd433 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -30,11 +30,17 @@ (defvar query-replace-history nil) -(defun query-replace-read-args (string) +(defvar query-replace-interactive nil + "Non-nil means `query-replace' uses the last search string. +That becomes the \"string to replace\".") + +(defun query-replace-read-args (string regexp-flag) (let (from to) - (setq from (read-from-minibuffer (format "%s: " string) - nil nil nil - 'query-replace-history)) + (if query-replace-interactive + (setq from (car (if regexp-flag regexp-search-ring search-ring))) + (setq from (read-from-minibuffer (format "%s: " string) + nil nil nil + 'query-replace-history))) (setq to (read-from-minibuffer (format "%s %s with: " string from) nil nil nil 'query-replace-history)) @@ -45,15 +51,21 @@ As each match is found, the user must type a character saying what to do with it. For directions, type \\[help-command] at that time. +If `query-replace-interactive' is non-nil, the last incremental search +string is used as FROM-STRING--you don't have to specify it with the +minibuffer. + Preserves case in each replacement if `case-replace' and `case-fold-search' are non-nil and FROM-STRING has no uppercase letters. +\(Preserving case means that if the string matched is all caps, or capitalized, +then its replacement is upcased or capitalized.) + Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace only matches surrounded by word boundaries. To customize possible responses, change the \"bindings\" in `query-replace-map'." - (interactive (query-replace-read-args "Query replace")) - (perform-replace from-string to-string t nil arg) - (or unread-command-events (message "Done"))) + (interactive (query-replace-read-args "Query replace" nil)) + (perform-replace from-string to-string t nil arg)) (define-key esc-map "%" 'query-replace) (defun query-replace-regexp (regexp to-string &optional arg) @@ -61,6 +73,10 @@ To customize possible responses, change the \"bindings\" in `query-replace-map'. As each match is found, the user must type a character saying what to do with it. For directions, type \\[help-command] at that time. +If `query-replace-interactive' is non-nil, the last incremental search +regexp is used as REGEXP--you don't have to specify it with the +minibuffer. + Preserves case in each replacement if `case-replace' and `case-fold-search' are non-nil and REGEXP has no uppercase letters. Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace @@ -68,9 +84,8 @@ only matches surrounded by word boundaries. In TO-STRING, `\\&' stands for whatever matched the whole of REGEXP, and `\\=\\N' (where N is a digit) stands for whatever what matched the Nth `\\(...\\)' in REGEXP." - (interactive (query-replace-read-args "Query replace regexp")) - (perform-replace regexp to-string t t arg) - (or unread-command-events (message "Done"))) + (interactive (query-replace-read-args "Query replace regexp" t)) + (perform-replace regexp to-string t t arg)) (defun map-query-replace-regexp (regexp to-strings &optional arg) "Replace some matches for REGEXP with various strings, in rotation. @@ -81,13 +96,18 @@ wrapping around from the last such string to the first. Non-interactively, TO-STRINGS may be a list of replacement strings. +If `query-replace-interactive' is non-nil, the last incremental search +regexp is used as REGEXP--you don't have to specify it with the minibuffer. + A prefix argument N says to use each replacement string N times before rotating to the next." (interactive (let (from to) - (setq from (read-from-minibuffer "Map query replace (regexp): " - nil nil nil - 'query-replace-history)) + (setq from (if query-replace-interactive + (car regexp-search-ring) + (read-from-minibuffer "Map query replace (regexp): " + nil nil nil + 'query-replace-history))) (setq to (read-from-minibuffer (format "Query replace %s with (space-separated strings): " from) @@ -107,24 +127,29 @@ before rotating to the next." (1+ (string-match " " to-strings)))) (setq replacements (append replacements (list to-strings)) to-strings "")))) - (perform-replace regexp replacements t t nil arg)) - (or unread-command-events (message "Done"))) + (perform-replace regexp replacements t t nil arg))) (defun replace-string (from-string to-string &optional delimited) "Replace occurrences of FROM-STRING with TO-STRING. Preserve case in each match if `case-replace' and `case-fold-search' are non-nil and FROM-STRING has no uppercase letters. +\(Preserving case means that if the string matched is all caps, or capitalized, +then its replacement is upcased or capitalized.) + Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace only matches surrounded by word boundaries. +If `query-replace-interactive' is non-nil, the last incremental search +string is used as FROM-STRING--you don't have to specify it with the +minibuffer. + This function is usually the wrong thing to use in a Lisp program. What you probably want is a loop like this: (while (search-forward FROM-STRING nil t) (replace-match TO-STRING nil t)) which will run faster and will not set the mark or print anything." - (interactive (query-replace-read-args "Replace string")) - (perform-replace from-string to-string nil nil delimited) - (or unread-command-events (message "Done"))) + (interactive (query-replace-read-args "Replace string" nil)) + (perform-replace from-string to-string nil nil delimited)) (defun replace-regexp (regexp to-string &optional delimited) "Replace things after point matching REGEXP with TO-STRING. @@ -134,16 +159,18 @@ Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace only matches surrounded by word boundaries. In TO-STRING, `\\&' stands for whatever matched the whole of REGEXP, and `\\=\\N' (where N is a digit) stands for - whatever what matched the Nth `\\(...\\)' in REGEXP." + whatever what matched the Nth `\\(...\\)' in REGEXP. + +If `query-replace-interactive' is non-nil, the last incremental search +regexp is used as REGEXP--you don't have to specify it with the minibuffer. This function is usually the wrong thing to use in a Lisp program. What you probably want is a loop like this: (while (re-search-forward REGEXP nil t) (replace-match TO-STRING nil nil)) which will run faster and will not set the mark or print anything." - (interactive (query-replace-read-args "Replace regexp")) - (perform-replace regexp to-string nil t delimited) - (or unread-command-events (message "Done"))) + (interactive (query-replace-read-args "Replace regexp" t)) + (perform-replace regexp to-string nil t delimited)) (defvar regexp-history nil "History list for some commands that read regular expressions.") @@ -326,8 +353,10 @@ It serves as a menu to find any of the occurrences in this buffer. (with-output-to-temp-buffer "*Occur*" (save-excursion (set-buffer standard-output) - (insert "Lines matching ") - (prin1 regexp) + ;; We will insert the number of lines, and "lines", later. + (insert " matching ") + (let ((print-escape-newlines t)) + (prin1 regexp)) (insert " in buffer " (buffer-name buffer) ?. ?\n) (occur-mode) (setq occur-buffer buffer) @@ -399,6 +428,10 @@ It serves as a menu to find any of the occurrences in this buffer. (set-buffer standard-output) ;; Put positions in increasing order to go with buffer. (setq occur-pos-list (nreverse occur-pos-list)) + (goto-char (point-min)) + (if (= (length occur-pos-list) 1) + (insert "1 line") + (insert (format "%d lines" (length occur-pos-list)))) (if (interactive-p) (message "%d matching lines." (length occur-pos-list))))))) @@ -420,7 +453,7 @@ C-l to clear the screen, redisplay, and offer same replacement again, The \"bindings\" in this map are not commands; they are answers. The valid answers include `act', `skip', `act-and-show', `exit', `act-and-exit', `edit', `delete-and-edit', `recenter', -`automatic', `backup', and `help'.") +`automatic', `backup', `exit-prefix', and `help'.") (define-key query-replace-map " " 'act) (define-key query-replace-map "\d" 'skip) @@ -428,6 +461,8 @@ The valid answers include `act', `skip', `act-and-show', (define-key query-replace-map [backspace] 'skip) (define-key query-replace-map "y" 'act) (define-key query-replace-map "n" 'skip) +(define-key query-replace-map "Y" 'act) +(define-key query-replace-map "N" 'skip) (define-key query-replace-map "," 'act-and-show) (define-key query-replace-map "q" 'exit) (define-key query-replace-map "\r" 'exit) @@ -442,6 +477,8 @@ The valid answers include `act', `skip', `act-and-show', (define-key query-replace-map "?" 'help) (define-key query-replace-map "\C-g" 'quit) (define-key query-replace-map "\C-]" 'quit) +(define-key query-replace-map "\e" 'exit-prefix) +(define-key query-replace-map [escape] 'exit-prefix) (defun perform-replace (from-string replacements query-flag regexp-flag delimited-flag @@ -467,7 +504,11 @@ which will run faster and probably do exactly what you want." (next-rotate-count 0) (replace-count 0) (lastrepl nil) ;Position after last match considered. - (match-again t)) + (match-again t) + (message + (if query-flag + (substitute-command-keys + "Query replacing %s with %s: (\\\\[help] for help) ")))) (if (stringp replacements) (setq next-replacement replacements) (or repeat-count (setq repeat-count 1))) @@ -524,15 +565,13 @@ which will run faster and probably do exactly what you want." ;; Loop reading commands until one of them sets done, ;; which means it has finished handling this occurrence. (while (not done) + (store-match-data real-match-data) (replace-highlight (match-beginning 0) (match-end 0)) - (message (substitute-command-keys - "Query replacing %s with %s: (\\\\[help] for help) ") - from-string next-replacement) + (message message from-string next-replacement) (setq key (read-event)) (setq key (vector key)) (setq def (lookup-key map key)) ;; Restore the match data while we process the command. - (store-match-data real-match-data) (cond ((eq def 'help) (with-output-to-temp-buffer "*Help*" (princ @@ -541,7 +580,10 @@ which will run faster and probably do exactly what you want." from-string " with " next-replacement ".\n\n" (substitute-command-keys - query-replace-help))))) + query-replace-help))) + (save-excursion + (set-buffer standard-output) + (help-mode)))) ((eq def 'exit) (setq keep-going nil) (setq done t)) @@ -593,7 +635,11 @@ which will run faster and probably do exactly what you want." (prog1 (match-data) (save-excursion (recursive-edit)))) (setq replaced t)) + ;; Note: we do not need to treat `exit-prefix' + ;; specially here, since we reread + ;; any unrecognized character. (t + (setq this-command 'mode-exited) (setq keep-going nil) (setq unread-command-events (append (listify-key-sequence key) @@ -614,7 +660,11 @@ which will run faster and probably do exactly what you want." (if replaced (setq replace-count (1+ replace-count))))) (setq lastrepl (point))) (replace-dehighlight)) - (and keep-going stack))) + (or unread-command-events + (message "Replaced %d occurrence%s" + replace-count + (if (= replace-count 1) "" "s"))) + (and keep-going stack))) (defvar query-replace-highlight nil "*Non-nil means to highlight words during query replacement.")