31 |
;; |
;; |
32 |
;; Have you ever wished to use C-x r t (string-rectangle), M-% |
;; Have you ever wished to use C-x r t (string-rectangle), M-% |
33 |
;; (query-replace), M-c (capitalize-word), etc. to change the name of |
;; (query-replace), M-c (capitalize-word), etc. to change the name of |
34 |
;; the files in a "dired" buffer? Now you can do this. All the power |
;; the files in a "dired" buffer? Now you can do this. All the power |
35 |
;; of emacs commands are available to renaming files! |
;; of Emacs commands are available to renaming files! |
36 |
;; |
;; |
37 |
;; This package provides a function that makes the filenames of a a |
;; This package provides a function that makes the filenames of a a |
38 |
;; dired buffer editable, by changing the buffer mode (which inhibits |
;; dired buffer editable, by changing the buffer mode (which inhibits |
40 |
;; one or more files and directories, and when you press C-c C-c, the |
;; one or more files and directories, and when you press C-c C-c, the |
41 |
;; renaming takes effect and you are back to dired mode. |
;; renaming takes effect and you are back to dired mode. |
42 |
;; |
;; |
43 |
;; Another things you can do with wdired: |
;; Another things you can do with WDired: |
44 |
;; |
;; |
45 |
;; - To move files to another directory (by typing their path, |
;; - To move files to another directory (by typing their path, |
46 |
;; absolute or relative, as a part of the new filename). |
;; absolute or relative, as a part of the new filename). |
49 |
;; |
;; |
50 |
;; - To change the permission bits of the filenames (in systems with a |
;; - To change the permission bits of the filenames (in systems with a |
51 |
;; working unix-alike `dired-chmod-program'). See and customize the |
;; working unix-alike `dired-chmod-program'). See and customize the |
52 |
;; variable `wdired-allow-to-change-permissions'. To change a single |
;; variable `wdired-allow-to-change-permissions'. To change a single |
53 |
;; char (toggling between its two more usual values) you can press |
;; char (toggling between its two more usual values) you can press |
54 |
;; the space bar over it or left-click the mouse. To set any char to |
;; the space bar over it or left-click the mouse. To set any char to |
55 |
;; an specific value (this includes the SUID, SGID and STI bits) you |
;; an specific value (this includes the SUID, SGID and STI bits) you |
56 |
;; can use the key labeled as the letter you want. Please note that |
;; can use the key labeled as the letter you want. Please note that |
57 |
;; permissions of the links cannot be changed in that way, because |
;; permissions of the links cannot be changed in that way, because |
58 |
;; the change would affect to their targets, and this would not be |
;; the change would affect to their targets, and this would not be |
59 |
;; WYSIWYG :-). |
;; WYSIWYG :-). |
60 |
;; |
;; |
61 |
;; - To mark files for deletion, by deleting their whole filename. |
;; - To mark files for deletion, by deleting their whole filename. |
|
;; |
|
|
;; I do not have a URL to hang wdired, but you can use the one below |
|
|
;; to find the latest version: |
|
|
;; |
|
|
;; http://groups.google.com/groups?as_ugroup=gnu.emacs.sources&as_q=wdired |
|
62 |
|
|
63 |
;;; Installation: |
;;; Installation: |
64 |
|
|
70 |
;; (require 'wdired) |
;; (require 'wdired) |
71 |
;; (define-key dired-mode-map "r" 'wdired-change-to-wdired-mode) |
;; (define-key dired-mode-map "r" 'wdired-change-to-wdired-mode) |
72 |
;; |
;; |
73 |
;; This is recommended way for faster emacs startup time and lower |
;; This is the recommended way for faster Emacs startup time and lower |
74 |
;; memory consumption, but remind to add these lines before dired.el |
;; memory consumption: |
|
;; gets loaded (i.e., near the beginning of your .emacs file): |
|
75 |
;; |
;; |
76 |
;; (autoload 'wdired-change-to-wdired-mode "wdired") |
;; (autoload 'wdired-change-to-wdired-mode "wdired") |
77 |
;; (add-hook 'dired-load-hook |
;; (eval-after-load "dired" |
78 |
;; '(lambda () |
;; '(lambda () |
79 |
;; (define-key dired-mode-map "r" 'wdired-change-to-wdired-mode) |
;; (define-key dired-mode-map "r" 'wdired-change-to-wdired-mode) |
80 |
;; (define-key dired-mode-map |
;; (define-key dired-mode-map |
81 |
;; [menu-bar immediate wdired-change-to-wdired-mode] |
;; [menu-bar immediate wdired-change-to-wdired-mode] |
82 |
;; '("Edit File Names" . wdired-change-to-wdired-mode)))) |
;; '("Edit File Names" . wdired-change-to-wdired-mode)))) |
83 |
;; |
;; |
84 |
;; |
;; Type "M-x customize-group RET wdired" if you want to make changes |
85 |
;; Type "M-x customize-group RET wdired" if you want make changes to |
;; to the default behavior. |
|
;; the default behavior. |
|
86 |
|
|
87 |
;;; Usage: |
;;; Usage: |
88 |
|
|
96 |
|
|
97 |
;;; Change Log: |
;;; Change Log: |
98 |
|
|
99 |
;; From 1.9 to 1.91 |
;; Google is your friend (previous versions with complete changelogs |
100 |
;; |
;; were posted to gnu.emacs.sources) |
|
;; - Fixed a bug (introduced in 1.9) so now files can be marked for |
|
|
;; deletion again, by deleting their whole filename. |
|
|
|
|
|
;; From 1.8 to 1.9 |
|
|
;; |
|
|
;; - Another alternative way of editing permissions allowed, see |
|
|
;; `wdired-allow-to-change-permissions' for details. |
|
|
;; |
|
|
;; - Now wdired doesn't rely on regexp so much. As a consequence of |
|
|
;; this, you can add newlines to filenames and symlinks targets |
|
|
;; (although this is not very usual, IMHO). Please note that dired |
|
|
;; (at least in Emacs 21.1 and previous) does not work very well |
|
|
;; with filenames with newlines in them, so RET is deactivated in |
|
|
;; wdired mode. But you can activate it if you want. |
|
|
;; |
|
|
;; - Now `upcase-word' `capitalize-word' and `downcase-word' are not |
|
|
;; advised to work better with wdired mode, but the keys bound to |
|
|
;; them use wdired versions of those commands. |
|
|
;; |
|
|
;; - Now "undo" actions are not inherited from wdired mode when |
|
|
;; changing to dired mode. |
|
|
;; |
|
|
;; - Code and documentation cleanups. |
|
|
;; |
|
|
;; - Fixed a bug that was making wdired to fail on users with |
|
|
;; `dired-backup-overwrite' set to t. |
|
|
;; |
|
|
;; - C-c C-[ now abort changes. |
|
|
|
|
|
;; From 1.7 to 1.8 |
|
|
;; |
|
|
;; - Now permission (access-control) bits of the files can be changed. |
|
|
;; Please see the commentary section and the custom variable |
|
|
;; `wdired-allow-to-change-permissions' for details. |
|
|
;; |
|
|
;; - Added another possible value for the variable |
|
|
;; `wdired-always-move-to-filename-beginning', useful to change |
|
|
;; permission bits of several files without the cursor jumping to |
|
|
;; filenames when changing lines. |
|
|
|
|
|
;; From 0.1 to 1.7 |
|
|
|
|
|
;; - I've moved the list of changes to another file, because it was |
|
|
;; huge. Ask me for it or search older versions in google. |
|
|
|
|
|
;;; TODO: |
|
|
|
|
|
;; - Make it to work in XEmacs. Any volunteer? |
|
101 |
|
|
102 |
;;; Code: |
;;; Code: |
103 |
|
|
104 |
(defvar dired-backup-overwrite) ; Only in emacs 20.x this is a custom var |
(defvar dired-backup-overwrite) ; Only in Emacs 20.x this is a custom var |
105 |
(eval-when-compile |
(eval-when-compile |
106 |
(set (make-local-variable 'byte-compile-dynamic) t)) |
(set (make-local-variable 'byte-compile-dynamic) t)) |
107 |
|
|
115 |
:group 'dired) |
:group 'dired) |
116 |
|
|
117 |
(defcustom wdired-use-interactive-rename nil |
(defcustom wdired-use-interactive-rename nil |
118 |
"*If t, confirmation is required before actually rename the files. |
"*If non-nil, WDired requires confirmation before actually renaming files. |
119 |
Confirmation is required also for overwriting files. If nil, no |
If nil, WDired doesn't require confirmation to change the file names, |
120 |
confirmation is required for change the file names, and the variable |
and the variable `wdired-confirm-overwrite' controls whether it is ok |
121 |
`wdired-is-ok-overwrite' is used to see if it is ok to overwrite files |
to overwrite files without asking." |
|
without asking." |
|
122 |
:type 'boolean |
:type 'boolean |
123 |
:group 'wdired) |
:group 'wdired) |
124 |
|
|
125 |
(defcustom wdired-is-ok-overwrite nil |
(defcustom wdired-confirm-overwrite t |
126 |
"*If non-nil the renames can overwrite files without asking. |
"*If nil the renames can overwrite files without asking. |
127 |
This variable is used only if `wdired-use-interactive-rename' is nil." |
This variable has no effect at all if `wdired-use-interactive-rename' |
128 |
|
is not nil." |
129 |
:type 'boolean |
:type 'boolean |
130 |
:group 'wdired) |
:group 'wdired) |
131 |
|
|
132 |
(defcustom wdired-always-move-to-filename-beginning nil |
(defcustom wdired-use-dired-vertical-movement nil |
133 |
"*If t the \"up\" and \"down\" movement is done as in dired mode. |
"*If t, the \"up\" and \"down\" movement works as in Dired mode. |
134 |
That is, always move the point to the beginning of the filename at line. |
That is, always move the point to the beginning of the filename at line. |
135 |
|
|
136 |
If `sometimes, only move to the beginning of filename if the point is |
If `sometimes, only move to the beginning of filename if the point is |
144 |
:group 'wdired) |
:group 'wdired) |
145 |
|
|
146 |
(defcustom wdired-allow-to-redirect-links t |
(defcustom wdired-allow-to-redirect-links t |
147 |
"*If non-nil, the target of the symbolic links can be changed also. |
"*If non-nil, the target of the symbolic links are editable. |
148 |
In systems without symbolic links support, this variable has no effect |
In systems without symbolic links support, this variable has no effect |
149 |
at all." |
at all." |
150 |
:type 'boolean |
:type 'boolean |
151 |
:group 'wdired) |
:group 'wdired) |
152 |
|
|
153 |
(defcustom wdired-allow-to-change-permissions nil |
(defcustom wdired-allow-to-change-permissions nil |
154 |
"*If non-nil, the permissions bits of the files can be changed also. |
"*If non-nil, the permissions bits of the files are editable. |
155 |
|
|
156 |
If t, to change a single bit, put the cursor over it and press the |
If t, to change a single bit, put the cursor over it and press the |
157 |
space bar, or left click over it. You can also hit the letter you want |
space bar, or left click over it. You can also hit the letter you want |
158 |
to set: if this value is allowed, the character in the buffer will be |
to set: if this value is allowed, the character in the buffer will be |
159 |
changed. Anyway, the point is advanced one position, so, for example, |
changed. Anyway, the point is advanced one position, so, for example, |
160 |
you can keep the \"x\" key pressed to give execution permissions to |
you can keep the <x> key pressed to give execution permissions to |
161 |
everybody to that file. |
everybody to that file. |
162 |
|
|
163 |
If `advanced, the bits are freely editable. You can use |
If `advanced, the bits are freely editable. You can use |
165 |
newlines), but if you want your changes to be useful, you better put a |
newlines), but if you want your changes to be useful, you better put a |
166 |
intelligible value. |
intelligible value. |
167 |
|
|
168 |
Anyway, the real change of the permissions is done with the external |
Anyway, the real change of the permissions is done by the external |
169 |
program `dired-chmod-program', which must exist." |
program `dired-chmod-program', which must exist." |
170 |
:type '(choice (const :tag "Not allowed" nil) |
:type '(choice (const :tag "Not allowed" nil) |
171 |
(const :tag "Toggle/set bits" t) |
(const :tag "Toggle/set bits" t) |
178 |
(define-key map "\C-c\C-c" 'wdired-finish-edit) |
(define-key map "\C-c\C-c" 'wdired-finish-edit) |
179 |
(define-key map "\C-c\C-k" 'wdired-abort-changes) |
(define-key map "\C-c\C-k" 'wdired-abort-changes) |
180 |
(define-key map "\C-c\C-[" 'wdired-abort-changes) |
(define-key map "\C-c\C-[" 'wdired-abort-changes) |
181 |
(define-key map "\C-m" 'wdired-newline) |
(define-key map "\C-m" 'ignore) |
182 |
(define-key map "\C-j" 'wdired-newline) |
(define-key map "\C-j" 'ignore) |
183 |
(define-key map "\C-o" 'wdired-newline) |
(define-key map "\C-o" 'ignore) |
184 |
(define-key map [up] 'wdired-previous-line) |
(define-key map [up] 'wdired-previous-line) |
185 |
(define-key map "\C-p" 'wdired-previous-line) |
(define-key map "\C-p" 'wdired-previous-line) |
186 |
(define-key map [down] 'wdired-next-line) |
(define-key map [down] 'wdired-next-line) |
206 |
map)) |
map)) |
207 |
|
|
208 |
(defvar wdired-mode-hook nil |
(defvar wdired-mode-hook nil |
209 |
"Hook run when changing to wdired mode.") |
"Hooks run when changing to WDired mode.") |
210 |
|
|
211 |
;; Local variables (put here to avoid compilation gripes) |
;; Local variables (put here to avoid compilation gripes) |
212 |
(defvar wdired-col-perm) ;; Column where the permission bits start |
(defvar wdired-col-perm) ;; Column where the permission bits start |
216 |
(defun wdired-mode () |
(defun wdired-mode () |
217 |
"\\<wdired-mode-map>File Names Editing mode. |
"\\<wdired-mode-map>File Names Editing mode. |
218 |
|
|
219 |
Press \\[wdired-finish-edit] to make the changes to take effect and |
Press \\[wdired-finish-edit] to make the changes to take effect |
220 |
exit. To abort the edit, use \\[wdired-abort-changes]. |
and exit. To abort the edit, use \\[wdired-abort-changes]. |
221 |
|
|
222 |
In this mode you can edit the names of the files, the target of the |
In this mode you can edit the names of the files, the target of |
223 |
links and the permission bits of the files. You can `customize-group' |
the links and the permission bits of the files. You can use |
224 |
wdired. |
\\[customize-group] RET wdired to customize WDired behavior. |
225 |
|
|
226 |
Editing things out of the filenames, or adding or deleting lines is |
The only editable texts in a WDired buffer are filenames, |
227 |
not allowed, because the rest of the buffer is read-only." |
symbolic link targets, and filenames permission." |
228 |
(interactive) |
(interactive) |
229 |
(error "This mode can be enabled only by `wdired-change-to-wdired-mode'")) |
(error "This mode can be enabled only by `wdired-change-to-wdired-mode'")) |
230 |
(put 'wdired-mode 'mode-class 'special) |
(put 'wdired-mode 'mode-class 'special) |
233 |
;;;###autoload |
;;;###autoload |
234 |
(defun wdired-change-to-wdired-mode () |
(defun wdired-change-to-wdired-mode () |
235 |
"Put a dired buffer in a mode in which filenames are editable. |
"Put a dired buffer in a mode in which filenames are editable. |
236 |
In this mode the names of the files can be changed, and after |
\\<wdired-mode-map> |
237 |
typing C-c C-c the files and directories in disk are renamed. |
This mode allows the user to change the names of the files, and after |
238 |
|
typing \\[wdired-finish-edit] Emacs renames the files and directories |
239 |
|
in disk. |
240 |
|
|
241 |
See `wdired-mode'." |
See `wdired-mode'." |
242 |
(interactive) |
(interactive) |
249 |
(dired-unadvertise default-directory) |
(dired-unadvertise default-directory) |
250 |
(add-hook 'kill-buffer-hook 'wdired-check-kill-buffer nil t) |
(add-hook 'kill-buffer-hook 'wdired-check-kill-buffer nil t) |
251 |
(setq major-mode 'wdired-mode) |
(setq major-mode 'wdired-mode) |
252 |
(setq mode-name "Edit filenames") |
(setq mode-name "Editable Dired") |
253 |
(setq revert-buffer-function 'wdired-revert) |
(setq revert-buffer-function 'wdired-revert) |
254 |
;; I temp disable undo for performance: since I'm going to clear the |
;; I temp disable undo for performance: since I'm going to clear the |
255 |
;; undo list, it can save more than a 9% of time with big |
;; undo list, it can save more than a 9% of time with big |
306 |
(defun wdired-get-filename (&optional no-dir old) |
(defun wdired-get-filename (&optional no-dir old) |
307 |
"Return the filename at line. |
"Return the filename at line. |
308 |
Similar to `dired-get-filename' but it doesn't rely on regexps. It |
Similar to `dired-get-filename' but it doesn't rely on regexps. It |
309 |
relies on wdired buffer's properties. Optional arg NO-DIR with value |
relies on WDired buffer's properties. Optional arg NO-DIR with value |
310 |
non-nil means don't include directory. Optional arg OLD with value |
non-nil means don't include directory. Optional arg OLD with value |
311 |
non-nil means return old filename." |
non-nil means return old filename." |
312 |
;; FIXME: Use dired-get-filename's new properties. |
;; FIXME: Use dired-get-filename's new properties. |
358 |
"Actually rename files based on your editing in the Dired buffer." |
"Actually rename files based on your editing in the Dired buffer." |
359 |
(interactive) |
(interactive) |
360 |
(wdired-change-to-dired-mode) |
(wdired-change-to-dired-mode) |
361 |
(let ((overwrite (or wdired-is-ok-overwrite 1)) |
(let ((overwrite (or (not wdired-confirm-overwrite) 1)) |
362 |
(changes nil) |
(changes nil) |
363 |
(files-deleted nil) |
(files-deleted nil) |
364 |
(errors 0) |
(errors 0) |
457 |
(forward-line))))) |
(forward-line))))) |
458 |
|
|
459 |
(defun wdired-customize () |
(defun wdired-customize () |
460 |
"Customize wdired options." |
"Customize WDired options." |
461 |
(interactive) |
(interactive) |
462 |
(customize-apropos "wdired" 'groups)) |
(customize-apropos "wdired" 'groups)) |
463 |
|
|
464 |
(defun wdired-revert (&optional arg noconfirm) |
(defun wdired-revert (&optional arg noconfirm) |
465 |
"Discard changes in the buffer and update the changes in the disk." |
"Discard changes in the buffer and update it based on changes on disk. |
466 |
|
Optional arguments are ignored." |
467 |
(wdired-change-to-dired-mode) |
(wdired-change-to-dired-mode) |
468 |
(revert-buffer) |
(revert-buffer) |
469 |
(wdired-change-to-wdired-mode)) |
(wdired-change-to-wdired-mode)) |
477 |
|
|
478 |
(defun wdired-next-line (arg) |
(defun wdired-next-line (arg) |
479 |
"Move down lines then position at filename or the current column. |
"Move down lines then position at filename or the current column. |
480 |
See `wdired-always-move-to-filename-beginning'. Optional prefix ARG |
See `wdired-use-dired-vertical-movement'. Optional prefix ARG |
481 |
says how many lines to move; default is one line." |
says how many lines to move; default is one line." |
482 |
(interactive "p") |
(interactive "p") |
483 |
(next-line arg) |
(next-line arg) |
484 |
(if (or (eq wdired-always-move-to-filename-beginning t) |
(if (or (eq wdired-use-dired-vertical-movement t) |
485 |
(and wdired-always-move-to-filename-beginning |
(and wdired-use-dired-vertical-movement |
486 |
(< (current-column) |
(< (current-column) |
487 |
(save-excursion (dired-move-to-filename) |
(save-excursion (dired-move-to-filename) |
488 |
(current-column))))) |
(current-column))))) |
490 |
|
|
491 |
(defun wdired-previous-line (arg) |
(defun wdired-previous-line (arg) |
492 |
"Move up lines then position at filename or the current column. |
"Move up lines then position at filename or the current column. |
493 |
See `wdired-always-move-to-filename-beginning'. Optional prefix ARG |
See `wdired-use-dired-vertical-movement'. Optional prefix ARG |
494 |
says how many lines to move; default is one line." |
says how many lines to move; default is one line." |
495 |
(interactive "p") |
(interactive "p") |
496 |
(previous-line arg) |
(previous-line arg) |
497 |
(if (or (eq wdired-always-move-to-filename-beginning t) |
(if (or (eq wdired-use-dired-vertical-movement t) |
498 |
(and wdired-always-move-to-filename-beginning |
(and wdired-use-dired-vertical-movement |
499 |
(< (current-column) |
(< (current-column) |
500 |
(save-excursion (dired-move-to-filename) |
(save-excursion (dired-move-to-filename) |
501 |
(current-column))))) |
(current-column))))) |
502 |
(dired-move-to-filename))) |
(dired-move-to-filename))) |
503 |
|
|
|
;; dired doesn't works well with newlines, so ... |
|
|
(defun wdired-newline () |
|
|
"Do nothing." |
|
|
(interactive)) |
|
|
|
|
504 |
;; Put the needed properties to allow the user to change links' targets |
;; Put the needed properties to allow the user to change links' targets |
505 |
(defun wdired-preprocess-symlinks () |
(defun wdired-preprocess-symlinks () |
506 |
(let ((inhibit-read-only t)) |
(let ((inhibit-read-only t)) |
577 |
(setq arg 0)))))))) |
(setq arg 0)))))))) |
578 |
|
|
579 |
(defun wdired-downcase-word (arg) |
(defun wdired-downcase-word (arg) |
580 |
"Wdired version of `downcase-word'. |
"WDired version of `downcase-word'. |
581 |
Like original function but it skips read-only words." |
Like original function but it skips read-only words." |
582 |
(interactive "p") |
(interactive "p") |
583 |
(wdired-xcase-word 'downcase-word arg)) |
(wdired-xcase-word 'downcase-word arg)) |
584 |
|
|
585 |
(defun wdired-upcase-word (arg) |
(defun wdired-upcase-word (arg) |
586 |
"Wdired version of `upcase-word'. |
"WDired version of `upcase-word'. |
587 |
Like original function but it skips read-only words." |
Like original function but it skips read-only words." |
588 |
(interactive "p") |
(interactive "p") |
589 |
(wdired-xcase-word 'upcase-word arg)) |
(wdired-xcase-word 'upcase-word arg)) |
590 |
|
|
591 |
(defun wdired-capitalize-word (arg) |
(defun wdired-capitalize-word (arg) |
592 |
"Wdired version of `capitalize-word'. |
"WDired version of `capitalize-word'. |
593 |
Like original function but it skips read-only words." |
Like original function but it skips read-only words." |
594 |
(interactive "p") |
(interactive "p") |
595 |
(wdired-xcase-word 'capitalize-word arg)) |
(wdired-xcase-word 'capitalize-word arg)) |