İnit dosyasındaki hatalar zarif bir şekilde nasıl ele alınır


20

İnit dosyamı çalıştırırken hataları yakalamanın ve daha sonra bunları zarif bir şekilde işlemenin bir yolunu istiyorum. En önemli özelleştirmelerim ve tuş bağlamalarımın çoğu, diğer ayarların üstlerine uygulanmadığından emin olmak için init dosyamın sonunda görünür. Sorun şu ki, başlatma işlemi erken iptal edildiğinde, tanıdık anahtar bağları ve ayarları uygulanmadan sorunu ayıklamaya çalışırken tamamen sakat hissediyorum.

Bir hata oluştuğunda başlatma işlemini zarif bir şekilde bitirmenin bir yolu var mı?

Yanıtlar:


9

Her ikisi de mükemmel olmayan iki seçenek akla geliyor. İlk olarak, erken başlatma kodunuzun çoğunu (yani, özelleştirmelerinize ulaşmadan önce) içine koyabilirsiniz (ignore-errors ...). Orada ise şunlardır - hataları, ancak, geribildirim bir sürü olmayacak ignore-errorssadece dönecektir nil.

Daha karmaşık bir seçenek, potansiyel olarak buggy kodunu unwind-protectve with-demoted-errors( debug-on-errornil olarak ayarlanmış) ile birleştirmek olacaktır. İkincisi, karşılaştığı ilk hatada nazikçe hata yapar ve hata mesajını *Messages*denetiminiz için arabelleğe bildirir . Bu arada, unwind-protectvücudun geri kalanı (muhtemelen özelleştirmeleriniz) değerlendirilecektir. Yani, örneğin:

(unwind-protect
    (let ((debug-on-error nil))
      (with-demoted-errors
        (message "The world is about to end")
        (sleep-for 2)
        (/ 10 0)                        ; divide by zero signals an error
        (message "This will never evaluate")
        (sleep-for 2)
        (setq some-var 5)))
  (message "Here are the unwind forms that will always evaluate")
  (sleep-for 2)
  (setq some-var 10)
  (setq another-var "puppies")
  (message "All done!"))

1
Güzel, hakkında konuşmadım with-demoted-errors. Bunun gibi bir dize bağımsız değişkeni ekleyebilirsiniz "LOOK OVER HERE!!! %s", böylece ileti arabelleğindeki hatayı kaçırma olasılığınız daha düşüktür.
Malabarba

@Malabarba Bu form with-demoted-errorssadece 24.4'te mevcuttur
lunaryorn

@lunaryorn Teşekkürler, bilmiyordum.
Malabarba

Aslında, üzerinde bulunduğum sürüm 24.3.1.
Dan

8

@ Hataları nasıl iletilere dönüştürebileceğinizi açıkladı. Kullanarak hatalarla istediğiniz her şeyi yapabilirsiniz condition-case. Yine başka bir seçenek kullanmaktır unwind-protect.

Buraya yapışacağım condition-case, hiçbir sebep yok.

Hatayı Yakalama

Bu, içeride ne olursa olsun, anahtar tanımlarınızın değerlendirilmesini daima garanti etmelidir condition-case. Herhangi bir hata içeride saklanır init-error.

(defvar init-error nil 
  "The error which happened.")

(condition-case the-error
    (progn
      ;; Do the dangerous stuff here.
      (require 'what-I-want))
  (error
   ;; This is only evaluated if there's an error.
   (setq init-error the-error)))

;;; Do the safe stuff here.
(define-key uncrippling-map "\C-h" 'help!)

Geri fırlatma

Daha sonra hatayı tekrar atın. Bunu yapmanın birkaç yolu var, işte bir tane.

;;; Throw the error again here.
(when init-error
  (funcall #'signal (car init-error) (cdr init-error)))

unwind-protectkurtarma yan tümcesine koyduğunuz kodu yürüttükten sonra hatanın hemen yeniden yükseltilmesine neden olur. Bunun finallyyerine Java gibi bir dilde olduğu gibi catch.
sanityinc

2

Diğer cevaplar, böyle bir durumda faydalı olacak düşük seviyeli hata işleme tesislerini oldukça iyi bir şekilde ele almıştır. Yardımcı olabilecek başka bir yaklaşım modülerliktir. Örneğin, başlatma dosyamı birkaç farklı dosyaya böldüm ( provideuygun şekilde kullanarak ) ve bunları yerine bu işlevi kullanarak yüklüyorum require:

(defun my/require-softly (feature &optional filename)
  "As `require', but instead of an error just print a message.

If there is an error, its message will be included in the message
printed.

Like `require', the return value will be FEATURE if the load was
successful (or unnecessary) and nil if not."
  (condition-case err
      (require feature filename) 
    (error (message "Error loading %s: \"%s\""
                    (if filename (format "%s (%s)" feature filename) feature)
                    (error-message-string err))
           nil)))

Bir dosyayı bu şekilde yüklerken bir hata yine de bir ileti yazdırır, ancak hatanın gerçekte meydana geldiği dosya dışında hiçbir şeyin yürütülmesini engellemez.

Tabii ki, bu fonksiyon bir requireçağrıyı sarmaktan gerçekten farklı değil with-demoted-errors(bilmeden önce yazdım with-demoted-errors), ama önemli olan nokta, Dan'ın sarma with-demoted-errorsve unwind-protectsarma olmadan kombinasyonu (potansiyel olarak çok uzun) kod blokları.


Bu işlev tam da peşindeydim. Emacs'ım şimdi bir hata bildirmesine rağmen önyükleme yapıyor. Bundan sonra, sadece init dosyamı yüklerim ve eval-buffer. Gönderdiğiniz için teşekkürler.
Kevin
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.