열려있는 모든 버퍼를 되돌리기 (오류 무시)


12

git으로 버전 관리중인 프로젝트에서 작업 할 때 종종 열려있는 많은 파일에 영향을 미치는 쉘에서 몇 가지 작업을 수행 한 다음 실수로 새 버전을 방해하지 않도록 열려있는 모든 버퍼를 되돌리려 고합니다. 내가 열었던 건 뭐든지 magit여기서 도움 이 될 수 있지만 셸의 워크 플로에 익숙하며 지금은 유지하고 싶습니다. 대신 열려있는 모든 버퍼를 되돌리고 기존 git checkout파일을 더 이상 가지고 있지 않은 분기로 인해 기존에 중지 된 것을 닫고 싶습니다 .

Google 검색에서 얻은 다음 코드 조각이 있습니다.

(defun revert-all-buffers ()
  "Refreshes all open buffers from their respective files"
  (interactive)
  (let* ((list (buffer-list))
         (buffer (car list)))
    (while buffer
      (when (and (buffer-file-name buffer) 
                 (not (buffer-modified-p buffer)))
        (set-buffer buffer)
        (revert-buffer t t t))
      (setq list (cdr list))
      (setq buffer (car list))))
  (message "Refreshed open files"))

그러나이 휴식이 복귀 할 때, 즉 내 열려있는 파일 중 하나에 오류가 안타 B1, B2, B3, ..., Bn복귀하는 동안 오류 B2방지를 B3- Bn에서이 복귀된다.

이 경우에 나타나는 오류를 emacs에 무시하도록하려면 어떻게해야합니까? global-auto-revert-mode각 되돌리기가 자동 완성 및 구문 검사기에서 파일을 다시 구문 분석하고 emacs를 1 초 정도 걸고 구문 검사기와 같은 무거운 물건을 트리거 하기 때문에 사용하고 싶지 않습니다 .


어떤 종류의 오류로 인해 B2예제 에서 버퍼를 되돌릴 수 없습니다. 나는 매우 비슷한 기능을 사용하고 있으며 (이 코드 조각에서 파생되었을 가능성이 높습니다) 제대로 작동했습니다.
Kaushal Modi

@Kaushal : "더 이상 존재하지 않는 파일"인 것 같고 패키지에서 발생한 오류로 인해 다시 실행 버퍼를 되돌릴 수 있습니다. 대부분 실행 한 후에도 "마지막 방문 이후 파일이 변경되었습니다!"라는 메시지가 계속 표시됩니다. onC-x s
Patrick Collins

"file no longer exists".. 아하! 내 버전은 다음과 같이 수정됩니다. :) 곧 게시합니다.
Kaushal Modi

답변:


12

기발한

다음은 질문에서 약간 개선 된 스 니펫 버전입니다. 내 VC 기록을 검토 한 결과 아래 스 니펫이 OP에서 게시 한 스 니펫으로 시작되었음을 확인했습니다. 그래서 나는 그것에 속성을 지불합니다.

나를 위해 안정된 코드는 다음과 같습니다.

(defun modi/revert-all-file-buffers ()
  "Refresh all open buffers from their respective files."
  (interactive)
  (let* ((list (buffer-list))
         (buffer (car list)))
    (while buffer
      (let ((filename (buffer-file-name buffer)))
        ;; Revert only buffers containing files, which are not modified;
        ;; do not try to revert non-file buffers like *Messages*.
        (when (and filename
                   (not (buffer-modified-p buffer)))
          (if (file-exists-p filename)
              ;; If the file exists, revert the buffer.
              (with-current-buffer buffer
                (revert-buffer :ignore-auto :noconfirm :preserve-modes))
            ;; If the file doesn't exist, kill the buffer.
            (let (kill-buffer-query-functions) ; No query done when killing buffer
              (kill-buffer buffer)
              (message "Killed non-existing file buffer: %s" filename)))))
      (setq buffer (pop list)))
    (message "Finished reverting buffers containing unmodified files.")))

최신 정보

@ Drew 's solution을 보고 위의 개선되고 더 나은 문서 버전이 있습니다 .

(defun modi/revert-all-file-buffers ()
  "Refresh all open file buffers without confirmation.
Buffers in modified (not yet saved) state in emacs will not be reverted. They
will be reverted though if they were modified outside emacs.
Buffers visiting files which do not exist any more or are no longer readable
will be killed."
  (interactive)
  (dolist (buf (buffer-list))
    (let ((filename (buffer-file-name buf)))
      ;; Revert only buffers containing files, which are not modified;
      ;; do not try to revert non-file buffers like *Messages*.
      (when (and filename
                 (not (buffer-modified-p buf)))
        (if (file-readable-p filename)
            ;; If the file exists and is readable, revert the buffer.
            (with-current-buffer buf
              (revert-buffer :ignore-auto :noconfirm :preserve-modes))
          ;; Otherwise, kill the buffer.
          (let (kill-buffer-query-functions) ; No query done when killing buffer
            (kill-buffer buf)
            (message "Killed non-existing/unreadable file buffer: %s" filename))))))
  (message "Finished reverting buffers containing unmodified files."))

참고


5

다른:

(defun revert-all-no-confirm ()
  "Revert all file buffers, without confirmation.
Buffers visiting files that no longer exist are ignored.
Files that are not readable (including do not exist) are ignored.
Other errors while reverting a buffer are reported only as messages."
  (interactive)
  (let (file)
    (dolist (buf  (buffer-list))
      (setq file  (buffer-file-name buf))
      (when (and file  (file-readable-p file))
        (with-current-buffer buf
          (with-demoted-errors "Error: %S" (revert-buffer t t)))))))

