ฉันได้ค้นพบแล้วว่าการวางไข่กระบวนการ Emacs ใหม่เป็นวิธีแก้ปัญหา
นี่คือสิ่งที่ฉันได้ทำ
1. เพิ่มฟังก์ชั่นเพื่อเริ่มกระบวนการ emacs ภายนอก
init.el
(defvar my/async-emacs-repl-org-babel-init-file "~/.emacs.d/org-babel-async-init" "File to load on executing async babel evaluation.")
(defun my/async-emacs-repl--start (process-name init-file)
"Start a new Emacs process as a REPL server."
(async-shell-command (concat
"TERM=vt200 emacs --batch -nw"
" --eval '(load \"" init-file "\")'"
" --eval '(while t (print (eval (read))))'"
)
process-name))
(defun my/async-emacs-repl--org-babel--start-server ()
"Starts an Emacs process for async org-babel execution."
(my/async-emacs-repl--start "*org-babel-async*" my/async-emacs-repl-org-babel-init-file))
(defun my/async-emacs-repl--org-babel--start-if-not-exists ()
"Starts an Emacs process if the process does not exist."
(if (not (get-buffer-process "*org-babel-async*")) (my/async-emacs-repl--org-babel--start-server)))
(defun my/async-emacs-repl--org-babel--execute--build-command (file-name line-number)
"Build the command for executing `org-babel-execute-src-block'."
(concat
"(progn"
" (find-file \"" file-name "\")"
" (revert-buffer t t)"
" (goto-line " (number-to-string line-number) ")"
" (org-babel-execute-src-block t)"
" (save-buffer)"
")"
"\n"))
(defun my/async-emacs-repl--org-babel--execute (process-name file-name line-number)
"Sends the command to the server to run the code-block the cursor is at."
(process-send-string
process-name
(my/async-emacs-repl--org-babel--execute--build-command file-name line-number)))
(defun my/async-emacs-repl-org-babel-do-execute ()
"Run org babel execution at point."
(my/async-emacs-repl--org-babel--execute "*org-babel-async*" (buffer-file-name) (line-number-at-pos)))
(defun my/async-emacs-repl-org-babel-execute ()
"Run by the user. Executes command. Starts buffer if not exists."
(interactive)
(save-buffer)
(my/async-emacs-repl--org-babel--start-if-not-exists)
(my/async-emacs-repl-org-babel-do-execute))
2. เพิ่มไฟล์กำหนดค่าเพื่อโหลดในกระบวนการ emacs ใหม่
ฟังก์ชั่นด้านบนเริ่ม emacs ใน--batch
โหมด ดังนั้น init.el ปกติจะไม่ถูกโหลด
แต่เราต้องการสร้างไฟล์กำหนดค่าที่สั้นกว่า (เพื่อโหลดพา ธ และอื่น ๆ )
เส้นทางไปยังไฟล์กำหนดค่าใหม่ของเราจะถูกจัดเก็บไว้ในasync-emacs-repl-org-babel-init-file
ข้อมูลโค้ดด้านบน
org-Babel-async-init.el
;; 1
(package-initialize)
;; 2
(setq org-confirm-babel-evaluate nil)
;; 3
(let ((my/org-babel-evaluated-languages
'(emacs-lisp
ditaa
python
ruby
C
matlab
clojure
sh
dot
plantuml)))
(org-babel-do-load-languages
'org-babel-load-languages
(mapcar (lambda (lang)
(cons lang t))
my/org-babel-evaluated-languages)))
ที่นี่เรา ...
- เพิ่มเส้นทางของแพ็คเกจ
- บอกโหมดองค์กรเพื่อไม่ให้ถามว่าจะเรียกใช้งานการบล็อกรหัส
- บอกองค์กรที่จำเป็นต้องใช้ภาษา
เชิงอรรถ 1: หากไม่มีการตั้งค่านี้การประเมินผลจะล้มเหลว "No org-babel-execute function for $lang!"
เชิงอรรถ 2: แน่นอนคุณสามารถโหลด init.el ปกติแทนที่จะสร้างไฟล์ config ใหม่ได้หากต้องการ ทำได้โดยการเพิ่มของคุณ(setq org-babel-async-init-file "~/.emacs.d/init")
init.el
แต่ฉันคิดว่าการสร้างไฟล์กำหนดค่าสำหรับงานนี้ตรงไปตรงมามากกว่า
3. นอกจากนี้ ...
เพิ่มในinit.el
;; This will stop the new process buffer from getting focus.
(setq display-buffer-alist (append display-buffer-alist '(("*org-babel-async*" display-buffer-no-window))))
;; This will automatically show the result section.
(global-auto-revert-mode 1)
เพิ่มในorg-babel-async-init.el
;; This will skip the "Save anyway?" confirmation of automatically saving the file when you also edited the buffer from Emacs while an asynchronous process is running.
(defun advice:verify-visited-file-modtime (orig-func &rest args) t)
(advice-add 'verify-visited-file-modtime :around 'advice:verify-visited-file-modtime)
;; This will skip the "Select coding system" prompt that appears when the result is inserted. This may vary among environments.
(setq coding-system-for-write 'utf-8)
;; This will skip the "changed on disk; really edit the buffer?" checking.
(defun ask-user-about-supersession-threat (fn) "blatantly ignore files that changed on disk")
เพิ่มในorg-babel-async-init.el (คุณอาจไม่ต้องการสิ่งเหล่านี้สำหรับ MATLAB)
;; This will set MATLAB cli path.
(setq-default matlab-shell-command "/Applications/MATLAB_R2016a.app/bin/matlab")
;; The MATLAB cli path can be obtained by running `fullfile(matlabroot, 'bin')` in your MATLAB.
;; This will stop MATLAB from showing the splash (the MATLAB logo) at the beginning.
(setq-default matlab-shell-command-switches '("-nodesktop" "-nosplash"))
เพิ่มในorg-babel-async-init.el (คุณอาจไม่ต้องการสิ่งเหล่านี้สำหรับ Julia, R และภาษาอื่น ๆ ที่ใช้ ESS)
;; This will enable :session header in Julia and other languages that use ESS (Emacs speaks statistics).
(load "/path/to/ess-site")
;; This will suppress ESS from prompting for session directory.
(setq ess-ask-for-ess-directory nil)
4. การใช้งาน
(หลังจากการตั้งค่าด้านบน)
- เลื่อนเคอร์เซอร์ไปที่ข้อมูลโค้ดที่คุณต้องการดำเนินการ
- เรียกใช้
M-x my/async-emacs-repl-org-babel-execute
(แทนที่จะทำC-c C-c
) สิ่งนี้จะเริ่มต้นกระบวนการ Emacs ภายนอกเป็นเซิร์ฟเวอร์ REPL หากจำเป็นจากนั้นเรียกใช้บล็อกต้นทางที่คุณอยู่
กิตติกรรมประกาศ
ฉันได้เรียนรู้แนวคิดของการเริ่มต้นกระบวนการ emacs สำหรับการประเมิน org-babel จากโพสต์นี้ ฉันอยากจะขอบคุณผู้เขียน
ความคิดเห็นสำหรับการปรับแต่ง
ความคิดที่นี่ง่าย เริ่ม emacs ใหม่ประมวลผลเป็น REPL สำหรับ Elisp ให้ทำfind-file
ไปยังแฟ้ม .org เดียวกันกับที่เราได้รับการแก้ไขgoto-line
ไปยังจุดเคอร์เซอร์เดียวกันทำงาน,org-babel-execute-src-block
save-buffer
หยุดออกจนกว่าผู้ใช้จะหยุดกระบวนการ (มิฉะนั้นกราฟจะหายไปทันทีหลังจากที่พวกเขาแสดง) หนึ่งสามารถคิดเกี่ยวกับการขยายโดย:
- การใช้โหมดองค์กร
C-c C-c
แทนการใช้ฟังก์ชั่นด้วยมือ / การตั้งค่าปุ่มลัดใหม่ (ซึ่งสามารถทำได้โดยคำแนะนำ)
- การสลับชื่อกระบวนการอย่างมีเงื่อนไขตาม: ตัวแปรเซสชันและภาษา
- การสลับไฟล์ init แบบมีเงื่อนไขขึ้นอยู่กับภาษา
ในความเป็นจริงความสำเร็จของวิธีการนี้ดูเหมือนว่าฉันจะแสดงวิธีทั่วไปในการพัฒนาคุณลักษณะ async ใน Emacs การสร้างเลเยอร์ "คำสั่ง" เพิ่มสคริปต์เพื่อทำงานและมีกรอบการทำงานสำหรับการเริ่มต้นและนำกระบวนการ emacs กลับมาใช้ใหม่ เช่นเดียวกับกรอบ Symfony ของ PHP (PHP ไม่มีเธรด) มีคุณลักษณะคำสั่ง
แก้ไขประวัติ
รหัส refactored (2016-04-02) โซลูชันนำกระบวนการ Emacs มาใช้ใหม่ (2016-04-02) โซลูชันตอนนี้ง่ายขึ้นและมีเพียงหนึ่งinteractive
คำสั่งให้เรียกใช้ (2016-04-02. เพิ่มการกำหนดค่า (2016-04-12)