Mercurial > emacs
diff lisp/files.el @ 90070:95879cc1ed20
Revision: miles@gnu.org--gnu-2004/emacs--unicode--0--patch-81
Merge from emacs--cvs-trunk--0
Patches applied:
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-748
- miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-749
Update from CVS
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-750
Merge from gnus--rel--5.10
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-751
- miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-753
Update from CVS
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-754
Merge from gnus--rel--5.10
* miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-755
- miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-757
Update from CVS
* miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-78
Merge from emacs--cvs-trunk--0
* miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-79
- miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-80
Update from CVS
* miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-81
Merge from emacs--cvs-trunk--0
* miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-82
Update from CVS
author | Miles Bader <miles@gnu.org> |
---|---|
date | Sun, 02 Jan 2005 09:13:19 +0000 |
parents | fb79180b618d e4a2eb7b1ae5 |
children | f6b4d0ebf147 |
line wrap: on
line diff
--- a/lisp/files.el Sat Dec 25 02:31:08 2004 +0000 +++ b/lisp/files.el Sun Jan 02 09:13:19 2005 +0000 @@ -273,14 +273,40 @@ :group 'backup) (defcustom require-final-newline nil - "*Value of t says silently ensure a file ends in a newline when it is saved. -Non-nil but not t says ask user whether to add a newline when there isn't one. -nil means don't add newlines." - :type '(choice (const :tag "Off" nil) - (const :tag "Add" t) + "*Whether to add a newline automatically at the end of the file. + +A value of t means do this only when the file is about to be saved. +A value of `visit' means do this right after the file is visited. +A value of `visit-save' means do it at both of those times. +Any other non-nil value means ask user whether to add a newline, when saving. +nil means don't add newlines. + +Certain major modes set this locally to the value obtained +from `mode-require-final-newline'." + :type '(choice (const :tag "When visiting" visit) + (const :tag "When saving" t) + (const :tag "When visiting or saving" visit-save) + (const :tag "Never" nil) (other :tag "Ask" ask)) :group 'editing-basics) +(defcustom mode-require-final-newline t + "*Whether to add a newline at the end of the file, in certain major modes. +Those modes set `require-final-newline' to this value when you enable them. +They do so because they are used for files that are supposed +to end in newlines, and the question is how to arrange that. + +A value of t means do this only when the file is about to be saved. +A value of `visit' means do this right after the file is visited. +A value of `visit-save' means do it at both of those times. +Any other non-nil value means ask user whether to add a newline, when saving." + :type '(choice (const :tag "When visiting" visit) + (const :tag "When saving" t) + (const :tag "When visiting or saving" visit-save) + (other :tag "Ask" ask)) + :group 'editing-basics + :version "21.4") + (defcustom auto-save-default t "*Non-nil says by default do auto-saving of every file-visiting buffer." :type 'boolean @@ -1200,7 +1226,8 @@ "Return the buffer visiting file FILENAME (a string). This is like `get-file-buffer', except that it checks for any buffer visiting the same file, possibly under a different name. -If PREDICATE is non-nil, only a buffer satisfying it can be returned. +If PREDICATE is non-nil, only buffers satisfying it are eligible, +and others are ignored. If there is no such live buffer, return nil." (let ((predicate (or predicate #'identity)) (truename (abbreviate-file-name (file-truename filename)))) @@ -1626,6 +1653,15 @@ (when (and view-read-only view-mode) (view-mode-disable)) (normal-mode t) + ;; If requested, add a newline at the end of the file. + (and (memq require-final-newline '(visit visit-save)) + (> (point-max) (point-min)) + (/= (char-after (1- (point-max))) ?\n) + (not (and (eq selective-display t) + (= (char-after (1- (point-max))) ?\r))) + (save-excursion + (goto-char (point-max)) + (insert "\n"))) (when (and buffer-read-only view-read-only (not (eq (get major-mode 'mode-class) 'special))) @@ -2182,7 +2218,7 @@ buffer-file-name) (concat "buffer " (buffer-name)))))))))) - (let (prefix prefixlen suffix beg + (let (prefix suffix beg (enable-local-eval enable-local-eval)) ;; The prefix is what comes before "local variables:" in its line. ;; The suffix is what comes after "local variables:" in its line. @@ -2196,8 +2232,7 @@ (buffer-substring (point) (progn (beginning-of-line) (point))))) - (if prefix (setq prefixlen (length prefix) - prefix (regexp-quote prefix))) + (setq prefix (if prefix (regexp-quote prefix) "^")) (if suffix (setq suffix (concat (regexp-quote suffix) "$"))) (forward-line 1) (let ((startpos (point)) @@ -3194,6 +3229,7 @@ (not (and (eq selective-display t) (= (char-after (1- (point-max))) ?\r))) (or (eq require-final-newline t) + (eq require-final-newline 'visit-save) (and require-final-newline (y-or-n-p (format "Buffer %s does not end in newline. Add one? " @@ -3238,7 +3274,8 @@ (if save-buffer-coding-system (let ((coding-system-for-write save-buffer-coding-system)) (basic-save-buffer-2)) - (basic-save-buffer-2))) + (basic-save-buffer-2)) + (setq buffer-file-coding-system-explicit last-coding-system-used)) ;; This returns a value (MODES . BACKUPNAME), like backup-buffer. (defun basic-save-buffer-2 () @@ -3363,6 +3400,10 @@ "ACTION-ALIST argument used in call to `map-y-or-n-p'.") (put 'save-some-buffers-action-alist 'risky-local-variable t) +(defvar buffer-save-without-query nil + "Non-nil means `save-some-buffers' should save this buffer without asking.") +(make-variable-buffer-local 'buffer-save-without-query) + (defun save-some-buffers (&optional arg pred) "Save some modified file-visiting buffers. Asks user about each one. You can answer `y' to save, `n' not to save, `C-r' to look at the @@ -3380,8 +3421,18 @@ change the additional actions you can take on files." (interactive "P") (save-window-excursion - (let* ((queried nil) - (files-done + (let* (queried some-automatic + files-done abbrevs-done) + (dolist (buffer (buffer-list)) + ;; First save any buffers that we're supposed to save unconditionally. + ;; That way the following code won't ask about them. + (with-current-buffer buffer + (when (and buffer-save-without-query (buffer-modified-p)) + (setq some-automatic t) + (save-buffer)))) + ;; Ask about those buffers that merit it, + ;; and record the number thus saved. + (setq files-done (map-y-or-n-p (function (lambda (buffer) @@ -3410,19 +3461,22 @@ (buffer-list) '("buffer" "buffers" "save") save-some-buffers-action-alist)) - (abbrevs-done - (and save-abbrevs abbrevs-changed - (progn - (if (or arg - (eq save-abbrevs 'silently) - (y-or-n-p (format "Save abbrevs in %s? " - abbrev-file-name))) - (write-abbrev-file nil)) - ;; Don't keep bothering user if he says no. - (setq abbrevs-changed nil) - t)))) + ;; Maybe to save abbrevs, and record whether + ;; we either saved them or asked to. + (and save-abbrevs abbrevs-changed + (progn + (if (or arg + (eq save-abbrevs 'silently) + (y-or-n-p (format "Save abbrevs in %s? " + abbrev-file-name))) + (write-abbrev-file nil)) + ;; Don't keep bothering user if he says no. + (setq abbrevs-changed nil) + (setq abbrevs-done t))) (or queried (> files-done 0) abbrevs-done - (message "(No files need saving)"))))) + (message (if some-automatic + "(Some special files were saved without asking)" + "(No files need saving)")))))) (defun not-modified (&optional arg) "Mark current buffer as unmodified, not needing to be saved. @@ -3691,11 +3745,11 @@ (unlock-buffer))) (widen) (let ((coding-system-for-read - ;; Auto-saved file shoule be read without - ;; any code conversion. - (if auto-save-p 'utf-8-emacs + ;; Auto-saved file shoule be read by Emacs' + ;; internal coding. + (if auto-save-p 'auto-save-coding (or coding-system-for-read - buffer-file-coding-system)))) + buffer-file-coding-system-explicit)))) ;; This force after-insert-file-set-coding ;; (called from insert-file-contents) to set ;; buffer-file-coding-system to a proper value. @@ -4309,6 +4363,8 @@ (buffer-substring (point) end))))))))) +(defvar insert-directory-ls-version 'unknown) + ;; insert-directory ;; - must insert _exactly_one_line_ describing FILE if WILDCARD and ;; FULL-DIRECTORY-P is nil. @@ -4418,6 +4474,56 @@ (concat (file-name-as-directory file) ".") file)))))))) + ;; If we got "//DIRED//" in the output, it means we got a real + ;; directory listing, even if `ls' returned nonzero. + ;; So ignore any errors. + (when (if (stringp switches) + (string-match "--dired\\>" switches) + (member "--dired" switches)) + (save-excursion + (forward-line -2) + (when (looking-at "//SUBDIRED//") + (forward-line -1)) + (if (looking-at "//DIRED//") + (setq result 0)))) + + (when (and (not (eq 0 result)) + (eq insert-directory-ls-version 'unknown)) + ;; The first time ls returns an error, + ;; find the version numbers of ls, + ;; and set insert-directory-ls-version + ;; to > if it is more than 5.2.1, < if it is less, nil if it + ;; is equal or if the info cannot be obtained. + ;; (That can mean it isn't GNU ls.) + (let ((version-out + (with-temp-buffer + (call-process "ls" nil t nil "--version") + (buffer-string)))) + (if (string-match "ls (.*utils) \\([0-9.]*\\)$" version-out) + (let* ((version (match-string 1 version-out)) + (split (split-string version "[.]")) + (numbers (mapcar 'string-to-int split)) + (min '(5 2 1)) + comparison) + (while (and (not comparison) (or numbers min)) + (cond ((null min) + (setq comparison '>)) + ((null numbers) + (setq comparison '<)) + ((> (car numbers) (car min)) + (setq comparison '>)) + ((< (car numbers) (car min)) + (setq comparison '<)) + (t + (setq numbers (cdr numbers) + min (cdr min))))) + (setq insert-directory-ls-version (or comparison '=))) + (setq insert-directory-ls-version nil)))) + + ;; For GNU ls versions 5.2.2 and up, ignore minor errors. + (when (and (eq 1 result) (eq insert-directory-ls-version '>)) + (setq result 0)) + ;; If `insert-directory-program' failed, signal an error. (unless (eq 0 result) ;; Delete the error message it may have output. @@ -4444,23 +4550,39 @@ (when (looking-at "//SUBDIRED//") (delete-region (point) (progn (forward-line 1) (point))) (forward-line -1)) - (if (looking-at "//DIRED//") - (let ((end (line-end-position))) - (forward-word 1) - (forward-char 3) - (while (< (point) end) - (let ((start (+ beg (read (current-buffer)))) - (end (+ beg (read (current-buffer))))) - (if (memq (char-after end) '(?\n ?\ )) - ;; End is followed by \n or by " -> ". - (put-text-property start end 'dired-filename t) - ;; It seems that we can't trust ls's output as to - ;; byte positions of filenames. - (put-text-property beg (point) 'dired-filename nil) - (end-of-line)))) - (goto-char end) - (beginning-of-line) - (delete-region (point) (progn (forward-line 2) (point)))) + (when (looking-at "//DIRED//") + (let ((end (line-end-position)) + (linebeg (point)) + error-lines) + ;; Find all the lines that are error messages, + ;; and record the bounds of each one. + (goto-char (point-min)) + (while (< (point) linebeg) + (or (eql (following-char) ?\s) + (push (list (point) (line-end-position)) error-lines)) + (forward-line 1)) + (setq error-lines (nreverse error-lines)) + ;; Now read the numeric positions of file names. + (goto-char linebeg) + (forward-word 1) + (forward-char 3) + (while (< (point) end) + (let ((start (insert-directory-adj-pos + (+ beg (read (current-buffer))) + error-lines)) + (end (insert-directory-adj-pos + (+ beg (read (current-buffer))) + error-lines))) + (if (memq (char-after end) '(?\n ?\ )) + ;; End is followed by \n or by " -> ". + (put-text-property start end 'dired-filename t) + ;; It seems that we can't trust ls's output as to + ;; byte positions of filenames. + (put-text-property beg (point) 'dired-filename nil) + (end-of-line)))) + (goto-char end) + (beginning-of-line) + (delete-region (point) (progn (forward-line 2) (point)))) (forward-line 1) (if (looking-at "//DIRED-OPTIONS//") (delete-region (point) (progn (forward-line 1) (point))) @@ -4512,6 +4634,18 @@ (end-of-line) (insert " available " available))))))))))) +(defun insert-directory-adj-pos (pos error-lines) + "Convert `ls --dired' file name position value POS to a buffer position. +File name position values returned in ls --dired output +count only stdout; they don't count the error messages sent to stderr. +So this function converts to them to real buffer positions. +ERROR-LINES is a list of buffer positions of error message lines, +of the form (START END)." + (while (and error-lines (< (caar error-lines) pos)) + (setq pos (+ pos (- (nth 1 (car error-lines)) (nth 0 (car error-lines))))) + (pop error-lines)) + pos) + (defun insert-directory-safely (file switches &optional wildcard full-directory-p) "Insert directory listing for FILE, formatted according to SWITCHES.