Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 934 lines (824 sloc) 39.088 kb
8219304 @victorhge Fix problem when iedit-stop-buffering is called when current point is…
authored
1 ;;; iedit.el --- Edit multiple regions in one buffer simultaneously.
e9a9485 updates
anybody authored
2
02946e0 @victorhge Update contributors and spell check
authored
3 ;; Copyright (C) 2010, 2011, 2012 Victor Ren
e9a9485 updates
anybody authored
4
d872cb7 @victorhge Update comments for restricting
authored
5 ;; Time-stamp: <2012-02-20 14:29:08 Victor Ren>
e9a9485 updates
anybody authored
6 ;; Author: Victor Ren <victorhge@gmail.com>
7 ;; Keywords: occurrence region replace simultaneous
799a0d1 @victorhge Bump to version 0.94
authored
8 ;; Version: 0.94
9 ;; X-URL: http://www.emacswiki.org/emacs/Iedit
5ad28b5 updates
anybody authored
10 ;; Compatibility: GNU Emacs: 22.x, 23.x, 24.x
e9a9485 updates
anybody authored
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
d2a6e16 @victorhge Update commentary with rectangle support
authored
30 ;; This package provides a more intuitive way of replace-string operation.
31 ;; Normal scenario of iedit-mode is like:
32
e9a9485 updates
anybody authored
33 ;; - Start iedit minor mode - by press C-;
d2a6e16 @victorhge Update commentary with rectangle support
authored
34 ;; The target contents (all occurrences of a symbol, string or a rectangle) in
35 ;; the buffer are highlighted. The content varies corresponding to mark,
36 ;; point and prefix. Refer to the comments of `iedit-mode'.
e9a9485 updates
anybody authored
37 ;;
38 ;; - Edit one of the contents
39 ;; The change is applied to other contents simultaneously
40 ;;
41 ;; - Finish - by pressing C-; again
42
e568677 @victorhge Add new functionality: restrict iedit-mode in region
authored
43 ;; If you would like to operate on certain region, just mark the region and
44 ;; press "C-;" again when iedit mode is active. Or use "narrowing" first when
45 ;; iedit mode is not active.
e9a9485 updates
anybody authored
46
d2a6e16 @victorhge Update commentary with rectangle support
authored
47 ;; With several lines of additional code, the package also provides rectangle
e568677 @victorhge Add new functionality: restrict iedit-mode in region
authored
48 ;; support with visible rectangle highlighting, which is similar with `cua-rect'.
e9a9485 updates
anybody authored
49
50 ;;; Suggested key bindings:
51 ;;
52 ;; (define-key global-map (kbd "C-;") 'iedit-mode)
53 ;; (define-key isearch-mode-map (kbd "C-;") 'iedit-mode)
54
55 ;;; todo:
9b3aaa8 @victorhge Fix occurrence from history does not exist problem
authored
56 ;; - Add more easy access keys for whole occurrence
ec6785b @victorhge host on git
authored
57 ;; - ert unit test
e9a9485 updates
anybody authored
58
ec6785b @victorhge host on git
authored
59 ;;; Contributors
60 ;; Adam Lindberg <eproxus@gmail.com> added a case sensitivity option that can be toggled.
02946e0 @victorhge Update contributors and spell check
authored
61
62 ;; Tassilo Horn <tassilo@member.fsf.org> added an option to match only complete
63 ;; words, not inside words
64
3bca7e2 @victorhge Fix iedit toggle case-sensitive problem when getting occurrence from …
authored
65 ;; Le Wang <l26wang@gmail.com> proposed to match only complete symbols, not
e99e65f @victorhge Fix current point move problem when call iedit-replace-occurrences.
authored
66 ;; inside symbols, contributed rectangle support
ec6785b @victorhge host on git
authored
67
e9a9485 updates
anybody authored
68 ;;; Code:
69
70 (eval-when-compile (require 'cl))
a8cbb68 @victorhge Add iedit-kill-rectangle to iedit-rect mode and adjust keymap help
authored
71 (require 'rect) ;; kill rectangle
e9a9485 updates
anybody authored
72
73 (defgroup iedit nil
74 "Edit multiple regions with the same content simultaneously."
75 :prefix "iedit-"
76 :group 'replace
77 :group 'convenience)
78
79 (defcustom iedit-occurrence-face 'highlight
80 "*Face used for the occurrences' default values."
81 :type 'face
82 :group 'iedit)
83
fc71952 @victorhge Boolean `t'
authored
84 (defcustom iedit-current-symbol-default t
f808bf1 @victorhge Merge from lewang/master and update comments
authored
85 "If no-nil, use current symbol by default for the occurrence."
e9a9485 updates
anybody authored
86 :type 'boolean
87 :group 'iedit)
88
fc71952 @victorhge Boolean `t'
authored
89 (defcustom iedit-case-sensitive-default t
5ad28b5 updates
anybody authored
90 "If no-nil, matching is case sensitive"
91 :type 'boolean
92 :group 'iedit)
93
f808bf1 @victorhge Merge from lewang/master and update comments
authored
94 (defcustom iedit-only-at-symbol-boundaries t
95 "If no-nil, matches have to start and end at symbol boundaries.
da0a247 @tsdh Add option to match only complete words, not inside words
tsdh authored
96 For example, when invoking iedit-mode on the \"in\" in the
97 sentence \"The king in the castle...\", the \"king\" is not
98 edited."
99 :type 'boolean
100 :group 'iedit)
101
e9a9485 updates
anybody authored
102 (defcustom iedit-unmatched-lines-invisible-default nil
9a891d7 updates
anybody authored
103 "If no-nil, hide lines that do not cover any occurrences by
104 default."
e9a9485 updates
anybody authored
105 :type 'boolean
106 :group 'iedit)
107
108 (defvar iedit-mode-hook nil
109 "Function(s) to call after starting up an iedit.")
110
111 (defvar iedit-mode-end-hook nil
112 "Function(s) to call after terminating an iedit.")
113
114 (defvar iedit-mode nil) ;; Name of the minor mode
115
116 (make-variable-buffer-local 'iedit-mode)
117
118 (or (assq 'iedit-mode minor-mode-alist)
119 (nconc minor-mode-alist
9bc57d2 @victorhge make iedit-skipped-modification-once buffer local
authored
120 (list '(iedit-mode iedit-mode))))
e9a9485 updates
anybody authored
121
122 (defvar iedit-occurrences-overlays nil
9a891d7 updates
anybody authored
123 "The occurrences slot contains a list of overlays used to
124 indicate the position of each occurrence. In addition, the
125 occurrence overlay is used to provide a different face
126 configurable via `iedit-occurrence-face'.")
e9a9485 updates
anybody authored
127
6e49225 @victorhge Add iedit-toggle-case-sensitive
authored
128 (defvar iedit-case-sensitive iedit-case-sensitive-default
5ad28b5 updates
anybody authored
129 "This is buffer local variable. If no-nil, matching is case
130 sensitive.")
131
e9a9485 updates
anybody authored
132 (defvar iedit-unmatched-lines-invisible nil
9a891d7 updates
anybody authored
133 "This is buffer local variable which indicates whether
134 unmatched lines are hided.")
e9a9485 updates
anybody authored
135
136 (defvar iedit-last-occurrence-in-history nil
137 "This is buffer local variable which is the occurrence when
9a891d7 updates
anybody authored
138 iedit mode is turned off last time.")
139
3bca7e2 @victorhge Fix iedit toggle case-sensitive problem when getting occurrence from …
authored
140 (defvar iedit-occurrence-is-complete-symbol nil
0edc86f @victorhge Fix the last occurrence problem when it is a complete symbol.
authored
141 "This is buffer local variable which indicates the occurrence
142 only matches complete symbol.")
143
9a891d7 updates
anybody authored
144 (defvar iedit-forward-success t
039c0e2 @victorhge Postpone iedit-done after commands are excuted.
authored
145 "This is buffer local variable which indicates the moving
9a891d7 updates
anybody authored
146 forward or backward successful")
e9a9485 updates
anybody authored
147
c8dac6b @victorhge exit iedit mode when change is not inside of occurrence.
authored
148 (defvar iedit-before-modification-string ""
149 "This is buffer local variable which is the buffer substring that is going to be changed.")
d4b9fd5 @victorhge don't call hooks when there is only text properites change
authored
150
c53a885 @victorhge Add bufferring modification functionalities
authored
151 (defvar iedit-before-modification-undo-list nil
152 "This is buffer local variable which is the buffer undo list before modification.")
61689f6 @victorhge Add arg handle for iedit-mode to exclude some occurrences.
authored
153
039c0e2 @victorhge Postpone iedit-done after commands are excuted.
authored
154 ;; `iedit-occurrence-update' gets called twice when change==0 and occurrence
a75c446 fix bug with autopair and iedit-rect
Le Wang authored
155 ;; is zero-width (beg==end)
039c0e2 @victorhge Postpone iedit-done after commands are excuted.
authored
156 ;; -- for front and back insertion.
a75c446 fix bug with autopair and iedit-rect
Le Wang authored
157 (defvar iedit-skipped-modification-once nil
158 "Variable used to skip first modification hook run when insertion against a zero-width occurrence.")
039c0e2 @victorhge Postpone iedit-done after commands are excuted.
authored
159
160 (defvar iedit-aborting nil
161 "This is buffer local variable which indicates iedit-mode is aborting.")
162
c53a885 @victorhge Add bufferring modification functionalities
authored
163 (defvar iedit-buffering nil
164 "This is buffer local variable which indicates iedit-mode is
165 buffering, which means the modification to the current
166 occurrence is not applied to other occurrences when it is true.")
167
a8cbb68 @victorhge Add iedit-kill-rectangle to iedit-rect mode and adjust keymap help
authored
168 (defvar iedit-rectangle nil
87053a3 @victorhge Remove two buffer local variables for rectangle.
authored
169 "This buffer local variable which is the rectangle geometry if
170 current mode is iedit-rect. Otherwise it is nil.
171 (car iedit-rectangle) is the top-left corner and
172 (cadr iedit-rectangle) is the bottom-right corner" )
a8cbb68 @victorhge Add iedit-kill-rectangle to iedit-rect mode and adjust keymap help
authored
173
e568677 @victorhge Add new functionality: restrict iedit-mode in region
authored
174 (defvar iedit-current-keymap nil)
a8cbb68 @victorhge Add iedit-kill-rectangle to iedit-rect mode and adjust keymap help
authored
175
4e31d50 @victorhge Add a prefix arg handling to iedit-toggle-unmatched-lines-visible
authored
176 (defvar iedit-occurrence-context-lines 0
177 "The number of lines before or after the occurrence.")
178
e9a9485 updates
anybody authored
179 (make-variable-buffer-local 'iedit-occurrences-overlays)
180 (make-variable-buffer-local 'iedit-unmatched-lines-invisible)
5ad28b5 updates
anybody authored
181 (make-variable-buffer-local 'iedit-case-sensitive)
9a891d7 updates
anybody authored
182 (make-variable-buffer-local 'iedit-last-occurrence-in-history)
183 (make-variable-buffer-local 'iedit-forward-success)
c8dac6b @victorhge exit iedit mode when change is not inside of occurrence.
authored
184 (make-variable-buffer-local 'iedit-before-modification-string)
c53a885 @victorhge Add bufferring modification functionalities
authored
185 (make-variable-buffer-local 'iedit-before-modification-undo-list)
9bc57d2 @victorhge make iedit-skipped-modification-once buffer local
authored
186 (make-variable-buffer-local 'iedit-skipped-modification-once)
039c0e2 @victorhge Postpone iedit-done after commands are excuted.
authored
187 (make-variable-buffer-local 'iedit-aborting)
c53a885 @victorhge Add bufferring modification functionalities
authored
188 (make-variable-buffer-local 'iedit-buffering)
a8cbb68 @victorhge Add iedit-kill-rectangle to iedit-rect mode and adjust keymap help
authored
189 (make-variable-buffer-local 'iedit-rectangle)
190 (make-variable-buffer-local 'iedit-current-keymap)
4e31d50 @victorhge Add a prefix arg handling to iedit-toggle-unmatched-lines-visible
authored
191 (make-variable-buffer-local 'iedit-occurrence-context-lines)
e9a9485 updates
anybody authored
192
193 (defconst iedit-occurrence-overlay-name 'iedit-occurrence-overlay-name)
194 (defconst iedit-invisible-overlay-name 'iedit-invisible-overlay-name)
5ad28b5 updates
anybody authored
195
196 ;;; Define iedit help map.
197 (eval-when-compile (require 'help-macro))
198
199 (defvar iedit-help-map
200 (let ((map (make-sparse-keymap)))
201 (define-key map (char-to-string help-char) 'iedit-help-for-help)
202 (define-key map [help] 'iedit-help-for-help)
203 (define-key map [f1] 'iedit-help-for-help)
204 (define-key map "?" 'iedit-help-for-help)
205 (define-key map "b" 'iedit-describe-bindings)
206 (define-key map "k" 'iedit-describe-key)
207 (define-key map "m" 'iedit-describe-mode)
208 (define-key map "q" 'help-quit)
209 map)
210 "Keymap for characters following the Help key for iedit mode.")
211
9bc57d2 @victorhge make iedit-skipped-modification-once buffer local
authored
212 (make-help-screen
213 iedit-help-for-help-internal
214 (purecopy "Type a help option: [bkm] or ?")
215 "You have typed %THIS-KEY%, the help character. Type a Help option:
5ad28b5 updates
anybody authored
216 \(Type \\<help-map>\\[help-quit] to exit the Help command.)
217
218 b Display all Iedit key bindings.
219 k KEYS Display full documentation of Iedit key sequence.
220 m Display documentation of Iedit mode.
221
222 You can't type here other help keys available in the global help map,
223 but outside of this help window when you type them in Iedit mode,
224 they exit Iedit mode before displaying global help."
9bc57d2 @victorhge make iedit-skipped-modification-once buffer local
authored
225 iedit-help-map)
5ad28b5 updates
anybody authored
226
227 (defun iedit-help-for-help ()
228 "Display Iedit help menu."
229 (interactive)
230 (let (same-window-buffer-names same-window-regexps)
231 (iedit-help-for-help-internal)))
232
61689f6 @victorhge Add arg handle for iedit-mode to exclude some occurrences.
authored
233 ;; todo: this function does not work
5ad28b5 updates
anybody authored
234 (defun iedit-describe-bindings ()
235 "Show a list of all keys defined in Iedit mode, and their definitions.
236 This is like `describe-bindings', but displays only Iedit keys."
237 (interactive)
238 (let (same-window-buffer-names same-window-regexps)
239 (with-help-window "*Help*"
240 (with-current-buffer standard-output
a8cbb68 @victorhge Add iedit-kill-rectangle to iedit-rect mode and adjust keymap help
authored
241 (princ "Iedit Mode Bindings: ")
242 (princ (substitute-command-keys "\\{iedit-current-keymap}"))))))
5ad28b5 updates
anybody authored
243
244 (defun iedit-describe-key ()
245 "Display documentation of the function invoked by iedit key."
246 (interactive)
247 (let (same-window-buffer-names same-window-regexps)
248 (call-interactively 'describe-key)))
249
250 (defun iedit-describe-mode ()
251 "Display documentation of iedit mode."
252 (interactive)
253 (let (same-window-buffer-names same-window-regexps)
254 (describe-function 'iedit-mode)))
255
256 ;;; Define iedit mode map
1d070b7 move init code for iedit-mode-map inside defvar
Le Wang authored
257 (defvar iedit-mode-map
652087d @victorhge fix warning: the function `make-sparse-key-map' is not known to be
authored
258 (let ((map (make-sparse-keymap)))
1d070b7 move init code for iedit-mode-map inside defvar
Le Wang authored
259 ;; Default key bindings
652087d @victorhge fix warning: the function `make-sparse-key-map' is not known to be
authored
260 (define-key map (kbd "TAB") 'iedit-next-occurrence)
261 (define-key map (kbd "<S-tab>") 'iedit-prev-occurrence)
262 (define-key map (kbd "<S-iso-lefttab>") 'iedit-prev-occurrence)
263 (define-key map (kbd "<backtab>") 'iedit-prev-occurrence)
264 (define-key map (kbd "C-'") 'iedit-toggle-unmatched-lines-visible)
265 (define-key map (char-to-string help-char) iedit-help-map)
266 (define-key map [help] iedit-help-map)
267 (define-key map [f1] iedit-help-map)
1d070b7 move init code for iedit-mode-map inside defvar
Le Wang authored
268 map)
e9a9485 updates
anybody authored
269 "Keymap used while iedit mode is enabled.")
270
da47784 @victorhge Add iedit mode easy access keys
authored
271 (defvar iedit-occurrence-local-map
272 (let ((map (make-sparse-keymap)))
273 (set-keymap-parent map iedit-mode-map)
274 (define-key map (kbd "M-u") 'iedit-upcase-occurrences)
275 (define-key map (kbd "M-l") 'iedit-downcase-occurrences)
276 (define-key map (kbd "M-r") 'iedit-replace-occurrences)
6e49225 @victorhge Add iedit-toggle-case-sensitive
authored
277 (define-key map (kbd "M-C") 'iedit-clear-occurrences)
278 (define-key map (kbd "M-c") 'iedit-toggle-case-sensitive)
c53a885 @victorhge Add bufferring modification functionalities
authored
279 (define-key map (kbd "M-D") 'iedit-delete-occurrences)
78f606d @victorhge Add iedit-number-occurrences function
authored
280 (define-key map (kbd "M-N") 'iedit-number-occurrences)
c53a885 @victorhge Add bufferring modification functionalities
authored
281 (define-key map [C-return] 'iedit-toggle-buffering)
7d18e5d @victorhge Add a help command C-? for occurrences
authored
282 (define-key map (kbd "C-?") 'iedit-help-for-occurrences)
da47784 @victorhge Add iedit mode easy access keys
authored
283 map)
a8cbb68 @victorhge Add iedit-kill-rectangle to iedit-rect mode and adjust keymap help
authored
284 "Keymap used within overlays in iedit mode.")
285
286 (defvar iedit-rect-local-map
287 (let ((map (make-sparse-keymap)))
288 (set-keymap-parent map iedit-occurrence-local-map)
289 (define-key map (kbd "M-k") 'iedit-kill-rectangle)
290 map)
291 "Keymap used within overlays in iedit-RECT mode.")
292
7d18e5d @victorhge Add a help command C-? for occurrences
authored
293 (defun iedit-help-for-occurrences ()
a8cbb68 @victorhge Add iedit-kill-rectangle to iedit-rect mode and adjust keymap help
authored
294 "Display `iedit-occurrence-local-map' or `iedit-rect-local-map'."
7d18e5d @victorhge Add a help command C-? for occurrences
authored
295 (interactive)
e568677 @victorhge Add new functionality: restrict iedit-mode in region
authored
296 (message (concat "M-u/l:up/downcase M-r:replace M-C:clear M-D:delete M-N:number C-return:buffering"
a8cbb68 @victorhge Add iedit-kill-rectangle to iedit-rect mode and adjust keymap help
authored
297 (if iedit-rectangle
298 " M-k:kill"))))
7d18e5d @victorhge Add a help command C-? for occurrences
authored
299
e9a9485 updates
anybody authored
300 (or (assq 'iedit-mode minor-mode-map-alist)
301 (setq minor-mode-map-alist
5ad28b5 updates
anybody authored
302 (cons (cons 'iedit-mode iedit-mode-map) minor-mode-map-alist)))
e9a9485 updates
anybody authored
303
304 ;;;###autoload
305 (defun iedit-mode (&optional arg)
306 "Toggle iedit mode.
d872cb7 @victorhge Update comments for restricting
authored
307 If iedit mode is off, turn iedit mode on.
e9a9485 updates
anybody authored
308
309 In Transient Mark mode, when iedit mode is turned on, all the
f808bf1 @victorhge Merge from lewang/master and update comments
authored
310 occurrences of the current region are highlighted. If one
e9a9485 updates
anybody authored
311 occurrence is modified, the change are propagated to all other
312 occurrences simultaneously.
313
314 If Transient Mark mode is disabled or the region is not active,
6d96992 @victorhge Remove duplicated comments
authored
315 the current symbol (returns from `current-word') is used as the
316 occurrence by default. The occurrences of the current
317 symbol, but not include occurrences that are part of other
318 symbols, are highlighted. This is good for renaming refactoring
319 during programming. If you still want to match all the
320 occurrences, even though they are parts of other symbols, you may
321 have to select the symbol first.
e9a9485 updates
anybody authored
322
323 You can also switch to iedit mode from isearch mode directly. The
324 current search string is used as occurrence. All occurrences of
325 the current search string are highlighted.
326
d872cb7 @victorhge Update comments for restricting
authored
327 With an universal prefix argument and no active region, the
ec765ee implement interactive string-rectangle mode with universal argument a…
Le Wang authored
328 occurrence when iedit is turned off last time is used as
329 occurrence. This is intended to recover last iedit which is
330 turned off by mistake.
331
d872cb7 @victorhge Update comments for restricting
authored
332 With an universal prefix argument and region active, interactively
ec765ee implement interactive string-rectangle mode with universal argument a…
Le Wang authored
333 edit region as a string rectangle.
e9a9485 updates
anybody authored
334
d872cb7 @victorhge Update comments for restricting
authored
335 If iedit mode is on and region is active, iedit mode is
336 restricted in the region, e.g. the occurrences outside of the region
337 is excluded.
338
339 If iedit mode is on and region is active, with a
340 prefix argument, iedit mode is restricted outside of the region,
341 e.g. the occurrences in the region is excluded.
342
343 Turn off iedit mode in other situations.
344
e9a9485 updates
anybody authored
345 Commands:
a8cbb68 @victorhge Add iedit-kill-rectangle to iedit-rect mode and adjust keymap help
authored
346 \\{iedit-current-keymap}"
e08ad59 @victorhge Make Iedit mode available for read only buffer
authored
347 (interactive "P")
e9a9485 updates
anybody authored
348 (if iedit-mode
e568677 @victorhge Add new functionality: restrict iedit-mode in region
authored
349 (if (and transient-mark-mode mark-active (not (equal (mark) (point))))
61689f6 @victorhge Add arg handle for iedit-mode to exclude some occurrences.
authored
350 ;; Restrict iedit-mode
351 (let ((beg (region-beginning))
352 (end (region-end)))
353 (if (null (iedit-find-overlay beg end 'iedit-occurrence-overlay-name arg))
e568677 @victorhge Add new functionality: restrict iedit-mode in region
authored
354 (iedit-done)
355 (when iedit-buffering
356 (iedit-stop-buffering))
357 (setq iedit-last-occurrence-in-history (iedit-current-occurrence-string))
358 (if (null iedit-last-occurrence-in-history)
359 (iedit-done)
360 (deactivate-mark)
361 (iedit-show-all)
61689f6 @victorhge Add arg handle for iedit-mode to exclude some occurrences.
authored
362 (iedit-cleanup-occurrences-overlays beg end arg)
363 (setq iedit-mode (propertize
364 (concat " Iedit:" (number-to-string (length iedit-occurrences-overlays)))
365 'face 'font-lock-warning-face))
366 (force-mode-line-update)
e568677 @victorhge Add new functionality: restrict iedit-mode in region
authored
367 (iedit-first-occurrence))))
368 (iedit-done))
3bca7e2 @victorhge Fix iedit toggle case-sensitive problem when getting occurrence from …
authored
369 (let (occurrence complete-symbol rect-string)
ec765ee implement interactive string-rectangle mode with universal argument a…
Le Wang authored
370 (cond ((and arg
0edc86f @victorhge Fix the last occurrence problem when it is a complete symbol.
authored
371 (or (not transient-mark-mode) (not mark-active)
372 (equal (mark) (point)))
ec765ee implement interactive string-rectangle mode with universal argument a…
Le Wang authored
373 iedit-last-occurrence-in-history)
3bca7e2 @victorhge Fix iedit toggle case-sensitive problem when getting occurrence from …
authored
374 (setq occurrence iedit-last-occurrence-in-history)
375 (setq complete-symbol iedit-occurrence-is-complete-symbol))
ec765ee implement interactive string-rectangle mode with universal argument a…
Le Wang authored
376 ((and arg
0edc86f @victorhge Fix the last occurrence problem when it is a complete symbol.
authored
377 transient-mark-mode mark-active (not (equal (mark) (point))))
ec765ee implement interactive string-rectangle mode with universal argument a…
Le Wang authored
378 (setq rect-string t))
e9a9485 updates
anybody authored
379 ((and transient-mark-mode mark-active (not (equal (mark) (point))))
df6c2ad fix search to use regexp-quote when needed
Le Wang authored
380 (setq occurrence (regexp-quote (buffer-substring-no-properties
381 (mark) (point)))))
e9a9485 updates
anybody authored
382 ((and isearch-mode (not (string= isearch-string "")))
0edc86f @victorhge Fix the last occurrence problem when it is a complete symbol.
authored
383 (setq occurrence (regexp-quote (buffer-substring-no-properties
384 (point) isearch-other-end)))
e9a9485 updates
anybody authored
385 (isearch-exit))
f808bf1 @victorhge Merge from lewang/master and update comments
authored
386 ((and iedit-current-symbol-default (current-word t))
df6c2ad fix search to use regexp-quote when needed
Le Wang authored
387 (setq occurrence (regexp-quote (current-word)))
f808bf1 @victorhge Merge from lewang/master and update comments
authored
388 (when iedit-only-at-symbol-boundaries
3bca7e2 @victorhge Fix iedit toggle case-sensitive problem when getting occurrence from …
authored
389 (setq complete-symbol t)))
e9a9485 updates
anybody authored
390 (t (error "No candidate of the occurrence, cannot enable iedit mode.")))
3bca7e2 @victorhge Fix iedit toggle case-sensitive problem when getting occurrence from …
authored
391 (setq iedit-occurrence-is-complete-symbol complete-symbol)
ec765ee implement interactive string-rectangle mode with universal argument a…
Le Wang authored
392 (if rect-string
393 (let ((beg (region-beginning))
394 (end (region-end)))
395 (deactivate-mark)
a8cbb68 @victorhge Add iedit-kill-rectangle to iedit-rect mode and adjust keymap help
authored
396 (iedit-rectangle-start beg end))
ec765ee implement interactive string-rectangle mode with universal argument a…
Le Wang authored
397 (deactivate-mark)
6e49225 @victorhge Add iedit-toggle-case-sensitive
authored
398 (setq iedit-case-sensitive iedit-case-sensitive-default)
ec765ee implement interactive string-rectangle mode with universal argument a…
Le Wang authored
399 (iedit-start occurrence)))))
e9a9485 updates
anybody authored
400
f808bf1 @victorhge Merge from lewang/master and update comments
authored
401 (defun iedit-start (occurrence-exp)
402 "Start an iedit for the occurrence-exp in the current buffer."
e9a9485 updates
anybody authored
403 (setq iedit-unmatched-lines-invisible iedit-unmatched-lines-invisible-default)
9b3aaa8 @victorhge Fix occurrence from history does not exist problem
authored
404 (setq iedit-aborting nil)
a8cbb68 @victorhge Add iedit-kill-rectangle to iedit-rect mode and adjust keymap help
authored
405 (setq iedit-rectangle nil)
406 (setq iedit-current-keymap iedit-occurrence-local-map)
e568677 @victorhge Add new functionality: restrict iedit-mode in region
authored
407 (iedit-refresh occurrence-exp (point-min) (point-max))
84c02ea @victorhge Fix toggle case-sensitive problem when occurrence is empty string.
authored
408 (run-hooks 'iedit-mode-hook)
409 ;; (add-hook 'mouse-leave-buffer-hook 'iedit-done)
410 (add-hook 'kbd-macro-termination-hook 'iedit-done))
411
e568677 @victorhge Add new functionality: restrict iedit-mode in region
authored
412 (defun iedit-refresh (occurrence-exp beg end)
84c02ea @victorhge Fix toggle case-sensitive problem when occurrence is empty string.
authored
413 "Refresh iedit-mode."
414 (setq iedit-occurrences-overlays nil)
3bca7e2 @victorhge Fix iedit toggle case-sensitive problem when getting occurrence from …
authored
415 (when iedit-occurrence-is-complete-symbol
416 (setq occurrence-exp (concat "\\_<" occurrence-exp "\\_>")))
e9a9485 updates
anybody authored
417 ;; Find and record each occurrence's markers and add the overlay to the occurrences
5ad28b5 updates
anybody authored
418 (let ((counter 0)
f808bf1 @victorhge Merge from lewang/master and update comments
authored
419 (case-fold-search (not iedit-case-sensitive)))
420 (save-excursion
e568677 @victorhge Add new functionality: restrict iedit-mode in region
authored
421 (goto-char beg)
422 (while (re-search-forward occurrence-exp end t)
f808bf1 @victorhge Merge from lewang/master and update comments
authored
423 (push (iedit-make-occurrence-overlay (match-beginning 0) (match-end 0))
424 iedit-occurrences-overlays)
9b3aaa8 @victorhge Fix occurrence from history does not exist problem
authored
425 (setq counter (1+ counter)))
426 (if (= 0 counter)
84c02ea @victorhge Fix toggle case-sensitive problem when occurrence is empty string.
authored
427 (error "0 matches for \"%s\"" (iedit-printable occurrence-exp))
9b3aaa8 @victorhge Fix occurrence from history does not exist problem
authored
428 (setq iedit-occurrences-overlays (nreverse iedit-occurrences-overlays))
429 (if iedit-unmatched-lines-invisible
4e31d50 @victorhge Add a prefix arg handling to iedit-toggle-unmatched-lines-visible
authored
430 (iedit-hide-unmatched-lines iedit-occurrence-context-lines)))
84c02ea @victorhge Fix toggle case-sensitive problem when occurrence is empty string.
authored
431 (message "%d matches for \"%s\"" counter (iedit-printable occurrence-exp))
a8cbb68 @victorhge Add iedit-kill-rectangle to iedit-rect mode and adjust keymap help
authored
432 (setq iedit-mode (propertize (concat " Iedit:" (number-to-string counter))
433 'face 'font-lock-warning-face))))
84c02ea @victorhge Fix toggle case-sensitive problem when occurrence is empty string.
authored
434 (force-mode-line-update))
435
a8cbb68 @victorhge Add iedit-kill-rectangle to iedit-rect mode and adjust keymap help
authored
436 (defun iedit-rectangle-start (beg end)
5ab9809 @victorhge Update documents
authored
437 "Start an iedit for the region as a rectangle."
e08ad59 @victorhge Make Iedit mode available for read only buffer
authored
438 (barf-if-buffer-read-only)
ec765ee implement interactive string-rectangle mode with universal argument a…
Le Wang authored
439 (setq iedit-mode (propertize " Iedit-RECT" 'face 'font-lock-warning-face))
440 (setq iedit-occurrences-overlays nil)
87053a3 @victorhge Remove two buffer local variables for rectangle.
authored
441 (setq iedit-rectangle (list beg end))
a8cbb68 @victorhge Add iedit-kill-rectangle to iedit-rect mode and adjust keymap help
authored
442 (setq iedit-current-keymap iedit-rect-local-map)
ec765ee implement interactive string-rectangle mode with universal argument a…
Le Wang authored
443 (force-mode-line-update)
444 (run-hooks 'iedit-mode-hook)
445 (add-hook 'kbd-macro-termination-hook 'iedit-done)
c53a885 @victorhge Add bufferring modification functionalities
authored
446 (save-excursion
447 (let ((beg-col (progn (goto-char beg) (current-column)))
448 (end-col (progn (goto-char end) (current-column))))
449 (when (< end-col beg-col)
450 (rotatef beg-col end-col))
451 (goto-char beg)
452 (loop do (progn
453 (push (iedit-make-occurrence-overlay
454 (progn
455 (move-to-column beg-col t)
456 (point))
457 (progn
458 (move-to-column end-col t)
459 (point)))
460 iedit-occurrences-overlays)
461 (forward-line 1))
462 until (> (point) end))
463 (setq iedit-occurrences-overlays (nreverse iedit-occurrences-overlays)))))
ec765ee implement interactive string-rectangle mode with universal argument a…
Le Wang authored
464
e9a9485 updates
anybody authored
465 (defun iedit-done ()
466 "Exit iedit mode."
c53a885 @victorhge Add bufferring modification functionalities
authored
467 (if iedit-buffering
468 (iedit-stop-buffering))
84c02ea @victorhge Fix toggle case-sensitive problem when occurrence is empty string.
authored
469 (setq iedit-last-occurrence-in-history (iedit-current-occurrence-string))
61689f6 @victorhge Add arg handle for iedit-mode to exclude some occurrences.
authored
470 (remove-overlays nil nil iedit-occurrence-overlay-name t)
4e31d50 @victorhge Add a prefix arg handling to iedit-toggle-unmatched-lines-visible
authored
471 (iedit-show-all)
e9a9485 updates
anybody authored
472 (setq iedit-occurrences-overlays nil)
c53a885 @victorhge Add bufferring modification functionalities
authored
473 (setq iedit-aborting nil)
474 (setq iedit-before-modification-string "")
475 (setq iedit-before-modification-undo-list nil)
e9a9485 updates
anybody authored
476 (setq iedit-mode nil)
477 (force-mode-line-update)
84c02ea @victorhge Fix toggle case-sensitive problem when occurrence is empty string.
authored
478 (remove-hook 'kbd-macro-termination-hook 'iedit-done)
e9a9485 updates
anybody authored
479 (run-hooks 'iedit-mode-end-hook))
480
481 (defun iedit-make-occurrence-overlay (begin end)
482 "Create an overlay for an occurrence in iedit mode.
483 Add the properties for the overlay: a face used to display a
484 occurrence's default value, and modification hooks to update
485 occurrences if the user starts typing."
486 (let ((occurrence (make-overlay begin end (current-buffer) nil t)))
487 (overlay-put occurrence iedit-occurrence-overlay-name t)
488 (overlay-put occurrence 'face iedit-occurrence-face)
a8cbb68 @victorhge Add iedit-kill-rectangle to iedit-rect mode and adjust keymap help
authored
489 (overlay-put occurrence 'local-map iedit-current-keymap)
e9a9485 updates
anybody authored
490 (overlay-put occurrence 'insert-in-front-hooks '(iedit-occurrence-update))
491 (overlay-put occurrence 'insert-behind-hooks '(iedit-occurrence-update))
492 (overlay-put occurrence 'modification-hooks '(iedit-occurrence-update))
493 occurrence))
494
495 (defun iedit-make-unmatched-lines-overlay (begin end)
496 "Create an overlay for lines between two occurrences in iedit mode."
497 (let ((unmatched-lines-overlay (make-overlay begin end (current-buffer) nil t)))
498 (overlay-put unmatched-lines-overlay iedit-invisible-overlay-name t)
4e31d50 @victorhge Add a prefix arg handling to iedit-toggle-unmatched-lines-visible
authored
499 (overlay-put unmatched-lines-overlay 'invisible 'iedit-invisible-overlay-name)
500 ;; (overlay-put unmatched-lines-overlay 'intangible t)
e9a9485 updates
anybody authored
501 unmatched-lines-overlay))
502
6e49225 @victorhge Add iedit-toggle-case-sensitive
authored
503 (defun iedit-reset-aborting ()
5ab9809 @victorhge Update documents
authored
504 "Turning iedit-mode off and reset iedit-aborting.
505
506 This is added to `post-command-hook when aborting iedit-mode is
507 decided. `iedit-done' is postponed after the current command is
508 executed for avoiding iedit-occurrence-update is called for a
509 removed overlay."
6e49225 @victorhge Add iedit-toggle-case-sensitive
authored
510 (iedit-done)
511 (remove-hook 'post-command-hook 'iedit-reset-aborting t)
512 (setq iedit-aborting nil))
513
e9a9485 updates
anybody authored
514 (defun iedit-occurrence-update (occurrence after beg end &optional change)
515 "Update all occurrences.
9a891d7 updates
anybody authored
516 This modification hook is triggered when a user edits any
c8dac6b @victorhge exit iedit mode when change is not inside of occurrence.
authored
517 occurrence and is responsible for updating all other occurrences.
5ab9809 @victorhge Update documents
authored
518 Current supported edits are insertion, yank, deletion and
519 replacement. If this modification is going out of the
520 occurrence, it will exit iedit mode."
039c0e2 @victorhge Postpone iedit-done after commands are excuted.
authored
521 (when (and (not iedit-aborting )
0edc86f @victorhge Fix the last occurrence problem when it is a complete symbol.
authored
522 (not undo-in-progress)) ; undo will do all the update
c8dac6b @victorhge exit iedit mode when change is not inside of occurrence.
authored
523 ;; before modification
13ecba1 Merge branch 'upstream-master'
Le Wang authored
524 (if (null after)
c8dac6b @victorhge exit iedit mode when change is not inside of occurrence.
authored
525 (if (or (< beg (overlay-start occurrence))
526 (> end (overlay-end occurrence)))
0edc86f @victorhge Fix the last occurrence problem when it is a complete symbol.
authored
527 (progn (setq iedit-aborting t) ; abort iedit-mode
528 (add-hook 'post-command-hook 'iedit-reset-aborting nil t))
17ce973 @victorhge Clean up code
authored
529 (setq iedit-before-modification-string
530 (buffer-substring-no-properties beg end)))
20c1075 remove conditions on setting `iedit-before-modification-string'.
Le Wang authored
531 ;; after modification
c53a885 @victorhge Add bufferring modification functionalities
authored
532 (when (not iedit-buffering)
9bc57d2 @victorhge make iedit-skipped-modification-once buffer local
authored
533 ;; Check if we are inserting into zero-width occurrence. If so, then
534 ;; TWO modification hooks will be called -- "insert-in-front-hooks" and
535 ;; "insert-behind-hooks". We need to run just once.
c53a885 @victorhge Add bufferring modification functionalities
authored
536 (if (and (= beg (overlay-start occurrence))
537 (= end (overlay-end occurrence))
538 (= change 0)
539 (not iedit-skipped-modification-once))
540 (setq iedit-skipped-modification-once t)
541 (setq iedit-skipped-modification-once nil)
542 (when (or (eq 0 change) ;; insertion
543 (eq beg end) ;; deletion
544 (not (string= iedit-before-modification-string
545 (buffer-substring-no-properties beg end))))
546 (let ((inhibit-modification-hooks t) ; todo: extract this as a function
547 (offset (- beg (overlay-start occurrence)))
548 (value (buffer-substring-no-properties beg end)))
549 (save-excursion
550 ;; insertion or yank
551 (if (eq 0 change)
552 (dolist (another-occurrence (remove occurrence iedit-occurrences-overlays))
553 (progn
554 (goto-char (+ (overlay-start another-occurrence) offset))
555 (insert-and-inherit value)))
556 ;; deletion
b81b9d6 @victorhge Clean code.
authored
557 (dolist (another-occurrence (remove occurrence iedit-occurrences-overlays))
c53a885 @victorhge Add bufferring modification functionalities
authored
558 (let* ((beginning (+ (overlay-start another-occurrence) offset))
559 (ending (+ beginning change)))
560 (delete-region beginning ending)
561 (unless (eq beg end) ;; replacement
562 (goto-char beginning)
563 (insert-and-inherit value)))))))))))))
17ce973 @victorhge Clean up code
authored
564 ;; (elp-instrument-list '(insert-and-inherit delete-region goto-char iedit-occurrence-update buffer-substring-no-properties string= re-search-forward replace-match))
c8dac6b @victorhge exit iedit mode when change is not inside of occurrence.
authored
565
e9a9485 updates
anybody authored
566 (defun iedit-next-occurrence ()
9a891d7 updates
anybody authored
567 "Move forward to the next occurrence in the `iedit'.
ec6785b @victorhge host on git
authored
568 If the point is already in the last occurrences, you are asked to type
9a891d7 updates
anybody authored
569 another `iedit-next-occurrence', it starts again from the
570 beginning of the buffer."
e9a9485 updates
anybody authored
571 (interactive)
9a891d7 updates
anybody authored
572 (let ((pos (point))
573 (in-occurrence (get-char-property (point) 'iedit-occurrence-overlay-name)))
574 (when in-occurrence
575 (setq pos (next-single-char-property-change pos 'iedit-occurrence-overlay-name)))
576 (setq pos (next-single-char-property-change pos 'iedit-occurrence-overlay-name))
577 (if (/= pos (point-max))
578 (setq iedit-forward-success t)
579 (if (and iedit-forward-success in-occurrence)
580 (progn (message "This is the last occurrence.")
581 (setq iedit-forward-success nil))
da0a247 @tsdh Add option to match only complete words, not inside words
tsdh authored
582 (progn
9a891d7 updates
anybody authored
583 (if (get-char-property (point-min) 'iedit-occurrence-overlay-name)
584 (setq pos (point-min))
3bca7e2 @victorhge Fix iedit toggle case-sensitive problem when getting occurrence from …
authored
585 (setq pos (next-single-char-property-change
586 (point-min)
587 'iedit-occurrence-overlay-name)))
9a891d7 updates
anybody authored
588 (setq iedit-forward-success t)
589 (message "Located the first occurrence."))))
590 (when iedit-forward-success
591 (goto-char pos))))
e9a9485 updates
anybody authored
592
593 (defun iedit-prev-occurrence ()
9a891d7 updates
anybody authored
594 "Move backward to the previous occurrence in the `iedit'.
ec6785b @victorhge host on git
authored
595 If the point is already in the first occurrences, you are asked to type
9a891d7 updates
anybody authored
596 another `iedit-prev-occurrence', it starts again from the end of
597 the buffer."
e9a9485 updates
anybody authored
598 (interactive)
9a891d7 updates
anybody authored
599 (let ((pos (point))
600 (in-occurrence (get-char-property (point) 'iedit-occurrence-overlay-name)))
601 (when in-occurrence
602 (setq pos (previous-single-char-property-change pos 'iedit-occurrence-overlay-name)))
603 (setq pos (previous-single-char-property-change pos 'iedit-occurrence-overlay-name))
5ad28b5 updates
anybody authored
604 ;; At the start of the first occurrence
9a891d7 updates
anybody authored
605 (if (or (and (eq pos (point-min))
606 (not (get-char-property (point-min) 'iedit-occurrence-overlay-name)))
da0a247 @tsdh Add option to match only complete words, not inside words
tsdh authored
607 (and (eq (point) (point-min))
9a891d7 updates
anybody authored
608 in-occurrence))
609 (if (and iedit-forward-success in-occurrence)
610 (progn (message "This is the first occurrence.")
611 (setq iedit-forward-success nil))
da0a247 @tsdh Add option to match only complete words, not inside words
tsdh authored
612 (progn
9a891d7 updates
anybody authored
613 (setq pos (previous-single-char-property-change (point-max) 'iedit-occurrence-overlay-name))
614 (if (not (get-char-property (- (point-max) 1) 'iedit-occurrence-overlay-name))
615 (setq pos (previous-single-char-property-change pos 'iedit-occurrence-overlay-name)))
616 (setq iedit-forward-success t)
617 (message "Located the last occurrence.")))
618 (setq iedit-forward-success t))
619 (when iedit-forward-success
620 (goto-char pos))))
e9a9485 updates
anybody authored
621
e568677 @victorhge Add new functionality: restrict iedit-mode in region
authored
622 (defun iedit-first-occurrence ()
623 "Move to the first occurrence."
624 (interactive)
625 (let ((pos (if (get-char-property (point-min) 'iedit-occurrence-overlay-name)
626 (point-min)
627 (next-single-char-property-change
628 (point-min)
629 'iedit-occurrence-overlay-name))))
630 (setq iedit-forward-success t)
631 (goto-char pos)
632 (message "Located the first occurrence.")))
633
634 (defun iedit-last-occurrence ()
635 "Move to the last occurrence."
636 (interactive)
61689f6 @victorhge Add arg handle for iedit-mode to exclude some occurrences.
authored
637 (let ((pos (previous-single-char-property-change (point-max) 'iedit-occurrence-overlay-name)))
638 (if (not (get-char-property (- (point-max) 1) 'iedit-occurrence-overlay-name))
639 (setq pos (previous-single-char-property-change pos 'iedit-occurrence-overlay-name)))
640 (setq iedit-forward-success t)
641 (goto-char pos)
642 (message "Located the last occurrence.")))
e568677 @victorhge Add new functionality: restrict iedit-mode in region
authored
643
4e31d50 @victorhge Add a prefix arg handling to iedit-toggle-unmatched-lines-visible
authored
644 (defun iedit-toggle-unmatched-lines-visible (&optional arg)
645 "Toggle whether to display unmatched lines.
646 A prefix ARG specifies how many lines before and after the
799a0d1 @victorhge Bump to version 0.94
authored
647 occurrences are not hided; negative is treated the same as zero.
e9a9485 updates
anybody authored
648
4e31d50 @victorhge Add a prefix arg handling to iedit-toggle-unmatched-lines-visible
authored
649 If no prefix argument, the prefix argument last time or default
650 value of `iedit-occurrence-context-lines' is used for this time."
651 (interactive "P")
652 (if (null arg)
653 (progn (setq iedit-unmatched-lines-invisible (not iedit-unmatched-lines-invisible))
654 (if iedit-unmatched-lines-invisible
655 (iedit-hide-unmatched-lines iedit-occurrence-context-lines)
656 (iedit-show-all)))
657 (setq arg (prefix-numeric-value arg))
658 (if (< arg 0)
659 (setq arg 0))
660 (unless (and iedit-unmatched-lines-invisible
661 (= arg iedit-occurrence-context-lines))
662 (when iedit-unmatched-lines-invisible
61689f6 @victorhge Add arg handle for iedit-mode to exclude some occurrences.
authored
663 (remove-overlays nil nil iedit-invisible-overlay-name t))
4e31d50 @victorhge Add a prefix arg handling to iedit-toggle-unmatched-lines-visible
authored
664 (setq iedit-occurrence-context-lines arg)
665 (setq iedit-unmatched-lines-invisible t)
666 (iedit-hide-unmatched-lines iedit-occurrence-context-lines))))
667
668 (defun iedit-show-all()
669 "Show hided lines."
670 (setq line-move-ignore-invisible nil)
61689f6 @victorhge Add arg handle for iedit-mode to exclude some occurrences.
authored
671 (remove-overlays nil nil iedit-invisible-overlay-name t)
4e31d50 @victorhge Add a prefix arg handling to iedit-toggle-unmatched-lines-visible
authored
672 (remove-from-invisibility-spec '(iedit-invisible-overlay-name . t)))
673
674 (defun iedit-hide-unmatched-lines (context-lines)
6e49225 @victorhge Add iedit-toggle-case-sensitive
authored
675 "Hide unmatched lines using invisible overlay."
676 (let ((prev-occurrence-end 0)
677 (unmatched-lines nil))
678 (save-excursion
679 (dolist (overlay iedit-occurrences-overlays)
680 (goto-char (overlay-start overlay))
4e31d50 @victorhge Add a prefix arg handling to iedit-toggle-unmatched-lines-visible
authored
681 (forward-line (- context-lines))
6e49225 @victorhge Add iedit-toggle-case-sensitive
authored
682 (let ((line-beginning (line-beginning-position)))
683 (if (> line-beginning (1+ prev-occurrence-end))
684 (push (list (1+ prev-occurrence-end) (1- line-beginning)) unmatched-lines)))
685 (goto-char (overlay-end overlay))
4e31d50 @victorhge Add a prefix arg handling to iedit-toggle-unmatched-lines-visible
authored
686 (forward-line context-lines)
6e49225 @victorhge Add iedit-toggle-case-sensitive
authored
687 (setq prev-occurrence-end (line-end-position)))
688 (if (< prev-occurrence-end (point-max))
689 (push (list (1+ prev-occurrence-end) (point-max)) unmatched-lines))
690 (when unmatched-lines
4e31d50 @victorhge Add a prefix arg handling to iedit-toggle-unmatched-lines-visible
authored
691 (set (make-local-variable 'line-move-ignore-invisible) t)
692 (add-to-invisibility-spec '(iedit-invisible-overlay-name . t))
6e49225 @victorhge Add iedit-toggle-case-sensitive
authored
693 (dolist (unmatch unmatched-lines)
694 (iedit-make-unmatched-lines-overlay (car unmatch) (cadr unmatch)))))))
695
696 ;;;; functions for overlay local-map
e99e65f @victorhge Fix current point move problem when call iedit-replace-occurrences.
authored
697 (defun iedit-apply-on-occurrences (function &rest args)
da47784 @victorhge Add iedit mode easy access keys
authored
698 "Call function for each occurrence."
699 (let* ((ov (car iedit-occurrences-overlays))
700 (beg (overlay-start ov))
701 (end (overlay-end ov)))
702 (when (/= beg end)
703 (let ((inhibit-modification-hooks t))
0d4027f @victorhge Move save-excursion out of dolist
authored
704 (save-excursion
705 (dolist (occurrence iedit-occurrences-overlays)
706 (apply function (overlay-start occurrence) (overlay-end occurrence) args)))))))
da47784 @victorhge Add iedit mode easy access keys
authored
707
708 (defun iedit-upcase-occurrences ()
709 "Covert occurrences to upper case."
e08ad59 @victorhge Make Iedit mode available for read only buffer
authored
710 (interactive "*")
e99e65f @victorhge Fix current point move problem when call iedit-replace-occurrences.
authored
711 (iedit-apply-on-occurrences 'upcase-region))
da47784 @victorhge Add iedit mode easy access keys
authored
712
713 (defun iedit-downcase-occurrences()
714 "Covert occurrences to lower case."
e08ad59 @victorhge Make Iedit mode available for read only buffer
authored
715 (interactive "*")
e99e65f @victorhge Fix current point move problem when call iedit-replace-occurrences.
authored
716 (iedit-apply-on-occurrences 'downcase-region))
da47784 @victorhge Add iedit mode easy access keys
authored
717
718 (defun iedit-replace-occurrences(string)
719 "Replace occurrences with STRING."
a8cbb68 @victorhge Add iedit-kill-rectangle to iedit-rect mode and adjust keymap help
authored
720 (interactive "*sReplace with: ")
e99e65f @victorhge Fix current point move problem when call iedit-replace-occurrences.
authored
721 (let* ((ov (iedit-find-current-occurrence-overlay))
722 (offset (- (point) (overlay-start ov))))
723 (iedit-apply-on-occurrences
724 (lambda (beg end string)
725 (delete-region beg end)
726 (goto-char beg)
0d4027f @victorhge Move save-excursion out of dolist
authored
727 (insert-and-inherit string))
e99e65f @victorhge Fix current point move problem when call iedit-replace-occurrences.
authored
728 string)
729 (goto-char (+ (overlay-start ov) offset))))
da47784 @victorhge Add iedit mode easy access keys
authored
730
731 (defun iedit-clear-occurrences()
732 "Replace occurrences with blank spaces."
e08ad59 @victorhge Make Iedit mode available for read only buffer
authored
733 (interactive "*")
78f606d @victorhge Add iedit-number-occurrences function
authored
734 (let* ((ov (car iedit-occurrences-overlays))
735 (count (- (overlay-end ov) (overlay-start ov))))
736 (iedit-replace-occurrences (make-string count 32))))
da47784 @victorhge Add iedit mode easy access keys
authored
737
738 (defun iedit-delete-occurrences()
739 "Delete occurrences."
e08ad59 @victorhge Make Iedit mode available for read only buffer
authored
740 (interactive "*")
e99e65f @victorhge Fix current point move problem when call iedit-replace-occurrences.
authored
741 (iedit-apply-on-occurrences 'delete-region))
da47784 @victorhge Add iedit mode easy access keys
authored
742
78f606d @victorhge Add iedit-number-occurrences function
authored
743 (defun iedit-toggle-case-sensitive ()
744 "Toggle case-sensitive matching occurrences."
745 (interactive)
e568677 @victorhge Add new functionality: restrict iedit-mode in region
authored
746 (setq iedit-case-sensitive (not iedit-case-sensitive))
84c02ea @victorhge Fix toggle case-sensitive problem when occurrence is empty string.
authored
747 (if iedit-buffering
748 (iedit-stop-buffering))
749 (setq iedit-last-occurrence-in-history (iedit-current-occurrence-string))
e568677 @victorhge Add new functionality: restrict iedit-mode in region
authored
750 (when iedit-last-occurrence-in-history
61689f6 @victorhge Add arg handle for iedit-mode to exclude some occurrences.
authored
751 (remove-overlays nil nil iedit-occurrence-overlay-name t)
e568677 @victorhge Add new functionality: restrict iedit-mode in region
authored
752 (iedit-show-all)
753 (iedit-refresh iedit-last-occurrence-in-history (point-min) (point-max))))
78f606d @victorhge Add iedit-number-occurrences function
authored
754
a8cbb68 @victorhge Add iedit-kill-rectangle to iedit-rect mode and adjust keymap help
authored
755 (defun iedit-toggle-buffering ()
756 "Toggle buffering.
757 This is intended to improve iedit's response time. If the number
758 of occurrences are huge, iedit might be slow to update all the
759 occurrences for each key stoke. When buffering is on,
760 modification is only applied to the current occurrence and will
761 be applied to other occurrences when buffering is off."
762 (interactive "*")
763 (if iedit-buffering
764 (iedit-stop-buffering)
8219304 @victorhge Fix problem when iedit-stop-buffering is called when current point is…
authored
765 (iedit-start-buffering))
766 (message (concat "Iedit-mode buffering "
767 (if iedit-buffering
768 "started."
769 "stopped."))))
a8cbb68 @victorhge Add iedit-kill-rectangle to iedit-rect mode and adjust keymap help
authored
770
c53a885 @victorhge Add bufferring modification functionalities
authored
771 (defun iedit-start-buffering ()
772 "Start buffering."
773 (setq iedit-buffering t)
84c02ea @victorhge Fix toggle case-sensitive problem when occurrence is empty string.
authored
774 (setq iedit-before-modification-string (iedit-current-occurrence-string))
775 (setq iedit-before-modification-undo-list buffer-undo-list)
776 (setq iedit-mode (propertize " Iedit-B" 'face 'font-lock-warning-face))
4e31d50 @victorhge Add a prefix arg handling to iedit-toggle-unmatched-lines-visible
authored
777 (force-mode-line-update))
c53a885 @victorhge Add bufferring modification functionalities
authored
778
779 (defun iedit-stop-buffering ()
8219304 @victorhge Fix problem when iedit-stop-buffering is called when current point is…
authored
780 "Stop buffering and apply the modification to other occurrences.
781 If current point is not at any occurrence, the buffered
782 modification is not going to be applied to other occurrences."
783 (let ((ov (iedit-find-current-occurrence-overlay)))
784 (when ov
785 (let* ((beg (overlay-start ov))
786 (end (overlay-end ov))
787 (modified-string (buffer-substring-no-properties beg end))
788 (offset (- (point) beg))) ;; delete-region moves cursor
789 (when (not (string= iedit-before-modification-string modified-string))
790 (save-excursion
791 ;; Rollback the current modification and buffer-undo-list. This is to
792 ;; avoid the inconsistency if user undoes modifications
793 (delete-region beg end)
794 (goto-char beg)
795 (insert-and-inherit iedit-before-modification-string)
796 (setq buffer-undo-list iedit-before-modification-undo-list)
797 (dolist (occurrence iedit-occurrences-overlays) ; todo:extract as a function
798 (let ((beginning (overlay-start occurrence))
799 (ending (overlay-end occurrence)))
800 (delete-region beginning ending)
801 (unless (eq beg end) ;; replacement
802 (goto-char beginning)
803 (insert-and-inherit modified-string)))))
804 (goto-char (+ (overlay-start ov) offset))))))
c53a885 @victorhge Add bufferring modification functionalities
authored
805 (setq iedit-buffering nil)
3bca7e2 @victorhge Fix iedit toggle case-sensitive problem when getting occurrence from …
authored
806 (setq iedit-mode (propertize
807 (concat " Iedit:" (number-to-string (length iedit-occurrences-overlays)))
808 'face 'font-lock-warning-face))
c53a885 @victorhge Add bufferring modification functionalities
authored
809 (force-mode-line-update)
8219304 @victorhge Fix problem when iedit-stop-buffering is called when current point is…
authored
810 (setq iedit-before-modification-undo-list nil))
c53a885 @victorhge Add bufferring modification functionalities
authored
811
a8cbb68 @victorhge Add iedit-kill-rectangle to iedit-rect mode and adjust keymap help
authored
812 (defvar iedit-number-line-counter 1
78f606d @victorhge Add iedit-number-occurrences function
authored
813 "Occurrence number for 'iedit-number-occurrences")
814
0d4027f @victorhge Move save-excursion out of dolist
authored
815 (defun iedit-default-line-number-format (start-at)
78f606d @victorhge Add iedit-number-occurrences function
authored
816 (concat "%"
817 (int-to-string
818 (length (int-to-string
819 (1- (+ (length iedit-occurrences-overlays) start-at)))))
820 "d "))
821
822 (defun iedit-number-occurrences (start-at &optional format)
823 "Insert numbers in front of the occurrences.
824 START-AT, if non-nil, should be a number from which to begin
825 counting. FORMAT, if non-nil, should be a format string to pass
826 to `format' along with the line count. When called interactively
827 with a prefix argument, prompt for START-AT and FORMAT."
828 (interactive
829 (if current-prefix-arg
830 (let* ((start-at (read-number "Number to count from: " 1)))
831 (list start-at
832 (read-string "Format string: "
0d4027f @victorhge Move save-excursion out of dolist
authored
833 (iedit-default-line-number-format
78f606d @victorhge Add iedit-number-occurrences function
authored
834 start-at))))
835 (list 1 nil)))
836 (unless format
0d4027f @victorhge Move save-excursion out of dolist
authored
837 (setq format (iedit-default-line-number-format start-at)))
78f606d @victorhge Add iedit-number-occurrences function
authored
838 (let ((iedit-number-line-counter start-at))
839 (iedit-apply-on-occurrences
840 (lambda (beg _end format-string)
841 (goto-char beg)
842 (insert (format format-string iedit-number-line-counter))
843 (setq iedit-number-line-counter
844 (1+ iedit-number-line-counter))) format)))
845
3bca7e2 @victorhge Fix iedit toggle case-sensitive problem when getting occurrence from …
authored
846 (defun iedit-kill-rectangle(&optional fill)
847 "Kill the rectangle.
848 The behavior is the same as `kill-rectangle' in rect mode."
849 (interactive "*P")
850 (let ((inhibit-modification-hooks t))
87053a3 @victorhge Remove two buffer local variables for rectangle.
authored
851 (kill-rectangle (car iedit-rectangle)
852 (cadr iedit-rectangle)
853 fill)))
3bca7e2 @victorhge Fix iedit toggle case-sensitive problem when getting occurrence from …
authored
854
5ab9809 @victorhge Update documents
authored
855 ;;; help functions
c53a885 @victorhge Add bufferring modification functionalities
authored
856 (defun iedit-find-current-occurrence-overlay ()
5ab9809 @victorhge Update documents
authored
857 "Return the current occurrence overlay at point or point - 1.
858 This function is supposed to be called in overlay local-map."
61689f6 @victorhge Add arg handle for iedit-mode to exclude some occurrences.
authored
859 (or (iedit-find-overlay-at-point (point) 'iedit-occurrence-overlay-name)
860 (iedit-find-overlay-at-point (1- (point)) 'iedit-occurrence-overlay-name)))
c53a885 @victorhge Add bufferring modification functionalities
authored
861
61689f6 @victorhge Add arg handle for iedit-mode to exclude some occurrences.
authored
862 (defun iedit-find-overlay-at-point (point property)
c53a885 @victorhge Add bufferring modification functionalities
authored
863 "Return the overlay with PROPERTY at POINT."
864 (let ((overlays (overlays-at point))
865 found)
866 (while (and overlays (not found))
867 (let ((overlay (car overlays)))
868 (if (overlay-get overlay property)
869 (setq found overlay)
870 (setq overlays (cdr overlays)))))
871 found))
872
e568677 @victorhge Add new functionality: restrict iedit-mode in region
authored
873 ;; This function might be called out of any occurrence
5ab9809 @victorhge Update documents
authored
874 (defun iedit-current-occurrence-string ()
e568677 @victorhge Add new functionality: restrict iedit-mode in region
authored
875 "Return current occurrence string.
876 Return nil if occurrence string is empty string."
877 (let* ((ov (or (iedit-find-current-occurrence-overlay)
878 (car iedit-occurrences-overlays)))
5ab9809 @victorhge Update documents
authored
879 (beg (overlay-start ov))
880 (end (overlay-end ov)))
881 (if (and ov (/= beg end))
882 (regexp-quote (buffer-substring-no-properties beg end))
883 nil)))
884
61689f6 @victorhge Add arg handle for iedit-mode to exclude some occurrences.
authored
885 (defun iedit-find-overlay (beg end property &optional exclusive)
886 "Return a overlay with property in region, or out of the region if EXCLUSIVE is not nil."
887 (if exclusive
888 (or (iedit-find-overlay-in-region (point-min) beg property)
889 (iedit-find-overlay-in-region end (point-max) property))
890 (iedit-find-overlay-in-region beg end property)))
891
e568677 @victorhge Add new functionality: restrict iedit-mode in region
authored
892 (defun iedit-find-overlay-in-region (beg end property)
893 "Return a overlay with property in region."
894 (let ((overlays (overlays-in beg end))
895 found)
896 (while (and overlays (not found))
897 (let ((overlay (car overlays)))
898 (if (and (overlay-get overlay property)
899 (>= (overlay-start overlay) beg)
900 (<= (overlay-end overlay) end))
901 (setq found overlay)
902 (setq overlays (cdr overlays)))))
903 found))
904
61689f6 @victorhge Add arg handle for iedit-mode to exclude some occurrences.
authored
905 (defun iedit-cleanup-occurrences-overlays (beg end &optional inclusive)
906 "Remove overlays deleted from `iedit-occurrences-overlays'."
907 (if inclusive
908 (remove-overlays beg end iedit-occurrence-overlay-name t)
909 (remove-overlays (point-min) beg iedit-occurrence-overlay-name t)
910 (remove-overlays end (point-max) iedit-occurrence-overlay-name t))
911 (let (overlays)
912 (dolist (overlay iedit-occurrences-overlays)
913 (if (overlay-buffer overlay)
914 (push overlay overlays)))
915 (setq iedit-occurrences-overlays (nreverse overlays))))
916
5ab9809 @victorhge Update documents
authored
917 (defun iedit-printable (string)
4e31d50 @victorhge Add a prefix arg handling to iedit-toggle-unmatched-lines-visible
authored
918 "Return a omitted substring that is not longer than 50.
919 STRING is already `regexp-quote'ed"
5ab9809 @victorhge Update documents
authored
920 (let ((first-newline-index (string-match "$" string))
921 (length (length string)))
922 (if (and first-newline-index
923 (/= first-newline-index length))
924 (if (< first-newline-index 50)
925 (concat (substring string 0 first-newline-index) "...")
926 (concat (substring string 0 50) "..."))
927 (if (> length 50)
928 (concat (substring string 0 50) "...")
929 string))))
930
e9a9485 updates
anybody authored
931 (provide 'iedit)
932
933 ;;; iedit.el ends here
Something went wrong with that request. Please try again.