diff options
| author | Richard M. Stallman | 2004-12-27 17:18:28 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 2004-12-27 17:18:28 +0000 |
| commit | a1b0c2a764aef31f347e87091ac3552d9b6e2fdb (patch) | |
| tree | 66490959c1f85fc5370d306c38562afe73bfa912 | |
| parent | 56011a8c59d3787778844018bbcd351dd8b431c2 (diff) | |
| download | emacs-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.el | 162 |
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). |
| 1201 | This is like `get-file-buffer', except that it checks for any buffer | 1201 | This is like `get-file-buffer', except that it checks for any buffer |
| 1202 | visiting the same file, possibly under a different name. | 1202 | visiting the same file, possibly under a different name. |
| 1203 | If PREDICATE is non-nil, only a buffer satisfying it can be returned. | 1203 | If PREDICATE is non-nil, only buffers satisfying it are eligible, |
| 1204 | and others are ignored. | ||
| 1204 | If there is no such live buffer, return nil." | 1205 | If 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. |
| 3368 | You can answer `y' to save, `n' not to save, `C-r' to look at the | 3373 | You 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 | |||
| 3380 | change the additional actions you can take on files." | 3385 | change 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. | ||
| 4603 | File name position values returned in ls --dired output | ||
| 4604 | count only stdout; they don't count the error messages sent to stderr. | ||
| 4605 | So this function converts to them to real buffer positions. | ||
| 4606 | ERROR-LINES is a list of buffer positions of error message lines, | ||
| 4607 | of 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. |