Mercurial > hg > xemacs-beta
annotate lisp/replace.el @ 5746:b8c2808b33d4
Document #'events-to-keys some more, use it less.
lisp/ChangeLog addition:
2013-07-10 Aidan Kehoe <kehoea@parhasard.net>
* minibuf.el (get-user-response):
* cmdloop.el (y-or-n-p-minibuf):
No need to call #'events-to-keys in these two functions,
#'lookup-key accepts events directly.
* keymap.el:
* keymap.el (events-to-keys):
Document this function some more.
Stop passing strings through unexamined, treat them as vectors of
characters.
Event keys are never integers, remove some code that only ran if
(integerp (event-key ce)).
Event keys are never numbers, don't check for that.
Don't create (menu-selection call-interactively function-name)
keystrokes for menu choices, #'character-to-event doesn't
understand that syntax, so nothing uses it.
Don't ever accept mouse events, #'character-to-event doesn't
accept our synthesising of them.
src/ChangeLog addition:
2013-07-10 Aidan Kehoe <kehoea@parhasard.net>
* keymap.c:
* keymap.c (key_desc_list_to_event):
Drop the allow_menu_events argument.
Don't accept lists starting with Qmenu_selection as describing
keys, nothing generates them in a way this function
understands. The intention is reasonable but the implementation
was never documented and never finished.
* keymap.c (syms_of_keymap):
Drop Qmenu_selection.
* events.c (Fcharacter_to_event):
* keymap.h:
Drop the allow_menu_events argument to key_desc_list_to_event.
| author | Aidan Kehoe <kehoea@parhasard.net> |
|---|---|
| date | Wed, 10 Jul 2013 14:14:30 +0100 |
| parents | c6b1500299a7 |
| children | 0bddb59072b6 |
| rev | line source |
|---|---|
| 428 | 1 ;;; replace.el --- search and replace commands for XEmacs. |
| 2 | |
|
5686
c6b1500299a7
recenter-top-bottom synced from GNU and new default for C-l
Mats Lidell <mats.lidell@cag.se>
parents:
5473
diff
changeset
|
3 ;; Copyright (C) 1985-7, 1992, 1994, 1997, 2003, 2012 Free Software Foundation, Inc. |
| 428 | 4 |
| 5 ;; Maintainer: XEmacs Development Team | |
| 6 ;; Keywords: dumped, matching | |
| 7 | |
| 8 ;; This file is part of XEmacs. | |
| 9 | |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3000
diff
changeset
|
10 ;; XEmacs is free software: you can redistribute it and/or modify it |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3000
diff
changeset
|
11 ;; under the terms of the GNU General Public License as published by the |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3000
diff
changeset
|
12 ;; Free Software Foundation, either version 3 of the License, or (at your |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3000
diff
changeset
|
13 ;; option) any later version. |
| 428 | 14 |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3000
diff
changeset
|
15 ;; XEmacs is distributed in the hope that it will be useful, but WITHOUT |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3000
diff
changeset
|
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3000
diff
changeset
|
17 ;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3000
diff
changeset
|
18 ;; for more details. |
| 428 | 19 |
| 20 ;; You should have received a copy of the GNU General Public License | |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3000
diff
changeset
|
21 ;; along with XEmacs. If not, see <http://www.gnu.org/licenses/>. |
| 428 | 22 |
| 23 ;;; Synched up with: FSF 19.34 [Partially]. | |
| 24 | |
| 25 ;;; Commentary: | |
| 26 | |
| 27 ;; This file is dumped with XEmacs. | |
| 28 | |
| 29 ;; This package supplies the string and regular-expression replace functions | |
| 30 ;; documented in the XEmacs Reference Manual. | |
| 31 | |
| 32 ;; All the gettext calls are for XEmacs I18N3 message catalog support. | |
| 33 ;; (This is hopelessly broken and we should remove it. -sb) | |
| 34 | |
| 35 ;;; Code: | |
| 36 | |
| 37 (defvar case-replace t "\ | |
| 38 *Non-nil means `query-replace' should preserve case in replacements. | |
| 39 What this means is that `query-replace' will change the case of the | |
| 40 replacement text so that it matches the text that was replaced. | |
| 41 If this variable is nil, the replacement text will be inserted | |
| 42 exactly as it was specified by the user, irrespective of the case | |
| 43 of the text that was replaced. | |
| 44 | |
| 45 Note that this flag has no effect if `case-fold-search' is nil, | |
| 46 or if the replacement text has any uppercase letters in it.") | |
| 47 | |
| 48 (defvar query-replace-history nil) | |
| 49 | |
| 50 (defvar query-replace-interactive nil | |
| 51 "Non-nil means `query-replace' uses the last search string. | |
| 52 That becomes the \"string to replace\".") | |
| 53 | |
| 54 (defvar replace-search-function | |
| 55 (lambda (str limit) | |
| 56 (search-forward str limit t)) | |
| 444 | 57 "Function used by perform-replace to search forward for a string. It will be |
| 428 | 58 called with two arguments: the string to search for and a limit bounding the |
| 59 search.") | |
| 60 | |
| 61 (defvar replace-re-search-function | |
| 62 (lambda (regexp limit) | |
| 63 (re-search-forward regexp limit t)) | |
| 64 "Function used by perform-replace to search forward for a regular | |
| 65 expression. It will be called with two arguments: the regexp to search for and | |
| 66 a limit bounding the search.") | |
| 67 | |
| 68 (defun query-replace-read-args (string regexp-flag) | |
| 69 (let (from to) | |
| 70 (if query-replace-interactive | |
| 71 (setq from (car (if regexp-flag regexp-search-ring search-ring))) | |
| 72 (setq from (read-from-minibuffer (format "%s: " (gettext string)) | |
| 73 nil nil nil | |
| 74 'query-replace-history))) | |
| 75 (setq to (read-from-minibuffer (format "%s %s with: " (gettext string) | |
| 76 from) | |
| 77 nil nil nil | |
| 78 'query-replace-history)) | |
| 79 (list from to current-prefix-arg))) | |
| 80 | |
| 81 ;; As per suggestion from Per Abrahamsen, limit replacement to the region | |
| 82 ;; if the region is active. | |
| 83 (defun query-replace (from-string to-string &optional delimited) | |
| 84 "Replace some occurrences of FROM-STRING with TO-STRING. | |
| 85 As each match is found, the user must type a character saying | |
| 86 what to do with it. For directions, type \\[help-command] at that time. | |
| 87 | |
| 88 If `query-replace-interactive' is non-nil, the last incremental search | |
| 89 string is used as FROM-STRING--you don't have to specify it with the | |
| 90 minibuffer. | |
| 91 | |
| 92 Preserves case in each replacement if `case-replace' and `case-fold-search' | |
| 93 are non-nil and FROM-STRING has no uppercase letters. | |
| 94 \(Preserving case means that if the string matched is all caps, or capitalized, | |
| 95 then its replacement is upcased or capitalized.) | |
| 96 | |
| 97 Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace | |
| 98 only matches surrounded by word boundaries. | |
| 99 | |
| 100 To customize possible responses, change the \"bindings\" in `query-replace-map'." | |
| 101 (interactive (query-replace-read-args "Query replace" nil)) | |
| 102 (perform-replace from-string to-string t nil delimited)) | |
| 103 | |
| 104 (defun query-replace-regexp (regexp to-string &optional delimited) | |
| 105 "Replace some things after point matching REGEXP with TO-STRING. | |
| 106 As each match is found, the user must type a character saying | |
| 107 what to do with it. For directions, type \\[help-command] at that time. | |
| 108 | |
| 109 If `query-replace-interactive' is non-nil, the last incremental search | |
| 110 regexp is used as REGEXP--you don't have to specify it with the | |
| 111 minibuffer. | |
| 112 | |
| 113 Preserves case in each replacement if `case-replace' and `case-fold-search' | |
| 114 are non-nil and REGEXP has no uppercase letters. | |
| 115 Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace | |
| 116 only matches surrounded by word boundaries. | |
| 117 In TO-STRING, `\\&' stands for whatever matched the whole of REGEXP, | |
| 118 and `\\=\\N' (where N is a digit) stands for | |
| 119 whatever what matched the Nth `\\(...\\)' in REGEXP." | |
| 120 (interactive (query-replace-read-args "Query replace regexp" t)) | |
| 121 (perform-replace regexp to-string t t delimited)) | |
| 122 | |
| 123 ;;#### Not patently useful | |
| 124 (defun map-query-replace-regexp (regexp to-strings &optional arg) | |
| 125 "Replace some matches for REGEXP with various strings, in rotation. | |
| 126 The second argument TO-STRINGS contains the replacement strings, separated | |
| 127 by spaces. This command works like `query-replace-regexp' except | |
| 128 that each successive replacement uses the next successive replacement string, | |
| 129 wrapping around from the last such string to the first. | |
| 130 | |
| 131 Non-interactively, TO-STRINGS may be a list of replacement strings. | |
| 132 | |
| 133 If `query-replace-interactive' is non-nil, the last incremental search | |
| 134 regexp is used as REGEXP--you don't have to specify it with the minibuffer. | |
| 135 | |
| 136 A prefix argument N says to use each replacement string N times | |
| 137 before rotating to the next." | |
| 138 (interactive | |
| 139 (let (from to) | |
| 140 (setq from (if query-replace-interactive | |
| 141 (car regexp-search-ring) | |
| 142 (read-from-minibuffer "Map query replace (regexp): " | |
| 143 nil nil nil | |
| 144 'query-replace-history))) | |
| 145 (setq to (read-from-minibuffer | |
| 146 (format "Query replace %s with (space-separated strings): " | |
| 147 from) | |
| 148 nil nil nil | |
| 149 'query-replace-history)) | |
| 150 (list from to current-prefix-arg))) | |
| 151 (let (replacements) | |
| 152 (if (listp to-strings) | |
| 153 (setq replacements to-strings) | |
|
5366
f00192e1cd49
Examining the result of #'length: `eql', not `=', it's better style & cheaper
Aidan Kehoe <kehoea@parhasard.net>
parents:
3000
diff
changeset
|
154 (while (not (eql (length to-strings) 0)) |
| 428 | 155 (if (string-match " " to-strings) |
| 156 (setq replacements | |
| 157 (append replacements | |
| 158 (list (substring to-strings 0 | |
| 159 (string-match " " to-strings)))) | |
| 160 to-strings (substring to-strings | |
| 161 (1+ (string-match " " to-strings)))) | |
| 162 (setq replacements (append replacements (list to-strings)) | |
| 163 to-strings "")))) | |
| 164 (perform-replace regexp replacements t t nil arg))) | |
| 165 | |
| 166 (defun replace-string (from-string to-string &optional delimited) | |
| 167 "Replace occurrences of FROM-STRING with TO-STRING. | |
| 168 Preserve case in each match if `case-replace' and `case-fold-search' | |
| 169 are non-nil and FROM-STRING has no uppercase letters. | |
| 170 \(Preserving case means that if the string matched is all caps, or capitalized, | |
| 171 then its replacement is upcased or capitalized.) | |
| 172 | |
| 173 Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace | |
| 174 only matches surrounded by word boundaries. | |
| 175 | |
| 176 If `query-replace-interactive' is non-nil, the last incremental search | |
| 177 string is used as FROM-STRING--you don't have to specify it with the | |
| 178 minibuffer. | |
| 179 | |
| 180 This function is usually the wrong thing to use in a Lisp program. | |
| 181 What you probably want is a loop like this: | |
| 182 (while (search-forward FROM-STRING nil t) | |
| 183 (replace-match TO-STRING nil t)) | |
| 184 which will run faster and will not set the mark or print anything." | |
| 185 (interactive (query-replace-read-args "Replace string" nil)) | |
| 186 (perform-replace from-string to-string nil nil delimited)) | |
| 187 | |
| 188 (defun replace-regexp (regexp to-string &optional delimited) | |
| 189 "Replace things after point matching REGEXP with TO-STRING. | |
| 190 Preserve case in each match if `case-replace' and `case-fold-search' | |
| 191 are non-nil and REGEXP has no uppercase letters. | |
| 192 \(Preserving case means that if the string matched is all caps, or capitalized, | |
| 193 then its replacement is upcased or capitalized.) | |
| 194 | |
| 195 Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace | |
| 196 only matches surrounded by word boundaries. | |
| 197 In TO-STRING, `\\&' stands for whatever matched the whole of REGEXP, | |
| 198 and `\\=\\N' (where N is a digit) stands for | |
| 199 whatever what matched the Nth `\\(...\\)' in REGEXP. | |
| 200 | |
| 201 If `query-replace-interactive' is non-nil, the last incremental search | |
| 202 regexp is used as REGEXP--you don't have to specify it with the minibuffer. | |
| 203 | |
| 204 This function is usually the wrong thing to use in a Lisp program. | |
| 205 What you probably want is a loop like this: | |
| 206 (while (re-search-forward REGEXP nil t) | |
| 207 (replace-match TO-STRING nil nil)) | |
| 208 which will run faster and will not set the mark or print anything." | |
| 209 (interactive (query-replace-read-args "Replace regexp" t)) | |
| 210 (perform-replace regexp to-string nil t delimited)) | |
| 211 | |
| 212 | |
| 1069 | 213 |
| 214 ;; gse wonders: Is there a better place for this to go? Might other packages | |
| 215 ;; want to use it? | |
| 428 | 216 (defvar regexp-history nil |
| 217 "History list for some commands that read regular expressions.") | |
| 218 | |
| 1069 | 219 (defun operate-on-non-matching-lines (regexp delete kill &optional beg end) |
| 220 "Internal function used by delete-non-matching-lines, | |
| 221 kill-non-matching-lines, and copy-matching-lines. | |
| 222 | |
| 223 REGEXP is a regular expression to *not* match when performing | |
| 224 operations. | |
| 225 | |
| 226 If DELETE is non-nil, the lines of text are deleted. It doesn't make | |
| 227 sense to set this to nil if KILL is nil -- nothing will happen. | |
| 228 | |
| 229 If KILL is non-nil, the lines of text are stored in the kill ring (as | |
| 230 one block of text). | |
| 231 | |
| 232 BEG and END, if non-nil, specify the start and end locations to work | |
| 233 within. If these are nil, point and point-max are used. | |
| 234 | |
| 235 A match split across lines preserves all the lines it lies in. | |
| 236 Applies to all lines after point. | |
| 237 | |
| 238 Returns the number of lines matched." | |
| 239 (with-search-caps-disable-folding regexp t | |
| 240 (save-excursion | |
| 241 ;; Move to a beginning point if specified. | |
| 242 (when beg (goto-char beg)) | |
| 243 ;; Always start on the beginning of a line. | |
| 244 (or (bolp) (forward-line 1)) | |
| 245 | |
| 246 (let ((matched-text nil) | |
| 247 (curmatch-start (point)) | |
| 2610 | 248 (limit (copy-marker (point-max))) |
| 249 (matched-text-buffer (generate-new-buffer " *matched-text*")) | |
| 250 lines-matched) | |
| 1069 | 251 ;; Limit search if limits were specified. |
| 252 (when end (setq limit (copy-marker end))) | |
| 253 | |
| 254 ;; Search. Stop if we are at end of buffer or outside the | |
| 255 ;; limit. | |
| 256 (while (not (or | |
| 257 (eobp) | |
| 258 (and limit (>= (point) limit)))) | |
| 259 ;; curmatch-start is first char not preserved by previous match. | |
| 260 (if (not (re-search-forward regexp limit 'move)) | |
| 261 (let ((curmatch-end limit)) | |
| 2610 | 262 (append-to-buffer matched-text-buffer curmatch-start curmatch-end) |
| 1069 | 263 (if delete (delete-region curmatch-start curmatch-end))) |
| 264 (let ((curmatch-end (save-excursion (goto-char (match-beginning 0)) | |
| 2610 | 265 (beginning-of-line) |
| 266 (point)))) | |
| 1069 | 267 ;; Now curmatch-end is first char preserved by the new match. |
| 268 (if (< curmatch-start curmatch-end) | |
| 269 (progn | |
| 2610 | 270 (append-to-buffer matched-text-buffer curmatch-start curmatch-end) |
| 1069 | 271 (if delete (delete-region curmatch-start curmatch-end)))))) |
| 272 (setq curmatch-start (save-excursion (forward-line 1) | |
| 2610 | 273 (point))) |
| 1069 | 274 ;; If the match was empty, avoid matching again at same place. |
| 275 (and (not (eobp)) (= (match-beginning 0) (match-end 0)) | |
| 276 (forward-char 1))) | |
| 277 | |
| 278 ;; If any lines were matched and KILL is non-nil, insert the | |
| 279 ;; matched lines into the kill ring. | |
| 2610 | 280 (setq matched-text (buffer-string matched-text-buffer)) |
| 1069 | 281 (if (and matched-text kill) (kill-new matched-text)) |
| 282 | |
| 283 ;; Return the number of matched lines. | |
| 2610 | 284 (setq lines-matched |
| 285 (with-current-buffer matched-text-buffer | |
| 286 (count-lines (point-min) (point-max)))) | |
| 287 (kill-buffer matched-text-buffer) | |
| 288 lines-matched)))) | |
| 1069 | 289 |
| 428 | 290 (define-function 'keep-lines 'delete-non-matching-lines) |
| 291 (defun delete-non-matching-lines (regexp) | |
| 1069 | 292 "Delete lines that do not match REGEXP, from point to the end of the |
| 293 buffer (or within the region, if it is active)." | |
| 428 | 294 (interactive (list (read-from-minibuffer |
| 295 "Keep lines (containing match for regexp): " | |
| 296 nil nil nil 'regexp-history))) | |
| 1069 | 297 (let ((beg nil) |
| 298 (end nil) | |
| 299 (count nil)) | |
| 300 (when (region-active-p) | |
| 301 (setq beg (region-beginning)) | |
| 302 (setq end (region-end))) | |
| 303 (setq count (operate-on-non-matching-lines regexp t nil beg end)) | |
| 1476 | 304 (when (interactive-p) |
| 305 (message "%i lines deleted" count)))) | |
| 1069 | 306 |
| 307 (defun kill-non-matching-lines (regexp) | |
| 308 "Delete the lines that do not match REGEXP, from point to the end of | |
| 309 the buffer (or within the region, if it is active). The deleted lines | |
| 310 are placed in the kill ring as one block of text." | |
| 311 (interactive (list (read-from-minibuffer | |
| 312 "Kill non-matching lines (regexp): " | |
| 313 nil nil nil 'regexp-history))) | |
| 314 (let ((beg nil) | |
| 315 (end nil) | |
| 316 (count nil)) | |
| 317 (when (region-active-p) | |
| 318 (setq beg (region-beginning)) | |
| 319 (setq end (region-end))) | |
| 320 (setq count (operate-on-non-matching-lines regexp t t beg end)) | |
| 1476 | 321 (when (interactive-p) |
| 322 (message "%i lines killed" count)))) | |
| 1069 | 323 |
| 324 (defun copy-non-matching-lines (regexp) | |
| 325 "Find all lines that do not match REGEXP from point to the end of the | |
| 326 buffer (or within the region, if it is active), and place them in the | |
| 327 kill ring as one block of text." | |
| 328 (interactive (list (read-from-minibuffer | |
| 329 "Copy non-matching lines (regexp): " | |
| 330 nil nil nil 'regexp-history))) | |
| 331 (let ((beg nil) | |
| 332 (end nil) | |
| 333 (count nil)) | |
| 334 (when (region-active-p) | |
| 335 (setq beg (region-beginning)) | |
| 336 (setq end (region-end))) | |
| 337 (setq count (operate-on-non-matching-lines regexp nil t beg end)) | |
| 1476 | 338 (when (interactive-p) |
| 339 (message "%i lines copied" count)))) | |
| 1069 | 340 |
| 341 (defun operate-on-matching-lines (regexp delete kill &optional beg end) | |
| 342 "Internal function used by delete-matching-lines, kill-matching-lines, | |
| 343 and copy-matching-lines. | |
| 344 | |
| 345 If DELETE is non-nil, the lines of text are deleted. It doesn't make | |
| 346 sense to set this to nil if KILL is nil -- nothing will happen. | |
| 347 | |
| 348 If KILL is non-nil, the lines of text are stored in the kill ring (as | |
| 349 one block of text). | |
| 350 | |
| 351 BEG and END, if non-nil, specify the start and end locations to work | |
| 352 within. If these are nil, point and point-max are used. | |
| 353 | |
| 354 If a match is split across lines, all the lines it lies in are deleted. | |
| 355 Applies to lines after point. | |
| 356 Returns the number of lines matched." | |
| 357 (with-search-caps-disable-folding regexp t | |
| 428 | 358 (save-excursion |
| 1069 | 359 (let ((matched-text nil) |
| 360 (curmatch-start nil) | |
| 361 (curmatch-end nil) | |
| 2610 | 362 (limit nil) |
| 363 (matched-text-buffer (generate-new-buffer " *matched-text*")) | |
| 364 lines-matched) | |
| 1069 | 365 ;; Limit search if limits were specified. |
| 366 (when beg (goto-char beg)) | |
| 367 (when end (setq limit (copy-marker end))) | |
| 368 | |
| 369 (while (and (not (eobp)) | |
| 370 (re-search-forward regexp limit t)) | |
| 371 (setq curmatch-start (save-excursion (goto-char (match-beginning 0)) | |
| 372 (beginning-of-line) | |
| 373 (point))) | |
| 374 (setq curmatch-end (progn (forward-line 1) (point))) | |
| 2610 | 375 (append-to-buffer matched-text-buffer curmatch-start curmatch-end) |
| 1069 | 376 (if delete (delete-region curmatch-start curmatch-end))) |
| 2610 | 377 (setq matched-text (buffer-string matched-text-buffer)) |
| 1069 | 378 (if (and matched-text kill) (kill-new matched-text)) |
| 379 | |
| 380 ;; Return the number of matched lines. | |
| 2610 | 381 (setq lines-matched |
| 382 (with-current-buffer matched-text-buffer | |
| 383 (count-lines (point-min) (point-max)))) | |
| 384 (kill-buffer matched-text-buffer) | |
| 385 lines-matched)))) | |
| 428 | 386 |
| 387 (define-function 'flush-lines 'delete-matching-lines) | |
| 388 (defun delete-matching-lines (regexp) | |
| 1069 | 389 "Delete the lines that match REGEXP, from point to the end of the |
| 390 buffer (or within the region, if it is active)." | |
| 428 | 391 (interactive (list (read-from-minibuffer |
| 392 "Flush lines (containing match for regexp): " | |
| 393 nil nil nil 'regexp-history))) | |
| 1069 | 394 (let ((beg nil) |
| 395 (end nil) | |
| 396 (count nil)) | |
| 397 (when (region-active-p) | |
| 398 (setq beg (region-beginning)) | |
| 399 (setq end (region-end))) | |
| 400 (setq count (operate-on-matching-lines regexp t nil beg end)) | |
| 1476 | 401 (when (interactive-p) |
| 402 (message "%i lines deleted" count)))) | |
| 1069 | 403 |
| 404 (defun kill-matching-lines (regexp) | |
| 405 "Delete the lines that match REGEXP, from point to the end of the | |
| 406 buffer (or within the region, if it is active). The deleted lines are | |
| 407 placed in the kill ring as one block of text." | |
| 408 (interactive (list (read-from-minibuffer | |
| 409 "Kill lines (containing match for regexp): " | |
| 410 nil nil nil 'regexp-history))) | |
| 411 (let ((beg nil) | |
| 412 (end nil) | |
| 413 (count nil)) | |
| 414 (when (region-active-p) | |
| 415 (setq beg (region-beginning)) | |
| 416 (setq end (region-end))) | |
| 417 (setq count (operate-on-matching-lines regexp t t beg end)) | |
| 1476 | 418 (when (interactive-p) |
| 419 (message "%i lines killed" count)))) | |
| 1069 | 420 |
| 421 (defun copy-matching-lines (regexp) | |
| 422 "Find all lines that match REGEXP from point to the end of the | |
| 423 buffer (or within the region, if it is active), and place them in the | |
| 424 kill ring as one block of text." | |
| 425 (interactive (list (read-from-minibuffer | |
| 426 "Copy lines (containing match for regexp): " | |
| 427 nil nil nil 'regexp-history))) | |
| 428 (let ((beg nil) | |
| 429 (end nil) | |
| 430 (count nil)) | |
| 431 (when (region-active-p) | |
| 432 (setq beg (region-beginning)) | |
| 433 (setq end (region-end))) | |
| 434 (setq count (operate-on-matching-lines regexp nil t beg end)) | |
| 1476 | 435 (when (interactive-p) |
| 436 (message "%i lines copied" count)))) | |
| 428 | 437 |
| 438 (define-function 'how-many 'count-matches) | |
| 439 (defun count-matches (regexp) | |
| 440 "Print number of matches for REGEXP following point." | |
| 441 (interactive (list (read-from-minibuffer | |
| 442 "How many matches for (regexp): " | |
| 443 nil nil nil 'regexp-history))) | |
| 444 (with-interactive-search-caps-disable-folding regexp t | |
| 445 (let ((count 0) opoint) | |
| 446 (save-excursion | |
| 447 (while (and (not (eobp)) | |
| 448 (progn (setq opoint (point)) | |
| 449 (re-search-forward regexp nil t))) | |
| 450 (if (= opoint (point)) | |
| 451 (forward-char 1) | |
| 452 (setq count (1+ count)))) | |
| 453 (message "%d occurrences" count))))) | |
| 454 | |
| 455 | |
| 3000 | 456 ;;; occur code moved to occur.el |
| 428 | 457 |
| 458 ;; It would be nice to use \\[...], but there is no reasonable way | |
| 459 ;; to make that display both SPC and Y. | |
| 460 (defconst query-replace-help | |
| 444 | 461 "Type Space or `y' to replace one match, Delete or `n' to skip to next, |
| 428 | 462 RET or `q' to exit, Period to replace one match and exit, |
| 463 Comma to replace but not move point immediately, | |
| 464 C-r to enter recursive edit (\\[exit-recursive-edit] to get out again), | |
| 465 C-w to delete match and recursive edit, | |
| 466 C-l to clear the frame, redisplay, and offer same replacement again, | |
| 467 ! to replace all remaining matches with no more questions, | |
| 468 ^ to move point back to previous match." | |
| 444 | 469 |
| 428 | 470 "Help message while in query-replace") |
| 471 | |
| 472 (defvar query-replace-map nil | |
| 473 "Keymap that defines the responses to questions in `query-replace'. | |
| 474 The \"bindings\" in this map are not commands; they are answers. | |
| 475 The valid answers include `act', `skip', `act-and-show', | |
| 476 `exit', `act-and-exit', `edit', `delete-and-edit', `recenter', | |
| 477 `automatic', `backup', `exit-prefix', and `help'.") | |
| 478 | |
| 479 ;; Why does it seem that ever file has a different method of doing this? | |
| 480 (if query-replace-map | |
| 481 nil | |
| 482 (let ((map (make-sparse-keymap))) | |
| 483 (set-keymap-name map 'query-replace-map) | |
| 484 (define-key map " " 'act) | |
| 485 (define-key map "\d" 'skip) | |
| 486 (define-key map [delete] 'skip) | |
| 487 (define-key map [backspace] 'skip) | |
| 488 (define-key map "y" 'act) | |
| 489 (define-key map "n" 'skip) | |
| 490 (define-key map "Y" 'act) | |
| 491 (define-key map "N" 'skip) | |
| 492 (define-key map "," 'act-and-show) | |
| 493 (define-key map [escape] 'exit) | |
| 494 (define-key map "q" 'exit) | |
| 495 (define-key map [return] 'exit) | |
| 496 (define-key map "." 'act-and-exit) | |
| 497 (define-key map "\C-r" 'edit) | |
| 498 (define-key map "\C-w" 'delete-and-edit) | |
| 499 (define-key map "\C-l" 'recenter) | |
| 500 (define-key map "!" 'automatic) | |
| 501 (define-key map "^" 'backup) | |
| 502 (define-key map [(control h)] 'help) ;; XEmacs change | |
| 503 (define-key map [f1] 'help) | |
| 504 (define-key map [help] 'help) | |
| 505 (define-key map "?" 'help) | |
| 506 (define-key map "\C-g" 'quit) | |
| 507 (define-key map "\C-]" 'quit) | |
| 508 ;FSFmacs (define-key map "\e" 'exit-prefix) | |
| 509 (define-key map [escape] 'exit-prefix) | |
| 444 | 510 |
| 428 | 511 (setq query-replace-map map))) |
| 512 | |
| 513 ;; isearch-mode is dumped, so don't autoload. | |
| 514 ;(autoload 'isearch-highlight "isearch") | |
| 515 | |
| 516 ;; XEmacs | |
| 517 (defun perform-replace-next-event (event) | |
| 442 | 518 (if search-highlight |
| 428 | 519 (let ((aborted t)) |
| 520 (unwind-protect | |
| 521 (progn | |
| 522 (if (match-beginning 0) | |
| 523 (isearch-highlight (match-beginning 0) (match-end 0))) | |
| 524 (next-command-event event) | |
| 525 (setq aborted nil)) | |
| 526 (isearch-dehighlight aborted))) | |
| 527 (next-command-event event))) | |
| 528 | |
| 529 (defun perform-replace (from-string replacements | |
| 530 query-flag regexp-flag delimited-flag | |
| 531 &optional repeat-count map) | |
| 532 "Subroutine of `query-replace'. Its complexity handles interactive queries. | |
| 533 Don't use this in your own program unless you want to query and set the mark | |
| 534 just as `query-replace' does. Instead, write a simple loop like this: | |
| 535 (while (re-search-forward \"foo[ \t]+bar\" nil t) | |
| 536 (replace-match \"foobar\" nil nil)) | |
| 537 which will run faster and probably do exactly what you want. | |
| 444 | 538 When searching for a match, this function uses |
| 539 `replace-search-function' and `replace-re-search-function'." | |
| 428 | 540 (or map (setq map query-replace-map)) |
| 541 (let* ((event (make-event)) | |
| 542 (nocasify (not (and case-fold-search case-replace | |
| 543 (string-equal from-string | |
| 544 (downcase from-string))))) | |
| 545 (literal (not regexp-flag)) | |
| 444 | 546 (search-function (if regexp-flag |
| 547 replace-re-search-function | |
| 428 | 548 replace-search-function)) |
| 549 (search-string from-string) | |
| 550 (real-match-data nil) ; the match data for the current match | |
| 551 (next-replacement nil) | |
| 552 (replacement-index 0) | |
| 553 (keep-going t) | |
| 554 (stack nil) | |
| 555 (next-rotate-count 0) | |
| 556 (replace-count 0) | |
| 557 (lastrepl nil) ;Position after last match considered. | |
| 558 ;; If non-nil, it is marker saying where in the buffer to | |
| 559 ;; stop. | |
| 560 (limit nil) | |
| 561 (match-again t) | |
|
5686
c6b1500299a7
recenter-top-bottom synced from GNU and new default for C-l
Mats Lidell <mats.lidell@cag.se>
parents:
5473
diff
changeset
|
562 (recenter-last-op nil) ; Start cycling order with initial position. |
| 428 | 563 ;; XEmacs addition |
| 564 (qr-case-fold-search | |
| 565 (if (and case-fold-search search-caps-disable-folding) | |
| 566 (no-upper-case-p search-string regexp-flag) | |
| 567 case-fold-search)) | |
| 568 (message | |
| 569 (if query-flag | |
| 570 (substitute-command-keys | |
| 571 "Query replacing %s with %s: (\\<query-replace-map>\\[help] for help) ")))) | |
| 572 ;; If the region is active, operate on region. | |
| 573 (when (region-active-p) | |
| 574 ;; Original Per Abrahamsen's code simply narrowed the region, | |
| 575 ;; thus providing a visual indication of the search boundary. | |
| 576 ;; Stallman, on the other hand, handles it like this. | |
| 577 (setq limit (copy-marker (region-end))) | |
| 578 (goto-char (region-beginning)) | |
| 579 (zmacs-deactivate-region)) | |
| 580 (if (stringp replacements) | |
| 581 (setq next-replacement replacements) | |
| 582 (or repeat-count (setq repeat-count 1))) | |
| 583 (if delimited-flag | |
| 584 (setq search-function replace-re-search-function | |
| 585 search-string (concat "\\b" | |
| 586 (if regexp-flag from-string | |
| 587 (regexp-quote from-string)) | |
| 588 "\\b"))) | |
| 589 (push-mark) | |
| 590 (undo-boundary) | |
| 591 (unwind-protect | |
| 592 ;; Loop finding occurrences that perhaps should be replaced. | |
| 593 (while (and keep-going | |
| 594 (not (eobp)) | |
| 595 (or (null limit) (< (point) limit)) | |
| 596 (let ((case-fold-search qr-case-fold-search)) | |
| 597 (funcall search-function search-string limit)) | |
| 598 ;; If the search string matches immediately after | |
| 599 ;; the previous match, but it did not match there | |
| 600 ;; before the replacement was done, ignore the match. | |
| 601 (if (or (eq lastrepl (point)) | |
| 602 (and regexp-flag | |
| 603 (eq lastrepl (match-beginning 0)) | |
| 604 (not match-again))) | |
| 605 (if (or (eobp) | |
| 606 (and limit (>= (point) limit))) | |
| 607 nil | |
| 444 | 608 ;; Don't replace the null string |
| 428 | 609 ;; right after end of previous replacement. |
| 610 (forward-char 1) | |
| 611 (let ((case-fold-search qr-case-fold-search)) | |
| 612 (funcall search-function search-string limit))) | |
| 613 t)) | |
| 614 | |
| 615 ;; Save the data associated with the real match. | |
| 616 (setq real-match-data (match-data)) | |
| 617 | |
| 618 ;; Before we make the replacement, decide whether the search string | |
| 619 ;; can match again just after this match. | |
| 620 (if regexp-flag | |
| 444 | 621 (progn |
| 428 | 622 (setq match-again (looking-at search-string)) |
| 623 ;; XEmacs addition | |
| 624 (store-match-data real-match-data))) | |
| 625 ;; If time for a change, advance to next replacement string. | |
| 626 (if (and (listp replacements) | |
| 627 (= next-rotate-count replace-count)) | |
| 628 (progn | |
| 629 (setq next-rotate-count | |
| 630 (+ next-rotate-count repeat-count)) | |
| 631 (setq next-replacement (nth replacement-index replacements)) | |
| 632 (setq replacement-index (% (1+ replacement-index) (length replacements))))) | |
| 633 (if (not query-flag) | |
| 634 (progn | |
| 635 (store-match-data real-match-data) | |
| 636 (replace-match next-replacement nocasify literal) | |
| 637 (setq replace-count (1+ replace-count))) | |
| 638 (undo-boundary) | |
| 639 (let ((help-form | |
| 640 '(concat (format "Query replacing %s%s with %s.\n\n" | |
| 641 (if regexp-flag (gettext "regexp ") "") | |
| 642 from-string next-replacement) | |
| 643 (substitute-command-keys query-replace-help))) | |
| 644 done replaced def) | |
| 645 ;; Loop reading commands until one of them sets done, | |
| 646 ;; which means it has finished handling this occurrence. | |
| 647 (while (not done) | |
| 648 ;; Don't fill up the message log | |
| 649 ;; with a bunch of identical messages. | |
| 650 ;; XEmacs change | |
| 651 (display-message 'prompt | |
| 652 (format message from-string next-replacement)) | |
| 653 (perform-replace-next-event event) | |
| 654 (setq def (lookup-key map (vector event))) | |
| 655 ;; Restore the match data while we process the command. | |
| 656 (store-match-data real-match-data) | |
| 657 (cond ((eq def 'help) | |
| 658 (with-output-to-temp-buffer (gettext "*Help*") | |
| 659 (princ (concat | |
| 660 (format "Query replacing %s%s with %s.\n\n" | |
| 661 (if regexp-flag "regexp " "") | |
| 662 from-string next-replacement) | |
| 663 (substitute-command-keys | |
| 664 query-replace-help))) | |
| 665 (save-excursion | |
| 666 (set-buffer standard-output) | |
| 667 (help-mode)))) | |
| 668 ((eq def 'exit) | |
| 669 (setq keep-going nil) | |
| 670 (setq done t)) | |
| 671 ((eq def 'backup) | |
| 672 (if stack | |
| 673 (let ((elt (car stack))) | |
| 674 (goto-char (car elt)) | |
| 675 (setq replaced (eq t (cdr elt))) | |
| 676 (or replaced | |
| 677 (store-match-data (cdr elt))) | |
| 678 (setq stack (cdr stack))) | |
| 679 (message "No previous match") | |
| 680 (ding 'no-terminate) | |
| 681 (sit-for 1))) | |
| 682 ((eq def 'act) | |
| 683 (or replaced | |
| 684 (replace-match next-replacement nocasify literal)) | |
| 685 (setq done t replaced t)) | |
| 686 ((eq def 'act-and-exit) | |
| 687 (or replaced | |
| 688 (replace-match next-replacement nocasify literal)) | |
| 689 (setq keep-going nil) | |
| 690 (setq done t replaced t)) | |
| 691 ((eq def 'act-and-show) | |
| 692 (if (not replaced) | |
| 693 (progn | |
| 694 (replace-match next-replacement nocasify literal) | |
| 695 (store-match-data nil) | |
| 696 (setq replaced t)))) | |
| 697 ((eq def 'automatic) | |
| 698 (or replaced | |
| 699 (replace-match next-replacement nocasify literal)) | |
| 700 (setq done t query-flag nil replaced t)) | |
| 701 ((eq def 'skip) | |
| 702 (setq done t)) | |
| 703 ((eq def 'recenter) | |
|
5686
c6b1500299a7
recenter-top-bottom synced from GNU and new default for C-l
Mats Lidell <mats.lidell@cag.se>
parents:
5473
diff
changeset
|
704 ;; `this-command' has the value `query-replace', |
|
c6b1500299a7
recenter-top-bottom synced from GNU and new default for C-l
Mats Lidell <mats.lidell@cag.se>
parents:
5473
diff
changeset
|
705 ;; so we need to bind it to `recenter-top-bottom' |
|
c6b1500299a7
recenter-top-bottom synced from GNU and new default for C-l
Mats Lidell <mats.lidell@cag.se>
parents:
5473
diff
changeset
|
706 ;; to allow it to detect a sequence of `C-l'. |
|
c6b1500299a7
recenter-top-bottom synced from GNU and new default for C-l
Mats Lidell <mats.lidell@cag.se>
parents:
5473
diff
changeset
|
707 (let ((this-command 'recenter-top-bottom) |
|
c6b1500299a7
recenter-top-bottom synced from GNU and new default for C-l
Mats Lidell <mats.lidell@cag.se>
parents:
5473
diff
changeset
|
708 (last-command 'recenter-top-bottom)) |
|
c6b1500299a7
recenter-top-bottom synced from GNU and new default for C-l
Mats Lidell <mats.lidell@cag.se>
parents:
5473
diff
changeset
|
709 (recenter-top-bottom))) |
| 428 | 710 ((eq def 'edit) |
| 711 (store-match-data | |
| 712 (prog1 (match-data) | |
| 713 (save-excursion (recursive-edit)))) | |
| 714 ;; Before we make the replacement, | |
| 715 ;; decide whether the search string | |
| 716 ;; can match again just after this match. | |
| 717 (if regexp-flag | |
| 718 (setq match-again (looking-at search-string)))) | |
| 719 ((eq def 'delete-and-edit) | |
| 720 (delete-region (match-beginning 0) (match-end 0)) | |
| 721 (store-match-data (prog1 (match-data) | |
| 722 (save-excursion (recursive-edit)))) | |
| 723 (setq replaced t)) | |
| 724 ;; Note: we do not need to treat `exit-prefix' | |
| 725 ;; specially here, since we reread | |
| 726 ;; any unrecognized character. | |
| 727 (t | |
| 728 (setq this-command 'mode-exited) | |
| 729 (setq keep-going nil) | |
| 730 (setq unread-command-events | |
| 731 (cons event unread-command-events)) | |
| 732 (setq done t)))) | |
|
5686
c6b1500299a7
recenter-top-bottom synced from GNU and new default for C-l
Mats Lidell <mats.lidell@cag.se>
parents:
5473
diff
changeset
|
733 (unless (eq def 'recenter) |
|
c6b1500299a7
recenter-top-bottom synced from GNU and new default for C-l
Mats Lidell <mats.lidell@cag.se>
parents:
5473
diff
changeset
|
734 ;; Reset recenter cycling order to initial position. |
|
c6b1500299a7
recenter-top-bottom synced from GNU and new default for C-l
Mats Lidell <mats.lidell@cag.se>
parents:
5473
diff
changeset
|
735 (setq recenter-last-op nil)) |
| 428 | 736 ;; Record previous position for ^ when we move on. |
| 737 ;; Change markers to numbers in the match data | |
| 738 ;; since lots of markers slow down editing. | |
| 739 (setq stack | |
| 740 (cons (cons (point) | |
| 741 (or replaced | |
| 742 (match-data t))) | |
| 743 stack)) | |
| 744 (if replaced (setq replace-count (1+ replace-count))))) | |
| 745 (setq lastrepl (point))) | |
| 746 ;; Useless in XEmacs. We handle (de)highlighting through | |
| 747 ;; perform-replace-next-event. | |
| 748 ;(replace-dehighlight) | |
| 749 ) | |
| 750 (or unread-command-events | |
| 751 (message "Replaced %d occurrence%s" | |
| 752 replace-count | |
| 753 (if (= replace-count 1) "" "s"))) | |
| 754 (and keep-going stack))) | |
| 755 | |
| 756 ;; FSFmacs code: someone should port it. | |
| 757 | |
| 758 ;(defvar query-replace-highlight nil | |
| 759 ; "*Non-nil means to highlight words during query replacement.") | |
| 760 | |
| 761 ;(defvar replace-overlay nil) | |
| 762 | |
| 763 ;(defun replace-dehighlight () | |
| 764 ; (and replace-overlay | |
| 765 ; (progn | |
| 766 ; (delete-overlay replace-overlay) | |
| 767 ; (setq replace-overlay nil)))) | |
| 768 | |
| 769 ;(defun replace-highlight (start end) | |
| 770 ; (and query-replace-highlight | |
| 771 ; (progn | |
| 772 ; (or replace-overlay | |
| 773 ; (progn | |
| 774 ; (setq replace-overlay (make-overlay start end)) | |
| 775 ; (overlay-put replace-overlay 'face | |
| 776 ; (if (internal-find-face 'query-replace) | |
| 777 ; 'query-replace 'region)))) | |
| 778 ; (move-overlay replace-overlay start end (current-buffer))))) | |
| 779 | |
| 780 ;;; replace.el ends here |
