lang/org: major refactor of +ipython feature

This commit is contained in:
Henrik Lissner 2018-05-30 18:13:22 +02:00
parent 98b439e3bb
commit ebfc5648ef
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
4 changed files with 112 additions and 158 deletions

View file

@ -50,3 +50,47 @@ string). Stops at the first function to return non-nil.")
for p in params for p in params
if (funcall fn (eq (car p) key)) if (funcall fn (eq (car p) key))
collect p))) collect p)))
;;
;; Plugins
;;
(def-package! ob-ipython
:when (featurep! +ipython)
:defer t
:init
(defvar +ob-ipython-local-runtime-dir nil
"TODO")
(setq ob-ipython-resources-dir ".ob-ipython-resrc")
(defun +org|babel-load-ipython (language)
(and (string-match-p "^jupyter-" language)
(require 'ob-ipython nil t)))
(add-hook '+org-babel-load-functions #'+org|babel-load-ipython)
:config
(set! :popups
'("^\\*Org Src"
((size . 100) (side . right) (slot . -1) (window-height . 0.6))
((quit) (select . t) (modeline)))
'("^\\*Python"
((slot . 0) (side . right) (size . 100))
((select) (quit) (transient)))
'("\\*ob-ipython.*"
((slot . 2) (side . right) (size . 100) (window-height . 0.2))
((select) (quit) (transient)))
'("\\*Python:.*"
((slot . 0) (side . right) (size . 100))
((select) (quit) (transient))))
;; TODO Add more popup styles
;; advices for remote kernel and org-src-edit
(advice-add 'org-babel-edit-prep:ipython :override #'+org*org-babel-edit-prep:ipython)
(advice-add 'org-babel-ipython-initiate-session :override #'+org*org-babel-ipython-initiate-session)
(advice-add 'ob-ipython--create-repl :override #'+org*ob-ipython--create-repl)
(advice-add 'org-babel-execute:ipython :override #'+org*org-babel-execute:ipython)
;; retina resolution image hack
(when (eq window-system 'ns)
(advice-add 'ob-ipython--write-base64-string :around #'+org*ob-ipython--write-base64-string)))

View file

@ -1,47 +0,0 @@
;;; lang/org/+ipython.el -*- lexical-binding: t; -*-
(defvar +org-ob-ipython-resources-dir ".ob-ipython-resrc")
(defvar +ob-ipython-local-runtime-dir
(substring (shell-command-to-string (concat "jupyter --runtime-dir")) 0 -1))
(def-package! ob-ipython
:when (featurep! +ipython)
:after (ob)
:config
(setq ob-ipython-resources-dir +org-ob-ipython-resources-dir)
;; popup
(when (featurep! +right-popup)
(set!
:popup "^\\*Org Src"
'((size . 100)
(side . right)
(slot . -1)
(window-height . 0.6))
'((quit)
(select . t)
(modeline)))
(set!
:popup "^\\*Python"
'((slot . 0)
(side . right)
(size . 100))
'((select) (quit) (transient)))
(set!
:popup "\\*ob-ipython.*"
'((slot . 2)
(side . right)
(size . 100)
(window-height . 0.2))
'((select) (quit) (transient)))
(set!
:popup "\\*Python:.*"
'((slot . 0)
(side . right)
(size . 100))
'((select) (quit) (transient))))
;; advices for remote kernel and org-src-edit
(advice-add 'org-babel-edit-prep:ipython :override #'+org*org-babel-edit-prep:ipython)
(advice-add 'org-babel-ipython-initiate-session :override #'+org*org-babel-ipython-initiate-session)
(advice-add 'ob-ipython--create-repl :override #'+org*ob-ipython--create-repl)
(advice-add 'org-babel-execute:ipython :override #'+org*org-babel-execute:ipython)
;; retina resolution image hack
(when (eq window-system 'ns)
(advice-add 'ob-ipython--write-base64-string :around #'+org*ob-ipython--write-base64-string)))

View file

