ฉันจะแก้ไขแพ็คเกจ Emacs ได้อย่างไร


16

ฉันต้องการแก้ไขแพ็คเกจทดสอบและหวังว่าจะส่งคำขอการดึงภายหลัง ฉันจะทำอย่างปลอดภัยและมีประสิทธิภาพได้อย่างไร คำถามอาจรู้สึกกว้างเกินไปฉันจะยอมรับคำตอบที่ครอบคลุมประเด็นต่อไปนี้:

  1. ฉันคาดว่าจะติดตั้งแยกสาขาของแพ็คเกจและสามารถสลับระหว่างมันและสาขาที่มั่นคงในราชประสงค์ด้วย recompilation ดำเนินการโดยอัตโนมัติเมื่อจำเป็น แต่package.elดูเหมือนจะไม่นำเสนอวิธีที่ตรงไปตรงมา คำตอบนี้บน emacs-SE บอกเราว่า“ถ้ามีการติดตั้งหลายสำเนาของแพคเกจแล้วคนแรกที่จะถูกโหลด” ดังนั้นฉันเดาหนึ่งได้ด้วยตนเองยุ่งกับload-pathแต่นี้ไม่ได้รู้สึกแข็งแกร่ง วิธีมาตรฐานในการเลือกแพ็คเกจรุ่นใดรุ่นหนึ่งในบรรดาแพ็คเกจที่ติดตั้งคืออะไร?

  2. แม้ว่าฉันจะสามารถเปิดเผยหลายสาขาไปยัง Emacs ได้ แต่สำหรับการปรับแต่งที่สำคัญฉันต้องตรวจสอบให้แน่ใจว่าสาขาที่ไม่ได้อัปเดตนั้น“ ไม่ได้โหลด” และผลข้างเคียงที่แยกได้ ไม่unload-featureจัดการนี้ถูกต้องหรือบางทีมันอาจจะมีนิสัยที่ทดสอบของแพคเกจหลาย versioned ทุกคนควรรู้เกี่ยวกับอะไร?

  3. ฉันจะติดตั้งและทดสอบเวอร์ชันในเครื่องได้อย่างไร คำตอบนั้นขึ้นอยู่กับว่าแพ็กเกจนั้นง่าย (= หนึ่งไฟล์) หรือหลายไฟล์ EmacsWiki พูดเกี่ยวกับแพ็คเกจที่หลากหลาย:“ MELPA สร้างแพ็คเกจสำหรับคุณ ” ฉันสงสัยว่าฉันต้อง (หรือควร) พูดคุยกับ MELPA ทุกครั้งที่ฉันเปลี่ยนdefunแบบฟอร์มในแพ็คเกจที่หลากหลาย แต่คำถามยังคงอยู่ อย่างน้อยฉันต้องบอกตัวจัดการแพคเกจเกี่ยวกับเวอร์ชันในเครื่องและถ้าเป็นเช่นนั้นฉันจะทำอย่างไร

  4. ฉันควรกำหนดชื่ออะไรให้กับแพ็คเกจในท้องถิ่น? สมมติว่าฉันต้องการทำงานกับคุณสมบัติหรือข้อบกพร่องหลายอย่างพร้อมกันซึ่งหมายความว่ามีหลายสาขา Emacs จะไม่อนุญาตให้ตั้งชื่อเวอร์ชันในลักษณะที่เป็นคำอธิบาย (ตามแนวของ20170117.666-somebugorfeature) ฉันเดาว่าฉันสามารถเปลี่ยนชื่อแพ็กเกจตัวเองคำต่อท้ายสาขา แต่อีกครั้งเช่นload-pathแฮ็คด้วยตนเองในไตรมาสที่ 1 นี่เป็นแฮ็คที่น่าเกลียดดังนั้นฉันจะไม่ลองกับสิ่งที่ฉันตั้งใจจะส่งอัปสตรีมเว้นแต่ว่าเป็นการปฏิบัติที่ยอมรับอย่างกว้างขวาง .

