Tüm açık arabellekleri geri al (ve hataları yoksay)


12

Git ile sürüm kontrolü altında bir proje üzerinde çalışırken, genellikle açık dosyalarımın çoğunu etkileyen bir kabukta bazı şeyler yapmak, ardından yanlışlıkla yeni sürümü tıkamadığımdan emin olmak için açık olan her arabelleği geri almak istiyorum ne varsa açtım. magitBurada yardımcı olabileceğini biliyorum , ama kabuğumdaki iş akışına alışkınım ve şimdilik saklamak istiyorum. Bunun yerine, tüm açık arabellekleri geri almak istiyorum ve belki de mevcut olanı durdurabilenleri kapatmak istiyorum (örneğin, git checkoutartık bu dosyaya sahip olmayan bir dal nedeniyle ).

Bir Google aramasından yakaladığım aşağıdaki elisp snippet'im var:

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

Ama bu araları geri alırken yani benim açık dosyalardan birinin, bir hataya vurursa B1, B2, B3, ..., Bngeri dönmek için çalışılırken bir hata B2önler B3- Bndan döndürüldü ediliyor.

Emacs'a bu durumda ortaya çıkan hataları yoksaymasını nasıl söyleyebilirim? global-auto-revert-modeKullanmak istemiyorum çünkü her geri alma, otomatik tamamlama ve sözdizimi denetleyicim gibi dosyayı yeniden ayrıştırarak, emac'leri bir saniye kadar asılı bırakarak bazı ağır iş öğelerini tetikler.


Ne tür bir hata B2, örneğin tamponun geri alınmasını engeller . Çok benzer bir işlev kullanıyorum (büyük olasılıkla bu snippet'ten türetilmiştir) ve iyi çalıştı.
Kaushal Modi

@Kaushal: "dosya artık yok" gibi görünüyor ve / veya yeniden çalıştırmak arabellek geri var paketleri tarafından atılan hatalar. Çoğunlukla çalıştırdıktan sonra hala "Dosya son ziyaretten bu yana değişti!" onC-x s
Patrick Collins

"file no longer exists".. aha! benim sürüm bunu düzeltir :) Kısa süre içinde gönderir.
Kaushal Modi

Yanıtlar:


12

orijinal

İşte sorudaki snippet'in biraz geliştirilmiş versiyonum. VC geçmişimi gözden geçirerek, aşağıdaki snippet'in OP tarafından gönderilen snippet olarak başladığını onaylıyorum. Ben bunun için ödeme niteliği ödüyorum.

İşte benim için kararlı olan kod:

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

Güncelleme

İşte @ Drew'un çözümüne baktıktan sonra, geliştirilmiş ve daha iyi belgelenmiş bir versiyon .

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

Referans


5

Bir diğeri:

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

Teşekkürler. Ben çalıyorum dolistyerine stil carve pop. Daha fazla elisp öğrenirken yapılandırmanızı geliştirmeye nasıl devam edebileceğiniz komik :)
Kaushal Modi

@KaushalModi Bu yüzden kısmen yayınladım. ;-)
Drew

1

Kausal'ın cevabını istediğim şeye en yakın olduğu için kabul ettim, ama Drew'un çözümünün bir kısmını da aldım. Ben sarılmış revert-bufferiçinde with-demoted-errorsve düştü :preserve-modesbenim sözdizimi denetleyicisi benim açık tüm dosyaları yeniden ayrıştırma böylece parametre. Ayrıca değiştirilmiş dosyaları öldürmesine izin verdim, ayrıca değiştirilmemiş, çünkü sık sık değiştirilmiş bir dosyayı C-x saçtıktan sonra yanlışlıkla sorunla karşılaşıyorum git checkout.

Son sürüm:

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

Bu, birçok dosya açıkken asılabileceğinden ilerleme mesajları eklendi: emacs.stackexchange.com/a/50730/2418
ideasman42

1

Ben bu tamir edeceklerini condition-caseveya ignore-errors(dokümanlar burada ). Ne yapmasını istediğini tam olarak bilmiyorum ; hataları olan bir şey yapmak istiyorsanız condition-case, sonucu belirtmek için veya ignore-errorsdevam etmek için kullanabilirsiniz . Gibi bir şey:

(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'un cevabına dayanarak, ilavelerle:

  • İlerleme raporlaması (birçok dosya açıkken yavaş olabileceğinden) .
  • Geri alma durumunu temizle (arabelleği yeniden yüklerken geri alma geçmişini yükleyen paketler için destek ile - örneğin geri al-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))))))
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.