Mercurial > hg > xemacs-beta
comparison lisp/efs/efs-dired.el @ 22:8fc7fe29b841 r19-15b94
Import from CVS: tag r19-15b94
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:50:29 +0200 |
parents | |
children | 4103f0995bd7 |
comparison
equal
deleted
inserted
replaced
21:b88636d63495 | 22:8fc7fe29b841 |
---|---|
1 ;; -*-Emacs-Lisp-*- | |
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
3 ;; | |
4 ;; File: efs-dired.el | |
5 ;; Release: $efs release: 1.15 $ | |
6 ;; Version: $Revision: 1.1 $ | |
7 ;; RCS: | |
8 ;; Description: Extends much of Dired to work under efs. | |
9 ;; Authors: Sebastian Kremer <sk@thp.uni-koeln.de>, | |
10 ;; Andy Norman <ange@hplb.hpl.hp.com>, | |
11 ;; Sandy Rutherford <sandy@ibm550.sissa.it> | |
12 ;; Created: Throughout the ages. | |
13 ;; Modified: Sun Nov 27 12:19:46 1994 by sandy on gandalf | |
14 ;; Language: Emacs-Lisp | |
15 ;; | |
16 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
17 | |
18 ;;; Provisions and requirements | |
19 | |
20 (provide 'efs-dired) | |
21 (require 'efs) | |
22 (require 'dired) | |
23 (autoload 'dired-shell-call-process "dired-shell") | |
24 | |
25 (defconst efs-dired-version | |
26 (concat (substring "$efs release: 1.15 $" 14 -2) | |
27 "/" | |
28 (substring "$Revision: 1.1 $" 11 -2))) | |
29 | |
30 ;;;; ---------------------------------------------------------------- | |
31 ;;;; User Configuration Variables | |
32 ;;;; ---------------------------------------------------------------- | |
33 | |
34 (defvar efs-dired-verify-modtime-host-regexp nil | |
35 "Regular expression determining on which hosts dired modtimes are checked.") | |
36 | |
37 (defvar efs-dired-verify-anonymous-modtime nil | |
38 "If non-nil, dired modtimes are checked for anonymous logins.") | |
39 | |
40 (defvar efs-remote-shell-file-name | |
41 (if (memq system-type '(hpux usg-unix-v)) ; hope that's right | |
42 "remsh" | |
43 "rsh") | |
44 "Remote shell used by efs.") | |
45 | |
46 (defvar efs-remote-shell-takes-user | |
47 (null (null (memq system-type '(aix-v3 hpux silicon-graphics-unix | |
48 berkeley-unix)))) | |
49 ;; Complete? Doubt it. | |
50 "Set to non-nil if your remote shell command takes \"-l USER\".") | |
51 | |
52 ;;; Internal Variables | |
53 | |
54 (make-variable-buffer-local 'dired-ls-F-marks-symlinks) | |
55 | |
56 ;;;; ----------------------------------------------------------- | |
57 ;;;; Inserting Directories into Buffers | |
58 ;;;; ----------------------------------------------------------- | |
59 | |
60 ;; The main command for inserting a directory listing in a buffer. | |
61 ;; In Emacs 19 this is in files.el, and not specifically connected to | |
62 ;; dired. Since our version of it uses some dired functions, it is | |
63 ;; included here, but there is an autoload for it in efs.el. | |
64 | |
65 (defun efs-insert-directory (file switches &optional wildcard full-directory-p | |
66 nowait marker-char) | |
67 ;; Inserts a remote directory. Can do this asynch. | |
68 (let* ((parsed (efs-ftp-path file)) | |
69 (mk (point-marker)) | |
70 (host (car parsed)) | |
71 (user (nth 1 parsed)) | |
72 (path (nth 2 parsed)) | |
73 (host-type (efs-host-type host)) | |
74 (dumb (memq host-type efs-dumb-host-types)) | |
75 (subdir (and (null (or full-directory-p wildcard)) | |
76 (condition-case nil | |
77 (dired-current-directory) | |
78 (error nil)))) | |
79 (case-fold-search nil) ; for testing switches | |
80 (parse (and full-directory-p (not wildcard) | |
81 (or dumb (efs-parsable-switches-p switches)))) | |
82 ;; In case dired-omit-silent isn't defined. | |
83 (dired-omit-silent (and (boundp 'dired-omit-silent) | |
84 dired-omit-silent))) | |
85 | |
86 ;; Insert the listing. If it's not a wild-card, and not a full-dir, | |
87 ;; then we are updating a dired-line. Do this asynch. | |
88 ;; This way of doing the listing makes sure that the dired | |
89 ;; buffer is still around after the listing is obtained. | |
90 | |
91 (efs-ls | |
92 file switches t (if parse 'parse t) nil | |
93 ;; asynch, if we're inserting in a subdir. Do it nowait = 0, so | |
94 ;; updating the file line gets a high priority?? | |
95 ;; Insert subdir listings NOWAIT = 0 also so 1-line | |
96 ;; updates don't toggle the mode line. | |
97 (if (and subdir nowait) 0 nowait) | |
98 (efs-cont (listing) (host user file path wildcard | |
99 nowait marker-char | |
100 mk subdir parse switches dired-omit-silent) | |
101 ;; We pass the value of dired-omit-silent from the caller to the cont. | |
102 (let ((host-type (efs-host-type host)) | |
103 (listing-type (efs-listing-type host user))) | |
104 (if (marker-buffer mk) | |
105 (efs-save-buffer-excursion | |
106 (set-buffer (marker-buffer mk)) | |
107 ;; parsing a listing, sometimes updates info | |
108 (if (and parse (eq major-mode 'dired-mode)) | |
109 (progn | |
110 (setq efs-dired-host-type host-type | |
111 efs-dired-listing-type listing-type | |
112 efs-dired-listing-type-string | |
113 (and efs-show-host-type-in-dired | |
114 (concat " " | |
115 (symbol-name | |
116 efs-dired-listing-type)))) | |
117 (if (memq host-type '(bsd-unix next-unix)) | |
118 (setq dired-ls-F-marks-symlinks nil) | |
119 (if (memq host-type '(sysV-unix apollo-unix)) | |
120 (setq dired-ls-F-marks-symlinks t))))) | |
121 (if subdir | |
122 ;; a 1-line re-list | |
123 (save-excursion | |
124 (efs-update-file-info | |
125 host-type file efs-data-buffer-name) | |
126 (goto-char mk) | |
127 (let ((new-subdir (condition-case nil | |
128 (dired-current-directory) | |
129 (error nil))) | |
130 buffer-read-only) | |
131 (if (and new-subdir | |
132 (string-equal subdir new-subdir)) | |
133 (progn | |
134 ;; Is there an existing entry? | |
135 (if (dired-goto-file file) | |
136 (progn | |
137 (delete-region | |
138 (save-excursion | |
139 (skip-chars-backward "^\n\r") | |
140 (1- (point))) | |
141 (progn | |
142 (skip-chars-forward "^\n\r") | |
143 (point))) | |
144 (goto-char mk))) | |
145 (insert listing) | |
146 (save-restriction | |
147 (narrow-to-region mk (point)) | |
148 (efs-dired-fixup-listing | |
149 listing-type file path switches wildcard) | |
150 (efs-dired-ls-trim | |
151 listing-type) | |
152 ;; save-excursion loses if fixup had to | |
153 ;; remove and re-add the region. Say for | |
154 ;; sorting. | |
155 (goto-char (point-max))) | |
156 (if (and nowait (eq major-mode 'dired-mode)) | |
157 (dired-after-add-entry | |
158 (marker-position mk) | |
159 marker-char)))))) | |
160 (goto-char mk) | |
161 (let (buffer-read-only) | |
162 (insert listing) | |
163 (save-restriction | |
164 (narrow-to-region mk (point)) | |
165 (efs-dired-fixup-listing | |
166 listing-type file path switches wildcard) | |
167 (goto-char (point-max)))))))))) | |
168 ;; Return 0 if synch, nil if asynch | |
169 (if nowait nil 0))) | |
170 | |
171 ;;; Functions for cleaning listings. | |
172 | |
173 (efs-defun efs-dired-ls-trim nil () | |
174 ;; Trims dir listings, so that the listing of a single file is one line. | |
175 nil) | |
176 | |
177 (efs-defun efs-dired-fixup-listing nil (file path &optional switches wildcard) | |
178 ;; FILE is in efs syntax. | |
179 ;; PATH is just the remote path. | |
180 ;; Some ftpd's put the whole directory name in front of each filename. | |
181 ;; Seems to depend in a strange way on server-client interaction. | |
182 ;; Walk down the listing generated and remove this stuff. | |
183 ;; SWITCHES is a string. | |
184 (if (memq efs-key efs-unix-host-types) | |
185 (let ((continue t) | |
186 spot bol) | |
187 (goto-char (point-min)) | |
188 (while (and (not (eobp)) continue) | |
189 (and (setq bol (point) | |
190 spot (dired-manual-move-to-filename nil bol)) | |
191 (setq continue (= (following-char) ?/)) | |
192 (dired-manual-move-to-end-of-filename t bol) | |
193 (progn | |
194 (skip-chars-backward "^/") | |
195 (delete-region spot (point)))) | |
196 (forward-line 1)) | |
197 (efs-save-match-data | |
198 (if (and switches (string-match "R" switches) | |
199 (not (string-match "d" switches))) | |
200 (let ((subdir-regexp "^\\(/[^ \n\r]+\\):[\n\r]") | |
201 name) | |
202 (goto-char (point-min)) | |
203 (while (re-search-forward subdir-regexp nil t) | |
204 (goto-char (match-beginning 0)) | |
205 ;; There may be /./ type nonsense. | |
206 ;; expand-file-name will handle it. | |
207 (setq name (expand-file-name | |
208 (buffer-substring (point) (match-end 0)))) | |
209 (delete-region (point) (match-end 0)) | |
210 (insert (efs-replace-path-component file name))))))))) | |
211 | |
212 | |
213 ;;;; ------------------------------------------------------------ | |
214 ;;;; Tree Dired support | |
215 ;;;; ------------------------------------------------------------ | |
216 | |
217 ;;; efs-dired keymap | |
218 | |
219 (defvar efs-dired-map nil | |
220 "Keymap for efs commands in dired buffers.") | |
221 | |
222 (if efs-dired-map | |
223 () | |
224 (setq efs-dired-map (make-sparse-keymap)) | |
225 (define-key efs-dired-map "c" 'efs-dired-close-ftp-process) | |
226 (define-key efs-dired-map "k" 'efs-dired-kill-ftp-process) | |
227 (define-key efs-dired-map "o" 'efs-dired-display-ftp-process-buffer) | |
228 (define-key efs-dired-map "p" 'efs-dired-ping-connection)) | |
229 | |
230 (fset 'efs-dired-prefix efs-dired-map) | |
231 | |
232 ;;; Functions for dealing with the FTP process | |
233 | |
234 (defun efs-dired-close-ftp-process () | |
235 "Close the FTP process for the current dired buffer. | |
236 Closing causes the connection to be dropped, but efs will retain its | |
237 cached data for the connection. This will make it more efficient to | |
238 reopen the connection." | |
239 (interactive) | |
240 (or efs-dired-host-type | |
241 (error "Dired buffer is not for a remote directory.")) | |
242 (efs-close-ftp-process (current-buffer)) | |
243 (let ((parsed (efs-ftp-path default-directory))) | |
244 (message "Closed FTP connection for %s@%s." (nth 1 parsed) (car parsed)))) | |
245 | |
246 (defun efs-dired-kill-ftp-process () | |
247 "Kills the FTP process for the current dired buffer. | |
248 Killing causes the connection to be closed, the process buffer to be killed, | |
249 and most of efs's cached data to be wiped." | |
250 (interactive) | |
251 (or efs-dired-host-type | |
252 (error "Dired buffer is not for a remote directory.")) | |
253 (efs-kill-ftp-process (current-buffer)) | |
254 (let ((parsed (efs-ftp-path default-directory))) | |
255 (message "Killed FTP connection for %s@%s." (nth 1 parsed) (car parsed)))) | |
256 | |
257 (defun efs-dired-display-ftp-process-buffer () | |
258 "Displays in another window the FTP process buffer for a dired buffer." | |
259 (interactive) | |
260 (or efs-dired-host-type | |
261 (error "Dired buffer is not for a remote directory.")) | |
262 (efs-display-ftp-process-buffer (current-buffer))) | |
263 | |
264 (defun efs-dired-ping-connection () | |
265 "Pings FTP connection associated with current dired buffer." | |
266 (interactive) | |
267 (or efs-dired-host-type | |
268 (error "Dired buffer is not for a remote directory.")) | |
269 (efs-ping-ftp-connection (current-buffer))) | |
270 | |
271 | |
272 ;;; Reading in dired buffers. | |
273 | |
274 (defun efs-dired-revert (&optional arg noconfirm) | |
275 (let ((efs-ls-uncache t)) | |
276 (dired-revert arg noconfirm))) | |
277 | |
278 (defun efs-dired-default-dir-function () | |
279 (let* ((cd (dired-current-directory)) | |
280 (parsed (efs-ftp-path cd))) | |
281 (if parsed | |
282 (efs-save-match-data | |
283 (let ((tail directory-abbrev-alist)) | |
284 (while tail | |
285 (if (string-match (car (car tail)) cd) | |
286 (setq cd (concat (cdr (car tail)) | |
287 (substring cd (match-end 0))) | |
288 parsed nil)) | |
289 (setq tail (cdr tail))) | |
290 (apply 'efs-unexpand-parsed-filename | |
291 (or parsed (efs-ftp-path cd))))) | |
292 cd))) | |
293 | |
294 (defun efs-dired-before-readin () | |
295 ;; Put in the dired-before-readin-hook. | |
296 (let ((parsed (efs-ftp-path default-directory))) | |
297 (if parsed | |
298 (let ((host (car parsed)) | |
299 (user (nth 1 parsed))) | |
300 (setq efs-dired-listing-type (efs-listing-type host user) | |
301 efs-dired-host-type (efs-host-type host) | |
302 efs-dired-listing-type-string | |
303 (and efs-show-host-type-in-dired | |
304 (concat " " (symbol-name efs-dired-listing-type)))) | |
305 (set (make-local-variable 'revert-buffer-function) | |
306 (function efs-dired-revert)) | |
307 (set (make-local-variable 'default-directory-function) | |
308 (function efs-dired-default-dir-function)) | |
309 (set (make-local-variable 'dired-verify-modtimes) | |
310 (null (null (and | |
311 efs-dired-verify-modtime-host-regexp | |
312 (efs-save-match-data | |
313 (let ((case-fold-search t)) | |
314 (string-match | |
315 efs-dired-verify-modtime-host-regexp host)) | |
316 (or efs-dired-verify-anonymous-modtime | |
317 (not (efs-anonymous-p user)))))))) | |
318 ;; The hellsoft ftp server mixes up cases. | |
319 ;; However, we may not be able to catch this until | |
320 ;; after the first directory is listed. | |
321 (if (and | |
322 (eq efs-dired-host-type 'hell) | |
323 (not (string-equal default-directory | |
324 (setq default-directory | |
325 (downcase default-directory))))) | |
326 (or (string-equal (buffer-name) (downcase (buffer-name))) | |
327 (rename-buffer (generate-new-buffer-name | |
328 (directory-file-name default-directory))))) | |
329 ;; Setup the executable and directory regexps | |
330 (let ((eentry (assq efs-dired-listing-type | |
331 efs-dired-re-exe-alist)) | |
332 (dentry (assq efs-dired-listing-type | |
333 efs-dired-re-dir-alist))) | |
334 (if eentry | |
335 (set (make-local-variable 'dired-re-exe) (cdr eentry))) | |
336 (if dentry | |
337 (set (make-local-variable 'dired-re-dir) (cdr dentry)))) | |
338 ;; No switches are sent to dumb hosts, so don't confuse dired. | |
339 ;; I hope that dired doesn't get excited if it doesn't see the l | |
340 ;; switch. If it does, then maybe fake things by setting this to | |
341 ;; "-Al". | |
342 (if (eq efs-dired-listing-type 'vms) | |
343 (setq dired-internal-switches | |
344 (delq ?F dired-internal-switches)) | |
345 (if (memq efs-dired-host-type efs-dumb-host-types) | |
346 (setq dired-internal-switches '(?l ?A) | |
347 ;; Don't lie on the mode line | |
348 dired-sort-mode ""))) | |
349 ;; If the remote file system is version-based, don't set | |
350 ;; dired-kept-versions to 0. It will flag the most recent | |
351 ;; copy of the file for deletion -- this isn't really a backup. | |
352 (if (memq efs-dired-host-type efs-version-host-types) | |
353 (set (make-local-variable 'dired-kept-versions) | |
354 (max 1 dired-kept-versions))))))) | |
355 | |
356 (efs-defun efs-dired-insert-headerline (&use efs-dired-listing-type) (dir) | |
357 "Documented as original." | |
358 (efs-real-dired-insert-headerline dir)) | |
359 | |
360 (defun efs-dired-uncache (file dir-p) | |
361 ;; Remove FILE from cache. | |
362 (if dir-p | |
363 (efs-del-from-ls-cache file nil t) | |
364 (efs-del-from-ls-cache file t nil))) | |
365 | |
366 ;;; Checking modtimes of directories. | |
367 ;; | |
368 ;; This only runs if efs-dired-verify-anonymous-modtime and | |
369 ;; efs-verify-modtime-host-regexp turn it on. Few (any?) FTP servers | |
370 ;; support getting MDTM for directories. As usual, we cache whether | |
371 ;; this works, and don't keep senselessly trying it if it doesn't. | |
372 | |
373 (defun efs-dired-file-modtime (file) | |
374 ;; Returns the modtime. | |
375 (let* ((parsed (efs-ftp-path file)) | |
376 (host (car parsed)) | |
377 (user (nth 1 parsed)) | |
378 (rpath (nth 2 parsed))) | |
379 (and (null (efs-get-host-property host 'dir-mdtm-failed)) | |
380 (let ((result (efs-send-cmd host user (list 'quote 'mdtm rpath) | |
381 (and (eq efs-verbose t) | |
382 "Getting modtime"))) | |
383 mp) | |
384 (if (and (null (car result)) | |
385 (setq mp (efs-parse-mdtime (nth 1 result)))) | |
386 (let ((ent (efs-get-file-entry file))) | |
387 (if ent | |
388 (setcdr ent (list (nth 1 ent) (nth 2 ent) | |
389 (nth 3 ent) (nth 4 ent) mp))) | |
390 parsed) | |
391 (efs-set-host-property host 'dir-mdtm-failed t) | |
392 nil))))) | |
393 | |
394 (defun efs-dired-set-file-modtime (file alist) | |
395 ;; This works asynch. | |
396 (let* ((parsed (efs-ftp-path file)) | |
397 (host (car parsed)) | |
398 (user (nth 1 parsed)) | |
399 (path (nth 2 parsed))) | |
400 (if (efs-get-host-property host 'dir-mdtm-failed) | |
401 (let ((elt (assoc file alist))) | |
402 (if elt (setcar (nthcdr 4 elt) nil))) | |
403 (efs-send-cmd | |
404 host user (list 'quote 'mdtm path) nil nil | |
405 (efs-cont (result line cont-lines) (file alist host) | |
406 (let ((elt (assoc file alist)) | |
407 modtime) | |
408 (if (and (null result) (setq modtime (efs-parse-mdtime line))) | |
409 (if elt (setcar (nthcdr 4 elt) modtime)) | |
410 (if elt (setcar (nthcdr 4 elt) nil)) | |
411 (efs-set-host-property host 'dir-mdtm-failed t)))) | |
412 0) ; Always do this NOWAIT = 0 | |
413 nil))) ; return NIL | |
414 | |
415 ;;; Asynch insertion of subdirs. Used when renaming subdirs. | |
416 | |
417 (defun efs-dired-insert-subdir (dirname &optional noerror nowait) | |
418 (let ((buff (current-buffer)) | |
419 (switches (delq ?R (copy-sequence dired-internal-switches)))) | |
420 (efs-ls | |
421 dirname (dired-make-switches-string switches) | |
422 t nil noerror nowait | |
423 (efs-cont (listing) (dirname buff switches) | |
424 (if (and listing (get-buffer buff)) | |
425 (save-excursion | |
426 (set-buffer buff) | |
427 (save-excursion | |
428 (let ((elt (assoc dirname dired-subdir-alist)) | |
429 mark-list) | |
430 (if elt | |
431 (setq mark-list (dired-insert-subdir-del elt)) | |
432 (dired-insert-subdir-newpos dirname)) | |
433 (dired-insert-subdir-doupdate | |
434 dirname | |
435 (efs-dired-insert-subdir-do-insert dirname listing) | |
436 switches elt mark-list))))))))) | |
437 | |
438 (defun efs-dired-insert-subdir-do-insert (dirname listing) | |
439 (let ((begin (point)) | |
440 indent-tabs-mode end) | |
441 (insert listing) | |
442 (setq end (point-marker)) | |
443 (indent-rigidly begin end 2) | |
444 (goto-char begin) | |
445 (dired-insert-headerline dirname) | |
446 ;; If the listing has null lines `quote' them so that "\n\n" delimits | |
447 ;; subdirs. This is OK, because we aren't inserting -R listings. | |
448 (save-excursion | |
449 (while (search-forward "\n\n" end t) | |
450 (forward-char -1) | |
451 (insert " "))) | |
452 ;; point is now like in dired-build-subdir-alist | |
453 (prog1 | |
454 (list begin (marker-position end)) | |
455 (set-marker end nil)))) | |
456 | |
457 ;;; Moving around in dired buffers. | |
458 | |
459 (efs-defun efs-dired-manual-move-to-filename (&use efs-dired-listing-type) | |
460 (&optional raise-error bol eol) | |
461 "Documented as original." | |
462 (efs-real-dired-manual-move-to-filename raise-error bol eol)) | |
463 | |
464 (efs-defun efs-dired-manual-move-to-end-of-filename | |
465 (&use efs-dired-listing-type) (&optional no-error bol eol) | |
466 "Documented as original." | |
467 (efs-real-dired-manual-move-to-end-of-filename no-error bol eol)) | |
468 | |
469 (efs-defun efs-dired-make-filename-string (&use efs-dired-listing-type) | |
470 (filename &optional reverse) | |
471 "Documented as original." | |
472 ;; This translates file names from the way that they are displayed | |
473 ;; in listings to the way that the user gives them in the minibuffer. | |
474 ;; For example, in CMS this should take "FOO BAR" to "FOO.BAR". | |
475 filename) | |
476 | |
477 (defun efs-dired-find-file () | |
478 "Documented as original." | |
479 (interactive) | |
480 (find-file | |
481 (if (memq efs-dired-host-type efs-version-host-types) | |
482 (efs-internal-file-name-sans-versions | |
483 efs-dired-host-type (dired-get-filename) t) | |
484 (dired-get-filename)))) | |
485 | |
486 (defun efs-dired-find-file-other-window (&optional display) | |
487 "Documented as original." | |
488 (interactive "P") | |
489 (if display | |
490 (dired-display-file) | |
491 (let ((file (dired-get-filename))) | |
492 (if (memq efs-dired-host-type efs-version-host-types) | |
493 (setq file (efs-internal-file-name-sans-versions | |
494 efs-dired-host-type file t))) | |
495 (find-file-other-window file)))) | |
496 | |
497 (defun efs-dired-display-file () | |
498 "Documented as original." | |
499 (interactive) | |
500 (let ((file (dired-get-filename))) | |
501 (if (memq efs-dired-host-type efs-version-host-types) | |
502 (setq file (efs-internal-file-name-sans-versions | |
503 efs-dired-host-type file t))) | |
504 (display-buffer (find-file-noselect file)))) | |
505 | |
506 (defun efs-dired-find-file-other-frame () | |
507 "Documented as original." | |
508 (interactive) | |
509 (find-file-other-frame | |
510 (if (memq efs-dired-host-type efs-version-host-types) | |
511 (efs-internal-file-name-sans-versions | |
512 efs-dired-host-type (dired-get-filename) t) | |
513 (dired-get-filename)))) | |
514 | |
515 ;;; Creating and deleting new directories. | |
516 | |
517 (defun efs-dired-recursive-delete-directory (fn) | |
518 ;; Does recursive deletion of remote directories for dired. | |
519 (or (file-exists-p fn) | |
520 (signal 'file-error | |
521 (list "Removing old file name" "no such directory" fn))) | |
522 (efs-dired-internal-recursive-delete-directory fn)) | |
523 | |
524 (defun efs-dired-internal-recursive-delete-directory (fn) | |
525 (if (eq (car (file-attributes fn)) t) | |
526 (let ((files (efs-directory-files fn))) | |
527 (if files | |
528 (mapcar (function | |
529 (lambda (ent) | |
530 (or (string-equal "." ent) | |
531 (string-equal ".." ent) | |
532 (efs-dired-internal-recursive-delete-directory | |
533 (expand-file-name ent fn))))) | |
534 files)) | |
535 (efs-delete-directory fn)) | |
536 (condition-case err | |
537 (efs-delete-file fn) | |
538 (ftp-error (if (and (nth 2 err) (stringp (nth 2 err)) | |
539 (efs-save-match-data | |
540 (string-match "^FTP Error: \"550 " (nth 2 err)))) | |
541 (message "File %s already deleted." fn) | |
542 (signal (car err) (cdr err))))))) | |
543 | |
544 ;;; File backups and versions. | |
545 | |
546 (efs-defun efs-dired-flag-backup-files | |
547 (&use efs-dired-host-type) (&optional unflag-p) | |
548 "Documented as original." | |
549 (interactive "P") | |
550 (efs-real-dired-flag-backup-files unflag-p)) | |
551 | |
552 (efs-defun efs-dired-collect-file-versions (&use efs-dired-host-type) () | |
553 ;; If it looks like a file has versions, return a list of the versions. | |
554 ;; The return value is ((FILENAME . (VERSION1 VERSION2 ...)) ...) | |
555 (efs-real-dired-collect-file-versions)) | |
556 | |
557 ;;; Sorting dired buffers | |
558 | |
559 (defun efs-dired-file-name-lessp (name1 name2) | |
560 (if (and efs-dired-host-type | |
561 (memq efs-dired-host-type efs-case-insensitive-host-types)) | |
562 (string< (downcase name1) (downcase name2)) | |
563 (string< name1 name2))) | |
564 | |
565 ;;; Support for async file creators. | |
566 | |
567 (defun efs-dired-copy-file (from to ok-flag &optional cont nowait) | |
568 ;; Version of dired-copy-file for remote files. | |
569 ;; Assumes that filenames are already expanded. | |
570 (dired-handle-overwrite to) | |
571 (efs-copy-file-internal from (efs-ftp-path from) to (efs-ftp-path to) | |
572 ok-flag dired-copy-preserve-time 0 cont nowait)) | |
573 | |
574 (defun efs-dired-rename-file (from to ok-flag &optional cont nowait | |
575 insert-subdir) | |
576 ;; Version of dired-rename-file for remote files. | |
577 (dired-handle-overwrite to) | |
578 (efs-rename-file-internal | |
579 from to ok-flag nil | |
580 (efs-cont (result line cont-lines) (from to cont insert-subdir) | |
581 (if result | |
582 (if cont | |
583 (efs-call-cont cont result line cont-lines) | |
584 (signal 'ftp-error | |
585 (list "Dired Renaming" | |
586 (format "FTP Error: \"%s\"" line) | |
587 from to))) | |
588 (dired-remove-file from) | |
589 ;; Silently rename the visited file of any buffer visiting this file. | |
590 ;; We do not maintain inserted subdirs for remote | |
591 (efs-dired-rename-update-buffers from to insert-subdir) | |
592 (if cont (efs-call-cont cont result line cont-lines)))) | |
593 nowait)) | |
594 | |
595 (defun efs-dired-rename-update-buffers (from to &optional insert-subdir) | |
596 (if (get-file-buffer from) | |
597 (save-excursion | |
598 (set-buffer (get-file-buffer from)) | |
599 (let ((modflag (buffer-modified-p))) | |
600 (set-visited-file-name to) ; kills write-file-hooks | |
601 (set-buffer-modified-p modflag))) | |
602 ;; It's a directory. More work to do. | |
603 (let ((blist (buffer-list)) | |
604 (from-dir (file-name-as-directory from)) | |
605 (to-dir (file-name-as-directory to))) | |
606 (save-excursion | |
607 (while blist | |
608 (set-buffer (car blist)) | |
609 (setq blist (cdr blist)) | |
610 (cond | |
611 (buffer-file-name | |
612 (if (dired-in-this-tree buffer-file-name from-dir) | |
613 (let ((modflag (buffer-modified-p))) | |
614 (unwind-protect | |
615 (set-visited-file-name | |
616 (concat to-dir (substring buffer-file-name | |
617 (length from-dir)))) | |
618 (set-buffer-modified-p modflag))))) | |
619 (dired-directory | |
620 (if (string-equal from-dir (expand-file-name default-directory)) | |
621 ;; If top level directory was renamed, lots of things | |
622 ;; have to be updated. | |
623 (progn | |
624 (dired-unadvertise from-dir) | |
625 (setq default-directory to-dir | |
626 dired-directory | |
627 ;; Need to beware of wildcards. | |
628 (expand-file-name | |
629 (file-name-nondirectory dired-directory) | |
630 to-dir)) | |
631 (let ((new-name (file-name-nondirectory | |
632 (directory-file-name dired-directory)))) | |
633 ;; Try to rename buffer, but just leave old name if new | |
634 ;; name would already exist (don't try appending "<%d>") | |
635 ;; Why? --sandy 19-8-94 | |
636 (or (get-buffer new-name) | |
637 (rename-buffer new-name))) | |
638 (dired-advertise)) | |
639 (and insert-subdir | |
640 (assoc (file-name-directory (directory-file-name to)) | |
641 dired-subdir-alist) | |
642 (if (efs-ftp-path to) | |
643 (efs-dired-insert-subdir to t 1) | |
644 (dired-insert-subdir to))))))))))) | |
645 | |
646 (defun efs-dired-make-relative-symlink (from to ok-flag &optional cont nowait) | |
647 ;; efs version of dired-make-relative-symlink | |
648 ;; Called as a file-name-handler when dired-make-relative-symlink is | |
649 ;; called interactively. | |
650 ;; efs-dired-create-files calls it directly to supply CONT | |
651 ;; and NOWAIT args. | |
652 (setq from (directory-file-name from) | |
653 to (directory-file-name to)) | |
654 (efs-make-symbolic-link-internal | |
655 (dired-make-relative from (file-name-directory to) t) | |
656 to ok-flag cont nowait)) | |
657 | |
658 (defun efs-dired-create-files (file-creator operation fn-list name-constructor | |
659 &optional marker-char query | |
660 implicit-to) | |
661 "Documented as original." | |
662 (if (catch 'found | |
663 (let ((list fn-list) | |
664 val) | |
665 (while list | |
666 (if (setq val (efs-ftp-path (car list))) | |
667 (throw 'found val) | |
668 (if (setq val (funcall name-constructor (car list))) | |
669 (throw 'found (efs-ftp-path val)) | |
670 (setq list (cdr list))))))) | |
671 (progn | |
672 (cond ((eq file-creator 'dired-copy-file) | |
673 (setq file-creator 'efs-dired-copy-file)) | |
674 ((eq file-creator 'dired-rename-file) | |
675 (setq file-creator 'efs-dired-rename-file)) | |
676 ((eq file-creator 'make-symbolic-link) | |
677 (setq file-creator 'efs-make-symbolic-link-internal)) | |
678 ((eq file-creator 'add-name-to-file) | |
679 (setq file-creator 'efs-add-name-to-file-internal)) | |
680 ((eq file-creator 'dired-make-relative-symlink) | |
681 (setq file-creator 'efs-dired-make-relative-symlink)) | |
682 ((eq file-creator 'dired-compress-file) | |
683 (setq file-creator 'efs-dired-compress-file)) | |
684 ((error "Unable to perform operation %s on remote hosts." | |
685 file-creator))) | |
686 ;; use the process-filter driven routine rather than the iterative one. | |
687 (efs-dcf-1 file-creator operation fn-list name-constructor | |
688 (if (eq marker-char t) | |
689 (mapcar 'dired-file-marker fn-list) | |
690 marker-char) | |
691 query (buffer-name (current-buffer)) | |
692 nil ;overwrite-query | |
693 nil ;dired-overwrite-backup-query | |
694 nil ;dired-file-creator-query | |
695 nil ;failures | |
696 nil ;skipped | |
697 0 ;success-count | |
698 (length fn-list) ;total | |
699 implicit-to | |
700 (and (eq file-creator 'efs-dired-rename-file) | |
701 (delq nil | |
702 (mapcar | |
703 (function | |
704 (lambda (x) | |
705 (and (assoc (file-name-as-directory x) | |
706 dired-subdir-alist) | |
707 x))) | |
708 fn-list))))) | |
709 ;; normal case... use the interative routine... much cheaper. | |
710 (efs-real-dired-create-files file-creator operation fn-list | |
711 name-constructor marker-char query | |
712 implicit-to))) | |
713 | |
714 (defun efs-dcf-1 (file-creator operation fn-list name-constructor | |
715 markers query buffer-name overwrite-query | |
716 overwrite-backup-query file-creator-query | |
717 failures skipped success-count total | |
718 implicit-to insertions) | |
719 (if (null fn-list) | |
720 (efs-dcf-3 failures operation total skipped | |
721 success-count buffer-name) | |
722 (let* ((from (car fn-list)) | |
723 ;; For dired-handle-overwrite and the file-creator-query, | |
724 ;; need to set these 2 fluid vars according to the cont data. | |
725 (dired-overwrite-backup-query overwrite-backup-query) | |
726 (dired-file-creator-query file-creator-query) | |
727 (to (funcall name-constructor from)) | |
728 (marker-char (if (consp markers) | |
729 (prog1 (car markers) | |
730 (setq markers (cdr markers))) | |
731 markers)) | |
732 (fn-list (cdr fn-list))) | |
733 (if to | |
734 (if (equal to from) | |
735 (progn | |
736 (dired-log buffer-name "Cannot %s to same file: %s\n" | |
737 (downcase operation) from) | |
738 (efs-dcf-1 file-creator operation fn-list name-constructor | |
739 markers query buffer-name overwrite-query | |
740 dired-overwrite-backup-query | |
741 dired-file-creator-query failures | |
742 (cons (dired-make-relative from nil t) skipped) | |
743 success-count total implicit-to insertions)) | |
744 (if (or (null query) | |
745 (funcall query from to)) | |
746 (let* ((overwrite (let (jka-compr-enabled) | |
747 ;; Don't let jka-compr fool us. | |
748 (file-exists-p to))) | |
749 (overwrite-confirmed ; for dired-handle-overwrite | |
750 (and overwrite | |
751 (let ((help-form '(format "\ | |
752 Type SPC or `y' to overwrite file `%s', | |
753 DEL or `n' to skip to next, | |
754 ESC or `q' to not overwrite any of the remaining files, | |
755 `!' to overwrite all remaining files with no more questions." to))) | |
756 (dired-query 'overwrite-query | |
757 "Overwrite `%s'?" to))))) | |
758 (condition-case err | |
759 (let ((dired-unhandle-add-files | |
760 (cons to dired-unhandle-add-files))) | |
761 (if implicit-to | |
762 (funcall file-creator from overwrite-confirmed | |
763 (list (function efs-dcf-2) | |
764 file-creator operation fn-list | |
765 name-constructor markers | |
766 query marker-char | |
767 buffer-name to from overwrite | |
768 overwrite-confirmed overwrite-query | |
769 dired-overwrite-backup-query | |
770 dired-file-creator-query | |
771 failures skipped success-count | |
772 total implicit-to insertions) | |
773 t) | |
774 (apply file-creator from to overwrite-confirmed | |
775 (list (function efs-dcf-2) | |
776 file-creator operation fn-list | |
777 name-constructor markers | |
778 query marker-char | |
779 buffer-name to from overwrite | |
780 overwrite-confirmed overwrite-query | |
781 dired-overwrite-backup-query | |
782 dired-file-creator-query | |
783 failures skipped success-count total | |
784 implicit-to insertions) | |
785 (if insertions | |
786 (list t insertions) | |
787 '(t))))) | |
788 (error ; FILE-CREATOR aborted | |
789 (efs-dcf-2 'failed ;result | |
790 (format "%s" err) ;line | |
791 "" file-creator operation fn-list | |
792 name-constructor markers query marker-char | |
793 buffer-name to from overwrite | |
794 overwrite-confirmed overwrite-query | |
795 dired-overwrite-backup-query | |
796 dired-file-creator-query failures skipped | |
797 success-count total implicit-to insertions)))) | |
798 (efs-dcf-1 file-creator operation fn-list name-constructor | |
799 markers query buffer-name overwrite-query | |
800 dired-overwrite-backup-query dired-file-creator-query | |
801 failures | |
802 (cons (dired-make-relative from nil t) skipped) | |
803 success-count total implicit-to insertions))) | |
804 (efs-dcf-1 file-creator operation fn-list name-constructor | |
805 markers query buffer-name overwrite-query | |
806 dired-overwrite-backup-query dired-file-creator-query | |
807 failures (cons (dired-make-relative from nil t) skipped) | |
808 success-count total implicit-to insertions))))) | |
809 | |
810 (defun efs-dcf-2 (result line cont-lines file-creator operation fn-list | |
811 name-constructor markers query marker-char | |
812 buffer-name to from overwrite overwrite-confirmed | |
813 overwrite-query overwrite-backup-query | |
814 file-creator-query failures skipped success-count | |
815 total implicit-to insertions) | |
816 (if result | |
817 (progn | |
818 (setq failures (cons (dired-make-relative from nil t) failures)) | |
819 (dired-log buffer-name "%s `%s' to `%s' failed:\n%s\n" | |
820 operation from to line)) | |
821 (setq success-count (1+ success-count)) | |
822 (message "%s: %d of %d" operation success-count total) | |
823 (let ((efs-ls-uncache t)) | |
824 (dired-add-file to marker-char))) | |
825 ;; iterate again | |
826 (efs-dcf-1 file-creator operation fn-list name-constructor | |
827 markers query buffer-name overwrite-query overwrite-backup-query | |
828 file-creator-query failures skipped success-count total | |
829 implicit-to insertions)) | |
830 | |
831 (defun efs-dcf-3 (failures operation total skipped success-count buffer-name) | |
832 (cond | |
833 (failures | |
834 (dired-log-summary buffer-name (format "%s failed for %d of %d file%s" | |
835 operation (length failures) total | |
836 (dired-plural-s total)) failures)) | |
837 (skipped | |
838 (dired-log-summary buffer-name (format "%s: %d of %d file%s skipped" | |
839 operation (length skipped) total | |
840 (dired-plural-s total)) skipped)) | |
841 (t | |
842 (message "%s: %s file%s." | |
843 operation success-count | |
844 (dired-plural-s success-count))))) | |
845 | |
846 ;;; Running remote shell commands | |
847 | |
848 ;;; This support isn't very good. efs is really about a virtual file system, | |
849 ;;; and not remote processes. What is really required is low-level | |
850 ;;; support for start-process & call-process on remote hosts. This shouldn't | |
851 ;;; be part of efs, although. | |
852 | |
853 (defun efs-dired-shell-unhandle-file-name (filename) | |
854 ;; Puts remote file names into a form where they can be passed to remsh. | |
855 (nth 2 (efs-ftp-path filename))) | |
856 | |
857 (defun efs-dired-shell-call-process (command dir &optional in-background) | |
858 ;; Runs shell process on remote hosts. | |
859 (let* ((parsed (efs-ftp-path dir)) | |
860 (host (car parsed)) | |
861 (user (nth 1 parsed)) | |
862 (rdir (nth 2 parsed)) | |
863 (file-name-handler-alist nil)) | |
864 (or (string-equal (efs-internal-directory-file-name dir) | |
865 (efs-expand-tilde "~" (efs-host-type host) host user)) | |
866 (string-match "^cd " command) | |
867 (setq command (concat "cd " rdir "; " command))) | |
868 (setq command | |
869 (format "%s %s%s \"%s\"" ; remsh -l USER does not work well | |
870 ; on a hp-ux machine I tried | |
871 efs-remote-shell-file-name host | |
872 (if efs-remote-shell-takes-user | |
873 (concat " -l " user) | |
874 "") | |
875 command)) | |
876 (message "Doing shell command on %s..." host) | |
877 (dired-shell-call-process | |
878 command (file-name-directory efs-tmp-name-template) in-background))) | |
879 | |
880 ;;; Dired commands for running local processes on remote files. | |
881 ;; | |
882 ;; Lots of things in this section need to be re-thunk. | |
883 | |
884 (defun efs-dired-call-process (program discard &rest arguments) | |
885 "Documented as original." | |
886 ;; PROGRAM is always one of those below in the cond in dired.el. | |
887 ;; The ARGUMENTS are (nearly) always files. | |
888 (if (efs-ftp-path default-directory) | |
889 ;; Can't use efs-dired-host-type here because the current | |
890 ;; buffer is *dired-check-process output* | |
891 (condition-case oops | |
892 (cond | |
893 ((string-equal "efs-call-compress" program) | |
894 (apply 'efs-call-compress arguments)) | |
895 ((string-equal "chmod" program) | |
896 (efs-call-chmod arguments)) | |
897 (t (error "Unknown remote command: %s" program))) | |
898 (ftp-error (dired-log (buffer-name (current-buffer)) | |
899 (format "%s: %s, %s\n" | |
900 (nth 1 oops) | |
901 (nth 2 oops) | |
902 (nth 3 oops)))) | |
903 (error (dired-log (buffer-name (current-buffer)) | |
904 (format "%s\n" (nth 1 oops))))) | |
905 (apply 'call-process program nil (not discard) nil arguments))) | |
906 | |
907 (defun efs-dired-make-compressed-filename (name &optional method) | |
908 ;; Version of dired-make-compressed-filename for efs. | |
909 ;; If NAME is in the syntax of a compressed file (according to | |
910 ;; dired-compression-method-alist), return the data (a list) from this | |
911 ;; alist on how to uncompress it. Otherwise, return a string, the | |
912 ;; uncompressed form of this file name. This is computed using the optional | |
913 ;; argument METHOD (a symbol). If METHOD is nil, the ambient value of | |
914 ;; dired-compression-method is used. | |
915 (let* ((host-type (efs-host-type (car (efs-ftp-path name)))) | |
916 (ef-alist (if (memq host-type efs-single-extension-host-types) | |
917 (mapcar | |
918 (function | |
919 (lambda (elt) | |
920 (list (car elt) | |
921 (mapconcat | |
922 (function | |
923 (lambda (char) | |
924 (if (= char ?.) | |
925 "-" | |
926 (char-to-string char)))) | |
927 (nth 1 elt) "") | |
928 (nth 2 elt) | |
929 (nth 3 elt)))) | |
930 dired-compression-method-alist) | |
931 dired-compression-method-alist)) | |
932 (alist ef-alist) | |
933 (len (length name)) | |
934 ext ext-len result) | |
935 (if (memq host-type efs-version-host-types) | |
936 (setq name (efs-internal-file-name-sans-versions host-type name))) | |
937 (if (memq host-type efs-case-insensitive-host-types) | |
938 (let ((name (downcase name))) | |
939 (while alist | |
940 (if (and (> len | |
941 (setq ext-len (length (setq ext (nth 1 (car alist)))))) | |
942 (string-equal (downcase ext) | |
943 (substring name (- ext-len)))) | |
944 (setq result (car alist) | |
945 alist nil) | |
946 (setq alist (cdr alist))))) | |
947 (while alist | |
948 (if (and (> len | |
949 (setq ext-len (length (setq ext (nth 1 (car alist)))))) | |
950 (string-equal ext (substring name (- ext-len)))) | |
951 (setq result (car alist) | |
952 alist nil) | |
953 (setq alist (cdr alist))))) | |
954 (or result | |
955 (concat name | |
956 (nth 1 (or (assq (or method dired-compression-method) | |
957 ef-alist) | |
958 (error "Unknown compression method: %s" | |
959 (or method dired-compression-method)))))))) | |
960 | |
961 (defun efs-dired-compress-file (file ok-flag &optional cont nowait) | |
962 ;; Version of dired-compress-file for remote files. | |
963 (let* ((compressed-fn (efs-dired-make-compressed-filename file)) | |
964 (host (car (efs-ftp-path file))) | |
965 (host-type (efs-host-type host))) | |
966 (cond ((file-symlink-p file) | |
967 (if cont | |
968 (efs-call-cont | |
969 cont 'failed | |
970 (format "Cannot compress %s, a symbolic link." file) "") | |
971 (signal 'file-error (list "Compress error:" file | |
972 "a symbolic link")))) | |
973 ((listp compressed-fn) | |
974 (let ((newname (substring (if (memq host-type | |
975 efs-version-host-types) | |
976 (efs-internal-file-name-sans-versions | |
977 host-type file) | |
978 file) | |
979 0 (- (length (nth 1 compressed-fn))))) | |
980 (program (nth 3 compressed-fn))) | |
981 (if (and (memq host-type efs-unix-host-types) | |
982 (null (efs-get-host-property host 'exec-failed)) | |
983 (null (eq (efs-get-host-property | |
984 host | |
985 (intern | |
986 (concat | |
987 "exec-" | |
988 (efs-compress-progname (car program))))) | |
989 'failed))) | |
990 (efs-call-remote-compress | |
991 program file newname t ok-flag | |
992 (efs-cont (result line cont-lines) (program file newname | |
993 cont nowait) | |
994 (if result | |
995 (if (eq result 'unsupported) | |
996 (efs-call-compress program file newname | |
997 t t cont nowait) | |
998 (if cont | |
999 (efs-call-cont cont result line cont-lines) | |
1000 (signal 'ftp-error | |
1001 (list "Uncompressing file" | |
1002 (format "FTP Error: \"%s\" " line) | |
1003 file)))) | |
1004 (if cont (efs-call-cont cont result line cont-lines)))) | |
1005 nowait) | |
1006 (efs-call-compress | |
1007 program file newname t ok-flag cont nowait) | |
1008 newname))) | |
1009 ((stringp compressed-fn) | |
1010 (let ((program (nth 2 (assq dired-compression-method | |
1011 dired-compression-method-alist)))) | |
1012 (if (and (memq host-type efs-unix-host-types) | |
1013 (null (efs-get-host-property host 'exec-failed)) | |
1014 (null (eq (efs-get-host-property | |
1015 host | |
1016 (intern | |
1017 (concat | |
1018 "exec-" | |
1019 (efs-compress-progname (car program))))) | |
1020 'failed))) | |
1021 (efs-call-remote-compress | |
1022 program file compressed-fn nil ok-flag | |
1023 (efs-cont (result line cont-lines) (program file | |
1024 compressed-fn | |
1025 cont nowait) | |
1026 (if result | |
1027 (if (eq result 'unsupported) | |
1028 (efs-call-compress program file compressed-fn nil | |
1029 t cont nowait) | |
1030 (if cont | |
1031 (efs-call-cont cont result line cont-lines) | |
1032 (signal 'ftp-error | |
1033 (list "Compressing file" | |
1034 (format "FTP Error: \"%s\" " line) | |
1035 file)))) | |
1036 (if cont (efs-call-cont cont result line cont-lines)))) | |
1037 nowait) | |
1038 (efs-call-compress | |
1039 program file compressed-fn nil ok-flag cont nowait))) | |
1040 compressed-fn) | |
1041 (t (error "Strange error in efs-dired-compress-file."))))) | |
1042 | |
1043 (defun efs-dired-print-file (command file) | |
1044 ;; Version of dired-print-file for remote files. | |
1045 (let ((command (dired-trans-command command (list file) ""))) | |
1046 ;; Only replace the first occurence of the file name? | |
1047 (if (string-match (concat "[ ><|]\\(" (regexp-quote | |
1048 (dired-shell-quote file)) | |
1049 "\\)\\($\\|[ |><&]\\)") | |
1050 command) | |
1051 (setq command (concat (substring command 0 (match-beginning 1)) | |
1052 "%s" | |
1053 (substring command (match-end 1)))) | |
1054 (error "efs-print-command: strange error")) | |
1055 (efs-call-lpr file command))) | |
1056 | |
1057 ;;;;---------------------------------------------------------------- | |
1058 ;;;; Support for `processes' run on remote files. | |
1059 ;;;; Usually (but not necessarily) these are only called from dired. | |
1060 ;;;;---------------------------------------------------------------- | |
1061 | |
1062 (defun efs-compress-progname (program) | |
1063 ;; Returns a canonicalized i.e. without the "un", version of a compress | |
1064 ;; program name. | |
1065 (efs-save-match-data | |
1066 (if (string-equal program "gunzip") | |
1067 "gzip" | |
1068 (if (string-match "^un" program) | |
1069 (substring program (match-end 0)) | |
1070 program)))) | |
1071 | |
1072 (defun efs-call-remote-compress (program filename newname &optional uncompress | |
1073 ok-if-already-exists cont nowait) | |
1074 ;; Run a remote compress process using SITE EXEC. | |
1075 (if (or (not ok-if-already-exists) | |
1076 (numberp ok-if-already-exists)) | |
1077 (efs-barf-or-query-if-file-exists | |
1078 newname | |
1079 (if uncompress | |
1080 "uncompress to it" | |
1081 "compress to it") | |
1082 (numberp ok-if-already-exists))) | |
1083 (let* ((filename (expand-file-name filename)) | |
1084 (parsed (efs-ftp-path filename)) | |
1085 (host (car parsed)) | |
1086 (user (nth 1 parsed)) | |
1087 (rpath (nth 2 parsed))) | |
1088 (if (efs-get-host-property host 'exec-failed) | |
1089 (if cont | |
1090 (efs-call-cont cont 'unsupported "SITE EXEC not supported" "") | |
1091 (signal 'ftp-error (list "Unable to SITE EXEC" host))) | |
1092 (let* ((progname (efs-compress-progname (car program))) | |
1093 (propsym (intern (concat "exec-" progname))) | |
1094 (prop (efs-get-host-property host propsym))) | |
1095 (cond | |
1096 ((eq prop 'failed) | |
1097 (if cont | |
1098 (efs-call-cont cont 'unsupported | |
1099 (concat progname " not in FTP exec path") "") | |
1100 (signal 'ftp-error | |
1101 (list (concat progname " not in FTP exec path") host)))) | |
1102 ((eq prop 'worked) | |
1103 (efs-send-cmd | |
1104 host user | |
1105 (list 'quote 'site 'exec | |
1106 (concat (mapconcat 'identity program " ") " " rpath)) | |
1107 (concat (if uncompress "Uncompressing " "Compressing ") filename) | |
1108 nil | |
1109 (efs-cont (result line cont-lines) (host user filename cont) | |
1110 (if result | |
1111 (progn | |
1112 (efs-set-host-property host 'exec-failed t) | |
1113 (efs-error host user (concat "FTP exec Error: " line))) | |
1114 (efs-save-match-data | |
1115 (if (string-match "\n200-\\([^\n]*\\)" cont-lines) | |
1116 (let ((err (substring cont-lines (match-beginning 1) | |
1117 (match-end 1)))) | |
1118 (if cont | |
1119 (efs-call-cont cont 'failed err cont-lines) | |
1120 (efs-error host user (concat "FTP Error: " err)))) | |
1121 ;; This function only gets called for unix hosts, so | |
1122 ;; we'll use the default version of efs-delete-file-entry | |
1123 ;; and save a host-type lookup. | |
1124 (efs-delete-file-entry nil filename) | |
1125 (dired-remove-file filename) | |
1126 (if cont (efs-call-cont cont nil line cont-lines)))))) | |
1127 nowait)) | |
1128 (t ; (null prop) | |
1129 (efs-send-cmd | |
1130 host user | |
1131 (list 'quote 'site 'exec (concat progname " " "-V")) | |
1132 (format "Checking for %s executable" progname) | |
1133 nil | |
1134 (efs-cont (result line cont-lines) (propsym host program filename | |
1135 newname uncompress | |
1136 cont nowait) | |
1137 (efs-save-match-data | |
1138 (if (string-match "\n200-" cont-lines) | |
1139 (efs-set-host-property host propsym 'worked) | |
1140 (efs-set-host-property host propsym 'failed))) | |
1141 (efs-call-remote-compress program filename newname uncompress | |
1142 t ; already tested for overwrite | |
1143 cont nowait)) | |
1144 nowait))))))) | |
1145 | |
1146 (defun efs-call-compress (program filename newname &optional uncompress | |
1147 ok-if-already-exists cont nowait) | |
1148 "Perform a compress command on a remote file. | |
1149 PROGRAM is a list of the compression program and args. Works by taking a | |
1150 copy of the file, compressing it and copying the file back. Returns 0 on | |
1151 success, 1 or 2 on failure. If UNCOMPRESS is non-nil, does this instead." | |
1152 (let* ((filename (expand-file-name filename)) | |
1153 (newname (expand-file-name newname)) | |
1154 (parsed (efs-ftp-path filename)) | |
1155 (tmp1 (car (efs-make-tmp-name nil (car parsed)))) | |
1156 (tmp2 (car (efs-make-tmp-name nil (car parsed)))) | |
1157 (program (mapconcat 'identity program " "))) | |
1158 (efs-copy-file-internal | |
1159 filename parsed tmp1 nil | |
1160 t nil 2 | |
1161 (efs-cont (result line cont-lines) (filename newname tmp1 tmp2 program | |
1162 uncompress ok-if-already-exists | |
1163 cont nowait) | |
1164 (if result | |
1165 (signal 'ftp-error | |
1166 (list "Opening input file" | |
1167 (format "FTP Error: \"%s\" " line) filename)) | |
1168 (let ((err-buff (let ((default-major-mode 'fundamental-mode)) | |
1169 (get-buffer-create | |
1170 (generate-new-buffer-name | |
1171 (format | |
1172 " efs-call-compress %s" filename)))))) | |
1173 (save-excursion | |
1174 (set-buffer err-buff) | |
1175 (set (make-local-variable 'efs-call-compress-filename) filename) | |
1176 (set (make-local-variable 'efs-call-compress-newname) newname) | |
1177 (set (make-local-variable 'efs-call-compress-tmp1) tmp1) | |
1178 (set (make-local-variable 'efs-call-compress-tmp2) tmp2) | |
1179 (set (make-local-variable 'efs-call-compress-cont) cont) | |
1180 (set (make-local-variable 'efs-call-compress-nowait) nowait) | |
1181 (set (make-local-variable 'efs-call-compress-ok) | |
1182 ok-if-already-exists) | |
1183 (set (make-local-variable 'efs-call-compress-uncompress) | |
1184 uncompress) | |
1185 (set (make-local-variable 'efs-call-compress-abbr) | |
1186 (efs-relativize-filename filename)) | |
1187 (if efs-verbose | |
1188 (efs-message | |
1189 (format "%s %s..." | |
1190 (if uncompress "Uncompressing" "Compressing") | |
1191 (symbol-value (make-local-variable | |
1192 'efs-call-compress-abbr))))) | |
1193 (set-process-sentinel | |
1194 (start-process (format "efs-call-compress %s" filename) | |
1195 err-buff shell-file-name | |
1196 "-c" (format "%s %s < %s > %s" | |
1197 program | |
1198 ;; Hope -c makes the compress | |
1199 ;; program write to std out. | |
1200 "-c" | |
1201 tmp1 tmp2)) | |
1202 (function | |
1203 (lambda (proc str) | |
1204 (let ((buff (get-buffer (process-buffer proc)))) | |
1205 (if buff | |
1206 (save-excursion | |
1207 (set-buffer buff) | |
1208 (if (/= (buffer-size) 0) | |
1209 (if cont | |
1210 (efs-call-cont | |
1211 (symbol-value | |
1212 (make-local-variable | |
1213 'efs-call-compress-cont)) | |
1214 'failed | |
1215 (concat | |
1216 "failed to compress " | |
1217 (symbol-value (make-local-variable | |
1218 'efs-call-compress-filename)) | |
1219 ", " | |
1220 (buffer-substring | |
1221 (point-min) | |
1222 (progn (goto-char (point-min)) | |
1223 (end-of-line) (point)))))) | |
1224 (efs-del-tmp-name (symbol-value | |
1225 (make-local-variable | |
1226 'efs-call-compress-tmp1))) | |
1227 (let ((tmp2 (symbol-value | |
1228 (make-local-variable | |
1229 'efs-call-compress-tmp2))) | |
1230 (newname (symbol-value | |
1231 (make-local-variable | |
1232 'efs-call-compress-newname))) | |
1233 (filename (symbol-value | |
1234 (make-local-variable | |
1235 'efs-call-compress-filename))) | |
1236 (cont (symbol-value | |
1237 (make-local-variable | |
1238 'efs-call-compress-cont))) | |
1239 (nowait (symbol-value | |
1240 (make-local-variable | |
1241 'efs-call-compress-nowait))) | |
1242 (ok (symbol-value | |
1243 (make-local-variable | |
1244 'efs-call-compress-ok))) | |
1245 (uncompress | |
1246 (symbol-value | |
1247 (make-local-variable | |
1248 'efs-call-compress-uncompress)))) | |
1249 (if efs-verbose | |
1250 (efs-message | |
1251 (format "%s %s...done" | |
1252 (if uncompress | |
1253 "Uncompressing" | |
1254 "Compressing") | |
1255 (symbol-value | |
1256 (make-local-variable | |
1257 'efs-call-compress-abbr))))) | |
1258 (kill-buffer (current-buffer)) | |
1259 (efs-copy-file-internal | |
1260 tmp2 nil newname (efs-ftp-path newname) | |
1261 ok nil 1 | |
1262 (efs-cont (result line cont-lines) (cont | |
1263 tmp2 | |
1264 filename) | |
1265 (efs-del-tmp-name tmp2) | |
1266 (or result | |
1267 (let (efs-verbose) | |
1268 (efs-delete-file filename) | |
1269 (dired-remove-file filename))) | |
1270 (if cont | |
1271 (efs-call-cont cont result line | |
1272 cont-lines))) | |
1273 nowait (if uncompress nil 'image))))) | |
1274 (error "Strange error: %s" proc)))))))))) | |
1275 nowait (if uncompress 'image nil)))) | |
1276 | |
1277 (defun efs-update-mode-string (perms modes) | |
1278 ;; For PERMS of the form `u+w', and MODES a unix 9-character mode string, | |
1279 ;; computes the new mode string. | |
1280 ;; Doesn't call efs-save-match-data. The calling function should. | |
1281 (or (string-match "^[augo]+\\([+-]\\)[rwxst]+$" perms) | |
1282 (error "efs-update-mode-string: invalid perms %s" perms)) | |
1283 (let* ((who (substring perms 0 (match-beginning 1))) | |
1284 (add (= (aref perms (match-beginning 1)) ?+)) | |
1285 (what (substring perms (match-end 1))) | |
1286 (newmodes (copy-sequence modes)) | |
1287 (read (string-match "r" what)) | |
1288 (write (string-match "w" what)) | |
1289 (execute (string-match "x" what)) | |
1290 (sticky (string-match "t" what)) | |
1291 (suid (string-match "s" what))) | |
1292 (if (string-match "a" who) | |
1293 (if add | |
1294 (progn | |
1295 (if read | |
1296 (progn | |
1297 (aset newmodes 0 ?r) | |
1298 (aset newmodes 3 ?r) | |
1299 (aset newmodes 6 ?r))) | |
1300 (if write | |
1301 (progn | |
1302 (aset newmodes 1 ?w) | |
1303 (aset newmodes 4 ?w) | |
1304 (aset newmodes 7 ?w))) | |
1305 (if execute | |
1306 (let ((curr (aref newmodes 2))) | |
1307 (if (= curr ?-) | |
1308 (aset newmodes 2 ?x) | |
1309 (if (= curr ?S) | |
1310 (aset newmodes 2 ?s))) | |
1311 (setq curr (aref newmodes 5)) | |
1312 (if (= curr ?-) | |
1313 (aset newmodes 5 ?x) | |
1314 (if (= curr ?S) | |
1315 (aset newmodes 5 ?s))) | |
1316 (setq curr (aref newmodes 8)) | |
1317 (if (= curr ?-) | |
1318 (aset newmodes 8 ?x) | |
1319 (if (= curr ?T) | |
1320 (aset newmodes 8 ?t))))) | |
1321 (if suid | |
1322 (let ((curr (aref newmodes 2))) | |
1323 (if (= curr ?-) | |
1324 (aset newmodes 2 ?S) | |
1325 (if (= curr ?x) | |
1326 (aset newmodes 2 ?s))) | |
1327 (setq curr (aref newmodes 5)) | |
1328 (if (= curr ?-) | |
1329 (aset newmodes 5 ?S) | |
1330 (if (= curr ?x) | |
1331 (aset newmodes 5 ?s))))) | |
1332 (if sticky | |
1333 (let ((curr (aref newmodes 8))) | |
1334 (if (= curr ?-) | |
1335 (aset newmodes 8 ?T) | |
1336 (if (= curr ?x) | |
1337 (aset newmodes 8 ?t)))))) | |
1338 (if read | |
1339 (progn | |
1340 (aset newmodes 0 ?-) | |
1341 (aset newmodes 3 ?-) | |
1342 (aset newmodes 6 ?-))) | |
1343 (if write | |
1344 (progn | |
1345 (aset newmodes 1 ?-) | |
1346 (aset newmodes 4 ?-) | |
1347 (aset newmodes 7 ?-))) | |
1348 (if execute | |
1349 (let ((curr (aref newmodes 2))) | |
1350 (if (= curr ?x) | |
1351 (aset newmodes 2 ?-) | |
1352 (if (= curr ?s) | |
1353 (aset newmodes 2 ?S))) | |
1354 (setq curr (aref newmodes 5)) | |
1355 (if (= curr ?x) | |
1356 (aset newmodes 5 ?-) | |
1357 (if (= curr ?s) | |
1358 (aset newmodes 5 ?S))) | |
1359 (setq curr (aref newmodes 8)) | |
1360 (if (= curr ?x) | |
1361 (aset newmodes 8 ?-) | |
1362 (if (= curr ?t) | |
1363 (aset newmodes 8 ?T))))) | |
1364 (if suid | |
1365 (let ((curr (aref newmodes 2))) | |
1366 (if (= curr ?s) | |
1367 (aset newmodes 2 ?x) | |
1368 (if (= curr ?S) | |
1369 (aset newmodes 2 ?-))) | |
1370 (setq curr (aref newmodes 5)) | |
1371 (if (= curr ?s) | |
1372 (aset newmodes 5 ?x) | |
1373 (if (= curr ?S) | |
1374 (aset newmodes 5 ?-))))) | |
1375 (if sticky | |
1376 (let ((curr (aref newmodes 8))) | |
1377 (if (= curr ?t) | |
1378 (aset newmodes 8 ?x) | |
1379 (if (= curr ?T) | |
1380 (aset newmodes 8 ?-)))))) | |
1381 (if (string-match "u" who) | |
1382 (if add | |
1383 (progn | |
1384 (if read | |
1385 (aset newmodes 0 ?r)) | |
1386 (if write | |
1387 (aset newmodes 1 ?w)) | |
1388 (if execute | |
1389 (let ((curr (aref newmodes 2))) | |
1390 (if (= curr ?-) | |
1391 (aset newmodes 2 ?x) | |
1392 (if (= curr ?S) | |
1393 (aset newmodes 2 ?s))))) | |
1394 (if suid | |
1395 (let ((curr (aref newmodes 2))) | |
1396 (if (= curr ?-) | |
1397 (aset newmodes 2 ?S) | |
1398 (if (= curr ?x) | |
1399 (aset newmodes 2 ?s)))))) | |
1400 (if read | |
1401 (aset newmodes 0 ?-)) | |
1402 (if write | |
1403 (aset newmodes 1 ?-)) | |
1404 (if execute | |
1405 (let ((curr (aref newmodes 2))) | |
1406 (if (= curr ?x) | |
1407 (aset newmodes 2 ?-) | |
1408 (if (= curr ?s) | |
1409 (aset newmodes 2 ?S))))) | |
1410 (if suid | |
1411 (let ((curr (aref newmodes 2))) | |
1412 (if (= curr ?s) | |
1413 (aset newmodes 2 ?x) | |
1414 (if (= curr ?S) | |
1415 (aset newmodes 2 ?-))))))) | |
1416 (if (string-match "g" who) | |
1417 (if add | |
1418 (progn | |
1419 (if read | |
1420 (aset newmodes 3 ?r)) | |
1421 (if write | |
1422 (aset newmodes 4 ?w)) | |
1423 (if execute | |
1424 (let ((curr (aref newmodes 5))) | |
1425 (if (= curr ?-) | |
1426 (aset newmodes 5 ?x) | |
1427 (if (= curr ?S) | |
1428 (aset newmodes 5 ?s))))) | |
1429 (if suid | |
1430 (let ((curr (aref newmodes 5))) | |
1431 (if (= curr ?-) | |
1432 (aset newmodes 5 ?S) | |
1433 (if (= curr ?x) | |
1434 (aset newmodes 5 ?s)))))) | |
1435 (if read | |
1436 (aset newmodes 3 ?-)) | |
1437 (if write | |
1438 (aset newmodes 4 ?-)) | |
1439 (if execute | |
1440 (let ((curr (aref newmodes 5))) | |
1441 (if (= curr ?x) | |
1442 (aset newmodes 5 ?-) | |
1443 (if (= curr ?s) | |
1444 (aset newmodes 5 ?S))))) | |
1445 (if suid | |
1446 (let ((curr (aref newmodes 5))) | |
1447 (if (= curr ?s) | |
1448 (aset newmodes 5 ?x) | |
1449 (if (= curr ?S) | |
1450 (aset newmodes 5 ?-))))))) | |
1451 (if (string-match "o" who) | |
1452 (if add | |
1453 (progn | |
1454 (if read | |
1455 (aset newmodes 6 ?r)) | |
1456 (if write | |
1457 (aset newmodes 7 ?w)) | |
1458 (if execute | |
1459 (let ((curr (aref newmodes 8))) | |
1460 (if (= curr ?-) | |
1461 (aset newmodes 8 ?x) | |
1462 (if (= curr ?T) | |
1463 (aset newmodes 8 ?t))))) | |
1464 (if sticky | |
1465 (let ((curr (aref newmodes 8))) | |
1466 (if (= curr ?-) | |
1467 (aset newmodes 8 ?T) | |
1468 (if (= curr ?x) | |
1469 (aset newmodes 5 ?t)))))) | |
1470 (if read | |
1471 (aset newmodes 6 ?-)) | |
1472 (if write | |
1473 (aset newmodes 7 ?-)) | |
1474 (if execute | |
1475 (let ((curr (aref newmodes 8))) | |
1476 (if (= curr ?x) | |
1477 (aset newmodes 8 ?-) | |
1478 (if (= curr ?t) | |
1479 (aset newmodes 8 ?T))))) | |
1480 (if suid | |
1481 (let ((curr (aref newmodes 8))) | |
1482 (if (= curr ?t) | |
1483 (aset newmodes 8 ?x) | |
1484 (if (= curr ?T) | |
1485 (aset newmodes 8 ?-)))))))) | |
1486 newmodes)) | |
1487 | |
1488 (defun efs-compute-chmod-arg (perms file) | |
1489 ;; Computes the octal number, represented as a string, required to | |
1490 ;; modify the permissions PERMS of FILE. | |
1491 (efs-save-match-data | |
1492 (cond | |
1493 ((string-match "^[0-7][0-7]?[0-7]?[0-7]?$" perms) | |
1494 perms) | |
1495 ((string-match "^[augo]+[-+][rwxst]+$" perms) | |
1496 (let ((curr-mode (nth 3 (efs-get-file-entry file)))) | |
1497 (or (and curr-mode | |
1498 (stringp curr-mode) | |
1499 (= (length curr-mode) 10)) | |
1500 (progn | |
1501 ;; Current buffer is process error buffer | |
1502 (insert "Require an octal integer to modify modes for " | |
1503 file ".\n") | |
1504 (error "Require an octal integer to modify modes for %s." file))) | |
1505 (format "%o" | |
1506 (efs-parse-mode-string | |
1507 (efs-update-mode-string perms | |
1508 (substring curr-mode 1)))))) | |
1509 (t | |
1510 (insert "Don't know how to set modes " perms " for " file ".\n") | |
1511 (error "Don't know how to set modes %s" perms))))) | |
1512 | |
1513 (defun efs-call-chmod (args) | |
1514 ;; Sends an FTP CHMOD command. | |
1515 (if (< (length args) 2) | |
1516 (error "efs-call-chmod: missing mode and/or filename: %s" args)) | |
1517 (let ((mode (car args)) | |
1518 bombed) | |
1519 (mapcar | |
1520 (function | |
1521 (lambda (file) | |
1522 (setq file (expand-file-name file)) | |
1523 (let ((parsed (efs-ftp-path file))) | |
1524 (if parsed | |
1525 (condition-case nil | |
1526 (let* ((mode (efs-compute-chmod-arg mode file)) | |
1527 (host (nth 0 parsed)) | |
1528 (user (nth 1 parsed)) | |
1529 (path (efs-quote-string | |
1530 (efs-host-type host user) (nth 2 parsed))) | |
1531 (abbr (efs-relativize-filename file)) | |
1532 (result (efs-send-cmd host user | |
1533 (list 'quote 'site 'chmod | |
1534 mode path) | |
1535 (format "doing chmod %s" | |
1536 abbr)))) | |
1537 (efs-del-from-ls-cache file t) | |
1538 (if (car result) | |
1539 (efs-error host user (format "chmod: %s: \"%s\"" file | |
1540 (nth 1 result))))) | |
1541 (error (setq bombed t))))))) | |
1542 (cdr args)) | |
1543 (if bombed 1 0))) ; return code | |
1544 | |
1545 (defun efs-call-lpr (file command-format) | |
1546 "Print remote file FILE. SWITCHES are passed to the print program." | |
1547 ;; Works asynch. | |
1548 (let* ((file (expand-file-name file)) | |
1549 (parsed (efs-ftp-path file)) | |
1550 (abbr (efs-relativize-filename file)) | |
1551 (temp (car (efs-make-tmp-name nil (car parsed))))) | |
1552 (efs-copy-file-internal | |
1553 file parsed temp nil t nil 2 | |
1554 (efs-cont (result line cont-lines) (command-format file abbr temp) | |
1555 (if result | |
1556 (signal 'ftp-error (list "Opening input file" | |
1557 (format "FTP Error: \"%s\" " line) | |
1558 file)) | |
1559 (message "Spooling %s..." abbr) | |
1560 (set-process-sentinel | |
1561 (start-process (format "*print %s /// %s*" abbr temp) | |
1562 (generate-new-buffer-name " *print temp*") | |
1563 "sh" "-c" (format command-format temp)) | |
1564 (function | |
1565 (lambda (proc status) | |
1566 (let ((buff (process-buffer proc)) | |
1567 (name (process-name proc))) | |
1568 (if (and buff (get-buffer buff)) | |
1569 (unwind-protect | |
1570 (save-excursion | |
1571 (set-buffer buff) | |
1572 (if (> (buffer-size) 0) | |
1573 (let ((log-buff (get-buffer-create | |
1574 "*Shell Command Output*"))) | |
1575 (set-buffer log-buff) | |
1576 (goto-char (point-max)) | |
1577 (or (bobp) | |
1578 (insert "\n")) | |
1579 (insert-buffer-substring buff) | |
1580 (goto-char (point-max)) | |
1581 (display-buffer log-buff)))) | |
1582 (condition-case nil (kill-buffer buff) (error nil)) | |
1583 (efs-save-match-data | |
1584 (if (string-match "^\\*print \\(.*\\) /// \\(.*\\)\\*$" | |
1585 name) | |
1586 (let ((abbr (substring name (match-beginning 1) | |
1587 (match-end 1))) | |
1588 (temp (substring name (match-beginning 2) | |
1589 (match-end 2)))) | |
1590 (or (= (match-beginning 2) (match-end 2)) | |
1591 (efs-del-tmp-name temp)) | |
1592 (message "Spooling %s...done" abbr)))))))))))) | |
1593 t))) | |
1594 | |
1595 ;;;; -------------------------------------------------------------- | |
1596 ;;;; Attaching onto dired. | |
1597 ;;;; -------------------------------------------------------------- | |
1598 | |
1599 ;;; Look out for MULE | |
1600 (if (or (boundp 'MULE) (featurep 'mule)) (load "efs-dired-mule")) | |
1601 | |
1602 ;;; Magic file name hooks for dired. | |
1603 | |
1604 (put 'dired-print-file 'efs 'efs-dired-print-file) | |
1605 (put 'dired-make-compressed-filename 'efs 'efs-dired-make-compressed-filename) | |
1606 (put 'dired-compress-file 'efs 'efs-dired-compress-file) | |
1607 (put 'dired-recursive-delete-directory 'efs | |
1608 'efs-dired-recursive-delete-directory) | |
1609 (put 'dired-uncache 'efs 'efs-dired-uncache) | |
1610 (put 'dired-shell-call-process 'efs 'efs-dired-shell-call-process) | |
1611 (put 'dired-shell-unhandle-file-name 'efs 'efs-dired-shell-unhandle-file-name) | |
1612 (put 'dired-file-modtime 'efs 'efs-dired-file-modtime) | |
1613 (put 'dired-set-file-modtime 'efs 'efs-dired-set-file-modtime) | |
1614 | |
1615 ;;; Overwriting functions | |
1616 | |
1617 (efs-overwrite-fn "efs" 'dired-call-process) | |
1618 (efs-overwrite-fn "efs" 'dired-insert-headerline) | |
1619 (efs-overwrite-fn "efs" 'dired-manual-move-to-filename) | |
1620 (efs-overwrite-fn "efs" 'dired-manual-move-to-end-of-filename) | |
1621 (efs-overwrite-fn "efs" 'dired-make-filename-string) | |
1622 (efs-overwrite-fn "efs" 'dired-flag-backup-files) | |
1623 (efs-overwrite-fn "efs" 'dired-create-files) | |
1624 (efs-overwrite-fn "efs" 'dired-find-file) | |
1625 (efs-overwrite-fn "efs" 'dired-find-file-other-window) | |
1626 (efs-overwrite-fn "efs" 'dired-find-file-other-frame) | |
1627 (efs-overwrite-fn "efs" 'dired-collect-file-versions) | |
1628 (efs-overwrite-fn "efs" 'dired-file-name-lessp) | |
1629 | |
1630 ;;; Hooks | |
1631 | |
1632 (add-hook 'dired-before-readin-hook 'efs-dired-before-readin) | |
1633 | |
1634 ;;; Handle dired-grep.el too. | |
1635 | |
1636 (if (featurep 'dired-grep) | |
1637 (efs-overwrite-fn "efs" 'dired-grep-delete-local-temp-file | |
1638 'efs-diff/grep-del-temp-file) | |
1639 (add-hook 'dired-grep-load-hook | |
1640 (function | |
1641 (lambda () | |
1642 (efs-overwrite-fn "efs" 'dired-grep-delete-local-temp-file | |
1643 'efs-diff/grep-del-temp-file))))) | |
1644 | |
1645 ;;; end of efs-dired.el |