คำถามที่อาจไร้เดียงสาเนื่องจากฉันไม่เคยเขียนแพทช์ไม่ได้ใช้กับ git หรือ vcs ที่คล้ายกัน อย่างไรก็ตามสำหรับผู้ใช้ Emacs จำนวนมากการแพ็คเก็จ Emacs อาจเป็นครั้งแรกที่พวกเขาพยายาม (หรืออาจจะเป็นคนเดียว) การเขียนโปรแกรมโซเชียลซึ่งเป็นเหตุผลว่าทำไมผมเชื่อว่าคำตอบของคำถามนี้จะมีค่า

คำตอบ:


7

หากต้องการสอดรับกับขั้นตอนการทำงานที่แตกต่างกันเล็กน้อยสำหรับการโหลดแพ็คเกจต่าง ๆ นี่คือความหลากหลายของสิ่งที่ฉันทำซึ่งทั้งคู่ใช้การload-pathควบคุมเพื่อควบคุมเวอร์ชันที่ฉันใช้อยู่ (การเปลี่ยนชื่อของแพ็คเกจเป็นความคิดที่ไม่ดี หากมีการอ้างอิง) ผมมีรุ่นปัจจุบันของ "ดีแพคเกจ" ที่ติดตั้งใน~/.emacs.d/elpaการใช้M-x package-installและโคลนแพคเกจ repo ในด้วย~/src/nice-packagegit clone ...

ด้วยแพ็คเกจการใช้งาน

ใน init.el ฉันมี

(use-package nice-package
  :load-path "~/src/nice-package"
  ...)

ด้วย:load-pathบรรทัดที่ไม่ใส่เครื่องหมายข้อคิดเห็นนี้จะใช้รุ่น git ของแพคเกจ การแสดงความคิดเห็นบรรทัดนี้และการโหลด emacs ใช้เวอร์ชัน elpa

ที่คล้ายกันโดยไม่ต้องใช้แพคเกจ

ใน init.el

