replace ein:aif with aif

This commit is contained in:
dickmao 2019-11-24 00:17:52 -05:00
parent ab87b7cb6c
commit e12a33588d
32 changed files with 298 additions and 288 deletions

1
Cask
View file

@ -5,6 +5,7 @@
(files "lisp/*.el" "lisp/*.py") (files "lisp/*.el" "lisp/*.py")
(development (development
(depends-on "anaphora")
(depends-on "websocket") (depends-on "websocket")
(depends-on "request") (depends-on "request")
(depends-on "dash") (depends-on "dash")

View file

@ -267,7 +267,6 @@ Note that the below work best with current (> v4.3.1) versions of jupyter.
.. el:variable:: ein:jupyter-server-use-subcommand .. el:variable:: ein:jupyter-server-use-subcommand
.. el:variable:: ein:jupyter-default-notebook-directory .. el:variable:: ein:jupyter-default-notebook-directory
.. el:variable:: ein:jupyter-server-args .. el:variable:: ein:jupyter-server-args
.. el:variable:: ein:jupyter-server-buffer-name
Notebook list Notebook list
^^^^^^^^^^^^^ ^^^^^^^^^^^^^

View file

@ -152,9 +152,9 @@
(multiple-value-bind (url-or-port token) (ein:jupyter-server-conn-info) (multiple-value-bind (url-or-port token) (ein:jupyter-server-conn-info)
(let (notebook) (let (notebook)
(with-current-buffer (ein:notebooklist-get-buffer url-or-port) (with-current-buffer (ein:notebooklist-get-buffer url-or-port)
(ein:and-let* ((kslist (mapcar #'car (ein:list-available-kernels url-or-port))) (-when-let* ((kslist (mapcar #'car (ein:list-available-kernels url-or-port)))
(found (seq-some (lambda (x) (and (search prefix x) x)) kslist)) (found (seq-some (lambda (x) (and (search prefix x) x)) kslist))
(ks (ein:get-kernelspec url-or-port found))) (ks (ein:get-kernelspec url-or-port found)))
(setq notebook (ein:testing-new-notebook url-or-port ks)))) (setq notebook (ein:testing-new-notebook url-or-port ks))))
(should notebook) (should notebook)
(let ((buf-name (format ein:notebook-buffer-name-template (let ((buf-name (format ein:notebook-buffer-name-template
@ -175,10 +175,10 @@
(cl-letf (((symbol-function 'y-or-n-p) #'ignore)) (cl-letf (((symbol-function 'y-or-n-p) #'ignore))
(ein:jupyter-server-stop t)) (ein:jupyter-server-stop t))
(loop repeat 10 (loop repeat 10
with buffer = (get-buffer ein:jupyter-server-buffer-name) with buffer = (get-buffer *ein:jupyter-server-buffer-name*)
until (null (get-buffer-process buffer)) until (null (get-buffer-process buffer))
do (sleep-for 0 1000) do (sleep-for 0 1000)
finally do (ein:aif (get-buffer-process buffer) (delete-process it))) finally do (aif (get-buffer-process buffer) (delete-process it)))
(condition-case err (condition-case err
(ein:testing-wait-until (lambda () (ein:testing-wait-until (lambda ()
(null (ein:notebooklist-keys))) (null (ein:notebooklist-keys)))
@ -187,7 +187,7 @@
(clrhash ein:notebooklist-map))) (clrhash ein:notebooklist-map)))
(unless final-p (unless final-p
(When "I clear log expr \"ein:log-all-buffer-name\"") (When "I clear log expr \"ein:log-all-buffer-name\"")
(When "I clear log expr \"ein:jupyter-server-buffer-name\"")))) (When "I clear log expr \"*ein:jupyter-server-buffer-name*\""))))
(When "^I start and login to jupyterhub configured \"\\(.*\\)\"$" (When "^I start and login to jupyterhub configured \"\\(.*\\)\"$"
(lambda (config) (lambda (config)
@ -349,8 +349,8 @@
(lambda (negate bogey) (lambda (negate bogey)
(ein:testing-wait-until (ein:testing-wait-until
(lambda () (lambda ()
(let* ((says (s-contains? (s-replace "\\n" "\n" bogey) (buffer-string)))) (let ((says (s-contains? (s-replace "\\n" "\n" bogey) (buffer-string))))
(ein:aif (if negate (not says) says) (aif (if negate (not says) says)
it it
(when (with-current-buffer ein:log-all-buffer-name (when (with-current-buffer ein:log-all-buffer-name
(search "WS closed unexpectedly" (buffer-string))) (search "WS closed unexpectedly" (buffer-string)))

View file

@ -62,7 +62,7 @@
do (sleep-for 0 1000) do (sleep-for 0 1000)
finally do (when extant finally do (when extant
(ein:display-warning (format "cannot del %s" path))))))) (ein:display-warning (format "cannot del %s" path)))))))
(ein:aif (ein:notebook-opened-notebooks) (aif (ein:notebook-opened-notebooks)
(loop for nb in it (loop for nb in it
for path = (ein:$notebook-notebook-path nb) for path = (ein:$notebook-notebook-path nb)
do (ein:log 'debug "Notebook %s still open" path) do (ein:log 'debug "Notebook %s still open" path)
@ -72,6 +72,7 @@
(ein:dev-start-debug) (ein:dev-start-debug)
(cl-assert (boundp 'company-frontends)) (cl-assert (boundp 'company-frontends))
(custom-set-variables '(company-frontends nil) (custom-set-variables '(company-frontends nil)
'(ein:jupyter-use-docker-stacks nil)
'(python-indent-guess-indent-offset-verbose nil)) '(python-indent-guess-indent-offset-verbose nil))
(setq ein:jupyter-default-kernel (setq ein:jupyter-default-kernel
(loop with cand = "" (loop with cand = ""

View file

@ -49,7 +49,7 @@
(traceback . ,(plist-get output :traceback)))) (traceback . ,(plist-get output :traceback))))
(defun ein:cell-execute-result-output-to-json (output) (defun ein:cell-execute-result-output-to-json (output)
(let ((data (ein:aif (plist-get output :text) (let ((data (aif (plist-get output :text)
`("text/plain" . ,it) `("text/plain" . ,it)
(plist-get output :data)))) (plist-get output :data))))
`((output_type . "execute_result") `((output_type . "execute_result")
@ -76,4 +76,3 @@
collect (list (cdr prop) (plist-get output-plist (cdr prop))))) collect (list (cdr prop) (plist-get output-plist (cdr prop)))))
(provide 'ein-cell-output) (provide 'ein-cell-output)

View file

@ -269,9 +269,9 @@ a number will limit the number of lines in a cell output."
(ein:oset-if-empty cell 'outputs (plist-get data :outputs)) (ein:oset-if-empty cell 'outputs (plist-get data :outputs))
(ein:oset-if-empty cell 'input (or (plist-get data :input) (ein:oset-if-empty cell 'input (or (plist-get data :input)
(plist-get data :source))) (plist-get data :source)))
(ein:aif (plist-get data :prompt_number) (aif (plist-get data :prompt_number)
(ein:oset-if-empty cell 'input-prompt-number it) (ein:oset-if-empty cell 'input-prompt-number it)
(ein:aif (plist-get data :execution_count) (aif (plist-get data :execution_count)
(ein:oset-if-empty cell 'input-prompt-number it))) (ein:oset-if-empty cell 'input-prompt-number it)))
(ein:oset-if-empty cell 'collapsed (ein:oset-if-empty cell 'collapsed
(let ((v (or (plist-get data :collapsed) (let ((v (or (plist-get data :collapsed)
@ -281,13 +281,13 @@ a number will limit the number of lines in a cell output."
cell) cell)
(cl-defmethod ein:cell-init ((cell ein:textcell) data) (cl-defmethod ein:cell-init ((cell ein:textcell) data)
(ein:aif (plist-get data :source) (aif (plist-get data :source)
(setf (slot-value cell 'input) it)) (setf (slot-value cell 'input) it))
cell) cell)
(cl-defmethod ein:cell-init ((cell ein:headingcell) data) ;; FIXME: Was :after method (cl-defmethod ein:cell-init ((cell ein:headingcell) data) ;; FIXME: Was :after method
(cl-call-next-method) (cl-call-next-method)
(ein:aif (plist-get data :level) (aif (plist-get data :level)
(setf (slot-value cell 'level) it)) (setf (slot-value cell 'level) it))
cell) cell)
@ -387,14 +387,14 @@ a number will limit the number of lines in a cell output."
(nth index (plist-get element prop))) (nth index (plist-get element prop)))
(case prop (case prop
(:after-input (:after-input
(ein:aif (nth 0 (plist-get element :output)) (aif (nth 0 (plist-get element :output))
it it
(plist-get element :footer))) (plist-get element :footer)))
(:after-output (plist-get element :footer)) (:after-output (plist-get element :footer))
(:before-input (plist-get element :prompt)) (:before-input (plist-get element :prompt))
(:before-output (plist-get element :input)) (:before-output (plist-get element :input))
(:last-output (:last-output
(ein:aif (plist-get element :output) (aif (plist-get element :output)
(car (last it)) (car (last it))
(plist-get element :input))) (plist-get element :input)))
(t (cl-call-next-method)))))) (t (cl-call-next-method))))))
@ -965,7 +965,7 @@ prettified text thus be used instead of HTML type."
ein:output-types-html-preferred)) ein:output-types-html-preferred))
(defun ein:fix-mime-type (type) (defun ein:fix-mime-type (type)
(ein:aif (assoc type ein:mime-type-map) (aif (assoc type ein:mime-type-map)
(cdr it) (cdr it)
type)) type))
@ -1021,7 +1021,7 @@ prettified text thus be used instead of HTML type."
"Return json-ready alist." "Return json-ready alist."
`((input . ,(ein:cell-get-text cell)) `((input . ,(ein:cell-get-text cell))
(cell_type . "code") (cell_type . "code")
,@(ein:aif (ein:oref-safe cell 'input-prompt-number) ,@(aif (ein:oref-safe cell 'input-prompt-number)
`((prompt_number . ,it))) `((prompt_number . ,it)))
(outputs . ,(if discard-output [] (apply #'vector (slot-value cell 'outputs)))) (outputs . ,(if discard-output [] (apply #'vector (slot-value cell 'outputs))))
(language . "python") (language . "python")
@ -1041,7 +1041,7 @@ prettified text thus be used instead of HTML type."
(outputs (if discard-output [] (outputs (if discard-output []
(slot-value cell 'outputs))) (slot-value cell 'outputs)))
(renamed-outputs '()) (renamed-outputs '())
(execute-count (ein:aif (ein:oref-safe cell 'input-prompt-number) (execute-count (aif (ein:oref-safe cell 'input-prompt-number)
(and (numberp it) it)))) (and (numberp it) it))))
(setq metadata (plist-put metadata :collapsed (if (slot-value cell 'collapsed) t json-false))) (setq metadata (plist-put metadata :collapsed (if (slot-value cell 'collapsed) t json-false)))
(setq metadata (plist-put metadata :autoscroll json-false)) (setq metadata (plist-put metadata :autoscroll json-false))
@ -1139,16 +1139,16 @@ prettified text thus be used instead of HTML type."
(cl-defmethod ein:cell-next ((cell ein:basecell)) (cl-defmethod ein:cell-next ((cell ein:basecell))
"Return next cell of the given CELL or nil if CELL is the last one." "Return next cell of the given CELL or nil if CELL is the last one."
(ein:aif (ewoc-next (slot-value cell 'ewoc) (aif (ewoc-next (slot-value cell 'ewoc)
(ein:cell-element-get cell :footer)) (ein:cell-element-get cell :footer))
(let ((cell (ein:$node-data (ewoc-data it)))) (let ((cell (ein:$node-data (ewoc-data it))))
(when (cl-typep cell 'ein:basecell) (when (cl-typep cell 'ein:basecell)
cell)))) cell))))
(cl-defmethod ein:cell-prev ((cell ein:basecell)) (cl-defmethod ein:cell-prev ((cell ein:basecell))
"Return previous cell of the given CELL or nil if CELL is the first one." "Return previous cell of the given CELL or nil if CELL is the first one."
(ein:aif (ewoc-prev (slot-value cell 'ewoc) (aif (ewoc-prev (slot-value cell 'ewoc)
(ein:cell-element-get cell :prompt)) (ein:cell-element-get cell :prompt))
(let ((cell (ein:$node-data (ewoc-data it)))) (let ((cell (ein:$node-data (ewoc-data it))))
(when (cl-typep cell 'ein:basecell) (when (cl-typep cell 'ein:basecell)
cell)))) cell))))

View file

@ -98,7 +98,7 @@
(destructuring-bind (msg-type content _) output (destructuring-bind (msg-type content _) output
(ein:case-equal msg-type (ein:case-equal msg-type
(("stream" "display_data" "pyout" "execute_result") (("stream" "display_data" "pyout" "execute_result")
(ein:aif (plist-get content :text) (aif (plist-get content :text)
(let ((oinfo (ein:json-read-from-string it))) (let ((oinfo (ein:json-read-from-string it)))
(unless (string= (plist-get oinfo :string_form) "None") (unless (string= (plist-get oinfo :string_form) "None")
(setf (gethash obj (ein:$kernel-oinfo-cache kernel)) (setf (gethash obj (ein:$kernel-oinfo-cache kernel))

View file

@ -183,7 +183,7 @@ notebooks."
"Connect any buffer to opened notebook and its kernel." "Connect any buffer to opened notebook and its kernel."
(interactive (list (ein:completing-read "Notebook buffer to connect: " (interactive (list (ein:completing-read "Notebook buffer to connect: "
(ein:notebook-opened-buffer-names)))) (ein:notebook-opened-buffer-names))))
(ein:aif (get-buffer buffer-or-name) (aif (get-buffer buffer-or-name)
(let ((notebook (buffer-local-value 'ein:%notebook% it))) (let ((notebook (buffer-local-value 'ein:%notebook% it)))
(ein:connect-buffer-to-notebook notebook)) (ein:connect-buffer-to-notebook notebook))
(error "No buffer %s" buffer-or-name))) (error "No buffer %s" buffer-or-name)))
@ -230,8 +230,8 @@ inside the ``if __name__ == \"__main__\":`` block."
"Run buffer using ``%run``. Ask for command if the prefix ``C-u`` is given. "Run buffer using ``%run``. Ask for command if the prefix ``C-u`` is given.
Variable `ein:connect-run-command' sets the default command." Variable `ein:connect-run-command' sets the default command."
(interactive "P") (interactive "P")
(ein:aif (ein:aand (ein:get-url-or-port) (aif (ein:aand (ein:get-url-or-port)
(ein:filename-to-python it (buffer-file-name))) (ein:filename-to-python it (buffer-file-name)))
(let* ((default-command (ein:connect-run-command-get)) (let* ((default-command (ein:connect-run-command-get))
(command (if ask-command (command (if ask-command
(read-from-minibuffer "Command: " default-command) (read-from-minibuffer "Command: " default-command)

View file

@ -131,7 +131,7 @@ global setting. For global setting and more information, see
(if (< (ein:notebook-version-numeric url-or-port) 3) (if (< (ein:notebook-version-numeric url-or-port) 3)
(setq content (ein:new-content-legacy url-or-port path data)) (setq content (ein:new-content-legacy url-or-port path data))
(setq content (ein:new-content url-or-port path data))) (setq content (ein:new-content url-or-port path data)))
(ein:aif response (aif response
(setf (ein:$content-url-or-port content) (ein:get-response-redirect it))) (setf (ein:$content-url-or-port content) (ein:get-response-redirect it)))
(when callback (when callback
(funcall callback content)))) (funcall callback content))))
@ -174,7 +174,7 @@ global setting. For global setting and more information, see
(defun ein:content-need-hierarchy (url-or-port) (defun ein:content-need-hierarchy (url-or-port)
"Callers assume ein:content-query-hierarchy succeeded. If not, nil." "Callers assume ein:content-query-hierarchy succeeded. If not, nil."
(ein:aif (gethash url-or-port *ein:content-hierarchy*) it (aif (gethash url-or-port *ein:content-hierarchy*) it
(ein:log 'warn "No recorded content hierarchy for %s" url-or-port) (ein:log 'warn "No recorded content hierarchy for %s" url-or-port)
nil)) nil))

View file

@ -34,6 +34,7 @@
(require 'ein) ; get autoloaded functions into namespace (require 'ein) ; get autoloaded functions into namespace
(require 'ein-utils) (require 'ein-utils)
(require 'anaphora)
(defgroup ein nil (defgroup ein nil
"IPython notebook client in Emacs" "IPython notebook client in Emacs"
@ -137,19 +138,23 @@ the source is in git repository) or elpa version."
(defvar *ein:kernelspecs* (make-hash-table :test #'equal) (defvar *ein:kernelspecs* (make-hash-table :test #'equal)
"url-or-port to kernelspecs") "url-or-port to kernelspecs")
(defun ein:get-kernelspec (url-or-port name) (defun ein:get-kernelspec (url-or-port name &optional lang)
(let* ((kernelspecs (ein:need-kernelspecs url-or-port)) (let* ((kernelspecs (ein:need-kernelspecs url-or-port))
(name (if (stringp name) (name (if (stringp name)
(intern (format ":%s" name)) (intern (format ":%s" name))
name)) name))
(ks (plist-get kernelspecs name))) (ks (or (plist-get kernelspecs name)
(if (stringp ks) (loop for (key spec) on (ein:plist-exclude kernelspecs '(:default)) by 'cddr
(ein:get-kernelspec url-or-port ks) if (string= (ein:$kernelspec-language spec) lang)
ks))) return spec
end))))
(cond ((stringp ks)
(ein:get-kernelspec url-or-port ks))
(t ks))))
(defun ein:need-kernelspecs (url-or-port) (defun ein:need-kernelspecs (url-or-port)
"Callers assume ein:query-kernelspecs succeeded. If not, nil." "Callers assume ein:query-kernelspecs succeeded. If not, nil."
(ein:aif (gethash url-or-port *ein:kernelspecs*) it (aif (gethash url-or-port *ein:kernelspecs*) it
(ein:log 'warn "No recorded kernelspecs for %s" url-or-port) (ein:log 'warn "No recorded kernelspecs for %s" url-or-port)
nil)) nil))
@ -215,7 +220,7 @@ the source is in git repository) or elpa version."
(defun ein:need-notebook-version (url-or-port) (defun ein:need-notebook-version (url-or-port)
"Callers assume ein:query-notebook-version succeeded. If not, we hardcode a guess." "Callers assume ein:query-notebook-version succeeded. If not, we hardcode a guess."
(ein:aif (gethash url-or-port *ein:notebook-version*) it (aif (gethash url-or-port *ein:notebook-version*) it
(ein:log 'warn "No recorded notebook version for %s" url-or-port) (ein:log 'warn "No recorded notebook version for %s" url-or-port)
"5.7.0")) "5.7.0"))
@ -233,7 +238,7 @@ the source is in git repository) or elpa version."
&allow-other-keys &allow-other-keys
&aux (resp-string (format "STATUS: %s DATA: %s" (request-response-status-code response) data))) &aux (resp-string (format "STATUS: %s DATA: %s" (request-response-status-code response) data)))
(ein:log 'debug "ein:query-notebook-version--complete %s" resp-string) (ein:log 'debug "ein:query-notebook-version--complete %s" resp-string)
(ein:aif (plist-get data :version) (aif (plist-get data :version)
(setf (gethash url-or-port *ein:notebook-version*) it) (setf (gethash url-or-port *ein:notebook-version*) it)
(case (request-response-status-code response) (case (request-response-status-code response)
(404 (ein:log 'warn "notebook version api not implemented") (404 (ein:log 'warn "notebook version api not implemented")
@ -251,12 +256,12 @@ the source is in git repository) or elpa version."
(ein:choose-setting 'ein:filename-translations url-or-port)) (ein:choose-setting 'ein:filename-translations url-or-port))
(defun ein:filename-to-python (url-or-port filename) (defun ein:filename-to-python (url-or-port filename)
(ein:aif (car (ein:filename-translations-get url-or-port)) (aif (car (ein:filename-translations-get url-or-port))
(funcall it filename) (funcall it filename)
filename)) filename))
(defun ein:filename-from-python (url-or-port filename) (defun ein:filename-from-python (url-or-port filename)
(ein:aif (cadr (ein:filename-translations-get url-or-port)) (aif (cadr (ein:filename-translations-get url-or-port))
(funcall it filename) (funcall it filename)
filename)) filename))
@ -375,7 +380,7 @@ but can operate in different contexts."
(let* ((files (directory-files ein:source-dir 'full "^ein-.*\\.el$")) (let* ((files (directory-files ein:source-dir 'full "^ein-.*\\.el$"))
(errors (cl-mapcan (lambda (f) (unless (byte-compile-file f) (list f))) (errors (cl-mapcan (lambda (f) (unless (byte-compile-file f) (list f)))
files))) files)))
(ein:aif errors (aif errors
(error "Got %s errors while compiling these files: %s" (error "Got %s errors while compiling these files: %s"
(length errors) (length errors)
(ein:join-str " " (mapcar #'file-name-nondirectory it)))) (ein:join-str " " (mapcar #'file-name-nondirectory it))))

View file

@ -38,7 +38,7 @@
(defun ein:events-trigger (events event-type &optional data) (defun ein:events-trigger (events event-type &optional data)
"Trigger EVENT-TYPE and let event handler EVENTS handle that event." "Trigger EVENT-TYPE and let event handler EVENTS handle that event."
(ein:log 'debug "Event: %S" event-type) (ein:log 'debug "Event: %S" event-type)
(ein:aif (gethash event-type (slot-value events 'callbacks)) (aif (gethash event-type (slot-value events 'callbacks))
(mapc (lambda (cb-arg) (ein:funcall-packed cb-arg data)) it) (mapc (lambda (cb-arg) (ein:funcall-packed cb-arg data)) it)
(ein:log 'info "Unknown event: %S" event-type))) (ein:log 'info "Unknown event: %S" event-type)))

View file

@ -49,8 +49,8 @@ If the previous execution timer is not fired yet, cancel the timer."
BEG and END." BEG and END."
(and (ein:codecell-p cell) (and (ein:codecell-p cell)
this-command this-command
(ein:aif (ein:cell-input-pos-min cell) (<= it beg)) (aif (ein:cell-input-pos-min cell) (<= it beg))
(ein:aif (ein:cell-input-pos-max cell) (>= it end)))) (aif (ein:cell-input-pos-max cell) (>= it end))))
(defun ein:iexec-after-change (beg end -ignore-len-) (defun ein:iexec-after-change (beg end -ignore-len-)
"Called via `after-change-functions' hook." "Called via `after-change-functions' hook."

View file

@ -37,7 +37,7 @@
current-payload) current-payload)
(defun ein:find-or-create-ipdb-session (kernel &optional buffer) (defun ein:find-or-create-ipdb-session (kernel &optional buffer)
(ein:aif (gethash (ein:$kernel-kernel-id kernel) *ein:ipdb-sessions*) (aif (gethash (ein:$kernel-kernel-id kernel) *ein:ipdb-sessions*)
it it
(let ((db-session (make-ein:$ipdb-session (let ((db-session (make-ein:$ipdb-session
:kernel kernel :kernel kernel
@ -120,7 +120,7 @@
(comint-output-filter proc ein:ipdb-buffer-prompt)) (comint-output-filter proc ein:ipdb-buffer-prompt))
(when ein:ipdb--received-quit-p (when ein:ipdb--received-quit-p
(kill-buffer) (kill-buffer)
(ein:aif (ein:$ipdb-session-notebook-buffer session) (aif (ein:$ipdb-session-notebook-buffer session)
(pop-to-buffer it))))))))) (pop-to-buffer it)))))))))

View file

@ -27,16 +27,51 @@
(require 'ein-notebooklist) (require 'ein-notebooklist)
(require 'ein-dev) (require 'ein-dev)
(defcustom ein:jupyter-server-buffer-name "*ein:jupyter-server*" (defcustom ein:jupyter-use-containers t
"The name of the buffer for the jupyter notebook server "Take EIN in a different direcsh."
session." :group 'ein
:type 'boolean)
(defcustom ein:jupyter-docker-image "jupyter/datascience-notebook"
"Docker pull whichever jupyter image you prefer. This defaults to
the 'jupyter docker stacks' on hub.docker.com.
Optionally append ':tag', e.g., ':latest' in the customary way."
:group 'ein :group 'ein
:type 'string) :type 'string)
(defcustom ein:jupyter-server-run-timeout 60000 (defcustom ein:jupyter-docker-home-directory "/home/jovyan/work"
"Time, in milliseconds, to wait for the jupyter server to start before declaring timeout and cancelling the operation." "Directory in docker image where to mount `ein:jupyter-default-notebook-directory'.
Defaults to home directory of 'jupyter docker stacks' on hub.docker.com."
:group 'ein :group 'ein
:type 'integer) :type 'string)
(defcustom ein:jupyter-docker-additional-switches "-e JUPYTER_ENABLE_LAB=no --rm"
"Additional options to the 'docker run' call.
Note some options like '-v' and '-network' are imposed by EIN."
:group 'ein
:type 'string)
(defcustom ein:jupyter-server-command "jupyter"
"The default command to start a jupyter notebook server.
Changing this to `jupyter-notebook' requires customizing `ein:jupyter-server-use-subcommand' to nil."
:group 'ein
:type 'string)
(defcustom ein:jupyter-default-server-command ein:jupyter-server-command
"Obsolete alias for `ein:jupyter-server-command'"
:group 'ein
:type 'string
:set (lambda (_symbol value)
(setq ein:jupyter-server-command value)))
(defcustom ein:jupyter-server-use-subcommand "notebook"
"Users of \"jupyter-notebook\" (as opposed to \"jupyter notebook\") need to Omit."
:group 'ein
:type '(choice (string :tag "Subcommand" "notebook")
(const :tag "Omit" nil)))
(defcustom ein:jupyter-server-args '("--no-browser") (defcustom ein:jupyter-server-args '("--no-browser")
"Add any additional command line options you wish to include "Add any additional command line options you wish to include
@ -45,34 +80,9 @@ with the call to the jupyter notebook."
:type '(repeat string)) :type '(repeat string))
(defcustom ein:jupyter-default-notebook-directory nil (defcustom ein:jupyter-default-notebook-directory nil
"If you are tired of always being queried for the location of "Default location of ipynb files."
the notebook directory, you can set it here for future calls to
`ein:jupyter-server-start'"
:group 'ein :group 'ein
:type '(directory)) :type 'directory)
(defvar *ein:jupyter-server-accept-timeout* 60)
(defvar *ein:jupyter-server-process-name* "EIN: Jupyter notebook server")
(defvar *ein:last-jupyter-command* nil)
(defvar *ein:last-jupyter-directory* nil)
(defcustom ein:jupyter-default-server-command "jupyter"
"The default command to start a jupyter notebook server.
Changing this to `jupyter-notebook' requires customizing `ein:jupyter-server-use-subcommand' to nil.
"
:group 'ein
:type '(file)
:set (lambda (symbol value)
(set-default symbol value)
(setq *ein:last-jupyter-command* nil)))
(defcustom ein:jupyter-server-use-subcommand "notebook"
"Users of \"jupyter-notebook\" (as opposed to \"jupyter notebook\") need to `Omit'."
:group 'ein
:type '(choice (string :tag "Subcommand" "notebook")
(const :tag "Omit" nil)))
(defcustom ein:jupyter-default-kernel 'first-alphabetically (defcustom ein:jupyter-default-kernel 'first-alphabetically
"With which of ${XDG_DATA_HOME}/jupyter/kernels to create new notebooks." "With which of ${XDG_DATA_HOME}/jupyter/kernels to create new notebooks."
@ -90,24 +100,37 @@ Changing this to `jupyter-notebook' requires customizing `ein:jupyter-server-use
(json-read-from-string (json-read-from-string
(shell-command-to-string (shell-command-to-string
(format "%s kernelspec list --json" (format "%s kernelspec list --json"
ein:jupyter-default-server-command))))) ein:jupyter-server-command)))))
collect `(,k . ,(alist-get 'display_name (alist-get 'spec spec))))) collect `(,k . ,(alist-get 'display_name (alist-get 'spec spec)))))
(error (ein:log 'warn "ein:jupyter-default-kernel: %s" err) (error (ein:log 'warn "ein:jupyter-default-kernel: %s" err)
'((string :tag "Ask")))))) '((string :tag "Ask"))))))
(defsubst ein:jupyter-server-process () (defvar *ein:jupyter-server-process-name* "ein server")
"Return the emacs process object of our session" (defvar *ein:jupyter-server-buffer-name*
(get-buffer-process (get-buffer ein:jupyter-server-buffer-name))) (format "*%s*" *ein:jupyter-server-process-name*))
(defun ein:jupyter-server--run (buf cmd dir &optional args) (defsubst ein:jupyter-server-process ()
(when ein:debug "Return the emacs process object of our session."
(add-to-list 'ein:jupyter-server-args "--debug")) (get-buffer-process (get-buffer *ein:jupyter-server-buffer-name*)))
(unless (stringp dir)
(error "ein:jupyter-server--run: notebook directory required")) (defun ein:jupyter-server--run (buf user-cmd dir &optional args)
(let* ((vargs (append (ein:aif ein:jupyter-server-use-subcommand (list it)) (let* ((cmd (if ein:jupyter-use-containers "docker" user-cmd))
(list (format "--notebook-dir=%s" (convert-standard-filename dir))) (vargs (cond (ein:jupyter-use-containers
args (split-string
ein:jupyter-server-args)) (format "run --network host -v %s:%s %s %s"
dir
ein:jupyter-docker-home-directory
ein:jupyter-docker-additional-switches
ein:jupyter-docker-image)))
(t
(append (aif ein:jupyter-server-use-subcommand (list it))
(list (format "--notebook-dir=%s"
(convert-standard-filename dir)))
args
(let ((copy ein:jupyter-server-args))
(when ein:debug
(add-to-list copy "--debug"))
copy)))))
(proc (apply #'start-process (proc (apply #'start-process
*ein:jupyter-server-process-name* buf cmd vargs))) *ein:jupyter-server-process-name* buf cmd vargs)))
(ein:log 'info "ein:jupyter-server--run: %s %s" cmd (ein:join-str " " vargs)) (ein:log 'info "ein:jupyter-server--run: %s %s" cmd (ein:join-str " " vargs))
@ -117,7 +140,7 @@ Changing this to `jupyter-notebook' requires customizing `ein:jupyter-server-use
(defun ein:jupyter-server-conn-info (&optional buffer-name) (defun ein:jupyter-server-conn-info (&optional buffer-name)
"Return the url-or-port and password for BUFFER or the global session." "Return the url-or-port and password for BUFFER or the global session."
(unless buffer-name (unless buffer-name
(setq buffer-name ein:jupyter-server-buffer-name)) (setq buffer-name *ein:jupyter-server-buffer-name*))
(let ((buffer (get-buffer buffer-name)) (let ((buffer (get-buffer buffer-name))
(result '(nil nil))) (result '(nil nil)))
(if buffer (if buffer
@ -157,67 +180,73 @@ our singleton jupyter server process here."
(set-process-sentinel (set-process-sentinel
proc proc
(apply-partially (lambda (url-or-port* sentinel proc* event) (apply-partially (lambda (url-or-port* sentinel proc* event)
(ein:aif sentinel (funcall it proc* event)) (aif sentinel (funcall it proc* event))
(funcall #'ein:notebooklist-sentinel url-or-port* proc* event)) (funcall #'ein:notebooklist-sentinel url-or-port* proc* event))
url-or-port (process-sentinel proc)))) url-or-port (process-sentinel proc))))
;;;###autoload ;;;###autoload
(defun ein:jupyter-server-start (server-cmd-path notebook-directory (defun ein:jupyter-server-start (server-command
&optional no-login-p login-callback port) notebook-directory
"Start SERVER-CMD_PATH with `--notebook-dir' NOTEBOOK-DIRECTORY. Login after connection established unless NO-LOGIN-P is set. LOGIN-CALLBACK takes two arguments, the buffer created by ein:notebooklist-open--finish, and the url-or-port argument of ein:notebooklist-open*. &optional no-login-p login-callback port)
"Start SERVER-COMMAND with `--notebook-dir' NOTEBOOK-DIRECTORY.
This command opens an asynchronous process running the jupyter Login after connection established unless NO-LOGIN-P is set.
notebook server and then tries to detect the url and password to LOGIN-CALLBACK takes two arguments, the buffer created by
generate automatic calls to `ein:notebooklist-login' and `ein:notebooklist-open--finish', and the url-or-port argument
`ein:notebooklist-open'. of `ein:notebooklist-open*'.
With \\[universal-argument] prefix arg, it will prompt the user for the path to With \\[universal-argument] prefix arg, prompt the user for the
the jupyter executable first. Else, it will try to use the server command."
value of `*ein:last-jupyter-command*' or the value of the
customizable variable `ein:jupyter-default-server-command'.
Then it prompts the user for the path of the root directory
containing the notebooks the user wants to access.
The buffer named by `ein:jupyter-server-buffer-name' will contain
the log of the running jupyter server."
(interactive (interactive
(let* ((default-command (or *ein:last-jupyter-command* (list (let ((default-command (executable-find ein:jupyter-server-command)))
ein:jupyter-default-server-command)) (if (and (not ein:jupyter-use-containers)
(server-cmd-path (or current-prefix-arg (not default-command)))
(executable-find (if current-prefix-arg (let (command result)
(read-file-name "Server command: " default-directory nil nil (while (not (setq
default-command) result
default-command))) (executable-find
(notebook-directory (setq
(read-directory-name "Notebook directory: " command
(or *ein:last-jupyter-directory* (read-string
ein:jupyter-default-notebook-directory)))) (format
(list server-cmd-path notebook-directory nil (lambda (buffer url-or-port) "%sServer command: "
(pop-to-buffer buffer))))) (if command
(unless (and (stringp server-cmd-path) (format "[%s not executable] " command)
(file-exists-p server-cmd-path) ""))
(file-executable-p server-cmd-path)) nil nil ein:jupyter-server-command))))))
(error "Command %s not found or not executable" result)
(or *ein:last-jupyter-command* default-command))
ein:jupyter-default-server-command))) (let (result
(setf *ein:last-jupyter-command* server-cmd-path (default-dir ein:jupyter-default-notebook-directory))
*ein:last-jupyter-directory* notebook-directory) (while (or (not result) (not (file-directory-p result)))
(setq result (read-directory-name
(format "%sNotebook directory: "
(if result
(format "[%s not a directory]" result)
""))
nil
ein:jupyter-default-notebook-directory
t)))
result)
nil
(lambda (buffer url-or-port)
(pop-to-buffer buffer))
nil))
(if (ein:jupyter-server-process) (if (ein:jupyter-server-process)
(error "Please first M-x ein:stop")) (error "ein:jupyter-server-start: please first M-x ein:stop"))
(add-hook 'kill-emacs-hook #'(lambda () (add-hook 'kill-emacs-hook #'(lambda ()
(ignore-errors (ein:jupyter-server-stop t)))) (ignore-errors (ein:jupyter-server-stop t))))
(let ((proc (ein:jupyter-server--run ein:jupyter-server-buffer-name (let ((proc (ein:jupyter-server--run *ein:jupyter-server-buffer-name*
*ein:last-jupyter-command* server-command
*ein:last-jupyter-directory* notebook-directory
(if (numberp port) (if (numberp port)
`("--port" ,(format "%s" port) `("--port" ,(format "%s" port)
"--port-retries" "0"))))) "--port-retries" "0")))))
(loop repeat 30 (loop repeat 30
until (car (ein:jupyter-server-conn-info ein:jupyter-server-buffer-name)) until (car (ein:jupyter-server-conn-info *ein:jupyter-server-buffer-name*))
do (sleep-for 0 500) do (sleep-for 0 500)
finally do finally do
(unless (car (ein:jupyter-server-conn-info ein:jupyter-server-buffer-name)) (unless (car (ein:jupyter-server-conn-info *ein:jupyter-server-buffer-name*))
(ein:log 'warn "Jupyter server failed to start, cancelling operation") (ein:log 'warn "Jupyter server failed to start, cancelling operation")
(ein:jupyter-server-stop t))) (ein:jupyter-server-stop t)))
(when (and (not no-login-p) (ein:jupyter-server-process)) (when (and (not no-login-p) (ein:jupyter-server-process))
@ -266,7 +295,7 @@ the log of the running jupyter server."
(ein:notebooklist-list-remove url-or-port) (ein:notebooklist-list-remove url-or-port)
(kill-buffer (ein:notebooklist-get-buffer url-or-port)) (kill-buffer (ein:notebooklist-get-buffer url-or-port))
(when log (when log
(with-current-buffer ein:jupyter-server-buffer-name (with-current-buffer *ein:jupyter-server-buffer-name*
(write-region (point-min) (point-max) log))))) (write-region (point-min) (point-max) log)))))
(provide 'ein-jupyter) (provide 'ein-jupyter)

View file

@ -33,6 +33,7 @@
(require 'ein-query) (require 'ein-query)
(require 'ein-websocket) (require 'ein-websocket)
(require 'ein-notebooklist) (require 'ein-notebooklist)
(require 'anaphora)
(defvar *ein:jupyterhub-connections* (make-hash-table :test #'equal)) (defvar *ein:jupyterhub-connections* (make-hash-table :test #'equal))
@ -54,7 +55,7 @@
(defsubst ein:jupyterhub-user-path (url-or-port &rest paths) (defsubst ein:jupyterhub-user-path (url-or-port &rest paths)
"Goes from URL-OR-PORT/PATHS to URL-OR-PORT/user/someone/PATHS" "Goes from URL-OR-PORT/PATHS to URL-OR-PORT/user/someone/PATHS"
(let ((user-base (ein:aif (gethash url-or-port *ein:jupyterhub-connections*) (let ((user-base (aif (gethash url-or-port *ein:jupyterhub-connections*)
(ein:$jh-user-server (ein:$jh-conn-user it))))) (ein:$jh-user-server (ein:$jh-conn-user it)))))
(apply #'ein:url url-or-port user-base paths))) (apply #'ein:url url-or-port user-base paths)))
@ -90,7 +91,7 @@
(ein:and-let* ((conn (gethash ,conn-key *ein:jupyterhub-connections*))) (ein:and-let* ((conn (gethash ,conn-key *ein:jupyterhub-connections*)))
(ein:jupyterhub--add-header (ein:jupyterhub--add-header
(cons "Referer" (ein:url (ein:$jh-conn-url-or-port conn) "hub/login"))) (cons "Referer" (ein:url (ein:$jh-conn-url-or-port conn) "hub/login")))
(ein:aif (ein:$jh-conn-token conn) (aif (ein:$jh-conn-token conn)
(ein:jupyterhub--add-header (ein:jupyterhub--add-header
(cons "Authorization" (format "token %s" it))))) (cons "Authorization" (format "token %s" it)))))
(apply #'ein:query-singleton-ajax (apply #'ein:query-singleton-ajax

View file

@ -318,7 +318,7 @@ See https://github.com/ipython/ipython/pull/3307"
"Close websocket connection to running kernel, but do not "Close websocket connection to running kernel, but do not
delete the kernel on the server side" delete the kernel on the server side"
(ein:events-trigger (ein:$kernel-events kernel) 'status_disconnected.Kernel) (ein:events-trigger (ein:$kernel-events kernel) 'status_disconnected.Kernel)
(ein:aif (ein:$kernel-websocket kernel) (aif (ein:$kernel-websocket kernel)
(progn (ein:websocket-close it) (progn (ein:websocket-close it)
(setf (ein:$kernel-websocket kernel) nil)))) (setf (ein:$kernel-websocket kernel) nil))))
@ -715,13 +715,13 @@ We need this to have proper behavior for the 'Stop' command in the ein:notebookl
(ein:log 'debug "KERNEL--HANDLE-SHELL-REPLY: msg_type=%s msg_id=%s" (ein:log 'debug "KERNEL--HANDLE-SHELL-REPLY: msg_type=%s msg_id=%s"
msg-type msg-id) msg-type msg-id)
(run-hook-with-args 'ein:on-shell-reply-functions msg-type header content metadata) (run-hook-with-args 'ein:on-shell-reply-functions msg-type header content metadata)
(ein:aif cb (ein:funcall-packed it content metadata)) (aif cb (ein:funcall-packed it content metadata))
(ein:aif (plist-get content :payload) (aif (plist-get content :payload)
(ein:kernel--handle-payload kernel callbacks it)) (ein:kernel--handle-payload kernel callbacks it))
(let ((events (ein:$kernel-events kernel))) (let ((events (ein:$kernel-events kernel)))
(ein:case-equal msg-type (ein:case-equal msg-type
(("execute_reply") (("execute_reply")
(ein:aif (plist-get content :execution_count) (aif (plist-get content :execution_count)
;; It can be `nil' for silent execution ;; It can be `nil' for silent execution
(ein:events-trigger events 'execution_count.Kernel it)))))))) (ein:events-trigger events 'execution_count.Kernel it))))))))
@ -763,7 +763,7 @@ We need this to have proper behavior for the 'Stop' command in the ein:notebookl
(ein:log 'verbose "Not processing msg_type=%s msg_id=%s" msg-type msg-id) (ein:log 'verbose "Not processing msg_type=%s msg_id=%s" msg-type msg-id)
(ein:case-equal msg-type (ein:case-equal msg-type
(("stream" "display_data" "pyout" "pyerr" "error" "execute_result") (("stream" "display_data" "pyout" "pyerr" "error" "execute_result")
(ein:aif (plist-get callbacks :output) (aif (plist-get callbacks :output)
(ein:funcall-packed it msg-type content metadata))) (ein:funcall-packed it msg-type content metadata)))
(("status") (("status")
(ein:case-equal (plist-get content :execution_state) (ein:case-equal (plist-get content :execution_state)
@ -776,7 +776,7 @@ We need this to have proper behavior for the 'Stop' command in the ein:notebookl
(("data_pub") (("data_pub")
(ein:log 'verbose (format "Received data_pub message w/content %s" packet))) (ein:log 'verbose (format "Received data_pub message w/content %s" packet)))
(("clear_output") (("clear_output")
(ein:aif (plist-get callbacks :clear_output) (aif (plist-get callbacks :clear_output)
(ein:funcall-packed it content metadata))))))))) (ein:funcall-packed it content metadata)))))))))
;;; Utility functions ;;; Utility functions
@ -829,7 +829,7 @@ as a string and the rest of the argument is the optional ARGS."
(let ((func (car packed)) (let ((func (car packed))
(args (cdr packed))) (args (cdr packed)))
(when (equal msg-type "stream") (when (equal msg-type "stream")
(ein:aif (plist-get content :text) (aif (plist-get content :text)
(apply func it args))))) (apply func it args)))))
(cons func args))))) (cons func args)))))

View file

@ -106,7 +106,7 @@ Otherwise, return result of last form in BODY."
(defun ein:log-pop-to-request-buffer () (defun ein:log-pop-to-request-buffer ()
(interactive) (interactive)
(ein:aif (get-buffer request-log-buffer-name) (aif (get-buffer request-log-buffer-name)
(pop-to-buffer it) (pop-to-buffer it)
(message "No buffer named \"%s\"" request-log-buffer-name))) (message "No buffer named \"%s\"" request-log-buffer-name)))

View file

@ -293,7 +293,7 @@ will be updated with kernel's cwd."
(pop-to-buffer (ein:notebook-buffer notebook*))))) (pop-to-buffer (ein:notebook-buffer notebook*)))))
(when (and (not noninteractive) (when (and (not noninteractive)
(null (plist-member (ein:$notebook-metadata notebook*) :kernelspec))) (null (plist-member (ein:$notebook-metadata notebook*) :kernelspec)))
(ein:aif (ein:$notebook-kernelspec notebook*) (aif (ein:$notebook-kernelspec notebook*)
(progn (progn
(setf (ein:$notebook-metadata notebook*) (setf (ein:$notebook-metadata notebook*)
(plist-put (ein:$notebook-metadata notebook*) (plist-put (ein:$notebook-metadata notebook*)
@ -343,7 +343,7 @@ where `created' indicates a new notebook or an existing one."
*ein:notebook--pending-query*)) *ein:notebook--pending-query*))
pending-key)) pending-key))
(existing (ein:notebook-get-opened-notebook url-or-port path)) (existing (ein:notebook-get-opened-notebook url-or-port path))
(notebook (ein:aif existing it (notebook (aif existing it
(ein:notebook-new url-or-port path kernelspec))) (ein:notebook-new url-or-port path kernelspec)))
(callback0 (ein:notebook-open--decorate-callback notebook existing pending-clear (callback0 (ein:notebook-open--decorate-callback notebook existing pending-clear
callback no-pop))) callback no-pop)))
@ -371,7 +371,7 @@ where `created' indicates a new notebook or an existing one."
(setf (ein:$notebook-api-version notebook) (ein:$content-notebook-version content) (setf (ein:$notebook-api-version notebook) (ein:$content-notebook-version content)
(ein:$notebook-notebook-name notebook) (ein:$content-name content)) (ein:$notebook-notebook-name notebook) (ein:$content-name content))
(ein:notebook-bind-events notebook (ein:events-new)) (ein:notebook-bind-events notebook (ein:events-new))
(ein:notebook-maybe-set-kernelspec notebook (plist-get (ein:$content-raw-content content) :metadata)) (ein:notebook-set-kernelspec notebook (plist-get (ein:$content-raw-content content) :metadata))
(ein:notebook-install-kernel notebook) (ein:notebook-install-kernel notebook)
(ein:notebook-from-json notebook (ein:$content-raw-content content)) (ein:notebook-from-json notebook (ein:$content-raw-content content))
(if (not (with-current-buffer (ein:notebook-buffer notebook) (if (not (with-current-buffer (ein:notebook-buffer notebook)
@ -393,11 +393,12 @@ where `created' indicates a new notebook or an existing one."
(ein:notebook--check-nbformat (ein:$content-raw-content content)) (ein:notebook--check-nbformat (ein:$content-raw-content content))
(ein:gc-complete-operation)))) (ein:gc-complete-operation))))
(defun ein:notebook-maybe-set-kernelspec (notebook content-metadata) (defun ein:notebook-set-kernelspec (notebook content-metadata)
(ein:aif (plist-get content-metadata :kernelspec) (-when-let* ((ks-plist (plist-get content-metadata :kernelspec))
(let ((kernelspec (ein:get-kernelspec (ein:$notebook-url-or-port notebook) (kernelspec (ein:get-kernelspec (ein:$notebook-url-or-port notebook)
(plist-get it :name)))) (plist-get ks-plist :name)
(setf (ein:$notebook-kernelspec notebook) kernelspec)))) (plist-get ks-plist :language))))
(setf (ein:$notebook-kernelspec notebook) kernelspec)))
(defun ein:notebook--different-number (n1 n2) (defun ein:notebook--different-number (n1 n2)
@ -451,12 +452,11 @@ of minor mode."
;;; Kernel related things ;;; Kernel related things
(defun ein:list-available-kernels (url-or-port) (defun ein:list-available-kernels (url-or-port)
(let ((kernelspecs (ein:need-kernelspecs url-or-port))) (when-let ((kernelspecs (ein:need-kernelspecs url-or-port)))
(if kernelspecs (sort (loop for (key spec) on (ein:plist-exclude kernelspecs '(:default)) by 'cddr
(sort (loop for (key spec) on (ein:plist-exclude kernelspecs '(:default)) by 'cddr collecting (cons (ein:$kernelspec-name spec)
collecting (cons (ein:$kernelspec-name spec) (ein:$kernelspec-display-name spec)))
(ein:$kernelspec-display-name spec))) (lambda (c1 c2) (string< (cdr c1) (cdr c2))))))
(lambda (c1 c2) (string< (cdr c1) (cdr c2)))))))
(defun ein:notebook-switch-kernel (notebook kernel-name) (defun ein:notebook-switch-kernel (notebook kernel-name)
"Change the kernel for a running notebook. If not called from a "Change the kernel for a running notebook. If not called from a
@ -468,7 +468,9 @@ notebook buffer then the user will be prompted to select an opened notebook."
(ein:notebook-opened-buffer-names)))) (ein:notebook-opened-buffer-names))))
(kernel-name (ein:completing-read (kernel-name (ein:completing-read
"Select kernel: " "Select kernel: "
(ein:list-available-kernels (ein:$notebook-url-or-port notebook))))) (cl-mapcar
#'car
(ein:list-available-kernels (ein:$notebook-url-or-port notebook))))))
(list notebook kernel-name))) (list notebook kernel-name)))
(let* ((kernelspec (ein:get-kernelspec (let* ((kernelspec (ein:get-kernelspec
(ein:$notebook-url-or-port notebook) kernel-name))) (ein:$notebook-url-or-port notebook) kernel-name)))
@ -504,9 +506,9 @@ notebook buffer then the user will be prompted to select an opened notebook."
(defun ein:notebook-restart-session-command () (defun ein:notebook-restart-session-command ()
"Delete session on server side. Start new session." "Delete session on server side. Start new session."
(interactive) (interactive)
(ein:aif ein:%notebook% (aif ein:%notebook%
(if (y-or-n-p "Are you sure? ") (if (y-or-n-p "Are you sure? ")
(ein:kernel-restart-session (ein:$notebook-kernel it))) (ein:kernel-restart-session (ein:$notebook-kernel it)))
(message "Not in notebook buffer!"))) (message "Not in notebook buffer!")))
(define-obsolete-function-alias (define-obsolete-function-alias
@ -571,7 +573,7 @@ This is equivalent to do ``C-c`` in the console program."
(funcall (ein:notebook-choose-mode)) (funcall (ein:notebook-choose-mode))
(ein:worksheet-reinstall-undo-hooks ws) (ein:worksheet-reinstall-undo-hooks ws)
(condition-case err (condition-case err
(ein:aif (ein:$notebook-kernelspec notebook) (aif (ein:$notebook-kernelspec notebook)
(ein:ml-lang-setup it)) (ein:ml-lang-setup it))
(error (ein:log 'error (error-message-string err)) (error (ein:log 'error (error-message-string err))
(setq multilang-failed t)))) (setq multilang-failed t))))
@ -685,7 +687,7 @@ This is equivalent to do ``C-c`` in the console program."
(setf (gethash 'name metadata) (ein:$notebook-notebook-name notebook)) (setf (gethash 'name metadata) (ein:$notebook-notebook-name notebook))
(plist-put metadata (plist-put metadata
:name (ein:$notebook-notebook-name notebook))) :name (ein:$notebook-notebook-name notebook)))
(ein:aif (ein:$notebook-nbformat-minor notebook) (aif (ein:$notebook-nbformat-minor notebook)
;; Do not set nbformat when it is not given from server. ;; Do not set nbformat when it is not given from server.
(push `(nbformat_minor . ,it) data)) (push `(nbformat_minor . ,it) data))
(push `(nbformat . ,(ein:$notebook-nbformat notebook)) data) (push `(nbformat . ,(ein:$notebook-nbformat notebook)) data)
@ -710,12 +712,12 @@ This is equivalent to do ``C-c`` in the console program."
for i from 0 for i from 0
append (ein:worksheet-to-nb4-json ws i)))) append (ein:worksheet-to-nb4-json ws i))))
;; should be in notebook constructor, not here ;; should be in notebook constructor, not here
(ein:aif (ein:$notebook-kernelspec notebook) (aif (ein:$notebook-kernelspec notebook)
(setf (ein:$notebook-metadata notebook) (setf (ein:$notebook-metadata notebook)
(plist-put (ein:$notebook-metadata notebook) (plist-put (ein:$notebook-metadata notebook)
:kernelspec (ein:notebook--spec-insert-name :kernelspec (ein:notebook--spec-insert-name
(ein:$kernelspec-name it) (ein:$kernelspec-spec it))))) (ein:$kernelspec-name it) (ein:$kernelspec-spec it)))))
`((metadata . ,(ein:aif (ein:$notebook-metadata notebook) `((metadata . ,(aif (ein:$notebook-metadata notebook)
it it
(make-hash-table))) (make-hash-table)))
(cells . ,(apply #'vector all-cells))))) (cells . ,(apply #'vector all-cells)))))
@ -849,7 +851,7 @@ NAME is any non-empty string that does not contain '/' or '\\'.
(ein:notebook-tidy-opened-notebooks notebook))))) (ein:notebook-tidy-opened-notebooks notebook)))))
(defsubst ein:notebook-kill-buffer-query () (defsubst ein:notebook-kill-buffer-query ()
(ein:aif (ein:get-notebook--notebook) (aif (ein:get-notebook--notebook)
(let ((buf (or (buffer-base-buffer (current-buffer)) (let ((buf (or (buffer-base-buffer (current-buffer))
(current-buffer)))) (current-buffer))))
(ein:notebook-ask-save it (apply-partially (ein:notebook-ask-save it (apply-partially
@ -1487,9 +1489,9 @@ watch the fireworks!"
;; It is executed after toggling the mode, and before running MODE-hook. ;; It is executed after toggling the mode, and before running MODE-hook.
(when ein:notebook-mode (when ein:notebook-mode
(ein:aif ein:helm-kernel-history-search-key (aif ein:helm-kernel-history-search-key
(ein:notebook--define-key ein:notebook-mode-map it helm-ein-kernel-history)) (ein:notebook--define-key ein:notebook-mode-map it helm-ein-kernel-history))
(ein:aif ein:anything-kernel-history-search-key (aif ein:anything-kernel-history-search-key
(ein:notebook--define-key ein:notebook-mode-map it anything-ein-kernel-history)) (ein:notebook--define-key ein:notebook-mode-map it anything-ein-kernel-history))
(setq indent-tabs-mode nil) ;; Being T causes problems with Python code. (setq indent-tabs-mode nil) ;; Being T causes problems with Python code.
(ein:worksheet-imenu-setup))) (ein:worksheet-imenu-setup)))
@ -1552,7 +1554,7 @@ the first argument and CBARGS as the rest of arguments."
(defun ein:notebook-close-notebooks (&optional blithely) (defun ein:notebook-close-notebooks (&optional blithely)
"Used in `ein:jupyter-server-stop' and `kill-emacs-query-functions' hook." "Used in `ein:jupyter-server-stop' and `kill-emacs-query-functions' hook."
(ein:aif (ein:notebook-opened-notebooks) (aif (ein:notebook-opened-notebooks)
(if (and (cl-notevery #'identity (mapcar #'ein:notebook-close it)) (if (and (cl-notevery #'identity (mapcar #'ein:notebook-close it))
(not blithely)) (not blithely))
(y-or-n-p "Some notebooks could not be saved. Exit anyway?") (y-or-n-p "Some notebooks could not be saved. Exit anyway?")

View file

@ -172,27 +172,33 @@ This function adds NBLIST to `ein:notebooklist-map'."
(defun ein:crib-token (url-or-port) (defun ein:crib-token (url-or-port)
"Shell out to jupyter for its credentials knowledge. Return list of (PASSWORD TOKEN)." "Shell out to jupyter for its credentials knowledge. Return list of (PASSWORD TOKEN)."
(ein:aif (loop for line in (condition-case err (aif (loop for line in (condition-case err
(process-lines ein:jupyter-default-server-command (apply #'process-lines
"notebook" "list" "--json") ein:jupyter-server-command
;; often there is no local jupyter installation (append (aif ein:jupyter-server-use-subcommand
(error (ein:log 'info "ein:crib-token: %s" err) nil)) (list it))
with token0 '("list" "--json")))
with password0 ;; often there is no local jupyter installation
when (destructuring-bind (error (ein:log 'info "ein:crib-token: %s" err) nil))
(&key password url token &allow-other-keys) with token0
(ein:json-read-from-string line) with password0
(prog1 (equal (ein:url url) url-or-port) when (destructuring-bind
(setq password0 password) ;; t or :json-false (&key password url token &allow-other-keys)
(setq token0 token))) (ein:json-read-from-string line)
return (list password0 token0)) (prog1 (equal (ein:url url) url-or-port)
(setq password0 password) ;; t or :json-false
(setq token0 token)))
return (list password0 token0))
it (list nil nil))) it (list nil nil)))
(defun ein:crib-running-servers () (defun ein:crib-running-servers ()
"Shell out to jupyter for running servers." "Shell out to jupyter for running servers."
(loop for line in (condition-case err (loop for line in (condition-case err
(process-lines ein:jupyter-default-server-command (apply #'process-lines
"notebook" "list" "--json") ein:jupyter-server-command
(append (aif ein:jupyter-server-use-subcommand
(list it))
'("list" "--json")))
(error (ein:log 'info "ein:crib-running-servers: %s" err) (error (ein:log 'info "ein:crib-running-servers: %s" err)
nil)) nil))
collecting (destructuring-bind collecting (destructuring-bind
@ -210,9 +216,9 @@ This function adds NBLIST to `ein:notebooklist-map'."
(t nil))))) (t nil)))))
(defun ein:notebooklist-ask-url-or-port () (defun ein:notebooklist-ask-url-or-port ()
(let* ((default (ein:url (ein:aif (ein:get-notebook) (let* ((default (ein:url (aif (ein:get-notebook)
(ein:$notebook-url-or-port it) (ein:$notebook-url-or-port it)
(ein:aif ein:%notebooklist% (aif ein:%notebooklist%
(ein:$notebooklist-url-or-port it) (ein:$notebooklist-url-or-port it)
(ein:default-url-or-port))))) (ein:default-url-or-port)))))
(url-or-port-list (url-or-port-list

View file

@ -199,7 +199,7 @@ insert-prev insert-next move-prev move-next)"
'help-echo "Click (mouse-1) to insert a new tab." 'help-echo "Click (mouse-1) to insert a new tab."
'mouse-face 'highlight 'mouse-face 'highlight
'face 'ein:notification-tab-normal) 'face 'ein:notification-tab-normal)
(propertize (ein:aif (and ein:%notebook% (ein:$notebook-kernelspec ein:%notebook%)) (propertize (aif (and ein:%notebook% (ein:$notebook-kernelspec ein:%notebook%))
(format "|%s|" (ein:$kernelspec-name it)) (format "|%s|" (ein:$kernelspec-name it))
"|unknown: please click and select a kernel|") "|unknown: please click and select a kernel|")
'keymap ein:header-line-switch-kernel-map 'keymap ein:header-line-switch-kernel-map

View file

@ -3,6 +3,7 @@
"Emacs IPython Notebook" "Emacs IPython Notebook"
'((emacs "25") '((emacs "25")
(websocket "20190620.338") (websocket "20190620.338")
(anaphora "20180618")
(request "20190621.1622") (request "20190621.1622")
(deferred "0.5") (deferred "0.5")
(polymode "20190426.1729") (polymode "20190426.1729")

View file

@ -124,8 +124,11 @@
"Use `jupyter notebook list --json` to populate ein:%processes%" "Use `jupyter notebook list --json` to populate ein:%processes%"
(clrhash ein:%processes%) (clrhash ein:%processes%)
(loop for line in (condition-case err (loop for line in (condition-case err
(process-lines ein:jupyter-default-server-command (apply #'process-lines
"notebook" "list" "--json") ein:jupyter-server-command
(append (aif ein:jupyter-server-use-subcommand
(list it))
'("list" "--json")))
;; often there is no local jupyter installation ;; often there is no local jupyter installation
(error (ein:log 'info "ein:process-refresh-processes: %s" err) nil)) (error (ein:log 'info "ein:process-refresh-processes: %s" err) nil))
do (destructuring-bind do (destructuring-bind
@ -182,7 +185,8 @@
(ein:notebook-open url-or-port (ein:notebook-open url-or-port
path* nil callback*)) path* nil callback*))
path callback))) path callback)))
(ein:jupyter-server-start (executable-find ein:jupyter-default-server-command) nbdir nil callback2))))) (ein:jupyter-server-start (executable-find ein:jupyter-server-command)
nbdir nil callback2)))))
(defun ein:process-open-notebook (&optional filename buffer-callback) (defun ein:process-open-notebook (&optional filename buffer-callback)
"When FILENAME is unspecified the variable `buffer-file-name' "When FILENAME is unspecified the variable `buffer-file-name'

View file

@ -178,7 +178,7 @@ pager buffer. You can explicitly specify the object by selecting it."
(ein:log 'debug "object[[%s]] other-window[[%s]]" object other-window) (ein:log 'debug "object[[%s]] other-window[[%s]]" object other-window)
(ein:case-equal msg-type (ein:case-equal msg-type
(("stream" "display_data") (("stream" "display_data")
(ein:aif (or (plist-get content :text) (plist-get content :data)) (aif (or (plist-get content :text) (plist-get content :data))
(if (string-match ein:pytools-jump-to-source-not-found-regexp it) (if (string-match ein:pytools-jump-to-source-not-found-regexp it)
(ein:log 'info (ein:log 'info
"Jumping to the source of %s...Not found" object) "Jumping to the source of %s...Not found" object)
@ -239,7 +239,7 @@ is defined."
(destructuring-bind (kernel object callback) packed (destructuring-bind (kernel object callback) packed
(if (or (string= msg-type "stream") (if (or (string= msg-type "stream")
(string= msg-type "display_data")) (string= msg-type "display_data"))
(ein:aif (or (plist-get content :text) (plist-get content :data)) (aif (or (plist-get content :text) (plist-get content :data))
(if (string-match ein:pytools-jump-to-source-not-found-regexp it) (if (string-match ein:pytools-jump-to-source-not-found-regexp it)
(ein:log 'info (ein:log 'info
"Source of %s not found" object) "Source of %s not found" object)
@ -282,7 +282,7 @@ given, open the last point in the other window."
(when (ein:aand (car ein:pytools-jump-stack) (when (ein:aand (car ein:pytools-jump-stack)
(equal (point) (marker-position it))) (equal (point) (marker-position it)))
(setq ein:pytools-jump-stack (cdr ein:pytools-jump-stack))) (setq ein:pytools-jump-stack (cdr ein:pytools-jump-stack)))
(ein:aif (car ein:pytools-jump-stack) (aif (car ein:pytools-jump-stack)
(ein:goto-marker it other-window) (ein:goto-marker it other-window)
(ein:log 'info "Nothing on stack.")))) (ein:log 'info "Nothing on stack."))))

View file

@ -140,7 +140,7 @@ KEY, then call `request' with URL and SETTINGS. KEY is compared by
do (ein:log 'warn "ein:query-singleton-ajax: %d running processes" do (ein:log 'warn "ein:query-singleton-ajax: %d running processes"
running) running)
do (sleep-for 3)) do (sleep-for 3))
(ein:aif (gethash key ein:query-running-process-table) (aif (gethash key ein:query-running-process-table)
(unless (request-response-done-p it) (unless (request-response-done-p it)
(ein:log 'debug "Race! %s %s" key (request-response-data it)))) (ein:log 'debug "Race! %s %s" key (request-response-data it))))
(let ((response (apply #'request (url-encode-url url) (let ((response (apply #'request (url-encode-url url)

View file

@ -83,7 +83,7 @@ Called from ewoc pretty printer via `ein:cell-pp'."
(when (slot-value cell 'popup) (when (slot-value cell 'popup)
(pop-to-buffer (ein:shared-output-create-buffer))) (pop-to-buffer (ein:shared-output-create-buffer)))
(cl-call-next-method) (cl-call-next-method)
(ein:aif (ein:oref-safe cell 'callback) (aif (ein:oref-safe cell 'callback)
(progn (progn
(funcall it cell) (funcall it cell)
(setf (slot-value cell 'callback-called) t)))) (setf (slot-value cell 'callback-called) t))))
@ -94,7 +94,7 @@ Called from ewoc pretty printer via `ein:cell-pp'."
"ein:cell--handle-execute-reply (cell ein:shared-output-cell): %s" "ein:cell--handle-execute-reply (cell ein:shared-output-cell): %s"
content) content)
(cl-call-next-method) (cl-call-next-method)
(ein:aif (ein:oref-safe cell 'callback) (aif (ein:oref-safe cell 'callback)
;; clear the way for waiting block in `ob-ein--execute-async' ;; clear the way for waiting block in `ob-ein--execute-async'
;; but only after 2 seconds to allow for handle-output stragglers ;; but only after 2 seconds to allow for handle-output stragglers
;; TODO avoid this hack ;; TODO avoid this hack

View file

@ -41,13 +41,6 @@ while maintaining the undo list for the current buffer."
`(let ((buffer-undo-list t)) `(let ((buffer-undo-list t))
,@body)) ,@body))
(defmacro ein:aif (test-form then-form &rest else-forms)
"Anaphoric IF. Adapted from `e2wm:aif'."
(declare (debug (form form &rest form)))
`(let ((it ,test-form))
(if it ,then-form ,@else-forms)))
(put 'ein:aif 'lisp-indent-function 2)
(defmacro ein:aand (test &rest rest) (defmacro ein:aand (test &rest rest)
"Anaphoric AND. Adapted from `e2wm:aand'." "Anaphoric AND. Adapted from `e2wm:aand'."
(declare (debug (form &rest form))) (declare (debug (form &rest form)))
@ -167,7 +160,7 @@ before previous opening parenthesis."
"\\s-\\|\n\\|\\.") "\\s-\\|\n\\|\\.")
(save-excursion (save-excursion
(with-syntax-table ein:dotty-syntax-table (with-syntax-table ein:dotty-syntax-table
(ein:aif (thing-at-point 'symbol) (aif (thing-at-point 'symbol)
it it
(unless (looking-at "(") (unless (looking-at "(")
(search-backward "(" (point-at-bol) t)) (search-backward "(" (point-at-bol) t))
@ -636,7 +629,7 @@ DONEBACK returns t or 'error when calling process is done, and nil if not done."
(deferred:$ (deferred:$
(deferred:next (deferred:next
(lambda () (lambda ()
(ein:aif (funcall doneback) it (aif (funcall doneback) it
(message "%s%s" mesg (make-string (1+ (% (incf count) 3)) ?.)) (message "%s%s" mesg (make-string (1+ (% (incf count) 3)) ?.))
(sleep-for 0 365))))))) (sleep-for 0 365)))))))
(deferred:nextc it (deferred:nextc it

View file

@ -73,7 +73,7 @@ Normalize `buffer-undo-list' by removing extraneous details, and update the ein:
(ein:log 'debug "truncating %s to %s: %S -> %S" (length ein:%which-cell%) (length buffer-undo-list) ein:%which-cell% (nthcdr (- fill) ein:%which-cell%)) (ein:log 'debug "truncating %s to %s: %S -> %S" (length ein:%which-cell%) (length buffer-undo-list) ein:%which-cell% (nthcdr (- fill) ein:%which-cell%))
(setq ein:%which-cell% (nthcdr (- fill) ein:%which-cell%))) (setq ein:%which-cell% (nthcdr (- fill) ein:%which-cell%)))
(when (> fill 0) (when (> fill 0)
(let ((cell-id (ein:aif (ein:worksheet-get-current-cell :noerror t) (let ((cell-id (aif (ein:worksheet-get-current-cell :noerror t)
(ein:worksheet--unique-enough-cell-id it) nil))) (ein:worksheet--unique-enough-cell-id it) nil)))
(let ((ein:log-print-level 5)) (let ((ein:log-print-level 5))
(ein:log 'debug "which-cell (%s . %s) %s %S fill=%s" change-beg change-end cell-id (cl-subseq buffer-undo-list 0 fill) fill)) (ein:log 'debug "which-cell (%s . %s) %s %S fill=%s" change-beg change-end cell-id (cl-subseq buffer-undo-list 0 fill) fill))
@ -143,7 +143,8 @@ Normalize `buffer-undo-list' by removing extraneous details, and update the ein:
(let ((mp (marker-position (car u)))) (let ((mp (marker-position (car u))))
(if (not (null mp)) (if (not (null mp))
(let* ((m (set-marker (make-marker) (+ ,distance mp) (marker-buffer (car u))))) (let* ((m (set-marker (make-marker) (+ ,distance mp) (marker-buffer (car u)))))
(cons m (cdr u))) u))) (cons m (cdr u)))
u)))
((and (consp u) (null (car u)) ((and (consp u) (null (car u))
(numberp (car (last u))) (numberp (cdr (last u)))) (numberp (car (last u))) (numberp (cdr (last u))))
(append (cl-subseq u 0 3) (append (cl-subseq u 0 3)
@ -281,7 +282,7 @@ Normalize `buffer-undo-list' by removing extraneous details, and update the ein:
(ein:worksheet--jigger-undo-list) (ein:worksheet--jigger-undo-list)
(cl-remprop 'ein:%cell-lengths% (slot-value cell 'cell-id)))))) (cl-remprop 'ein:%cell-lengths% (slot-value cell 'cell-id))))))
;;; Class and variable ;;; Class and variable
(defvar ein:worksheet-buffer-name-template "*ein: %s/%s*") (defvar ein:worksheet-buffer-name-template "*ein: %s/%s*")
@ -289,7 +290,7 @@ Normalize `buffer-undo-list' by removing extraneous details, and update the ein:
(ein:deflocal ein:%worksheet% nil (ein:deflocal ein:%worksheet% nil
"Buffer local variable to store an instance of `ein:worksheet'.") "Buffer local variable to store an instance of `ein:worksheet'.")
;;; Initialization of object and buffer ;;; Initialization of object and buffer
(defun ein:worksheet-new (nbformat get-notebook-name discard-output-p (defun ein:worksheet-new (nbformat get-notebook-name discard-output-p
@ -348,7 +349,7 @@ Normalize `buffer-undo-list' by removing extraneous details, and update the ein:
(cl-defmethod ein:worksheet-full-name ((ws ein:worksheet)) (cl-defmethod ein:worksheet-full-name ((ws ein:worksheet))
(let ((nb-name (ein:worksheet-notebook-name ws))) (let ((nb-name (ein:worksheet-notebook-name ws)))
(ein:aif (ein:worksheet-name ws) (aif (ein:worksheet-name ws)
(concat nb-name "/" it) (concat nb-name "/" it)
nb-name))) nb-name)))
@ -445,7 +446,7 @@ Normalize `buffer-undo-list' by removing extraneous details, and update the ein:
(case (car path) (case (car path)
(cell (ein:cell-pp (cdr path) data))))) (cell (ein:cell-pp (cdr path) data)))))
;;; Persistance and loading ;;; Persistance and loading
(cl-defmethod ein:worksheet-from-json ((ws ein:worksheet) data) (cl-defmethod ein:worksheet-from-json ((ws ein:worksheet) data)
@ -517,7 +518,7 @@ worksheet WS is reopened.
\(fn ws)" \(fn ws)"
(setf (slot-value ws 'dont-save-cells) t)) (setf (slot-value ws 'dont-save-cells) t))
;;; Cell indexing, retrieval, etc. ;;; Cell indexing, retrieval, etc.
(cl-defmethod ein:worksheet-cell-from-type ((ws ein:worksheet) type &rest args) (cl-defmethod ein:worksheet-cell-from-type ((ws ein:worksheet) type &rest args)
@ -588,7 +589,7 @@ buffer or there is no cell in the current buffer, return `nil'."
(unless noerror (unless noerror
(error "Cell not found")))) (error "Cell not found"))))
;;; Insertion and deletion of cells ;;; Insertion and deletion of cells
(defun ein:worksheet--get-ws-or-error () (defun ein:worksheet--get-ws-or-error ()
@ -856,7 +857,7 @@ If prefix is given, merge current cell into next cell."
(insert head "\n")) (insert head "\n"))
(when focus (ein:cell-goto next-cell))))) (when focus (ein:cell-goto next-cell)))))
;;; Cell selection. ;;; Cell selection.
(cl-defun ein:worksheet-next-input-cell (ewoc-node &optional up (nth 1)) (cl-defun ein:worksheet-next-input-cell (ewoc-node &optional up (nth 1))
@ -887,7 +888,7 @@ When NTH is specified, return NTH cell. Note that this function is
(funcall (if up #'ein:cell-prev #'ein:cell-next) cell)))) (funcall (if up #'ein:cell-prev #'ein:cell-next) cell))))
(defun ein:worksheet-goto-input (ewoc-node up) (defun ein:worksheet-goto-input (ewoc-node up)
(ein:aif (ein:worksheet-next-input-cell ewoc-node up) (aif (ein:worksheet-next-input-cell ewoc-node up)
(ein:cell-goto it) (ein:cell-goto it)
(message "No %s input" (if up "previous" "next")))) (message "No %s input" (if up "previous" "next"))))
@ -906,7 +907,7 @@ When NTH is specified, return NTH cell. Note that this function is
Go to previous cell if UP is t. Go to previous cell if UP is t.
Return t when the movement is succeeded." Return t when the movement is succeeded."
(unless prop (setq prop :input)) (unless prop (setq prop :input))
(ein:and-let* ((current-node (ein:worksheet-get-current-ewoc-node)) (-when-let* ((current-node (ein:worksheet-get-current-ewoc-node))
(current-cell (ein:cell-from-ewoc-node current-node)) (current-cell (ein:cell-from-ewoc-node current-node))
(target-cell (target-cell
(if (and (= nth 1) (if (and (= nth 1)
@ -934,12 +935,12 @@ similarly with `end-of-defun'.
It is set in `ein:notebook-multilang-mode'." It is set in `ein:notebook-multilang-mode'."
(ein:worksheet-goto-next-cell-element (or arg 1) nil 0 :after-input)) (ein:worksheet-goto-next-cell-element (or arg 1) nil 0 :after-input))
;;; Cell movement ;;; Cell movement
(defun ein:worksheet-move-cell (ws cell up) (defun ein:worksheet-move-cell (ws cell up)
;; effectively kill and yank modulo dirtying kill ring ;; effectively kill and yank modulo dirtying kill ring
(ein:aif (if up (ein:cell-prev cell) (ein:cell-next cell)) (aif (if up (ein:cell-prev cell) (ein:cell-next cell))
(let ((inhibit-read-only t) (let ((inhibit-read-only t)
(pivot-cell it) clone) (pivot-cell it) clone)
(ein:cell-save-text cell) (ein:cell-save-text cell)
@ -965,7 +966,6 @@ It is set in `ein:notebook-multilang-mode'."
(ein:worksheet-get-current-cell))) (ein:worksheet-get-current-cell)))
(ein:worksheet-move-cell ws cell nil)) (ein:worksheet-move-cell ws cell nil))
;;; Cell collapsing and output clearing ;;; Cell collapsing and output clearing
(defun ein:worksheet-toggle-output (ws cell) (defun ein:worksheet-toggle-output (ws cell)
@ -1009,7 +1009,6 @@ Do not clear input prompts when the prefix argument is given."
(mapc (lambda (c) (ein:worksheet-clear-output c preserve-input-prompt)) (mapc (lambda (c) (ein:worksheet-clear-output c preserve-input-prompt))
(seq-filter #'ein:codecell-p (ein:worksheet-get-cells ws)))) (seq-filter #'ein:codecell-p (ein:worksheet-get-cells ws))))
;;; Kernel related things ;;; Kernel related things
(defun ein:worksheet-kernel-status (ws) (defun ein:worksheet-kernel-status (ws)
@ -1051,7 +1050,7 @@ next cell, or insert if none."
(ein:worksheet-get-current-cell))) (ein:worksheet-get-current-cell)))
(when (cl-typep cell 'ein:codecell) (when (cl-typep cell 'ein:codecell)
(ein:worksheet-execute-cell ws cell)) (ein:worksheet-execute-cell ws cell))
(ein:aif (and (not insert) (ein:cell-next cell)) (aif (and (not insert) (ein:cell-next cell))
(ein:cell-goto it) (ein:cell-goto it)
(ein:worksheet-insert-cell-below ws 'code cell t))) (ein:worksheet-insert-cell-below ws 'code cell t)))
@ -1128,7 +1127,6 @@ in the history."
(ein:worksheet--get-history-index -1))) (ein:worksheet--get-history-index -1)))
(ein:worksheet-insert-last-input-history ws cell index)) (ein:worksheet-insert-last-input-history ws cell index))
;;; Metadata ;;; Metadata
(defun ein:worksheet-rename-sheet (ws name) (defun ein:worksheet-rename-sheet (ws name)
@ -1142,7 +1140,6 @@ in the history."
(ein:worksheet-set-modified-p ws t) (ein:worksheet-set-modified-p ws t)
(ein:worksheet-set-buffer-name ws))) (ein:worksheet-set-buffer-name ws)))
;;; Generic getter ;;; Generic getter
(defun ein:get-url-or-port--worksheet () (defun ein:get-url-or-port--worksheet ()
@ -1158,7 +1155,7 @@ in the history."
(defun ein:get-traceback-data--worksheet () (defun ein:get-traceback-data--worksheet ()
(ein:aand (ein:get-cell-at-point--worksheet) (ein:cell-get-tb-data it))) (ein:aand (ein:get-cell-at-point--worksheet) (ein:cell-get-tb-data it)))
;;; Predicate ;;; Predicate
(defun ein:worksheet-buffer-p () (defun ein:worksheet-buffer-p ()
@ -1174,7 +1171,7 @@ in the history."
(or (slot-value ws 'dirty) (or (slot-value ws 'dirty)
(buffer-modified-p buffer))))) (buffer-modified-p buffer)))))
;;; Utility commands ;;; Utility commands
(defun ein:worksheet-dedent-cell-text (cell) (defun ein:worksheet-dedent-cell-text (cell)
@ -1205,7 +1202,7 @@ in the history."
(defun ein:worksheet-jump-to-first-executing-cell () (defun ein:worksheet-jump-to-first-executing-cell ()
"Move the point to the first executing cell in the current worksheet." "Move the point to the first executing cell in the current worksheet."
(interactive) (interactive)
(ein:aif (ein:worksheet-first-executing-cell (ein:worksheet-get-cells ein:%worksheet%)) (aif (ein:worksheet-first-executing-cell (ein:worksheet-get-cells ein:%worksheet%))
(ein:cell-goto it) (ein:cell-goto it)
(message "No cell currently executing."))) (message "No cell currently executing.")))
@ -1214,11 +1211,11 @@ in the history."
(interactive) (interactive)
(let* ((curcell (ein:get-cell-at-point--worksheet)) (let* ((curcell (ein:get-cell-at-point--worksheet))
(restcells (ein:worksheet--cells-after-cell ein:%worksheet% curcell))) (restcells (ein:worksheet--cells-after-cell ein:%worksheet% curcell)))
(ein:aif (ein:worksheet-first-executing-cell restcells) (aif (ein:worksheet-first-executing-cell restcells)
(ein:cell-goto it) (ein:cell-goto it)
(message "No additional cells are executing.")))) (message "No additional cells are executing."))))
;;; Auto-execution ;;; Auto-execution
(defun ein:worksheet-toggle-autoexec (cell) (defun ein:worksheet-toggle-autoexec (cell)
@ -1260,7 +1257,7 @@ function."
(ein:worksheet-get-cells ws)))))) (ein:worksheet-get-cells ws))))))
ws (current-buffer))))) ws (current-buffer)))))
;;; Imenu ;;; Imenu
(defun ein:worksheet-imenu-create-index () (defun ein:worksheet-imenu-create-index ()
@ -1279,7 +1276,7 @@ function."
"Called via notebook mode hooks." "Called via notebook mode hooks."
(setq imenu-create-index-function #'ein:worksheet-imenu-create-index)) (setq imenu-create-index-function #'ein:worksheet-imenu-create-index))
;;; Workarounds ;;; Workarounds
(defadvice fill-paragraph (around ein:worksheet-fill-paragraph activate) (defadvice fill-paragraph (around ein:worksheet-fill-paragraph activate)

View file

@ -1,9 +1,11 @@
;;; ein.el --- IPython notebook client in Emacs ;;; ein.el --- jupyter notebook client
;; Copyright (C) 2012-2015 Takafumi Arakaki, John Miller ;; Copyright (C) 2012-2019 The Authors of the Emacs IPython Notebook (EIN)
;; Author: John Miller <millejoh at millejoh.com>, Takafumi Arakaki <aka.tkf at gmail.com> ;; Authors: dickmao <github id: dickmao>
;; URL: http://millejoh.github.io/emacs-ipython-notebook/ ;; John Miller <millejoh at millejoh.com>
;; Takafumi Arakaki <aka.tkf at gmail.com>
;; URL: https://github.com/dickmao/emacs-ipython-notebook
;; Keywords: jupyter, literate programming, reproducible research ;; Keywords: jupyter, literate programming, reproducible research
;; This file is NOT part of GNU Emacs. ;; This file is NOT part of GNU Emacs.
@ -38,42 +40,10 @@
;;; Code: ;;; Code:
(eval-when-compile (require 'cl)) (eval-when-compile (require 'cl))
(provide 'ein)
;;; Old commentary:
;; Development
;; ===========
;; Event vs hook vs callback
;; -------------------------
;;
;; * Use events (`ein:events') for calling (possibly multiple) functions
;; for its side effect.
;; * Use hooks for global/configurable setting.
;; * Use callback when caller needs returned value.
;; (e.g., `:get-buffers' slot in `ein:kernelinfo')
;; Naming
;; ------
;;
;; Variable named `ein:%VAR-NAME%' is a permanent buffer local
;; variable defined by `ein:deflocal'. It is often an instance of a
;; class/struct named `ein:VAR-NAME'.
;;
;; Old naming rule:
;; * `ein:@VAR-NAME'/`ein:VAR-NAME' is a permanent buffer local
;; variable. These variables are obsolete now.
;; * `ein:$STRUCT-NAME' is a name of struct.
;; These strcuts will be renamed to `ein:CLASS-NAME' when
;; reimplementing them using EIEIO class instead of CL struct.
;;
;; See also:
;; `CLiki : naming conventions <http://www.cliki.net/naming%20conventions>`_
;; Integrate ein into core emacs functionality
(when (boundp 'mouse-buffer-menu-mode-groups) (when (boundp 'mouse-buffer-menu-mode-groups)
(add-to-list 'mouse-buffer-menu-mode-groups (add-to-list 'mouse-buffer-menu-mode-groups
'("^ein:" . "ein"))) '("^ein:" . "ein")))
(provide 'ein)
;;; ein.el ends here ;;; ein.el ends here

View file

@ -36,6 +36,7 @@
;;; Code: ;;; Code:
(require 'ob) (require 'ob)
(require 'ein-utils) (require 'ein-utils)
(require 'anaphora)
(autoload 'org-element-property "org-element") (autoload 'org-element-property "org-element")
(autoload 'org-element-context "org-element") (autoload 'org-element-context "org-element")
@ -91,7 +92,7 @@
(defcustom ob-ein-inline-image-directory "ein-images" (defcustom ob-ein-inline-image-directory "ein-images"
"Store ob-ein images here." "Store ob-ein images here."
:group 'ein :group 'ein
:type '(directory)) :type 'directory)
(defcustom ob-ein-default-header-args:ein nil (defcustom ob-ein-default-header-args:ein nil
"No documentation." "No documentation."
@ -186,7 +187,7 @@ Based on ob-ipython--configure-kernel."
ein:url-localhost)) ein:url-localhost))
(lang (nth 0 (org-babel-get-src-block-info))) (lang (nth 0 (org-babel-get-src-block-info)))
(kernelspec (or (cdr (assoc :kernelspec processed-params)) (kernelspec (or (cdr (assoc :kernelspec processed-params))
(ein:aif (cdr (assoc lang org-src-lang-modes)) (aif (cdr (assoc lang org-src-lang-modes))
(cons 'language (format "%s" it)) (cons 'language (format "%s" it))
(error "ob-ein--execute-body: %s not among %s" (error "ob-ein--execute-body: %s not among %s"
lang (mapcar #'car org-src-lang-modes))))) lang (mapcar #'car org-src-lang-modes)))))
@ -236,7 +237,7 @@ Based on ob-ipython--configure-kernel."
`ein:shared-output-eval-string' completes." `ein:shared-output-eval-string' completes."
(apply-partially (apply-partially
(lambda (buffer* params* result-params* name* cell) (lambda (buffer* params* result-params* name* cell)
(let* ((raw (ein:aif (ein:oref-safe cell 'traceback) (let* ((raw (aif (ein:oref-safe cell 'traceback)
(ansi-color-apply (ein:join-str "\n" it)) (ansi-color-apply (ein:join-str "\n" it))
(ob-ein--process-outputs (ob-ein--process-outputs
(ein:oref-safe cell 'outputs) params*))) (ein:oref-safe cell 'outputs) params*)))
@ -352,7 +353,7 @@ if necessary. Install CALLBACK (i.e., cell execution) upon notebook retrieval."
(notebook (funcall callback notebook)) (notebook (funcall callback notebook))
((string= (url-host parsed-url) ein:url-localhost) ((string= (url-host parsed-url) ein:url-localhost)
(ein:process-refresh-processes) (ein:process-refresh-processes)
(ein:aif (ein:process-url-match nbpath) (aif (ein:process-url-match nbpath)
(ein:notebooklist-login (ein:process-url-or-port it) callback-login) (ein:notebooklist-login (ein:process-url-or-port it) callback-login)
(ein:jupyter-server-start (ein:jupyter-server-start
(executable-find (or (ein:eval-if-bound 'ein:jupyter-default-server-command) (executable-find (or (ein:eval-if-bound 'ein:jupyter-default-server-command)

View file

@ -173,7 +173,7 @@ TYPE can be 'body, nil."
(span `(nil ,(point-min) ,(point-min))) (span `(nil ,(point-min) ,(point-min)))
(cell (ein:worksheet-get-current-cell :pos pos :noerror nil))) (cell (ein:worksheet-get-current-cell :pos pos :noerror nil)))
;; Change :mode if necessary ;; Change :mode if necessary
(ein:and-let* ((lang (-when-let* ((lang
(condition-case err (condition-case err
(ein:$kernelspec-language (ein:$kernelspec-language
(ein:$notebook-kernelspec (ein:$notebook-kernelspec
@ -185,7 +185,7 @@ TYPE can be 'body, nil."
((ein:markdowncell-p cell) "markdown") ((ein:markdowncell-p cell) "markdown")
(t "fundamental"))) (t "fundamental")))
(mode (pm-get-mode-symbol-from-name what)) (mode (pm-get-mode-symbol-from-name what))
((not (equal mode (ein:oref-safe cm 'mode))))) (_ (not (equal mode (ein:oref-safe cm 'mode)))))
(when (eq mode 'poly-fallback-mode) (when (eq mode 'poly-fallback-mode)
(ein:display-warning (ein:display-warning
(format "pm:get-span: no major mode for kernelspec language '%s'" what))) (format "pm:get-span: no major mode for kernelspec language '%s'" what)))
@ -251,7 +251,7 @@ TYPE can be 'body, nil."
(setq jit-lock-context-unfontify-pos nil) (setq jit-lock-context-unfontify-pos nil)
(if (eq type 'host) (if (eq type 'host)
(setq syntax-propertize-function nil) (setq syntax-propertize-function nil)
(ein:aif pm--syntax-propertize-function-original (aif pm--syntax-propertize-function-original
(progn (progn
(setq syntax-propertize-function it) (setq syntax-propertize-function it)
(add-function :before-until (local 'syntax-propertize-function) (add-function :before-until (local 'syntax-propertize-function)

View file

@ -74,9 +74,9 @@ construct CONTENT and RESULT."
for content = (append for content = (append
(when pcallsig (list pcallsig callsig)) (when pcallsig (list pcallsig callsig))
(when pdoc (list pdoc docstring))) (when pdoc (list pdoc docstring)))
for result = (ein:aif (append for result = (aif (append
(when pcallsig (list callsig)) (when pcallsig (list callsig))
(when pdoc (list docstring))) (when pdoc (list docstring)))
(ein:join-str "\n" it)) (ein:join-str "\n" it))
do (funcall test content result)))) do (funcall test content result))))

View file

@ -27,6 +27,7 @@
(require 'ein-log) (require 'ein-log)
(require 'request) (require 'request)
(require 'anaphora)
(defmacro ein:setq-if-not (sym val) (defmacro ein:setq-if-not (sym val)
`(unless ,sym (setq ,sym ,val))) `(unless ,sym (setq ,sym ,val)))
@ -38,7 +39,7 @@
"File to save the ``*Messages*`` buffer.") "File to save the ``*Messages*`` buffer.")
(defvar ein:testing-dump-file-server nil (defvar ein:testing-dump-file-server nil
"File to save `ein:jupyter-server-buffer-name`.") "File to save `*ein:jupyter-server-buffer-name*`.")
(defvar ein:testing-dump-file-request nil (defvar ein:testing-dump-file-request nil
"File to save `request-log-buffer-name`.") "File to save `request-log-buffer-name`.")
@ -99,7 +100,7 @@ if I call this between links in a deferred chain. Adding a flush-queue."
"Wait until PREDICATE function returns non-`nil'. "Wait until PREDICATE function returns non-`nil'.
PREDARGS is argument list for the PREDICATE function. PREDARGS is argument list for the PREDICATE function.
MS is milliseconds to wait. INTERVAL is polling interval in milliseconds." MS is milliseconds to wait. INTERVAL is polling interval in milliseconds."
(let* ((int (ein:aif interval it (ein:aif ms (max 300 (/ ms 10)) 300))) (let* ((int (aif interval it (aif ms (max 300 (/ ms 10)) 300)))
(count (max 1 (if ms (truncate (/ ms int)) 25)))) (count (max 1 (if ms (truncate (/ ms int)) 25))))
(unless (or (loop repeat count (unless (or (loop repeat count
when (apply predicate predargs) when (apply predicate predargs)