init 파일의 오류를 정상적으로 처리하는 방법


20

init 파일을 실행할 때 오류를 포착하고 정상적으로 처리하는 방법을 원합니다. 가장 중요한 많은 사용자 정의 및 키 바인딩이 init 파일 끝에 표시되어 다른 설정이 그 위에 적용되지 않도록합니다. 문제는 초기화가 일찍 중단되면 익숙한 키 바인딩과 설정을 적용하지 않고 문제를 디버깅하려고 시도하는 것이 완전히 좌절된다는 것입니다.

오류가 발생했을 때 초기화 프로세스를 정상적으로 완료 할 수있는 방법이 있습니까?

답변:


9

완벽하지 않은 두 가지 옵션이 떠 오릅니다. 먼저 초기 초기화 코드의 대부분을 (즉, 사용자 정의하기 전에) 랩핑 할 수 있습니다 (ignore-errors ...). 그러나 오류 있으면 많은 피드백 ignore-errors이 없을 것 nil입니다.

더 복잡한 옵션의 조합으로 잠재적 버그 코드를 포장하는 것 unwind-protectwith-demoted-errors(과 debug-on-error전무로 설정). 후자는 첫 번째 오류가 발생하면 정상적으로 오류를 일으켜 오류 메시지를 *Messages*검사 를 위해 버퍼에 보고합니다 . 한편, 나머지 unwind-protect바디 (아마도 사용자 정의)가 평가됩니다. 예를 들어,

(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
좋았어요 with-demoted-errors. 과 같이 문자열 인수를 추가 할 수 "LOOK OVER HERE!!! %s"있으므로 메시지 버퍼의 오류를 놓칠 가능성이 적습니다.
Malabarba

이러한 형태의 @Malabarba with-demoted-errors24.4에서만 사용할 수 있습니다
lunaryorn

@lunaryorn 감사합니다, 그것을 몰랐습니다.
Malabarba

사실, 내가 사용하는 버전은 24.3.1입니다.
Dan

8

@Dan은 오류를 메시지로 전환하는 방법을 잘 설명했습니다. 를 사용하여 원하는 오류를 원하는대로 수행 할 수도 있습니다 condition-case. 또 다른 옵션은을 사용하는 것 unwind-protect입니다.

condition-case아무 이유없이 여기에 집착 하겠습니다.

오류 잡기

이것은 내부에서 발생한 일에 관계없이 항상 키 정의가 평가되도록 보장해야합니다 condition-case. 모든 오류가 내부에 저장됩니다 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!)

그것을 다시 던지기

나중에 오류를 다시 발생시킵니다. 몇 가지 방법이 있습니다. 여기 있습니다.

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

unwind-protect구조 절에 넣은 코드를 실행 한 후 오류가 즉시 다시 발생합니다. 그것은처럼 finally보다는 Java와 같은 언어에서 catch.
sanityinc

2

다른 답변은 이와 같은 경우에 유용한 저수준 오류 처리 기능을 잘 다루었습니다. 도움이 될 수있는 또 다른 방법은 모듈성입니다. 예를 들어 초기화 파일을 여러 파일로 나누고 ( provide적절하게 사용) 다음 대신이 함수를 사용하여로드합니다 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)))

이런 방식으로 파일을로드하는 동안 오류가 발생해도 여전히 메시지가 인쇄되지만 실제로 오류가 발생한 파일 이외의 항목은 실행되지 않습니다.

물론이 함수는 실제로 require호출 을 래핑하는 것과 다르지 않지만 with-demoted-errors(내가 알기 전에 작성했습니다 with-demoted-errors) 중요한 점은 본질적으로 Dan의 래핑 with-demoted-errorsunwind-protect래핑없이 (잠재적으로 매우 긴) 무언가를 구현할 수 있다는 것입니다 코드 블록.


이 기능은 내가 추구했던 것입니다. 오류보고에도 불구하고 내 emacs가 부팅됩니다. 그 후, 나는 단지 init 파일과을로드합니다 eval-buffer. 게시 해 주셔서 감사합니다.
케빈
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.