Add one dir to magit-repo-dirs
[emacs.git] / .emacs.d / elisp / iedit / iedit.el
1 ;;; iedit.el --- Edit multiple regions in the same way simultaneously.
2
3 ;; Copyright (C) 2010, 2011, 2012 Victor Ren
4
5 ;; Time-stamp: <2013-10-07 11:26:05 Victor Ren>
6 ;; Author: Victor Ren <victorhge@gmail.com>
7 ;; Keywords: occurrence region simultaneous refactoring
8 ;; Version: 0.97
9 ;; X-URL: http://www.emacswiki.org/emacs/Iedit
10 ;; Compatibility: GNU Emacs: 22.x, 23.x, 24.x
11
12 ;; This file is not part of GNU Emacs, but it is distributed under
13 ;; the same terms as GNU Emacs.
14
15 ;; GNU Emacs is free software: you can redistribute it and/or modify
16 ;; it under the terms of the GNU General Public License as published by
17 ;; the Free Software Foundation, either version 3 of the License, or
18 ;; (at your option) any later version.
19
20 ;; GNU Emacs is distributed in the hope that it will be useful,
21 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
22 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 ;; GNU General Public License for more details.
24
25 ;; You should have received a copy of the GNU General Public License
26 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
27
28 ;;; Commentary:
29
30 ;; This package is an Emacs minor mode and allows you to edit one occurrence of
31 ;; some text in a buffer (possibly narrowed) or region, and simultaneously have
32 ;; other occurrences edited in the same way.
33 ;;
34 ;; Normal scenario of iedit-mode is like:
35 ;;
36 ;; - Highlight certain contents - by press C-; (The default binding)
37 ;; All occurrences of a symbol, string in the buffer or a region may be
38 ;; highlighted corresponding to current mark, point and prefix argument.
39 ;; Refer to the document of `iedit-mode' for details.
40 ;;
41 ;; - Edit one of the occurrences
42 ;; The change is applied to other occurrences simultaneously.
43 ;;
44 ;; - Finish - by pressing C-; again
45 ;;
46 ;; You can also use Iedit mode as a quick way to temporarily show only the
47 ;; buffer lines that match the current text being edited. This gives you the
48 ;; effect of a temporary `keep-lines' or `occur'. To get this effect, hit C-'
49 ;; when in Iedit mode - it toggles hiding non-matching lines.
50 ;;
51 ;; Renaming refactoring is convenient in Iedit mode
52 ;;
53 ;; - The symbol under point is selected as occurrence by default and only
54 ;; complete symbols are matched
55 ;; - With digit prefix argument 0, only symbols in current function are matched
56 ;; - Restricting symbols in current region can be done by pressing C-; again
57 ;; - Last renaming refactoring is remembered and can be applied to other buffers
58 ;; later
59 ;;
60 ;; There are also some other facilities you may never think about. Refer to the
61 ;; document of function `iedit-mode' (C-h f iedit-mode RET) for more details.
62
63 ;; The code was developed and fully tested on Gnu Emacs 24.0.93, partially
64 ;; tested on Gnu Emacs 22. If you have any compatible problem, please let me
65 ;; know.
66
67 ;;; todo:
68 ;; - Add more easy access keys for whole occurrence
69
70 ;;; Contributors
71 ;; Adam Lindberg <eproxus@gmail.com> added a case sensitivity option that can be toggled.
72
73 ;; Tassilo Horn <tassilo@member.fsf.org> added an option to match only complete
74 ;; words, not inside words
75
76 ;; Le Wang <l26wang@gmail.com> proposed to match only complete symbols, not
77 ;; inside symbols, contributed rectangle support
78
79 ;;; Code:
80
81 (eval-when-compile (require 'cl))
82 (require 'iedit-lib)
83
84 (defcustom iedit-current-symbol-default t
85 "If no-nil, use current symbol by default for the occurrence."
86 :type 'boolean
87 :group 'iedit)
88
89 (defcustom iedit-only-at-symbol-boundaries t
90 "If no-nil, matches have to start and end at symbol boundaries.
91 For example, when invoking command `iedit-mode' on the \"in\" in the
92 sentence \"The king in the castle...\", the \"king\" is not
93 edited."
94 :type 'boolean
95 :group 'iedit)
96
97 (defcustom iedit-toggle-key-default (kbd "C-;")
98 "If no-nil, the key is inserted into global-map, isearch-mode-map, esc-map and help-map."
99 :type 'vector
100 :group 'iedit)
101
102 (defvar iedit-mode-hook nil
103 "Function(s) to call after starting up an iedit.")
104
105 (defvar iedit-mode-end-hook nil
106 "Function(s) to call after terminating an iedit.")
107
108 (defvar iedit-mode nil) ;; Name of the minor mode
109
110 (defvar iedit-only-complete-symbol-local nil
111 "This is buffer local variable which indicates the occurrence
112 only matches complete symbol.")
113
114 (defvar iedit-only-complete-symbol-global nil
115 "This is global variable which indicates the last global occurrence
116 only matches complete symbol.")
117
118 (defvar iedit-last-occurrence-local nil
119 "This is buffer local variable which is the occurrence when
120 Iedit mode is turned off last time.")
121
122 (defvar iedit-last-occurrence-global nil
123 "This is global variable which is the occurrence when
124 Iedit mode is turned off last time.")
125
126 (defvar iedit-last-initial-string-global nil
127 "This is a global variable which is the last initial occurrence string.")
128
129 (defvar iedit-initial-string-local nil
130 "This is buffer local variable which is the initial string to start Iedit mode.")
131 (defvar iedit-initial-region nil
132 "This is buffer local variable which is the initial region
133 where Iedit mode is started from.")
134
135 (defvar iedit-num-lines-to-expand-up 0
136 "This is a global variable indicating how many lines up from
137 point should be included in the replacement region.")
138
139 (defvar iedit-num-lines-to-expand-down 0
140 "This is a global variable indicating how many lines down from
141 point should be included in the replacement region.")
142
143 (defvar iedit-current-symbol '(lambda () (current-word t))
144 "This is a function which returns a string as occurrence candidate.
145 This local buffer varialbe can be configured in some modes.
146 An example of how to use this variable: todo")
147
148 (make-variable-buffer-local 'iedit-mode)
149 (make-variable-buffer-local 'iedit-only-complete-symbol-local)
150 (make-variable-buffer-local 'iedit-last-occurrence-local)
151 (make-variable-buffer-local 'iedit-initial-string-local)
152 (make-variable-buffer-local 'iedit-initial-region)
153 (make-variable-buffer-local 'iedit-current-symbol)
154
155 (or (assq 'iedit-mode minor-mode-alist)
156 (nconc minor-mode-alist
157 (list '(iedit-mode iedit-mode))))
158
159 ;;; Define iedit help map.
160 (eval-when-compile (require 'help-macro))
161
162 (defvar iedit-help-map
163 (let ((map (make-sparse-keymap)))
164 (define-key map (char-to-string help-char) 'iedit-help-for-help)
165 (define-key map [help] 'iedit-help-for-help)
166 (define-key map [f1] 'iedit-help-for-help)
167 (define-key map "?" 'iedit-help-for-help)
168 (define-key map "b" 'iedit-describe-bindings)
169 (define-key map "k" 'iedit-describe-key)
170 (define-key map "m" 'iedit-describe-mode)
171 (define-key map "q" 'help-quit)
172 map)
173 "Keymap for characters following the Help key for Iedit mode.")
174
175 (make-help-screen
176 iedit-help-for-help-internal
177 (purecopy "Type a help option: [bkm] or ?")
178 "You have typed %THIS-KEY%, the help character. Type a Help option:
179 \(Type \\<help-map>\\[help-quit] to exit the Help command.)
180
181 b Display all Iedit key bindings.
182 k KEYS Display full documentation of Iedit key sequence.
183 m Display documentation of Iedit mode.
184
185 You can't type here other help keys available in the global help map,
186 but outside of this help window when you type them in Iedit mode,
187 they exit Iedit mode before displaying global help."
188 iedit-help-map)
189
190 (defun iedit-help-for-help ()
191 "Display Iedit help menu."
192 (interactive)
193 (let (same-window-buffer-names same-window-regexps)
194 (iedit-help-for-help-internal)))
195
196 (defun iedit-describe-bindings ()
197 "Show a list of all keys defined in Iedit mode, and their definitions.
198 This is like `describe-bindings', but displays only Iedit keys."
199 (interactive)
200 (let (same-window-buffer-names
201 same-window-regexps
202 (keymap (substitute-command-keys "\\{iedit-mode-keymap}\\{iedit-mode-occurrence-keymap}")))
203 (with-help-window "*Help*"
204 (with-current-buffer standard-output
205 (princ "Iedit Mode Bindings: ")
206 (princ keymap)))))
207
208 (defun iedit-describe-key ()
209 "Display documentation of the function invoked by Iedit mode key."
210 (interactive)
211 (let (same-window-buffer-names same-window-regexps)
212 (call-interactively 'describe-key)))
213
214 (defun iedit-describe-mode ()
215 "Display documentation of Iedit mode."
216 (interactive)
217 (let (same-window-buffer-names same-window-regexps)
218 (describe-function 'iedit-mode)))
219
220 ;;; Default key bindings:
221 (when iedit-toggle-key-default
222 (define-key global-map iedit-toggle-key-default 'iedit-mode)
223 (define-key isearch-mode-map iedit-toggle-key-default 'iedit-mode-from-isearch)
224 (define-key esc-map iedit-toggle-key-default 'iedit-execute-last-modification)
225 (define-key help-map iedit-toggle-key-default 'iedit-mode-toggle-on-function))
226
227 ;; Avoid to restore Iedit mode when restoring desktop
228 (add-to-list 'desktop-minor-mode-handlers
229 '(iedit-mode . nil))
230
231 ;;; Define iedit help map.
232 (eval-when-compile (require 'help-macro))
233
234 (defvar iedit-mode-occurrence-keymap
235 (let ((map (make-sparse-keymap)))
236 (set-keymap-parent map iedit-occurrence-keymap-default)
237 (define-key map (kbd "M-H") 'iedit-restrict-function)
238 (define-key map (kbd "M-I") 'iedit-restrict-current-line)
239 (define-key map (kbd "M-{") 'iedit-expand-up-a-line)
240 (define-key map (kbd "M-}") 'iedit-expand-down-a-line)
241 (define-key map (kbd "M-G") 'iedit-apply-global-modification)
242 (define-key map (kbd "M-C") 'iedit-toggle-case-sensitive)
243 map)
244 "Keymap used within overlays in Iedit mode.")
245
246 (defvar iedit-mode-keymap
247 (let ((map (make-sparse-keymap)))
248 (set-keymap-parent map iedit-lib-keymap)
249 (define-key map (char-to-string help-char) iedit-help-map)
250 (define-key map [help] iedit-help-map)
251 (define-key map [f1] iedit-help-map)
252 (define-key map (kbd "M-;") 'iedit-toggle-selection)
253 map)
254 "Keymap used while Iedit mode is enabled.")
255
256 ;;; Define Iedit mode map
257 (or (assq 'iedit-mode minor-mode-map-alist)
258 (setq minor-mode-map-alist
259 (cons (cons 'iedit-mode iedit-mode-keymap) minor-mode-map-alist)))
260
261 ;; Avoid to restore Iedit mode when restoring desktop
262 (add-to-list 'desktop-minor-mode-handlers
263 '(iedit-mode . nil))
264
265 ;;;###autoload
266 (defun iedit-mode (&optional arg)
267 "Toggle Iedit mode.
268 This command behaves differently, depending on the mark, point,
269 prefix argument and variable `iedit-transient-mark-sensitive'.
270
271 If Iedit mode is off, turn Iedit mode on.
272
273 When Iedit mode is turned on, all the occurrences of the current
274 region in the buffer (possibly narrowed) or a region are
275 highlighted. If one occurrence is modified, the change are
276 propagated to all other occurrences simultaneously.
277
278 If region is not active, the current symbol (returns from
279 `iedit-current-symbol') is used as the occurrence by default.
280 The occurrences of the current symbol, but not include
281 occurrences that are part of other symbols, are highlighted. If
282 you still want to match all the occurrences, even though they are
283 parts of other symbols, you may have to mark the symbol first.
284
285 In the above two situations, with digit prefix argument 0, only
286 occurrences in current function are matched. This is good for
287 renaming refactoring in programming.
288
289 You can also switch to Iedit mode from isearch mode directly. The
290 current search string is used as occurrence. All occurrences of
291 the current search string are highlighted.
292
293 With an universal prefix argument, the occurrence when Iedit mode
294 is turned off last time in current buffer is used as occurrence.
295 This is intended to recover last Iedit mode which is turned off.
296 If region active, Iedit mode is limited within the current
297 region.
298
299 With repeated universal prefix argument, the occurrence when
300 Iedit mode is turned off last time (might be in other buffer) is
301 used as occurrence. If region active, Iedit mode is limited
302 within the current region.
303
304 If Iedit mode is on and region is active, Iedit mode is
305 restricted in the region, e.g. the occurrences outside of the
306 region is excluded.
307
308 If Iedit mode is on and region is active, with an universal
309 prefix argument, Iedit mode is restricted outside of the region,
310 e.g. the occurrences in the region is excluded.
311
312 Turn off Iedit mode in other situations.
313
314 Commands:
315 \\{iedit-mode-keymap}
316 Keymap used within overlays:
317 \\{iedit-mode-occurrence-keymap}"
318 (interactive "P")
319 (if iedit-mode
320 (progn
321 (iedit-mode-on-action arg)
322 (setq iedit-only-complete-symbol-global iedit-only-complete-symbol-local))
323 (iedit-barf-if-lib-active)
324 (let (occurrence
325 complete-symbol
326 (beg (if (eq major-mode 'occur-edit-mode) ; skip the first occurrence
327 (next-single-char-property-change 1 'read-only)
328 (point-min)))
329 (end (point-max)))
330 (cond ((and arg
331 (= 4 (prefix-numeric-value arg))
332 iedit-last-occurrence-local)
333 (setq occurrence iedit-last-occurrence-local)
334 (setq complete-symbol iedit-only-complete-symbol-local))
335 ((and arg
336 (= 16 (prefix-numeric-value arg))
337 iedit-last-initial-string-global)
338 (setq occurrence iedit-last-initial-string-global)
339 (setq complete-symbol iedit-only-complete-symbol-global))
340 ((iedit-region-active)
341 (setq occurrence (buffer-substring-no-properties
342 (mark) (point))))
343 ((and iedit-current-symbol-default
344 (setq occurrence (funcall iedit-current-symbol)))
345 (when iedit-only-at-symbol-boundaries
346 (setq complete-symbol t)))
347 (t (error "No candidate of the occurrence, cannot enable Iedit mode")))
348 (when arg
349 (if (= 0 (prefix-numeric-value arg))
350 (save-excursion
351 (mark-defun)
352 (setq beg (region-beginning))
353 (setq end (region-end)))
354 (when (iedit-region-active)
355 (setq beg (region-beginning))
356 (setq end (region-end)))))
357 (setq iedit-only-complete-symbol-local complete-symbol)
358 (setq mark-active nil)
359 (run-hooks 'deactivate-mark-hook)
360 (setq iedit-initial-string-local occurrence)
361 (iedit-start (iedit-regexp-quote occurrence) beg end))))
362
363 (defun iedit-mode-from-isearch (regexp)
364 "Start Iedit mode using last search string as the regexp."
365 (interactive
366 (let ((regexp (cond
367 ((functionp isearch-word)
368 (funcall isearch-word isearch-string))
369 (isearch-word (word-search-regexp isearch-string))
370 (isearch-regexp isearch-string)
371 (t (regexp-quote isearch-string)))))
372 (list regexp)))
373 (or isearch-success
374 (error "No match" ))
375 (if (or isearch-regexp isearch-word)
376 nil
377 (setq iedit-initial-string-local isearch-string))
378 (let ((iedit-case-sensitive (not isearch-case-fold-search)))
379 (isearch-exit)
380 (setq mark-active nil)
381 (run-hooks 'deactivate-mark-hook)
382 (when iedit-mode
383 (iedit-cleanup))
384 (iedit-start regexp (point-min) (point-max))
385 ;; TODO: reconsider how to avoid the loop in iedit-same-length
386 (cond ((not iedit-occurrences-overlays)
387 (message "No matches found")
388 (iedit-done))
389 ((not (iedit-same-length))
390 (message "Matches are not the same length.")
391 (iedit-done)))))
392
393 (defun iedit-start (occurrence-regexp beg end)
394 "Start Iedit mode for the `occurrence-regexp' in the current buffer."
395
396 ;; enforce skip modification once, errors may happen to cause this to be
397 ;; unset.
398 (setq iedit-skip-modification-once t)
399 (setq iedit-unmatched-lines-invisible iedit-unmatched-lines-invisible-default)
400 (setq iedit-initial-region (list beg end))
401 (message "%d matches for \"%s\""
402 (iedit-start2 occurrence-regexp beg end)
403 (iedit-printable occurrence-regexp))
404 (run-hooks 'iedit-mode-hook)
405 (add-hook 'kbd-macro-termination-hook 'iedit-done nil t)
406 (add-hook 'change-major-mode-hook 'iedit-done nil t)
407 (add-hook 'iedit-aborting-hook 'iedit-done nil t))
408
409 (defun iedit-regexp-quote (exp)
410 "Return a regexp string."
411 (if iedit-only-complete-symbol-local
412 (concat "\\_<" (regexp-quote exp) "\\_>")
413 (regexp-quote exp)))
414
415 (defun iedit-start2 (occurrence-regexp beg end)
416 "Refresh Iedit mode."
417 (setq iedit-occurrence-keymap iedit-mode-occurrence-keymap)
418 (let ((counter(iedit-make-occurrences-overlays occurrence-regexp beg end)))
419 (setq iedit-mode
420 (propertize
421 (concat " Iedit:" (number-to-string counter))
422 'face
423 'font-lock-warning-face))
424 (force-mode-line-update)
425 counter))
426
427 (defun iedit-done ()
428 "Exit Iedit mode.
429 Save the current occurrence string locally and globally. Save
430 the initial string globally."
431 (when iedit-buffering
432 (iedit-stop-buffering))
433 (setq iedit-last-occurrence-local (iedit-current-occurrence-string))
434 (setq iedit-last-occurrence-global iedit-last-occurrence-local)
435 (setq iedit-last-initial-string-global iedit-initial-string-local)
436 (if iedit-last-occurrence-local
437 (kill-new iedit-last-occurrence-local)) ; Make occurrence the latest kill in the kill ring.
438 (setq iedit-num-lines-to-expand-up 0)
439 (setq iedit-num-lines-to-expand-down 0)
440
441 (iedit-cleanup)
442
443 (setq iedit-initial-string-local nil)
444 (setq iedit-mode nil)
445 (force-mode-line-update)
446 (remove-hook 'kbd-macro-termination-hook 'iedit-done t)
447 (remove-hook 'change-major-mode-hook 'iedit-done t)
448 (remove-hook 'iedit-aborting-hook 'iedit-done t)
449 (run-hooks 'iedit-mode-end-hook))
450
451 (defun iedit-mode-on-action (&optional arg)
452 "Turn off Iedit mode or restrict it in a region if region is active."
453 (if (iedit-region-active)
454 ;; Restrict iedit-mode
455 (let ((beg (region-beginning))
456 (end (region-end)))
457 (if (null (iedit-find-overlay beg end 'iedit-occurrence-overlay-name arg))
458 (iedit-done)
459 (iedit-restrict-region beg end arg)))
460 (iedit-done)))
461
462
463 ;;;###autoload
464 (defun iedit-mode-toggle-on-function ()
465 "Toggle Iedit mode on current function."
466 (interactive)
467 (iedit-mode 0))
468
469 (defun iedit-execute-last-modification (&optional arg)
470 "Apply last modification in Iedit mode to the current buffer or an active region."
471 (interactive "*P")
472 (or (and iedit-last-initial-string-global
473 (not (string= iedit-last-initial-string-global iedit-last-occurrence-global)))
474 (error "No modification available"))
475 (let ((occurrence-exp (regexp-quote iedit-last-initial-string-global))
476 (replacement iedit-last-occurrence-global)
477 (case-fold-search (not iedit-case-sensitive))
478 beg end)
479 (when case-fold-search
480 (setq occurrence-exp (downcase occurrence-exp))
481 (setq replacement (downcase replacement)))
482 (if iedit-only-complete-symbol-global
483 (setq occurrence-exp (concat "\\_<" occurrence-exp "\\_>")))
484 (when (iedit-region-active)
485 (setq beg (region-beginning))
486 (setq end (region-end)))
487 (perform-replace occurrence-exp replacement t t nil nil nil beg end)))
488
489 (defun iedit-apply-global-modification ()
490 "Apply last global modification."
491 (interactive "*")
492 (if (and iedit-last-initial-string-global
493 (string= iedit-initial-string-local iedit-last-initial-string-global)
494 (not (string= iedit-last-initial-string-global iedit-last-occurrence-global)))
495 (iedit-replace-occurrences iedit-last-occurrence-global)
496 (message "No global modification available.")))
497
498 (defun iedit-toggle-selection ()
499 "Select or deselect the occurrence under point."
500 (interactive)
501 (iedit-barf-if-buffering)
502 (let ((ov (iedit-find-current-occurrence-overlay)))
503 (if ov
504 (iedit-restrict-region (overlay-start ov) (overlay-end ov) t)
505 (let ((current-occurrence-string (iedit-current-occurrence-string)))
506 (when (not (null current-occurrence-string))
507 (save-excursion
508 (goto-char (if (> (point) (length current-occurrence-string))
509 ( - (point) (length current-occurrence-string))
510 (point-min)))
511 (iedit-add-next-occurrence-overlay
512 (iedit-regexp-quote current-occurrence-string)))
513 (setq iedit-mode (propertize
514 (concat " Iedit:" (number-to-string
515 (length iedit-occurrences-overlays)))
516 'face 'font-lock-warning-face))
517 (force-mode-line-update))))))
518
519 (defun iedit-restrict-function(&optional arg)
520 "Restricting Iedit mode in current function."
521 (interactive "P")
522 (save-excursion
523 (mark-defun)
524 (iedit-restrict-region (region-beginning) (region-end) arg))
525 (message "Restricted in current function, %d matches."
526 (length iedit-occurrences-overlays)))
527
528 (defun iedit-restrict-current-line ()
529 "Restrict Iedit mode to current line."
530 (interactive)
531 (iedit-restrict-region (iedit-char-at-bol) (iedit-char-at-eol))
532 (message "Restricted to current line, %d match%s."
533 (length iedit-occurrences-overlays)
534 (if (= 1 (length iedit-occurrences-overlays)) "" "es")))
535
536 (defun iedit-expand-by-a-line (where amount)
537 "After restricting iedit to the current line with
538 `iedit-restrict-current-line', this function expands the top or
539 bottom of the search region upwards or downwards by `amount'
540 lines. The region being acted upon is controlled with
541 `where' ('top to act on the top, anything else for the
542 bottom). With a prefix, collapses the top or bottom of the search
543 region by `amount' lines."
544 (interactive "P")
545 ;; Since iedit-done resets iedit-num-lines-to-expand-{down,up}, we
546 ;; have to hang on to them in tmp variables
547 (let ((tmp-up iedit-num-lines-to-expand-up)
548 (tmp-down iedit-num-lines-to-expand-down)
549 ;; we want to call iedit-mode with a universal prefix arg
550 (current-prefix-arg '(4)))
551 (iedit-done)
552 (call-interactively 'iedit-mode)
553 (setq iedit-num-lines-to-expand-up tmp-up)
554 (setq iedit-num-lines-to-expand-down tmp-down)
555 (if (eq where 'top)
556 (setq iedit-num-lines-to-expand-up (max 0
557 (+ amount iedit-num-lines-to-expand-up)))
558 (setq iedit-num-lines-to-expand-down (max 0
559 (+ amount iedit-num-lines-to-expand-down))))
560 (iedit-restrict-region (iedit-char-at-bol (- iedit-num-lines-to-expand-up))
561 (iedit-char-at-eol iedit-num-lines-to-expand-down))
562 (message "Now looking -%d/+%d lines around current line, %d match%s."
563 iedit-num-lines-to-expand-up
564 iedit-num-lines-to-expand-down
565 (length iedit-occurrences-overlays)
566 (if (= 1 (length iedit-occurrences-overlays)) "" "es"))))
567
568 (defun iedit-expand-up-a-line (&optional arg)
569 "After restricting iedit to the current line with
570 `iedit-restrict-current-line', this function expands the search
571 region upwards by one line. With a prefix, bring the top of the
572 region back down one line."
573 (interactive "P")
574 (iedit-expand-by-a-line 'top
575 (if arg -1 1)))
576
577 (defun iedit-expand-down-a-line (&optional arg)
578 "After restricting iedit to the current line with
579 `iedit-restrict-current-line', this function expands the search
580 region downwards by one line. With a prefix, bring the bottom of
581 the region back up one line."
582 (interactive "P")
583 (iedit-expand-by-a-line 'bottom
584 (if arg -1 1)))
585
586 (defun iedit-restrict-region (beg end &optional inclusive)
587 "Restricting Iedit mode in a region."
588 (when iedit-buffering
589 (iedit-stop-buffering))
590 (setq iedit-last-occurrence-local (iedit-current-occurrence-string))
591 (setq mark-active nil)
592 (run-hooks 'deactivate-mark-hook)
593 (iedit-show-all)
594 (iedit-cleanup-occurrences-overlays beg end inclusive)
595 (if iedit-unmatched-lines-invisible
596 (iedit-hide-unmatched-lines iedit-occurrence-context-lines))
597 (setq iedit-mode (propertize
598 (concat " Iedit:" (number-to-string
599 (length iedit-occurrences-overlays)))
600 'face 'font-lock-warning-face))
601 (force-mode-line-update))
602
603 (defun iedit-toggle-case-sensitive ()
604 "Toggle case-sensitive matching occurrences. "
605 (interactive)
606 (setq iedit-case-sensitive (not iedit-case-sensitive))
607 (if iedit-buffering
608 (iedit-stop-buffering))
609 (setq iedit-last-occurrence-local (iedit-current-occurrence-string))
610 (when iedit-last-occurrence-local
611 (remove-overlays nil nil iedit-occurrence-overlay-name t)
612 (iedit-show-all)
613 (let* ((occurrence-regexp (iedit-regexp-quote iedit-last-occurrence-local))
614 (begin (car iedit-initial-region))
615 (end (cadr iedit-initial-region))
616 (counter (iedit-start2 occurrence-regexp begin end)))
617 (message "iedit %s. %d matches for \"%s\""
618 (if iedit-case-sensitive
619 "is case sensitive"
620 "ignores case")
621 counter
622 (iedit-printable occurrence-regexp)))))
623
624 (provide 'iedit)
625
626 ;;; iedit.el ends here
627
628 ;; LocalWords: iedit el MERCHANTABILITY kbd isearch todo ert Lindberg Tassilo
629 ;; LocalWords: eval defgroup defcustom boolean defvar assq alist nconc
630 ;; LocalWords: substring cadr keymap defconst purecopy bkm defun princ prev
631 ;; LocalWords: iso lefttab backtab upcase downcase concat setq autoload arg
632 ;; LocalWords: refactoring propertize cond goto nreverse progn rotatef eq elp
633 ;; LocalWords: dolist pos unmatch args ov sReplace iedit's cdr quote'ed