開いているすべてのバッファを元に戻します(エラーは無視します)


12

gitを使用してバージョン管理下のプロジェクトで作業するとき、開いているファイルの多くに影響を与えるシェルでいくつかのことを実行したい場合があります。次に、開いているすべてのバッファを元に戻して、新しいバージョンを誤って上書きしないようにします。私が開いていたもので。私が知っているmagit、ここで参考にすることができますが、私はシェルで私のワークフローに使用していると私は今のところそれを維持したいと思います。そのため、代わりに、開いているすべてのバッファを元に戻し、おそらく存在git checkoutしなくなったもの(たとえば、そのファイルがなくなったブランチのため)を閉じます。

私はGoogle検索から取得した次のelispのスニペットを持っています。

(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"))

しかし、この休憩、それは私の開いているファイルのいずれかでエラーがヒットした場合、すなわち元に戻すときB1B2B3、...、Bn復帰しようとしたときにエラーをB2防止するB3- Bn元に戻すされているから。

この場合ポップアップするエラーを無視するようにemacsに指示するにはどうすればよいですか?使用したくないのはglobal-auto-revert-mode、元に戻すたびに、オートコンプリートや構文チェッカーがファイルを再解析したり、emacsを1秒ほど停止したりするなど、かなりの負荷がかかるためです。


B2あなたの例でどのようなエラーがバッファを元に戻すのを妨げていますか?私は非常によく似た関数(おそらくこのスニペットから派生したもの)を使用していますが、うまく機能しています。
Kaushal Modi

@Kaushal:「ファイルがもう存在しない」ようです。また、再実行されたバッファを元に戻したパッケージによってエラーがスローされたようです。ほとんどの場合、実行後も「最後にアクセスしてからファイルが変更されました」というメッセージが表示されることに気づきました。オンC-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の ソリューションを見た後の、上記の改善され、より適切に文書化されたバージョンを次に示します。

(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スタイルを盗んで入れ替えcarpopます。elispを学習するにつれて、構成を改善し続ける方法をおもしろい:)
Kaushal Modi

@KaushalModiそれが私がそれを部分的に投稿した理由です。;-)
ドリュー

1

カウサルの答えは私が望んでいたものに最も近いので受け入れましたが、ドリューの解の一部も手に入れました。構文チェッカーが開いているすべてのファイルを再解析できるように、パラメーターをラップ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

これをcondition-caseまたはignore-errors(ドキュメントはこちら)で修正します。何をしたいのか正確にはわかりません。エラーで何かをしたい場合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の回答に基づいて、追加:

  • 進行状況レポート(多くのファイルを開いていると遅くなる可能性があるため)
  • 元に戻す状態をクリアします(バッファーを再ロードするときに元に戻す履歴をロードするパッケージのサポート-undo-fu-sessionなど)
(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.