aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman2004-12-27 17:18:28 +0000
committerRichard M. Stallman2004-12-27 17:18:28 +0000
commita1b0c2a764aef31f347e87091ac3552d9b6e2fdb (patch)
tree66490959c1f85fc5370d306c38562afe73bfa912
parent56011a8c59d3787778844018bbcd351dd8b431c2 (diff)
downloademacs-a1b0c2a764aef31f347e87091ac3552d9b6e2fdb.tar.gz
emacs-a1b0c2a764aef31f347e87091ac3552d9b6e2fdb.zip
(buffer-save-without-query): New var (buffer-local).
(save-some-buffers): Save those buffers first, w/o asking. (insert-directory-ls-version): New variable. (insert-directory): When ls returns an error, test the version number to decide what the return code means. With --dired output format, detect and distinguish lines that are really error messages. (insert-directory-adj-pos): New function.
-rw-r--r--lisp/files.el162
1 files changed, 130 insertions, 32 deletions
diff --git a/lisp/files.el b/lisp/files.el
index 37de166d522..504b1ba7d9d 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -1200,7 +1200,8 @@ name to this list as a string."
1200 "Return the buffer visiting file FILENAME (a string). 1200 "Return the buffer visiting file FILENAME (a string).
1201This is like `get-file-buffer', except that it checks for any buffer 1201This is like `get-file-buffer', except that it checks for any buffer
1202visiting the same file, possibly under a different name. 1202visiting the same file, possibly under a different name.
1203If PREDICATE is non-nil, only a buffer satisfying it can be returned. 1203If PREDICATE is non-nil, only buffers satisfying it are eligible,
1204and others are ignored.
1204If there is no such live buffer, return nil." 1205If there is no such live buffer, return nil."
1205 (let ((predicate (or predicate #'identity)) 1206 (let ((predicate (or predicate #'identity))
1206 (truename (abbreviate-file-name (file-truename filename)))) 1207 (truename (abbreviate-file-name (file-truename filename))))
@@ -3363,6 +3364,10 @@ This requires the external program `diff' to be in your `exec-path'."
3363 "ACTION-ALIST argument used in call to `map-y-or-n-p'.") 3364 "ACTION-ALIST argument used in call to `map-y-or-n-p'.")
3364(put 'save-some-buffers-action-alist 'risky-local-variable t) 3365(put 'save-some-buffers-action-alist 'risky-local-variable t)
3365 3366
3367(defvar buffer-save-without-query nil
3368 "Non-nil means `save-some-buffers' should save this buffer without asking.")
3369(make-variable-buffer-local 'buffer-save-without-query)
3370
3366(defun save-some-buffers (&optional arg pred) 3371(defun save-some-buffers (&optional arg pred)
3367 "Save some modified file-visiting buffers. Asks user about each one. 3372 "Save some modified file-visiting buffers. Asks user about each one.
3368You can answer `y' to save, `n' not to save, `C-r' to look at the 3373You can answer `y' to save, `n' not to save, `C-r' to look at the
@@ -3380,8 +3385,18 @@ See `save-some-buffers-action-alist' if you want to
3380change the additional actions you can take on files." 3385change the additional actions you can take on files."
3381 (interactive "P") 3386 (interactive "P")
3382 (save-window-excursion 3387 (save-window-excursion
3383 (let* ((queried nil) 3388 (let* (queried some-automatic
3384 (files-done 3389 files-done abbrevs-done)
3390 (dolist (buffer (buffer-list))
3391 ;; First save any buffers that we're supposed to save unconditionally.
3392 ;; That way the following code won't ask about them.
3393 (with-current-buffer buffer
3394 (when (and buffer-save-without-query (buffer-modified-p))
3395 (setq some-automatic t)
3396 (save-buffer))))
3397 ;; Ask about those buffers that merit it,
3398 ;; and record the number thus saved.
3399 (setq files-done
3385 (map-y-or-n-p 3400 (map-y-or-n-p
3386 (function 3401 (function
3387 (lambda (buffer) 3402 (lambda (buffer)
@@ -3410,19 +3425,22 @@ change the additional actions you can take on files."
3410 (buffer-list) 3425 (buffer-list)
3411 '("buffer" "buffers" "save") 3426 '("buffer" "buffers" "save")
3412 save-some-buffers-action-alist)) 3427 save-some-buffers-action-alist))
3413 (abbrevs-done 3428 ;; Maybe to save abbrevs, and record whether
3414 (and save-abbrevs abbrevs-changed 3429 ;; we either saved them or asked to.
3415 (progn 3430 (and save-abbrevs abbrevs-changed
3416 (if (or arg 3431 (progn
3417 (eq save-abbrevs 'silently) 3432 (if (or arg
3418 (y-or-n-p (format "Save abbrevs in %s? " 3433 (eq save-abbrevs 'silently)
3419 abbrev-file-name))) 3434 (y-or-n-p (format "Save abbrevs in %s? "
3420 (write-abbrev-file nil)) 3435 abbrev-file-name)))
3421 ;; Don't keep bothering user if he says no. 3436 (write-abbrev-file nil))
3422 (setq abbrevs-changed nil) 3437 ;; Don't keep bothering user if he says no.
3423 t)))) 3438 (setq abbrevs-changed nil)
3439 (setq abbrevs-done t)))
3424 (or queried (> files-done 0) abbrevs-done 3440 (or queried (> files-done 0) abbrevs-done
3425 (message "(No files need saving)"))))) 3441 (message (if some-automatic
3442 "(Some special files were saved without asking)"
3443 "(No files need saving)"))))))
3426 3444
3427(defun not-modified (&optional arg) 3445(defun not-modified (&optional arg)
3428 "Mark current buffer as unmodified, not needing to be saved. 3446 "Mark current buffer as unmodified, not needing to be saved.
@@ -4309,6 +4327,8 @@ program specified by `directory-free-space-program' if that is non-nil."
4309 (buffer-substring (point) end))))))))) 4327 (buffer-substring (point) end)))))))))
4310 4328
4311 4329
4330(defvar insert-directory-ls-version 'unknown)
4331
4312;; insert-directory 4332;; insert-directory
4313;; - must insert _exactly_one_line_ describing FILE if WILDCARD and 4333;; - must insert _exactly_one_line_ describing FILE if WILDCARD and
4314;; FULL-DIRECTORY-P is nil. 4334;; FULL-DIRECTORY-P is nil.
@@ -4418,6 +4438,56 @@ normally equivalent short `-D' option is just passed on to
4418 (concat (file-name-as-directory file) ".") 4438 (concat (file-name-as-directory file) ".")
4419 file)))))))) 4439 file))))))))
4420 4440
4441 ;; If we got "//DIRED//" in the output, it means we got a real
4442 ;; directory listing, even if `ls' returned nonzero.
4443 ;; So ignore any errors.
4444 (when (if (stringp switches)
4445 (string-match "--dired\\>" switches)
4446 (member "--dired" switches))
4447 (save-excursion
4448 (forward-line -2)
4449 (when (looking-at "//SUBDIRED//")
4450 (forward-line -1))
4451 (if (looking-at "//DIRED//")
4452 (setq result 0))))
4453
4454 (when (and (not (eq 0 result))
4455 (eq insert-directory-ls-version 'unknown))
4456 ;; The first time ls returns an error,
4457 ;; find the version numbers of ls,
4458 ;; and set insert-directory-ls-version
4459 ;; to > if it is more than 5.2.1, < if it is less, nil if it
4460 ;; is equal or if the info cannot be obtained.
4461 ;; (That can mean it isn't GNU ls.)
4462 (let ((version-out
4463 (with-temp-buffer
4464 (call-process "ls" nil t nil "--version")
4465 (buffer-string))))
4466 (if (string-match "ls (.*utils) \\([0-9.]*\\)$" version-out)
4467 (let* ((version (match-string 1 version-out))
4468 (split (split-string version "[.]"))
4469 (numbers (mapcar 'string-to-int split))
4470 (min '(5 2 1))
4471 comparison)
4472 (while (and (not comparison) (or numbers min))
4473 (cond ((null min)
4474 (setq comparison '>))
4475 ((null numbers)
4476 (setq comparison '<))
4477 ((> (car numbers) (car min))
4478 (setq comparison '>))
4479 ((< (car numbers) (car min))
4480 (setq comparison '<))
4481 (t
4482 (setq numbers (cdr numbers)
4483 min (cdr min)))))
4484 (setq insert-directory-ls-version (or comparison '=)))
4485 (setq insert-directory-ls-version nil))))
4486
4487 ;; For GNU ls versions 5.2.2 and up, ignore minor errors.
4488 (when (and (eq 1 result) (eq insert-directory-ls-version '>))
4489 (setq result 0))
4490
4421 ;; If `insert-directory-program' failed, signal an error. 4491 ;; If `insert-directory-program' failed, signal an error.
4422 (unless (eq 0 result) 4492 (unless (eq 0 result)
4423 ;; Delete the error message it may have output. 4493 ;; Delete the error message it may have output.
@@ -4444,23 +4514,39 @@ normally equivalent short `-D' option is just passed on to
4444 (when (looking-at "//SUBDIRED//") 4514 (when (looking-at "//SUBDIRED//")
4445 (delete-region (point) (progn (forward-line 1) (point))) 4515 (delete-region (point) (progn (forward-line 1) (point)))
4446 (forward-line -1)) 4516 (forward-line -1))
4447 (if (looking-at "//DIRED//") 4517 (when (looking-at "//DIRED//")
4448 (let ((end (line-end-position))) 4518 (let ((end (line-end-position))
4449 (forward-word 1) 4519 (linebeg (point))
4450 (forward-char 3) 4520 error-lines)
4451 (while (< (point) end) 4521 ;; Find all the lines that are error messages,
4452 (let ((start (+ beg (read (current-buffer)))) 4522 ;; and record the bounds of each one.
4453 (end (+ beg (read (current-buffer))))) 4523 (goto-char (point-min))
4454 (if (memq (char-after end) '(?\n ?\ )) 4524 (while (< (point) linebeg)
4455 ;; End is followed by \n or by " -> ". 4525 (or (eql (following-char) ?\s)
4456 (put-text-property start end 'dired-filename t) 4526 (push (list (point) (line-end-position)) error-lines))
4457 ;; It seems that we can't trust ls's output as to 4527 (forward-line 1))
4458 ;; byte positions of filenames. 4528 (setq error-lines (nreverse error-lines))
4459 (put-text-property beg (point) 'dired-filename nil) 4529 ;; Now read the numeric positions of file names.
4460 (end-of-line)))) 4530 (goto-char linebeg)
4461 (goto-char end) 4531 (forward-word 1)
4462 (beginning-of-line) 4532 (forward-char 3)
4463 (delete-region (point) (progn (forward-line 2) (point)))) 4533 (while (< (point) end)
4534 (let ((start (insert-directory-adj-pos
4535 (+ beg (read (current-buffer)))
4536 error-lines))
4537 (end (insert-directory-adj-pos
4538 (+ beg (read (current-buffer)))
4539 error-lines)))
4540 (if (memq (char-after end) '(?\n ?\ ))
4541 ;; End is followed by \n or by " -> ".
4542 (put-text-property start end 'dired-filename t)
4543 ;; It seems that we can't trust ls's output as to
4544 ;; byte positions of filenames.
4545 (put-text-property beg (point) 'dired-filename nil)
4546 (end-of-line))))
4547 (goto-char end)
4548 (beginning-of-line)
4549 (delete-region (point) (progn (forward-line 2) (point))))
4464 (forward-line 1) 4550 (forward-line 1)
4465 (if (looking-at "//DIRED-OPTIONS//") 4551 (if (looking-at "//DIRED-OPTIONS//")
4466 (delete-region (point) (progn (forward-line 1) (point))) 4552 (delete-region (point) (progn (forward-line 1) (point)))
@@ -4512,6 +4598,18 @@ normally equivalent short `-D' option is just passed on to
4512 (end-of-line) 4598 (end-of-line)
4513 (insert " available " available))))))))))) 4599 (insert " available " available)))))))))))
4514 4600
4601(defun insert-directory-adj-pos (pos error-lines)
4602 "Convert `ls --dird' file name position value POS to a buffer position.
4603File name position values returned in ls --dired output
4604count only stdout; they don't count the error messages sent to stderr.
4605So this function converts to them to real buffer positions.
4606ERROR-LINES is a list of buffer positions of error message lines,
4607of the form (START END)."
4608 (while (and error-lines (< (caar error-lines) pos))
4609 (setq pos (+ pos (- (nth 1 (car error-lines)) (nth 0 (car error-lines)))))
4610 (pop error-lines))
4611 pos)
4612
4515(defun insert-directory-safely (file switches 4613(defun insert-directory-safely (file switches
4516 &optional wildcard full-directory-p) 4614 &optional wildcard full-directory-p)
4517 "Insert directory listing for FILE, formatted according to SWITCHES. 4615 "Insert directory listing for FILE, formatted according to SWITCHES.