@ -1,5 +1,6 @@
;;; lang/org/autoload/ipython.el -*- lexical-binding: t; -*- ;;; lang/org/autoload/ipython.el -*- lexical-binding: t; -*-
;; * remote ;;;###if (featurep! +ipython)
;;;###autoload ;;;###autoload
(defun +org*org-babel-ipython-initiate-session (&optional session params) (defun +org*org-babel-ipython-initiate-session (&optional session params)
"Create a session named SESSION according to PARAMS." "Create a session named SESSION according to PARAMS."
@ -7,7 +8,7 @@
(error (error
"ob-ipython currently only supports evaluation using a session. "ob-ipython currently only supports evaluation using a session.
Make sure your src block has a :session param.") Make sure your src block has a :session param.")
(when (not (s-ends-with-p ".json" session)) (when (not (string-suffix-p ".json" session t))
(ob-ipython--create-kernel (ob-ipython--create-kernel
(ob-ipython--normalize-session (ob-ipython--normalize-session
session) session)
@ -22,50 +23,34 @@ Make sure your src block has a :session param.")
"Create repl based on NAME and PARAMS. "Create repl based on NAME and PARAMS.
If PARAMS specifies remote kernel, copy the kernel config from remote server and If PARAMS specifies remote kernel, copy the kernel config from remote server and
create a repl connecting to remote session." create a repl connecting to remote session."
(let ((cmd (s-join (let ((cmd (string-join (ob-ipython--kernel-repl-cmd name) " ")))
" " (cond ((string= "default" name)
(ob-ipython--kernel-repl-cmd (run-python cmd nil nil)
name)))) (format "*%s*" python-shell-buffer-name))
(if (string= "default" name) ((string-match "^remote-.*ssh.json" name)
(progn (when (not (ignore-errors
(run-python cmd nil nil) (process-live-p
(format (get-process
"*%s*" (format
python-shell-buffer-name)) "Python:ob-ipython-%s"
(if (string-match name)))))
"^remote-.*ssh.json" (let* ((remote (s-split "-" name))
name) (remote-host (nth 1 remote))
(when (not (ignore-errors (remote-session (nth 3 remote)))
(process-live-p (+org/ob-ipython-generate-local-path-from-remote
(get-process remote-session
(format remote-host
"Python:ob-ipython-%s" params))))
name))))) ((let* ((process-name (format "Python:ob-ipython-%s" name))
(let* ((remote (s-split "-" name)) (python-shell-prompt-detect-enabled nil)
(remote-host (nth 1 remote)) (python-shell-completion-native-enable nil)
(remote-session (nth 3 remote))) (buf (python-shell-make-comint cmd process-name t))
(+org/ob-ipython-generate-local-path-from-remote (dir (cdr (assoc :pydir params))))
remote-session (if dir
remote-host (with-current-buffer buf
params))) (setq-local default-directory dir)))
(let* ((process-name (format (sleep-for 1)
"Python:ob-ipython-%s" (format "*%s*" process-name))))))
name))
(python-shell-prompt-detect-enabled nil)
(python-shell-completion-native-enable nil)
(buf (python-shell-make-comint
cmd
process-name
t))
(dir (cdr (assoc :pydir params))))
(if dir
(with-current-buffer
buf
(setq-local
default-directory
dir)))
(sleep-for 1)
(format "*%s*" process-name))))))
;;;###autoload ;;;###autoload
(defun +org*org-babel-execute:ipython (body params) (defun +org*org-babel-execute:ipython (body params)
@ -73,17 +58,11 @@ create a repl connecting to remote session."
This function is called by `org-babel-execute-src-block'." This function is called by `org-babel-execute-src-block'."
(message default-directory) (message default-directory)
(let ((session (cdr (assoc :session params)))) (let ((session (cdr (assoc :session params))))
(org-babel-ipython-initiate-session (org-babel-ipython-initiate-session session params))
session
params))
(ob-ipython--clear-output-buffer) (ob-ipython--clear-output-buffer)
(if (cdr (assoc :async params)) (if (cdr (assoc :async params))
(ob-ipython--execute-async (ob-ipython--execute-async body params)
body (ob-ipython--execute-sync body params)))
params)
(ob-ipython--execute-sync
body
params)))
;;;###autoload ;;;###autoload
(defun +org/ob-ipython-generate-local-path-from-remote (session host params) (defun +org/ob-ipython-generate-local-path-from-remote (session host params)
@ -92,7 +71,10 @@ This function is called by `org-babel-execute-src-block'."
(substring (shell-command-to-string (concat "ssh " host " jupyter --runtime-dir")) 0 -1)) (substring (shell-command-to-string (concat "ssh " host " jupyter --runtime-dir")) 0 -1))
(runtime-file (concat runtime-dir "/" "kernel-" session ".json")) (runtime-file (concat runtime-dir "/" "kernel-" session ".json"))
(tramp-path (concat "/ssh:" host ":" runtime-file)) (tramp-path (concat "/ssh:" host ":" runtime-file))
(tramp-copy (concat +ob-ipython-local-runtime-dir "/remote-" host "-kernel-" session ".json")) (tramp-copy (concat (or +ob-ipython-local-runtime-dir
(substring (shell-command-to-string "jupyter --runtime-dir")
0 -1))
"/remote-" host "-kernel-" session ".json"))
(local-path (local-path
(concat (concat
"Python:ob-ipython-" "Python:ob-ipython-"
@ -105,21 +87,17 @@ This function is called by `org-babel-execute-src-block'."
(python-shell-prompt-detect-enabled nil) (python-shell-prompt-detect-enabled nil)
(python-shell-completion-native-enable nil) (python-shell-completion-native-enable nil)
(buf (python-shell-make-comint (buf (python-shell-make-comint
(concat (concat ob-ipython-command
ob-ipython-command " console --simple-prompt --existing "
" console --simple-prompt --existing " tramp-copy " --ssh " host)
tramp-copy
" --ssh "
host)
(concat "" local-path) (concat "" local-path)
t)) t))
(proc (get-buffer-process buf)) (proc (get-buffer-process buf))
(dir (cdr (assoc :pydir params)))) (dir (cdr (assoc :pydir params))))
(sleep-for 3) (sleep-for 3)
(if dir (when dir
(with-current-buffer (with-current-buffer buf
buf (setq-local default-directory dir)))
(setq-local default-directory dir)))
(format "*%s*" proc)))) (format "*%s*" proc))))
;; * org-src-edit ;; * org-src-edit
@ -127,51 +105,31 @@ This function is called by `org-babel-execute-src-block'."
(defun +org*org-babel-edit-prep:ipython (info) (defun +org*org-babel-edit-prep:ipython (info)
(let* ((params (nth 2 info)) (let* ((params (nth 2 info))
(session (cdr (assoc :session params)))) (session (cdr (assoc :session params))))
(org-babel-ipython-initiate-session (org-babel-ipython-initiate-session session params))
session
params))
;; Support for python.el's "send-code" commands within edit buffers. ;; Support for python.el's "send-code" commands within edit buffers.
(setq-local (setq-local python-shell-buffer-name
python-shell-buffer-name (format "Python:ob-ipython-%s"
(format (->> info (nth 2) (assoc :session)
"Python:ob-ipython-%s" cdr ob-ipython--normalize-session)))
(->> (setq-local default-directory
info (format "%s"
(nth 2) (->> info (nth 2) (assoc :pydir)
(assoc :session) cdr ob-ipython--normalize-session)))
cdr ob-ipython--normalize-session)))
(setq-local
default-directory
(format
"%s"
(->>
info
(nth 2)
(assoc :pydir)
cdr ob-ipython--normalize-session)))
(ob-ipython-mode 1) (ob-ipython-mode 1)
;; hack on company mode to use company-capf rather than company-anaconda ;; hack on company mode to use company-capf rather than company-anaconda
(when (featurep! :completion company) (when (featurep! :completion company)
(setq-local (setq-local company-backends
company-backends '(company-capf
'(company-capf company-dabbrev
company-dabbrev company-files
company-files company-yasnippet))
company-yasnippet)) (setq-local company-idle-delay nil))
(setq-local
company-idle-delay
nil))
(when (featurep 'lpy) (when (featurep 'lpy)
(setq lispy-python-proc (setq lispy-python-proc
(format (format "Python:ob-ipython-%s"
"Python:ob-ipython-%s" (->> info (nth 2) (assoc :session)
(->> cdr ob-ipython--normalize-session))
info lispy--python-middleware-loaded-p nil)
(nth 2)
(assoc :session)
cdr ob-ipython--normalize-session)))
(setq lispy--python-middleware-loaded-p
nil)
(lispy--python-middleware-load))) (lispy--python-middleware-load)))
;; * retina ;; * retina
@ -180,11 +138,11 @@ This function is called by `org-babel-execute-src-block'."
"Return the name of high-resolution image file for FILENAME. "Return the name of high-resolution image file for FILENAME.
The optional arg SCALE is scale factor, and defaults to 2." The optional arg SCALE is scale factor, and defaults to 2."
(let ((pos (or (string-match "\\.[^./]*\\'" filename) (length filename)))) (let ((pos (or (string-match "\\.[^./]*\\'" filename) (length filename))))
(format (format "%s@%dx%s"
"%s@%dx%s" (substring filename 0 pos)
(substring filename 0 pos) (or scale 2)
(or scale 2) (substring filename pos))))
(substring filename pos))))
;;;###autoload ;;;###autoload
(defun +org*ob-ipython--write-base64-string (oldfunc &rest args) (defun +org*ob-ipython--write-base64-string (oldfunc &rest args)
(let ((file (car args)) (let ((file (car args))

View file

@ -8,7 +8,6 @@
(if (featurep! +babel) (load! "+babel")) (if (featurep! +babel) (load! "+babel"))
(if (featurep! +capture) (load! "+capture")) (if (featurep! +capture) (load! "+capture"))
(if (featurep! +export) (load! "+export")) (if (featurep! +export) (load! "+export"))
(if (featurep! +ipython) (load! "+ipython"))
(if (featurep! +present) (load! "+present")) (if (featurep! +present) (load! "+present"))
;; TODO (if (featurep! +publish) (load! "+publish")) ;; TODO (if (featurep! +publish) (load! "+publish"))