comparison lisp/dired/dired-cd.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 ;;; -*- Mode: Emacs-lisp -*- ;;;
2 ;;; dired-cd.el - Adjust Working Directory for Tree Dired Shell Commands
3 ;;; Id: dired-cd.el,v 1.14 1991/11/01 14:28:27 sk RelBeta
4 ;;; Copyright (C) 1991 Hugh Secker-Walker
5 ;;;
6 ;;; Author: Hugh Secker-Walker hugh@ear-ache.mit.edu
7 ;;;
8 ;;; Modified by Sebastian Kremer <sk@thp.uni-koeln.de>
9 ;;;
10 ;;; This program is free software; you can redistribute it and/or modify
11 ;;; it under the terms of the GNU General Public License as published by
12 ;;; the Free Software Foundation; either version 1, or (at your option)
13 ;;; any later version.
14 ;;;
15 ;;; This program is distributed in the hope that it will be useful,
16 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;;; GNU General Public License for more details.
19 ;;;
20 ;;; A copy of the GNU General Public License can be obtained from this
21 ;;; program's author (send electronic mail to the above address) or from
22 ;;; Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23
24 ;; LISPDIR ENTRY for the Elisp Archive ===============================
25 ;; LCD Archive Entry:
26 ;; dired-cd|Hugh Secker-Walker|hugh@ear-ache.mit.edu
27 ;; |Adjust Working Directory for Tree Dired Shell Commands
28 ;; |Date: 1991/11/01 14:28:27 |Revision: 1.14 |
29
30 ;;; SUMMARY
31
32 ;;; This extension to Sebastian Kremer's (sk@thp.Uni-Koeln.DE) Tree-Dired
33 ;;; permits the working directory of the dired shell commands
34 ;;; dired-do-shell-command and dired-do-background-shell-command
35 ;;; to be the files' subdirectory under certain circumstances.
36 ;;; Loading this extension does not change the behavior of dired until
37 ;;; the variables dired-cd-same-subdir and/or dired-cd-on-each are
38 ;;; non-nil.
39
40
41 ;;; FUNCTIONALITY PROVIDED
42
43 ;;; If dired-cd-same-subdir is non-nil and if all the selected files
44 ;;; (marked, non-zero numeric ARG, etc.) are in the same directory, then
45 ;;; dired-do-shell-command and dired-do-background-shell-command will
46 ;;; cause the shell to perform a cd into that directory before the
47 ;;; commands are executed. Also, the selected filenames will be provided
48 ;;; to the command without any directory components.
49
50 ;;; If dired-cd-on-each is non-nil and if the on-each option is specified
51 ;;; (numeric arg of zero), then dired-do-shell-command and
52 ;;; dired-do-background-shell-command will perform a cd into the
53 ;;; directory of each file before the commands on that file are executed.
54 ;;; Also, each filename will be provided to the command without any
55 ;;; directory components. Note that this on-each behavior occurs
56 ;;; regardless of whether the files are all in the same directory or not.
57
58 ;;; After the above "cd wrapping" has occured, the existing
59 ;;; dired-shell-stuff-it is used to do file-name substitution and
60 ;;; quoting, so custom versions of this procedure should work, e.g.
61 ;;; dired-trans will transform commands correctly. However, since
62 ;;; filenames lack any directory components, features that use the
63 ;;; directory components will fail, e.g. the dired-trans [d] transform
64 ;;; specifier will be empty.
65
66 ;;; New variables (user options):
67 ;;; dired-cd-same-subdir
68 ;;; dired-cd-on-each
69 ;;;
70 ;;; Replaces procedures:
71 ;;; dired-do-shell-command (new doc and prompt, calls dired-cd-wrap-it)
72 ;;;
73 ;;; Adds procedures:
74 ;;; dired-cd-wrap-it (wraps calls to dired-shell-stuff-it with "cd <dir>")
75 ;;; dired-files-same-directory
76
77
78 ;; INSTALLATION
79 ;;
80 ;; Put this file into your load-path and add (load "dired-cd") to
81 ;; your dired-load-hook, e.g.
82 ;;
83 ;; (setq dired-load-hook '(lambda ()
84 ;; ;; possibly more statements here
85 ;; (load "dired-cd")))
86 ;;
87 ;; Do (setq dired-cd-same-subdir t) and perhaps (setq dired-cd-on-each t)
88 ;; in your .emacs. By default, dired-cd doesn't change the behavior of
89 ;; dired when it is loaded.
90 ;;
91 ;; If dired-cd-same-subdir is non-nil, then the shell commands cd to
92 ;; the appropriate directory if all the selected files (marked,
93 ;; numeric ARG, etc.) are in that directory; however, on-each behavior
94 ;; is not changed.
95 ;;
96 ;; If dired-cd-on-each is non-nil, then each instance of the command
97 ;; for an on-each shell command runs in the file's directory
98 ;; regardless of whether the files are all in the same directory.
99
100
101 (defvar dired-cd-same-subdir nil
102 "*If non-nil, and selected file(s) (by marks, numeric arg, \\[universal-argument]) are in same
103 subdir, causes dired shell command to run in that subdir. Filenames provided
104 to shell commands are stripped of their directory components. Does not
105 affect behavior of on-each, for that see variable dired-cd-on-each.")
106
107 (defvar dired-cd-on-each nil
108 "*If non-nil, on-each causes each dired shell command to run in the
109 file's directory. Filenames provided to shell commands are stripped of
110 their directory components. Also see variable dired-cd-same-subdir.")
111
112 ;; Redefines dired.el's version.
113 ;; Changes to documentation and prompt, and uses dired-cd-wrap-it.
114 (defun dired-do-shell-command (&optional arg in-background)
115 "Run a shell command on the marked files.
116 If there is output, it goes to a separate buffer.
117 The list of marked files is appended to the command string unless asterisks
118 `*' indicate the place(s) where the list should go.
119 If no files are marked or a specific numeric prefix arg is given, uses
120 next ARG files. With a zero argument, run command on each marked file
121 separately: `cmd * foo' results in `cmd F1 foo; ...; cmd Fn foo'.
122 As always, a raw arg (\\[universal-argument]) means the current file.
123 The option variables dired-cd-same-subdir and dired-cd-on-each
124 permit the command\(s\) to run in the files' directories if appropriate,
125 and thus determine where output files are created. Default is top
126 directory. The prompt mentions the file(s) or the marker, the cd subdir,
127 and the on-each flags when they apply.
128 No automatic redisplay is attempted, as the file names may have
129 changed. Type \\[dired-do-redisplay] to redisplay the marked files."
130 ;; Function dired-shell-stuff-it (called by dired-cd-wrap-it) does the
131 ;; actual file-name substitution and can be redefined for customization.
132 (interactive "P")
133 (let* ((on-each (equal arg 0))
134 (file-list (dired-mark-get-files t (if on-each nil arg)))
135 (prompt (concat (if in-background "& " "! ")
136 (if (or (and on-each dired-cd-on-each)
137 (and dired-cd-same-subdir
138 (not on-each)
139 (dired-files-same-directory file-list)))
140 "cd <dir>; " "")
141 "on "
142 (if on-each "each " "")
143 "%s: "))
144 ;; Give feedback on file(s) and working directory status
145 (command (dired-read-shell-command
146 prompt (if on-each nil arg) file-list))
147 (result (dired-cd-wrap-it command file-list on-each arg)))
148 ;; execute the shell command
149 (dired-run-shell-command result in-background)))
150
151 (defun dired-cd-wrap-it (command files on-each &optional raw)
152 "Args COMMAND FILES ON-EACH &optional RAW-ARG, like dired-shell-stuff-it.
153 Calls dired-shell-stuff-it, but wraps the resulting command\(s\)
154 with \"cd <dir>\" commands when appropriate. Note: when ON-EACH is non-nil,
155 dired-shell-stuff-it is called once for each file in FILES.
156 See documentation of variables dired-cd-same-subdir and dired-cd-on-each
157 for wrap conditions."
158 (if on-each;; command applied to each file separately
159 ;; cd's are done in subshells since all shells I know of have subshells
160 (let* ((cwd "");; current working directory
161 (in-subshell nil)
162 (cmd (mapconcat;; files over command, fuss with "cd <dir>"
163 (function
164 (lambda (file)
165 (let ((cd "") d);; cd command and file's directory
166 (if (not dired-cd-on-each) nil;; poor man's (when ...)
167 (setq d;; directory, relative to default-directory
168 (directory-file-name
169 (or (file-name-directory file) ""))
170 file (file-name-nondirectory file))
171 (if (not (string= d cwd));; new subdir, new subshell
172 (setq cwd d
173 ;; close existing subshell,
174 ;; open a new one
175 cd (concat (if in-subshell "); " "")
176 "(cd " (shell-quote cwd) "; ")
177 in-subshell t))
178 )
179 ;; existing dired-shell-stuff-it does
180 ;; actual command substitution
181 (concat cd (dired-shell-stuff-it command (list file)
182 on-each raw)))))
183 files "; ")))
184 (if in-subshell (concat cmd ")") cmd));; close an open subshell
185
186 ;; not on-each, all files are args to single command instance
187 (let ((same-dir (and dired-cd-same-subdir
188 (dired-files-same-directory files nil)))
189 (cd ""))
190 ;; Let the prepended cd command be relative to default-directory,
191 ;; and only give it if necessary. This way, after ange-ftp
192 ;; prepends its own cd command, it will still work.
193 ;; sk 3-Sep-1991 14:23
194 ;; hsw 31-Oct-1991 -- filenames relative to default-directory
195 (if (and same-dir (not (equal same-dir "")))
196 (setq files (mapcar (function file-name-nondirectory) files)
197 cd (concat "cd " (shell-quote same-dir) "; ")))
198 ;; existing dired-shell-stuff-it does the command substitution
199 (concat cd (dired-shell-stuff-it command files on-each raw)))))
200
201 (defun dired-files-same-directory (file-list &optional absolute)
202 "If all files in LIST are in the same directory return it, otherwise nil.
203 Returned name has no trailing slash. \"Same\" means file-name-directory of
204 the files are string=. File names in LIST must all be absolute or all be
205 relative. Implicitly, relative file names are in default-directory. If
206 optional ABS is non-nil, the returned name will be absolute, otherwise the
207 returned name will be absolute or relative as per the files in LIST."
208 (let ((dir (file-name-directory (car file-list))))
209 (if (memq nil (mapcar (function
210 (lambda (file)
211 (string= dir (file-name-directory file))))
212 file-list))
213 nil
214 (directory-file-name
215 (if (or (not absolute) (and dir (file-name-absolute-p dir)))
216 (or dir "")
217 (concat default-directory dir))))))
218
219 (provide 'dired-cd)