ライブラリをリロードして、defvarに値を再割り当てさせることはできますか?


10

ライブラリを開発していて、編集後にEmacsを終了せずに再ロードしたい(オンになっていると想定load-path):

(load-library "myname")

私がこれを行うと、Emacsはdefvar-bound変数への変更を取得しません。

各トップレベルフォームで手動でeval-defunC-M-x)を呼び出したくありません。DOESのM-x eval-buffer尊重defvar/ defcustom


1
たぶん(unload-feature 'myname)最初?
npostavs

試してみて、いいえ、それとは逆に、のeval-defun変更は反映されませんdefvar
JeanPierre

1
@KaushalModi:重複しているとは思いません。この質問はdefvar、私が正しく理解していれば、ファイルまたはバッファ内のすべてのに作用することについてです。
2016

1
通常、defvar だけを評価する必要はありません。また、使用しているOP load-fileは、defvarが再評価されていることを確認しながら、ファイル全体を評価したいことを意味します。
Kaushal Modi

2
私自身のアプローチは、値を変更するときにeval-defunすることです。それは私にとって使用できるほど頻繁ではありません。YMMV。
YoungFrog

回答:


3

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

これは、限り、あなたは最初のEmacsてライブラリをロードし、使用しないでdefvarsをロードして動作しますeval-defuneval-bufferなど

を使用するとrequireload-libraryEmacsはどの変数と関数がライブラリの一部であるかを追跡し、使用時にそれらを完全に削除しますunload-feature

パッケージを作成するとき、上記のコードを使用する方が、eval-defun新しいコードを作成して中間状態にならないように実行するよりも優れたソリューションであることがわかりました。


(info "(elisp) Loading")(info "(elisp) Unloading")およびライブラリが別のライブラリの依存関係である場合はunload-featureforceargが必要です。正解です。Emacs
のどの

3

defvar、と言うのと同じ方法で変数の値を再割り当てしません setqsetf。変数に値が設定されたら、defvar それに触れないでください。

defvarのドキュメント文字列から:

(defvar SYMBOL &optional INITVALUE DOCSTRING)

SYMBOLを変数として定義し、SYMBOLを返します。

...

オプションの引数INITVALUEが評価され、SYMBOLの値がvoidの場合のみ、SYMBOLを設定するために使用されます。SYMBOLがバッファローカルである場合、そのデフォルト値は設定されたものです。バッファローカル値は影響を受けません。INITVALUEがない場合、SYMBOLの値は設定されません。

...

あなたはおそらくのでdefvar与える問題の変数を編彼らはあなたが最初のライブラリをロードしたとき、再ロードライブラリーに値が変更されません値。

グローバル変数の定義に関するelisp手動ノードも参照してください 。

に依存する代わりにdefvar、常にで値を再割り当てできますsetq。別の不格好なオプションとして、リロード時にsが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
タイラー

@タイラー、はい、私はそれdefvarがパッケージ開発に適していることに同意します。私はそれdefvarが値を再割り当てしないことを指摘しているだけですが、そうしてsetqいます。
ダン

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たものでも機能しますが、コードを完全に理解することは困難です。

uninternDanが提案したように)シンボルプレフィックス/正規表現に基づいてすべてのシンボルについても考えますが、毎回プレフィックスを入力するのが面倒です... 特定のプレフィックスを持つすべてのシンボル定義をアンバインドするにどうすればよいですか?を参照してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.