diff options
author | Stefan Monnier <monnier@iro.umontreal.ca> | 2011-02-21 17:34:51 -0500 |
---|---|---|
committer | Stefan Monnier <monnier@iro.umontreal.ca> | 2011-02-21 17:34:51 -0500 |
commit | f619ad4ca2ce943d53589469c010e451afab97dd (patch) | |
tree | e1b71f79518372ecab4c677ae948504450d8bf5d /lisp/files.el | |
parent | a647cb26b695a542e3a546104afdf4c7c47eb061 (diff) | |
parent | 9f8370e63f65f76887b319ab6a0368d4a332777c (diff) | |
download | emacs-f619ad4ca2ce943d53589469c010e451afab97dd.tar.gz emacs-f619ad4ca2ce943d53589469c010e451afab97dd.tar.bz2 emacs-f619ad4ca2ce943d53589469c010e451afab97dd.zip |
Merge from trunk
Diffstat (limited to 'lisp/files.el')
-rw-r--r-- | lisp/files.el | 109 |
1 files changed, 66 insertions, 43 deletions
diff --git a/lisp/files.el b/lisp/files.el index e7dd96ca2ff..42f09f8b6da 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -681,26 +681,37 @@ that list of directories (separated by occurrences of `path-separator') when resolving a relative directory name. The path separator is colon in GNU and GNU-like systems." (interactive - (list (read-directory-name "Change default directory: " - default-directory default-directory - (and (member cd-path '(nil ("./"))) - (null (getenv "CDPATH")))))) - (if (file-name-absolute-p dir) - (cd-absolute (expand-file-name dir)) - (if (null cd-path) - (let ((trypath (parse-colon-path (getenv "CDPATH")))) - (setq cd-path (or trypath (list "./"))))) - (if (not (catch 'found - (mapc - (function (lambda (x) - (let ((f (expand-file-name (concat x dir)))) - (if (file-directory-p f) - (progn - (cd-absolute f) - (throw 'found t)))))) - cd-path) - nil)) - (error "No such directory found via CDPATH environment variable")))) + (list + ;; FIXME: There's a subtle bug in the completion below. Seems linked + ;; to a fundamental difficulty of implementing `predicate' correctly. + ;; The manifestation is that TAB may list non-directories in the case where + ;; those files also correspond to valid directories (if your cd-path is (A/ + ;; B/) and you have A/a a file and B/a a directory, then both `a' and `a/' + ;; will be listed as valid completions). + ;; This is because `a' (listed because of A/a) is indeed a valid choice + ;; (which will lead to the use of B/a). + (minibuffer-with-setup-hook + (lambda () + (setq minibuffer-completion-table + (apply-partially #'locate-file-completion-table + cd-path nil)) + (setq minibuffer-completion-predicate + (lambda (dir) + (locate-file dir cd-path nil + (lambda (f) (and (file-directory-p f) 'dir-ok)))))) + (unless cd-path + (setq cd-path (or (parse-colon-path (getenv "CDPATH")) + (list "./")))) + (read-directory-name "Change default directory: " + default-directory default-directory + t)))) + (unless cd-path + (setq cd-path (or (parse-colon-path (getenv "CDPATH")) + (list "./")))) + (cd-absolute + (or (locate-file dir cd-path nil + (lambda (f) (and (file-directory-p f) 'dir-ok))) + (error "No such directory found via CDPATH environment variable")))) (defun load-file (file) "Load the Lisp file named FILE." @@ -720,9 +731,12 @@ If SUFFIXES is non-nil, it should be a list of suffixes to append to file name when searching. If SUFFIXES is nil, it is equivalent to '(\"\"). Use '(\"/\") to disable PATH search, but still try the suffixes in SUFFIXES. If non-nil, PREDICATE is used instead of `file-readable-p'. + +This function will normally skip directories, so if you want it to find +directories, make sure the PREDICATE function returns `dir-ok' for them. + PREDICATE can also be an integer to pass to the `access' system call, in which case file-name handlers are ignored. This usage is deprecated. - For compatibility, PREDICATE can also be one of the symbols `executable', `readable', `writable', or `exists', or a list of one or more of those symbols." @@ -2058,7 +2072,8 @@ Don't call it from programs! Use `insert-file-contents-literally' instead. (defvar find-file-literally nil "Non-nil if this buffer was made by `find-file-literally' or equivalent. -This is a permanent local.") +This has the `permanent-local' property, which takes effect if you +make the variable buffer-local.") (put 'find-file-literally 'permanent-local t) (defun find-file-literally (filename) @@ -4310,7 +4325,11 @@ Before and after saving the buffer, this function runs ;; In an indirect buffer, save its base buffer instead. (if (buffer-base-buffer) (set-buffer (buffer-base-buffer))) - (if (buffer-modified-p) + (if (or (buffer-modified-p) + ;; handle the case when no modification has been made but + ;; the file disappeared since visited + (and buffer-file-name + (not (file-exists-p buffer-file-name)))) (let ((recent-save (recent-auto-save-p)) setmodes) ;; If buffer has no file name, ask user for one. @@ -4823,10 +4842,8 @@ given. With a prefix argument, TRASH is nil." directory 'full directory-files-no-dot-files-regexp))) (delete-directory-internal directory))))) -(defun copy-directory (directory newname &optional keep-time parents) +(defun copy-directory (directory newname &optional keep-time parents copy-contents) "Copy DIRECTORY to NEWNAME. Both args must be strings. -If NEWNAME names an existing directory, copy DIRECTORY as subdirectory there. - This function always sets the file modes of the output files to match the corresponding input file. @@ -4837,7 +4854,12 @@ A prefix arg makes KEEP-TIME non-nil. Noninteractively, the last argument PARENTS says whether to create parent directories if they don't exist. Interactively, -this happens by default." +this happens by default. + +If NEWNAME names an existing directory, copy DIRECTORY as a +subdirectory there. However, if called from Lisp with a non-nil +optional argument COPY-CONTENTS, copy the contents of DIRECTORY +directly into NEWNAME instead." (interactive (let ((dir (read-directory-name "Copy directory: " default-directory default-directory t nil))) @@ -4845,7 +4867,7 @@ this happens by default." (read-file-name (format "Copy directory %s to: " dir) default-directory default-directory nil nil) - current-prefix-arg t))) + current-prefix-arg t nil))) ;; If default-directory is a remote directory, make sure we find its ;; copy-directory handler. (let ((handler (or (find-file-name-handler directory 'copy-directory) @@ -4857,21 +4879,22 @@ this happens by default." (setq directory (directory-file-name (expand-file-name directory)) newname (directory-file-name (expand-file-name newname))) - (if (not (file-directory-p newname)) - ;; If NEWNAME is not an existing directory, create it; that - ;; is where we will copy the files of DIRECTORY. - (make-directory newname parents) - ;; If NEWNAME is an existing directory, we will copy into - ;; NEWNAME/[DIRECTORY-BASENAME]. - (setq newname (expand-file-name - (file-name-nondirectory - (directory-file-name directory)) - newname)) - (and (file-exists-p newname) - (not (file-directory-p newname)) - (error "Cannot overwrite non-directory %s with a directory" - newname)) - (make-directory newname t)) + (cond ((not (file-directory-p newname)) + ;; If NEWNAME is not an existing directory, create it; + ;; that is where we will copy the files of DIRECTORY. + (make-directory newname parents)) + ;; If NEWNAME is an existing directory and COPY-CONTENTS + ;; is nil, copy into NEWNAME/[DIRECTORY-BASENAME]. + ((not copy-contents) + (setq newname (expand-file-name + (file-name-nondirectory + (directory-file-name directory)) + newname)) + (and (file-exists-p newname) + (not (file-directory-p newname)) + (error "Cannot overwrite non-directory %s with a directory" + newname)) + (make-directory newname t))) ;; Copy recursively. (dolist (file |