(add-to-list 'load-path "~/src/nice-package")
(require 'nice-package)
...

ตอนนี้ทำเคล็ดลับการแสดงความคิดเห็นเดียวกันกับบรรทัดแรก

การใช้ emacs -L

นี่เป็นแนวคิดเดียวกัน แต่จัดการกับload-pathจากบรรทัดคำสั่ง คุณสามารถโหลดอินสแตนซ์ของ emacs ด้วยเวอร์ชัน git ของแพ็คเกจด้วย

emacs -L ~/src/nice-package

ซึ่งเพิ่งเพิ่มพา ธ นี้ไปยังด้านหน้าของโหลดพา ธ ด้วยวิธีนี้คุณสามารถเปิดใช้งานemacsจากเทอร์มินัลอื่นและรับแพคเกจเวอร์ชันเก่าและใหม่ที่ใช้งานแบบเคียงข้างกัน

ความคิดเห็นอื่น ๆ

  1. ใช้M-x eval-bufferหลังจากแก้ไขไฟล์แพ็กเกจเพื่อโหลดข้อกำหนดใหม่ที่คุณสร้างขึ้น
  2. การตรวจสอบสิ่งที่คอมไพเลอร์พูดด้วยM-x emacs-lisp-byte-compileมีประโยชน์เช่นกัน

ฉันใช้emacs -Lวิธีการโหลดแพ็คเกจท้องถิ่นที่ฉันติดตั้งไว้ทั่วโลกด้วย Cask สิ่งหนึ่งที่ทำให้ฉันผิดหวังคือการที่ใช้งาน<package>-versionจะส่งคืนเวอร์ชันที่ติดตั้งไว้ทั่วโลกเสมอแม้ในขณะที่ฉันกำลังใช้งานเวอร์ชันที่ปรับเปลี่ยนในเครื่องอยู่ก็ตาม จะเปิดออกนี้เป็นเพราะสำหรับแพคเกจนี้ได้รับรุ่นจาก<package>-version packages.el
ntc2

3

คำถามที่ดี! คำตอบก็คือว่าจนถึงขณะนี้ยังไม่มีคำตอบที่ดีเนื่องจากไม่มีผู้จัดการแพคเกจที่มีอยู่ได้รับการออกแบบสำหรับใช้กรณีนี้(ยกเว้นแอนเดอแต่แอนเดอไม่พยายามที่จะจัดการกับการดำเนินการจัดการแพคเกจอื่น ๆ ทั่วไปเช่นการจัดการการพึ่งพา)

แต่ตอนนี้มีstraight.elผู้จัดการแพ็คเกจรุ่นใหม่สำหรับ Emacs ที่จัดการปัญหานี้อย่างครอบคลุมที่สุดเท่าที่จะทำได้ คำเตือน: ฉันเขียนstraight.el!

หลังจากใส่ข้อมูลโค้ด bootstrapแล้วการติดตั้งแพคเกจก็ง่ายเหมือนกัน

(straight-use-package 'magit)

สิ่งนี้จะทำการโคลนที่เก็บ Git สำหรับ Magit สร้างแพ็คเกจโดยเชื่อมโยงไฟล์ของมันลงในไดเรกทอรีแยกรวบรวมคอมไพล์ไบต์สร้างและประเมินผลการโหลดอัตโนมัติและกำหนดค่าload-pathอย่างถูกต้อง แน่นอนว่าถ้าแพ็คเกจนั้นถูกโคลนและสร้างขึ้นมาแล้วจะไม่มีอะไรเกิดขึ้นและเวลาเริ่มต้นของคุณจะไม่ประสบ

คุณทำการเปลี่ยนแปลง Magit อย่างไร มันเป็นเรื่องเล็กน้อย! เพียงแค่ใช้M-x find-functionหรือM-x find-libraryเพื่อข้ามไปยังซอร์สโค้ดและแฮกออกไป! คุณสามารถประเมินการเปลี่ยนแปลงของคุณเพื่อทดสอบพวกมันแบบสดๆเช่นเดียวกับการปฏิบัติทั่วไปสำหรับการพัฒนา Emacs Lisp และเมื่อคุณรีสตาร์ท Emacs แพคเกจจะถูกสร้างใหม่รวบรวมใหม่โดยอัตโนมัติและอื่น ๆ มันเป็นไปโดยอัตโนมัติและเข้าใจผิดได้อย่างสมบูรณ์

เมื่อคุณพอใจกับการเปลี่ยนแปลงของคุณเพียงแค่ส่งและผลักคำขอ คุณสามารถควบคุมแพ็คเกจของคุณได้ทั้งหมด แต่การกำหนดค่าของคุณยังสามารถทำซ้ำได้ 100% เพราะคุณสามารถขอstraight.elให้สร้างไฟล์ล็อคที่บันทึกการแก้ไข Git ของแพ็คเกจทั้งหมดของคุณรวมถึงstraight.elตัวเอง MELPA และอื่น ๆ

straight.elสามารถติดตั้งแพ็คเกจใดก็ได้จาก MELPA, GNU ELPA หรือ EmacsMirror แต่มันยังมีสูตร DSL ที่ยืดหยุ่นสูงที่ช่วยให้คุณสามารถติดตั้งได้จากทุกที่รวมถึงการปรับแต่งวิธีการสร้างแพ็คเกจ นี่คือตัวอย่างที่แสดงตัวเลือกบางอย่าง:

(straight-use-package
 '(magit :type git 
         :files ("lisp/magit*.el" "lisp/git-rebase.el"
                 "Documentation/magit.texi" "Documentation/AUTHORS.md"
                 "COPYING" (:exclude "lisp/magit-popup.el"))
         :host github :repo "raxod502/magit"
         :upstream (:host github :repo "magit/magit")))

straight.elมีเอกสารที่ครอบคลุมอย่างน่าขัน อ่านทั้งหมดเกี่ยวกับมันบนGitHub


2

นี่เป็นคำถามที่ดีทั้งหมด!

Emacs ทำงานบนโมเดลหน่วยความจำภาพซึ่งการโหลดรหัสใหม่จะเปลี่ยนแปลงภาพหน่วยความจำของอินสแตนซ์ที่กำลังทำงานอยู่ การกำหนดฟังก์ชั่นและตัวแปรใหม่นั้นสามารถยกเลิกได้อย่างง่ายดายหากคุณเก็บรายการไว้ แต่มีผลข้างเคียงมากมายที่โมดูลอาจมีซึ่งคุณต้องการยกเลิก ดูเหมือนunload-featureว่ามันจะไปได้สวยทีเดียว

ฉันคิดว่าสิ่งที่คุณต้องการจะทำคือการรวมกันของการเข้ารหัสสดและการเปิดใช้งาน Emacs ใหม่เป็นครั้งคราวโหลดโมดูลที่คุณกำลังทำงานจากสาขาของคุณมากกว่าที่จะติดตั้ง หากคุณจบลงด้วยสาขาจำนวนมากเหล่านี้คุณอาจต้องการเชลล์สคริปที่เรียกใช้ emacs ที่ถูกต้องload-pathสำหรับสาขาที่คุณกำลังทำงานอยู่ในขณะนี้ ไม่ว่าในกรณีใดฉันจะไม่เปลี่ยนชื่อแพ็คเกจ ฉันคิดว่ามันน่าสับสนมากขึ้นเนื่องจาก emacs สามารถโหลดได้ทั้งคู่

ในขณะที่คุณพัฒนาแพตช์คุณสามารถเริ่มต้นได้โดยการกำหนดฟังก์ชั่นใหม่ที่คุณกำลังเปลี่ยนแปลงในเซสชั่น Emacs สดของคุณ สิ่งนี้ช่วยให้คุณทดสอบคำจำกัดความใหม่ได้ทันทีโดยไม่ต้องออกจาก Emacs โดยเฉพาะอย่างยิ่งเมื่อคุณแก้ไขไฟล์ elisp คุณสามารถใช้C-M-x( eval-defun) เพื่อประเมินฟังก์ชั่นปัจจุบันในเซสชัน Emacs ปัจจุบันของคุณ จากนั้นคุณสามารถโทรหาเพื่อให้แน่ใจว่าใช้งานได้ หากคุณกำลังเปลี่ยนแปลงบางอย่างที่เกิดขึ้นเมื่อเริ่มต้น Emacs คุณอาจต้องเริ่มต้นและหยุด Emacs เพื่อทดสอบ คุณอาจทำเช่นนั้นโดยเริ่มต้นและหยุดกระบวนการ Emacs แยกต่างหากเพื่อให้เซสชันการแก้ไขของคุณไม่ถูกขัดจังหวะ


2

ฉันไม่คิดว่าจะมีคำตอบที่ดีสำหรับเรื่องนี้ (ฉันคาดหวังว่าคุณจะได้รับการแก้ปัญหาบางส่วนกับ Cask แต่ฉันไม่คุ้นเคยพอที่จะให้คำตอบที่ดีแก่คุณในการใช้มันหวังว่าจะมีคนอื่น) สิ่งที่ฉันทำ (ฉันไม่ค่อยใช้แพคเกจ Elisp โดยไม่ทำการเปลี่ยนแปลงภายในเครื่องดังนั้นจึงเป็นวิธี "ปกติ" ของฉันจริง ๆ ):

  • cd ~/src; git clone ..../elpa.git
  • สำหรับแต่ละแพคเกจ cd ~/src/elisp; git clone ....thepackage.git
  • cd ~/src/elpa/packages; ln -s ~/src/elisp/* .
  • cd ~/src/elpa; make
  • ในการ~/.emacsเพิ่มของคุณ

    (eval-after-load 'package
     '(add-to-list 'package-directory-list
                   "~/src/elpa/packages"))
    

ด้วยวิธีนี้แพคเกจทั้งหมดจะถูกติดตั้ง "ตรงจาก Git" ง่าย ๆcd ~/src/elpa; makeจะคอมไพล์ใหม่ที่ต้องการและC-h o thepackage-functionจะข้ามไปยังไฟล์ต้นฉบับที่อยู่ภายใต้ Git

หากต้องการ "สลับระหว่างมันกับสาขาที่มีความเสถียรในสิ่งที่ต้องการ" คุณจะต้องgit checkout <branch>; cd ~/src/elpa; make; และถ้าคุณต้องการให้มันส่งผลกระทบต่อการเรียกใช้เซสชัน Emacs มันจะทำงานได้มากขึ้น โดยทั่วไปฉันไม่แนะนำให้ใช้unload-featureยกเว้นในกรณีพิเศษ (เป็นคุณลักษณะที่ดี แต่ยังไม่น่าเชื่อถือพอ)

มันไม่ได้ตอบสนองความต้องการของคุณมากมาย และมันมีข้อเสียพิเศษบางอย่างส่วนใหญ่ความจริงที่ว่า Git โคลนหลายแพ็คเกจไม่ตรงกับรูปแบบและเนื้อหาที่คาดหวังโดย elfile.git ของ makefile ดังนั้นคุณจะต้องเริ่มต้นด้วยการปรับแต่งแพ็คเกจเหล่านั้น (โดยทั่วไปสิ่งที่เกี่ยวข้องกับ<pkg>-pkg.elเนื่องจาก makefile ของ elpa.git คาดว่าจะสร้างไฟล์นี้<pkg>.elแทนที่จะให้มา แต่มีปัญหามากกว่าการรวบรวมจะดำเนินการแตกต่างกันดังนั้นบางครั้งคุณต้องเล่นกับrequires)

โอ้และแน่นอนว่าสิ่งนี้หมายความว่าคุณกำลังติดตั้งแพ็กเกจเหล่านั้นด้วยตัวเองดังนั้นคุณต้องใส่ใจกับการพึ่งพา การตั้งค่านี้ทำงานอย่างถูกต้องกับแพ็คเกจอื่น ๆ ที่ติดตั้งโดยpackage-installดังนั้นจึงไม่น่ากลัวขนาดนั้น


2

คำตอบอื่น ๆ สำหรับคำถามนี้รวมถึงคำตอบอื่น ๆ ของฉันพูดคุยเกี่ยวกับการแก้ไขแพ็คเกจ Emacs โดยทำการเปลี่ยนแปลงรหัส แต่ผู้คนที่ค้นหาคำถามนี้ผ่านทาง Google อาจกำลังคิดถึงสิ่งอื่นเมื่อพวกเขาพูดว่า "แก้ไขแพคเกจ Emacs" - กล่าวคือเอาชนะพฤติกรรมของตนโดยไม่ต้องแก้ไขซอร์สโค้ด

กลไกในการทำสิ่งนี้รวมถึงเพื่อเพิ่มความก้าวร้าว:

แม้จะมีพลังของสองตัวเลือกแรก แต่ฉันก็พบว่าตัวเองใช้เส้นทางที่สามค่อนข้างบ่อยเพราะบางครั้งไม่มีวิธีอื่น แต่คำถามคือจะเกิดอะไรขึ้นถ้านิยามฟังก์ชั่นดั้งเดิมเปลี่ยนไป? คุณจะไม่มีทางรู้ว่าคุณจำเป็นต้องอัปเดตเวอร์ชันของคำจำกัดความที่คุณคัดลอกและวางลงในไฟล์ init ของคุณ!

เนื่องจากฉันหมกมุ่นกับการปะแก้ฉันจึงเขียนแพ็คเกจel-patchซึ่งแก้ปัญหานี้ให้ครอบคลุมที่สุดเท่าที่จะทำได้ แนวคิดคือให้คุณกำหนด s-expression based ต่างกันในไฟล์ init ของคุณซึ่งอธิบายทั้งนิยามฟังก์ชันดั้งเดิมและการเปลี่ยนแปลงของคุณ สิ่งนี้ทำให้แพตช์ของคุณสามารถอ่านได้มากขึ้นและยังช่วยให้el-patchสามารถตรวจสอบได้ในภายหลังว่าคำจำกัดความของฟังก์ชั่นดั้งเดิมได้รับการปรับปรุงหรือไม่ (ถ้าเป็นเช่นนั้นจะแสดงการเปลี่ยนแปลงผ่าน Ediff!) การอ้างอิงจากเอกสาร:

พิจารณาฟังก์ชั่นต่อไปนี้ที่กำหนดไว้ใน company-statisticsแพ็คเกจ:

(defun company-statistics--load ()
  "Restore statistics."
  (load company-statistics-file 'noerror nil 'nosuffix))

สมมติว่าเราต้องการเปลี่ยนอาร์กิวเมนต์ที่สามจากnilเป็น 'nomessageเพื่อระงับข้อความที่บันทึกไว้เมื่อ company-statisticsโหลดไฟล์สถิติ เราสามารถทำได้โดยการวางรหัสต่อไปนี้ในinit.el:

(el-patch-defun company-statistics--load ()
  "Restore statistics."
  (load company-statistics-file 'noerror
        (el-patch-swap nil 'nomessage)
        'nosuffix))

เพียงแค่เรียกel-patch-defunแทนการdefunกำหนดแพทช์ no-op: นั่นคือมันไม่มีผลกระทบ (ดีไม่มาก - ดูใน ภายหลัง ) อย่างไรก็ตามโดยการรวมคำสั่งแพทช์คุณสามารถทำให้ฟังก์ชั่นเวอร์ชั่นที่ปรับเปลี่ยนนั้นแตกต่างจากของเดิมได้

ในกรณีนี้เราใช้el-patch-swapคำสั่ง el-patch-swapรูปแบบจะถูกแทนที่ด้วยnilในความหมายเดิม (นั่นคือรุ่นที่เมื่อเทียบกับ "อย่างเป็นทางการ" นิยามcompany-statistics.el) และมี'nomessageในความหมายที่ถูกปรับเปลี่ยน (นั่นคือรุ่นที่ได้รับการประเมินจริงใน init ไฟล์ของคุณ)


0

เมื่อคุณทำให้การเปลี่ยนแปลงมากผมคิดว่าคุณควรจะใช้straight.elให้ดูคำตอบโดยเรดอน Rosborough

หากคุณต้องการเปลี่ยนแปลงเพียงครั้งเดียวสมมติว่ามีโครงการที่เรียกว่าfork-modeให้ทำตามขั้นตอนต่อไปนี้:

  • สร้างไดเรกทอรีเพื่อจัดเก็บคอมไพล์ mkdir ~/.emacs.d/lisp-gits
  • หาทางแยกโครงการที่คุณต้องการเปลี่ยนพูดที่ https://github.com/user/fork-mode
  • โคลนส้อมของคุณ cd ~/.emacs.d/lisp-gits && git clone git@github.com:user/fork-mode.git

เขียนรหัสต่อไปนี้ในของคุณ .emacs

(if (file-exists-p "~/.emacs.d/lisp-gits/fork-mode")
    (use-package fork-mode :load-path "~/.emacs.d/lisp-gits/fork-mode")
  (use-package fork-mode :ensure t))

(use-package fork-mode
  :config
  (setq fork-mode-setting t)
  :hook
  ((fork-mode . (lambda () (message "Inside hook"))))

ตอนนี้คุณสามารถใช้โหมด emacs โดยใช้C-h fเพื่อค้นหาฟังก์ชันที่คุณต้องการเปลี่ยน คุณจะสังเกตเห็นว่าเมื่อติดตั้งแพ็คเกจใน lisp-gits แล้วคุณจะข้ามไปที่นั่น ใช้ magit หรือคำสั่ง git อื่น ๆ เพื่อคอมมิชชัน / พุชการเปลี่ยนแปลงจากนั้นใช้ github เพื่อส่งคำร้องขอแบบ pull

เมื่อคำขอดึงของคุณได้รับการยอมรับคุณสามารถลบโครงการออก~/.emacs.d/lisp-gitsและให้ผู้จัดการแพคเกจทำงานได้

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