감사. 나는 도둑질하고 dolist대체하는 스타일을 car하고 pop. 더 자세히 배우면서 구성을 계속 향상시킬 수있는 재미있는 방법 :)
Kaushal Modi

@KaushalModi 그것이 부분적으로 게시 한 이유입니다. ;-)
Drew

1

내가 원했던 것에 가장 가깝기 때문에 Kausal의 대답을 받아 들였지만 Drew의 해결책 중 일부를 움켜 잡았습니다. 나는 포장 revert-bufferwith-demoted-errors와 떨어 :preserve-modes내 문법 검사기가 내 열려있는 모든 파일을 다시 구문 분석 있도록 매개 변수를. 또한 수정 된 파일을 열어 C-x s두면 실수로 실수로 문제를 일으켜 수정 된 파일과 수정되지 않은 파일을 모두 죽일 수 git checkout있습니다.

최종 버전은 다음과 같습니다.

(defun revert-all-buffers ()
  "Refresh all open buffers from their respective files."
  (interactive)
  (let* ((list (buffer-list))
         (buffer (car list)))
    (while buffer
      (let ((filename (buffer-file-name buffer)))
        ;; Revert only buffers containing files, which are not modified;
        ;; do not try to revert non-file buffers like *Messages*.
        (when filename
          (if (file-exists-p filename)
              ;; If the file exists, revert the buffer.
              (with-demoted-errors "Error: %S"
                (with-current-buffer buffer
                  (revert-buffer :ignore-auto :noconfirm)))
            ;; If the file doesn't exist, kill the buffer.
            (let (kill-buffer-query-functions) ; No query done when killing buffer
              (kill-buffer buffer)
              (message "Killed non-existing file buffer: %s" buffer))))
        (setq buffer (pop list)))))
  (message "Finished reverting non-file buffers."))

많은 파일 열기와 함께이 요령이 나타날 수 있기 때문에 진행 메시지를 추가 : emacs.stackexchange.com/a/50730/2418
ideasman42

1

이 문제를 a condition-case또는 ignore-errors(docs here )로 수정했습니다 . 나는 당신이 그것을 할 수 있습니다 정확히 모르는 ; 오류가있는 작업을 수행하려는 경우 condition-case결과를 지정하는 데 사용하거나 ignore-errors계속 진행 하는 데 사용할 수 있습니다 . 다음과 같은 것 :

(defun revert-all-buffers ()
  "Refreshes all open buffers from their respective files"
  (interactive)
  (let* ((list (buffer-list))
         (buffer (car list)))
    (while buffer
      (when (and (buffer-file-name buffer) 
                 (not (buffer-modified-p buffer)))
        (set-buffer buffer)
        (ignore-errors (revert-buffer t t t)))
      (setq list (cdr list))
      (setq buffer (car list))))
  (message "Refreshed open files"))

0

@Drew의 답변을 바탕으로 다음을 추가했습니다.

  • 진행률보고 (많은 파일을 열면 느려질 수 있으므로) .
  • 실행 취소 상태 를 지 웁니다 ( 예 : 버퍼 실행 취소 후 세션 을 다시로드 할 때 실행 취소 기록을로드하는 패키지 지원 ) .
(defun revert-all-buffers ()
  "Refresh all open buffers from their respective files.

Buffers which no longer exist are closed.

This can be useful when updating or checking out branches outside of Emacs."
  (interactive)
  (let* ((filename-and-buffer-list ;; Pairs of '(filename . buf)'.
          (let ((temp-list nil))
            (dolist (buf (buffer-list))
              (let ((filename (buffer-file-name buf)))
                (when filename
                  (push (cons filename buf) temp-list))))
            temp-list))

         (count (length filename-and-buffer-list))
         (count-final 0)
         (count-close 0)
         (count-error 0)
         ;; Keep text at a fixed width when redrawing.
         (format-count
          (format "%%%dd" (length (number-to-string count))))
         (format-text
          (concat "Reverting [" format-count " of " format-count "] %3d%%: %s"))
         (index 1))

    (message "Begin reverting %d buffers..." count)
    (while filename-and-buffer-list
      (pcase-let ((`(,filename . ,buf) (pop filename-and-buffer-list)))
        ;; Revert only buffers containing files, which are not modified;
        ;; do not try to revert non-file buffers such as '*Messages*'.
        (message format-text
                 index count (round (* 100 (/ (float index) count))) filename)
        (if (file-exists-p filename)
            ;; If the file exists, revert the buffer.
            (if (with-demoted-errors "Error: %S"
                  (with-current-buffer buf
                    (let ((no-undo (eq buffer-undo-list t)))

                      ;; Disable during revert.
                      (unless no-undo
                        (setq buffer-undo-list t)
                        (setq pending-undo-list nil))

                      (unwind-protect
                          (revert-buffer :ignore-auto :noconfirm)

                        ;; Enable again (always run).
                        (unless no-undo
                          ;; It's possible a plugin loads undo data from disk,
                          ;; check if this is still unset.
                          (when (and (eq buffer-undo-list t)
                                     (null pending-undo-list))
                            (setq buffer-undo-list nil))))))
                  t)
                (setq count-final (1+ count-final))
              (setq count-error (1+ count-error)))

          ;; If the file doesn't exist, kill the buffer.
          (let (kill-buffer-query-functions) ;; No query done when killing buffer.
            (message "Closing non-existing file buffer: %s" buf)
            (kill-buffer buf)
            (setq count-close (1+ count-close))))
        (setq index (1+ index))))
    (message
     (concat
      "Finished Revert All: " (format "%d buffer(s)" count-final)
      (if (zerop count-close)
          ""
        (format ", %d closed" count-close))
      (if (zerop count-error)
          ""
        (format ", %d error (see message buffer)" count-error))))))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.