ฉันสามารถโหลดห้องสมุดใหม่และกำหนดค่า 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
@KaushalModi: ฉันไม่คิดว่ามันซ้ำซ้อน คำถามนี้เกี่ยวกับการกระทำdefvarในไฟล์หรือบัฟเฟอร์ถ้าฉันเข้าใจอย่างถูกต้อง
ดึง

1
ปกติใครจะไม่จำเป็นต้อง EVAL เพียง defvars นอกจากนี้การใช้ OP ก็load-fileหมายความว่าเขาต้องการประเมินไฟล์ทั้งหมดในขณะที่ตรวจสอบให้แน่ใจว่ามีการประเมิน defvars อีกครั้ง
Kaushal Modi

2
แนวทางของฉันคือการปรับค่า EVAL เมื่อฉันเปลี่ยนค่า ไม่บ่อยนักที่จะใช้งานได้สำหรับฉัน YMMV
YoungFrog

คำตอบ:


3

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

วิธีนี้จะใช้ได้ตราบใดที่คุณโหลด defvars เป็นครั้งแรกโดยการโหลดไลบรารีผ่าน emacs และไม่ได้ใช้eval-defunงานeval-bufferฯลฯ

เมื่อคุณใช้require, load-libraryฯลฯ Emacs unload-featureจะติดตามซึ่งตัวแปรและฟังก์ชั่นเป็นส่วนหนึ่งของห้องสมุดของคุณและจะเอาพวกเขาทั้งหมดที่คุณเมื่อคุณใช้

เมื่อเขียนแพคเกจฉันพบว่าการใช้โค้ดด้านบนเป็นทางออกที่ดีกว่าการรันeval-defunในขณะที่คุณเขียนโค้ดใหม่ดังนั้นคุณจึงไม่ได้รับสถานะระหว่างกลาง


(info "(elisp) Loading"), (info "(elisp) Unloading")และunload-featureต้องforceหาเรื่องถ้าห้องสมุดพึ่งพาห้องสมุดอื่น คำตอบที่ดี! ผมสงสัยว่าสิ่งที่รุ่น Emacs เริ่มต้นที่จะให้ถ่าย ...
gavenkoa

3

defvarไม่ได้โอนค่าของตัวแปรในลักษณะเดียวกับที่พูด หรือsetq setfเมื่อตัวแปรมีค่าdefvar จะไม่แตะต้องมัน

จากdefvardocstring ของ:

(defvar SYMBOL &optional INITVALUE DOCSTRING)

กำหนด SYMBOL เป็นตัวแปรแล้วส่งคืน SYMBOL

...

อาร์กิวเมนต์ทางเลือก INITVALUE ได้รับการประเมินและใช้เพื่อตั้งค่า SYMBOL เฉพาะในกรณีที่ค่าของ SYMBOL เป็นโมฆะ ถ้า SYMBOL เป็นบัฟเฟอร์ท้องถิ่นค่าเริ่มต้นของมันคือสิ่งที่มีการตั้งค่า; ค่าบัฟเฟอร์ท้องถิ่นจะไม่ได้รับผลกระทบ หาก INITVALUE หายไปค่าของ SYMBOL จะไม่ถูกตั้งค่า

...

เนื่องจากคุณอาจdefvarแก้ไขตัวแปรที่เป็นปัญหาเพื่อให้พวกเขามีค่าเมื่อคุณโหลดไลบรารีครั้งแรกการโหลดไลบรารีอีกครั้งจะไม่เปลี่ยนค่า

ดูเพิ่มเติมโหนดคู่มือ Elisp ใน ตัวแปรที่กำหนดทั่วโลก

แทนที่จะอาศัยค่าคุณสามารถกำหนดอีกครั้งกับdefvar setqคุณสามารถuninternใช้สัญลักษณ์แทน clunky เพื่อให้defvars ไม่พบสัญลักษณ์เหล่านั้นเมื่อทำการรีโหลด:

(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ตัวแปรในระหว่างการพัฒนาแพคเกจ การสลับไปsetqใช้จะต้องเปลี่ยนกลับเป็นdefvarเมื่อมีการเปิดตัวแพ็คเกจ
ไทเลอร์

@ ไทเลอร์ใช่ฉันเห็นด้วยที่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แต่มันยากที่จะเข้าใจรหัสอย่างสมบูรณ์

ฉันยังคิดถึงuninternสัญลักษณ์ทั้งหมดตามคำนำหน้าสัญลักษณ์ / regex (ตามที่แนะนำDan ) แต่ฉันขี้เกียจที่จะพิมพ์คำนำหน้าในแต่ละครั้ง ... ดูฉันจะยกเลิกคำจำกัดความสัญลักษณ์ทั้งหมดด้วยคำนำหน้าบางคำได้อย่างไร

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.