;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
both at the file level and at the levels of the containing directories."
:type 'boolean
:group 'find-file)
-(put 'find-file-visit-truename 'safe-local-variable 'boolean)
+(put 'find-file-visit-truename 'safe-local-variable 'booleanp)
(defcustom revert-without-query nil
"Specify which files should be reverted without query.
((null action) (try-completion string names))
(t (test-completion string names))))))
+(defun locate-dominating-file (file regexp)
+ "Look up the directory hierarchy from FILE for a file matching REGEXP."
+ (while (and file (not (file-directory-p file)))
+ (setq file (file-name-directory (directory-file-name file))))
+ (catch 'found
+ (let ((user (nth 2 (file-attributes file)))
+ ;; Abbreviate, so as to stop when we cross ~/.
+ (dir (abbreviate-file-name (file-name-as-directory file)))
+ files)
+ ;; As a heuristic, we stop looking up the hierarchy of directories as
+ ;; soon as we find a directory belonging to another user. This should
+ ;; save us from looking in things like /net and /afs. This assumes
+ ;; that all the files inside a project belong to the same user.
+ (while (and dir (equal user (nth 2 (file-attributes dir))))
+ (if (setq files (directory-files dir 'full regexp))
+ (throw 'found (car files))
+ (if (equal dir
+ (setq dir (file-name-directory
+ (directory-file-name dir))))
+ (setq dir nil))))
+ nil)))
+
(defun executable-find (command)
"Search for COMMAND in `exec-path' and return the absolute file name.
Return nil if COMMAND is not found anywhere in `exec-path'."
(cons load-path (get-load-suffixes)))))
(load library))
-(defun file-remote-p (file)
+(defun file-remote-p (file &optional identification connected)
"Test whether FILE specifies a location on a remote system.
Return an identification of the system if the location is indeed
remote. The identification of the system may comprise a method
to access the system and its hostname, amongst other things.
For example, the filename \"/user@host:/foo\" specifies a location
-on the system \"/user@host:\"."
+on the system \"/user@host:\".
+
+IDENTIFICATION specifies which part of the identification shall
+be returned as string. IDENTIFICATION can be the symbol
+`method', `user' or `host'; any other value is handled like nil
+and means to return the complete identification string.
+
+If CONNECTED is non-nil, the function returns an identification only
+if FILE is located on a remote system, and a connection is established
+to that remote system.
+
+`file-remote-p' will never open a connection on its own."
(let ((handler (find-file-name-handler file 'file-remote-p)))
(if handler
- (funcall handler 'file-remote-p file)
+ (funcall handler 'file-remote-p file identification connected)
nil)))
(defun file-local-copy (file)
,@body)
(remove-hook 'minibuffer-setup-hook ,hook)))))
+(defcustom find-file-confirm-nonexistent-file nil
+ "If non-nil, `find-file' requires confirmation before visiting a new file."
+ :group 'find-file
+ :version "23.1"
+ :type 'boolean)
+
(defun find-file-read-args (prompt mustmatch)
(list (let ((find-file-default
(and buffer-file-name
To visit a file without any kind of conversion and without
automatically choosing a major mode, use \\[find-file-literally]."
- (interactive (find-file-read-args "Find file: " nil))
+ (interactive
+ (find-file-read-args "Find file: "
+ (if find-file-confirm-nonexistent-file 'confirm-only)))
(let ((value (find-file-noselect filename nil nil wildcards)))
(if (listp value)
(mapcar 'switch-to-buffer (nreverse value))
Interactively, or if WILDCARDS is non-nil in a call from Lisp,
expand wildcards (if any) and visit multiple files."
- (interactive (find-file-read-args "Find file in other window: " nil))
+ (interactive
+ (find-file-read-args "Find file in other window: "
+ (if find-file-confirm-nonexistent-file 'confirm-only)))
(let ((value (find-file-noselect filename nil nil wildcards)))
(if (listp value)
(progn
Interactively, or if WILDCARDS is non-nil in a call from Lisp,
expand wildcards (if any) and visit multiple files."
- (interactive (find-file-read-args "Find file in other frame: " nil))
+ (interactive
+ (find-file-read-args "Find file in other frame: "
+ (if find-file-confirm-nonexistent-file 'confirm-only)))
(let ((value (find-file-noselect filename nil nil wildcards)))
(if (listp value)
(progn
"Edit file FILENAME but don't allow changes.
Like \\[find-file] but marks buffer as read-only.
Use \\[toggle-read-only] to permit editing."
- (interactive (find-file-read-args "Find file read-only: " nil))
+ (interactive
+ (find-file-read-args "Find file read-only: "
+ (if find-file-confirm-nonexistent-file 'confirm-only)))
(unless (or (and wildcards find-file-wildcards
(not (string-match "\\`/:" filename))
(string-match "[[*?]" filename))
"Edit file FILENAME in another window but don't allow changes.
Like \\[find-file-other-window] but marks buffer as read-only.
Use \\[toggle-read-only] to permit editing."
- (interactive (find-file-read-args "Find file read-only other window: " nil))
+ (interactive
+ (find-file-read-args "Find file read-only other window: "
+ (if find-file-confirm-nonexistent-file 'confirm-only)))
(unless (or (and wildcards find-file-wildcards
(not (string-match "\\`/:" filename))
(string-match "[[*?]" filename))
"Edit file FILENAME in another frame but don't allow changes.
Like \\[find-file-other-frame] but marks buffer as read-only.
Use \\[toggle-read-only] to permit editing."
- (interactive (find-file-read-args "Find file read-only other frame: " nil))
+ (interactive
+ (find-file-read-args "Find file read-only other frame: "
+ (if find-file-confirm-nonexistent-file 'confirm-only)))
(unless (or (and wildcards find-file-wildcards
(not (string-match "\\`/:" filename))
(string-match "[[*?]" filename))
("\\.[sS]\\'" . asm-mode)
("\\.asm\\'" . asm-mode)
("[cC]hange\\.?[lL]og?\\'" . change-log-mode)
- ("[cC]hange[lL]og[-.][-0-9a-z]+\\'" . change-log-mode)
+ ("[cC]hange[lL]og[-.][0-9]+\\'" . change-log-mode)
("\\$CHANGE_LOG\\$\\.TXT" . change-log-mode)
("\\.scm\\.[0-9]*\\'" . scheme-mode)
("\\.[ck]?sh\\'\\|\\.shar\\'\\|/\\.z?profile\\'" . sh-mode)
("[/.]c\\(?:on\\)?f\\(?:i?g\\)?\\(?:\\.[a-zA-Z0-9._-]+\\)?\\'" . conf-mode)
("\\`/etc/\\(?:DIR_COLORS\\|ethers\\|.?fstab\\|.*hosts\\|lesskey\\|login\\.?de\\(?:fs\\|vperm\\)\\|magic\\|mtab\\|pam\\.d/.*\\|permissions\\(?:\\.d/.+\\)?\\|protocols\\|rpc\\|services\\)\\'" . conf-space-mode)
("\\`/etc/\\(?:acpid?/.+\\|aliases\\(?:\\.d/.+\\)?\\|default/.+\\|group-?\\|hosts\\..+\\|inittab\\|ksysguarddrc\\|opera6rc\\|passwd-?\\|shadow-?\\|sysconfig/.+\\)\\'" . conf-mode)
+ ;; ChangeLog.old etc. Other change-log-mode entries are above;
+ ;; this has lower priority to avoid matching changelog.sgml etc.
+ ("[cC]hange[lL]og[-.][-0-9a-z]+\\'" . change-log-mode)
;; either user's dot-files or under /etc or some such
("/\\.?\\(?:gnokiirc\\|kde.*rc\\|mime\\.types\\|wgetrc\\)\\'" . conf-mode)
;; alas not all ~/.*rc files are like this
minor-mode-overriding-map-alist
mode-line-buffer-identification
mode-line-format
+ mode-line-client
mode-line-modes
mode-line-modified
mode-line-mule-info
mode-line-position
mode-line-process
+ mode-line-remote
mode-name
outline-level
overriding-local-map
(defun make-directory (dir &optional parents)
"Create the directory DIR and any nonexistent parent dirs.
+If DIR already exists as a directory, do nothing.
+
Interactively, the default choice of directory to create
is the current default directory for file names.
That is useful when you have visited a file in a nonexistent directory.
(message "No files can be recovered from this session now")))
(kill-buffer buffer))))
+(defun kill-buffer-ask (buffer)
+ "Kill buffer if confirmed."
+ (when (yes-or-no-p
+ (format "Buffer %s %s. Kill? " (buffer-name buffer)
+ (if (buffer-modified-p buffer)
+ "HAS BEEN EDITED" "is unmodified")))
+ (kill-buffer buffer)))
+
(defun kill-some-buffers (&optional list)
"Kill some buffers. Asks the user whether to kill each one of them.
Non-interactively, if optional argument LIST is non-nil, it
; if we killed the base buffer.
(not (string-equal name ""))
(/= (aref name 0) ?\s)
- (yes-or-no-p
- (format "Buffer %s %s. Kill? "
- name
- (if (buffer-modified-p buffer)
- "HAS BEEN EDITED" "is unmodified")))
- (kill-buffer buffer)))
+ (kill-buffer-ask buffer)))
(setq list (cdr list))))
+
+(defun kill-matching-buffers (regexp &optional internal-too)
+ "Kill buffers whose name matches the specified regexp.
+The optional second argument indicates whether to kill internal buffers too."
+ (interactive "sKill buffers matching this regular expression: \nP")
+ (dolist (buffer (buffer-list))
+ (let ((name (buffer-name buffer)))
+ (when (and name (not (string-equal name ""))
+ (or internal-too (/= (aref name 0) ?\s))
+ (string-match regexp name))
+ (kill-buffer-ask buffer)))))
+
\f
(defun auto-save-mode (arg)
"Toggle auto-saving of contents of current buffer.
(or (null confirm-kill-emacs)
(funcall confirm-kill-emacs "Really exit Emacs? "))
(kill-emacs)))
+
+(defun save-buffers-kill-terminal (&optional arg)
+ "Offer to save each buffer, then kill the current connection.
+If the current frame has no client, kill Emacs itself.
+
+With prefix arg, silently save all file-visiting buffers, then kill.
+
+If emacsclient was started with a list of filenames to edit, then
+only these files will be asked to be saved."
+ (interactive "P")
+ (let ((proc (frame-parameter (selected-frame) 'client))
+ (frame (selected-frame)))
+ (if (null proc)
+ (save-buffers-kill-emacs)
+ (server-save-buffers-kill-terminal proc arg))))
+
\f
;; We use /: as a prefix to "quote" a file name
;; so that magic file name handlers will not apply to it.
(define-key ctl-x-map "i" 'insert-file)
(define-key esc-map "~" 'not-modified)
(define-key ctl-x-map "\C-d" 'list-directory)
-(define-key ctl-x-map "\C-c" 'save-buffers-kill-emacs)
+(define-key ctl-x-map "\C-c" 'save-buffers-kill-terminal)
(define-key ctl-x-map "\C-q" 'toggle-read-only)
(define-key ctl-x-4-map "f" 'find-file-other-window)