지금까지 새로운 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 프로세스에서로드 할 구성 파일을 추가하십시오.
위의 기능은 --batch
모드 에서 emacs를 시작 합니다. 따라서 일반 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)))
여기 우리는 ...
- 패키지 경로를 추가하십시오.
- 코드 블록을 실행할지 묻지 않도록 org-mode에 지시하십시오.
- 어떤 언어가 필요한지 org-babel에게 알려주십시오.
각주 1 :이 설정이 없으면 평가가 실패합니다 "No org-babel-execute function for $lang!"
각주 2 : 물론 원하는 경우 새 구성 파일을 만드는 대신 일반 init.el을로드 할 수 있습니다. 에 추가하여이 작업 (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)
에 추가 조직 - 바벨 - 비동기 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
. 필요한 경우 REPL 서버로 외부 Emacs 프로세스를 시작한 다음 현재 소스 블록을 실행합니다.
감사의 말
이 게시물 에서 org-babel 평가를 위해 emacs 프로세스를 시작하는 아이디어를 배웠 습니다 . 저자에게 감사드립니다.
사용자 정의에 대한 주석
여기서 아이디어는 간단합니다. Elisp의 REPL로 새 emacs 프로세스를 시작하고 find-file
편집중인 동일한 .org 파일 goto-line
에서 동일한 커서 포인트로 run org-babel-execute-src-block
,을 수행하십시오 save-buffer
. 사용자가 프로세스를 중지 할 때까지 종료를 중지하십시오 (그렇지 않으면 그래프가 표시된 후 즉시 사라짐). 자연스럽게 이것을 확장하여 생각할 수 있습니다 :
C-c C-c
수동으로 기능을 실행하는 대신 org-mode를 사용 하거나 새로운 키 바인드를 설정합니다 (이는 조언으로 얻을 수 있음).
- : session 변수 및 언어에 따라 조건부로 프로세스 이름 전환
- 언어에 따라 init 파일을 조건부로 전환합니다.
사실,이 접근법의 성공은 Emacs에서 비동기 기능을 개발하는 일반적인 방법을 보여주고있는 것 같습니다. "명령"레이어를 생성하고, 작업을 수행 할 스크립트를 추가하고, emacs 프로세스를 시작하고 재사용하기위한 프레임 워크를 갖습니다. PHP의 Symfony 프레임 워크와 마찬가지로 (PHP에는 스레드가 없음) 명령 기능이 있습니다.
기록 편집
리팩토링 된 코드 (2016-04-02). 솔루션은 이제 Emacs 프로세스를 재사용합니다 (2016-04-02). 이제 솔루션이 단순화되었으며 interactive
실행할 명령 이 하나만 있습니다 (2016-04-02. 구성 추가 (2016-04-12).