라이브러리를 다시로드하고 defvar에 값을 다시 할당 할 수 있습니까?


10

라이브러리를 개발 중이며 Emacs를 종료하지 않고 편집 후 라이브러리를 다시로드하고 싶습니다 (켜져 있다고 가정 load-path).

(load-library "myname")

이 작업을 수행 할 때 Emacs는 defvar바운드 변수의 변경 사항을 선택하지 않습니다 .

각 최상위 양식에서 eval-defun( C-M-x)을 수동으로 호출하고 싶지 않습니다 . 합니까 M-x eval-buffer존중 defvar/은 defcustom?


1
아마 (unload-feature 'myname)먼저?
npostavs

방금 시도했지만 아니요와는 달리 eval-defun변경 사항이 없습니다 defvar.
JeanPierre

1
@ KashalModi : 나는 그것이 중복이라고 생각하지 않습니다. 이 질문은 defvar내가 올바르게 이해한다면 파일이나 버퍼의 모든 것에 대해 행동 하는 것입니다.
Drew

1
일반적으로 defvar 평가할 필요는 없습니다 . 또한 OP를 사용 load-file하면 defvar가 재평가되는지 확인하면서 전체 파일을 평가하려고합니다.
Kaushal Modi

2
내 자신의 접근 방식은 값을 변경함에 따라 평가를 내리는 것입니다. 나를 위해 사용할 수있을 정도로 드물다. YMMV.
YoungFrog

답변:


3

(progn (unload-feature 'your-lib) (load-library "your-lib"))

먼저 이맥스를 통해 라이브러리를로드하고, 사용하지 않음으로써 defvars로드 이것은 한 작동 eval-defun, eval-buffer

당신이 사용하는 경우 require, load-library등 이맥스는 변수와 함수는 라이브러리의 일부가되는 추적하며, 사용할 때 당신을 위해 완전히 제거합니다 unload-feature.

패키지를 작성할 때 위의 코드를 사용하는 것이 eval-defun새 코드를 작성할 때 실행하는 것보다 더 나은 솔루션 이므로 중간 상태가되지 않습니다.


(info "(elisp) Loading"), (info "(elisp) Unloading")unload-feature필요 force라이브러리가 다른 라이브러리에 대한 의존성 경우 인수. 좋은 대답입니다! 나는 어떤 Emacs 버전이 언 로딩을 제공하기 시작하는지 궁금합니다.
gavenkoa

3

defvarsetq또는 say와 같은 방식으로 변수 값을 다시 할당하지 않습니다 setf. 변수에 값이 있으면 defvar 만지지 않습니다.

에서 defvar의 문서화 문자열 :

(defvar SYMBOL &optional INITVALUE DOCSTRING)

SYMBOL을 변수로 정의하고 SYMBOL을 리턴하십시오.

...

선택적 인수 INITVALUE가 평가되고 SYMBOL의 값이 void 인 경우에만 SYMBOL을 설정하는 데 사용됩니다 . SYMBOL이 버퍼 로컬 인 경우 기본값은 설정된 값입니다. 버퍼 로컬 값은 영향을받지 않습니다. INITVALUE가 없으면 SYMBOL의 값이 설정되지 않습니다.

...

defvar라이브러리를 처음로드 할 때 해당 변수를 사용하여 값을 제공하는 것으로 추정되므로 라이브러리를 다시로드해도 값이 변경되지 않습니다.

전역 변수 정의 의 elisp 수동 노드도 참조하십시오 .

에 의존하는 대신 defvar항상을 사용하여 값을 다시 할당 할 수 있습니다 setq. 대안으로, 엉뚱한 옵션으로, 당신은 unintern심볼 defvar을 다시로드 할 때 심볼을 찾을 수 없도록 할 수 있습니다 :

(defvar test-1 "test this")
(defvar test-2 "test this one, too")

test-1                                  ; => "test this"
test-2                                  ; => "test this one, too"

(defvar test-1 "trying to redefine")
(defvar test-2 "trying to redefine, too")

test-1                                  ; => "test this"
test-2                                  ; => "test this one, too"

(mapc #'unintern '(test-1 test-2))

test-1                                  ; => error!
test-2                                  ; => error!

(defvar test-1 "trying to redefine")
(defvar test-2 "trying to redefine, too")

test-1                                  ; => "trying to redefine"
test-2                                  ; => "trying to redefine, too"

2
이러한 맥락에서, 즉 elisp 패키지를 개발할 때 defvar사용하는 것이 올바른 것입니다. setq개별 사용자에 의해 설정된 클로버 사용자 정의. OP는 패키지 개발 중에defvar 변수 를 강제로 덮어 쓸 수있는 방법을 요구하고있다 . 로 전환 하려면 패키지가 릴리스 될 때 다시 전환해야합니다 . setqdefvar
Tyler

@Tyler, 그렇습니다 defvar. 패키지 개발에 적합 하다는 데 동의합니다 . 나는 defvar값을 다시 할당하지 않는 반면 지적하고 setq있습니다.
Dan

2

이 시도:

(defun foo ()
  "(Re-)evaluate all `defvar's in the buffer (or its restriction)."
  (interactive)
  (save-excursion
    (goto-char (point-min))
    (while (not (eobp))
      (when (re-search-forward "\\s-*(defvar \\([^ \t\n(\"]+\\)[ \t\n]+[^)]" nil 'MOVE)
        (let ((old-value (make-symbol "t"))
              new-value value)
          (let ((debug-on-error old-value))
            (setq value (eval-defun-2))
            (setq new-value debug-on-error))
          (unless (eq old-value new-value)
            (setq debug-on-error new-value))
          value)))))

그것은에서 사용하는 것과 동일한 코드를 eval-defun사용합니다 defvar. 각 정차 버퍼 (또는 축소하여 그 제한)을 통과 defvar하여 사용 eval-defun그것에 코드.


1

의 재 할당으로 버퍼를 재평가하는 편리한 솔루션이 없다고 들었을 때 defvar나는 릴레이를 사용하는 간단한 기능을 만들었습니다 eval-defun.

(defun my/eval-buffer ()
  "Evaluate entire buffer with re-assigning values to `defvar' / `defcustom'.
Useful during package development."
  (interactive)
  (save-excursion
    (beginning-of-buffer)
    (while (not (eobp))
      (eval-defun nil)
      (end-of-defun))))

eval-defun-2구현에서 영감을 얻은 코드 구조 . defvar를 강제로 재평가하는 방법 과 비슷합니다 . 해결책.

원래 빌드 스크립트를 통해 다시 설치된 라이브러리를 다시 평가하기 위해 고급 기능을 원합니다.

(defun my/load-library (library)
  "Evaluate entire library with re-assigning values to `defvar' / `defcustom'.
Useful during package development."
  (interactive
   (list (completing-read "Load library: "
                          (apply-partially 'locate-file-completion-table
                                           load-path
                                           '("" ".el")))))
  (with-temp-buffer
    (insert-file-contents (locate-file library load-path '("" ".el")))
    (my/eval-buffer)))

Drew 솔루션은 중첩에서도 작동 defvar하지만 코드를 완전히 이해하기는 어렵습니다.

또한 unintern기호 접두사 / 정규식 ( Dan이 제안한대로)을 기반으로 하는 모든 기호 에 대해 생각 하지만 매번 접두사를 입력하는 것이 게으 릅니다 ... 모든 기호 정의를 특정 접두사와 바인딩 해제하려면 어떻게합니까?를 참조하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.