notebooklist delete

This commit is contained in:
dickmao 2020-01-12 23:01:26 -05:00
parent b749cf7792
commit 6ea920dd0f
12 changed files with 180 additions and 126 deletions

View file

@ -37,15 +37,30 @@ Scenario: Stop after closing notebook
And I keep clicking "Resync" until "Stop" And I keep clicking "Resync" until "Stop"
And I click on "Stop" And I click on "Stop"
And I switch to log expr "ein:log-all-buffer-name" And I switch to log expr "ein:log-all-buffer-name"
Then I should see "Deleted session" Then I should see "kernel-delete-session--success"
And I am in notebooklist buffer And I am in notebooklist buffer
And I go to word "Untitled" And I go to word "Untitled"
And I go to beginning of line And I go to beginning of line
And I dump buffer
And I click without going top on "Open" And I click without going top on "Open"
And no notebooks pending And no notebooks pending
And I switch to buffer like "Untitled" And I switch to buffer like "Untitled"
@delete
Scenario: Delete closes buffers and sessions
Given I am in notebooklist buffer
And I click on "New Notebook"
And no notebooks pending
And I switch to buffer like "Untitled"
And I am in notebooklist buffer
And I clear log expr "ein:log-all-buffer-name"
And I click on "Delete"
And I wait for buffer to not say "Untitled"
Then eval "(should-not (ein:notebook-opened-notebooks)))"
Then eval "(should-not (seq-some (lambda (b) (cl-search "Untitled" (buffer-name b))) (buffer-list)))"
And I switch to log expr "ein:log-all-buffer-name"
Then I should see "kernel-delete-session--success"
Then I should see "notebooklist-delete-notebook--complete"
@content @content
Scenario: Read a massive directory Scenario: Read a massive directory
Given I create a directory "/var/tmp/fg7Cv8" with depth 4 and width 8 Given I create a directory "/var/tmp/fg7Cv8" with depth 4 and width 8

View file

@ -40,7 +40,7 @@
(When "^I kill kernel$" (When "^I kill kernel$"
(lambda () (lambda ()
(ein:kernel-delete-session (ein:$notebook-kernel ein:%notebook%)) (ein:kernel-delete-session nil :kernel (ein:$notebook-kernel ein:%notebook%))
(And "I wait for the smoke to clear"))) (And "I wait for the smoke to clear")))
(When "^my reconnect is questioned" (When "^my reconnect is questioned"
@ -122,6 +122,10 @@
do (sleep-for 0 500) do (sleep-for 0 500)
finally do (should (zerop (hash-table-count *ein:notebook--pending-query*)))))) finally do (should (zerop (hash-table-count *ein:notebook--pending-query*))))))
(When "^no notebooks open$"
(lambda ()
(should ())))
(When "^I switch to buffer like \"\\(.+\\)\"$" (When "^I switch to buffer like \"\\(.+\\)\"$"
(lambda (substr) (lambda (substr)
(cl-loop repeat 10 (cl-loop repeat 10
@ -284,6 +288,10 @@
(When "I call \"ein:notebooklist-login\"") (When "I call \"ein:notebooklist-login\"")
(And "I wait for the smoke to clear"))))))) (And "I wait for the smoke to clear")))))))
(When "^eval \"\\(.*\\)\"$"
(lambda (command)
(eval (car (read-from-string command)))))
(When "^I wait for completions \"\\(.+\\)\"$" (When "^I wait for completions \"\\(.+\\)\"$"
(lambda (key) (lambda (key)
(cl-loop repeat 10 (cl-loop repeat 10

View file

@ -46,6 +46,7 @@
(ein:testing-flush-queries) (ein:testing-flush-queries)
(with-current-buffer (ein:notebooklist-get-buffer (car (ein:jupyter-server-conn-info))) (with-current-buffer (ein:notebooklist-get-buffer (car (ein:jupyter-server-conn-info)))
(cl-loop for notebook in (ein:notebook-opened-notebooks) (cl-loop for notebook in (ein:notebook-opened-notebooks)
for url-or-port = (ein:$notebook-url-or-port notebook)
for path = (ein:$notebook-notebook-path notebook) for path = (ein:$notebook-notebook-path notebook)
for done-p = nil for done-p = nil
do (ein:notebook-kill-kernel-then-close-command do (ein:notebook-kill-kernel-then-close-command
@ -58,14 +59,14 @@
do (when (or (ob-ein-anonymous-p path) do (when (or (ob-ein-anonymous-p path)
(search "Untitled" path) (search "Untitled" path)
(search "Renamed" path)) (search "Renamed" path))
(ein:notebooklist-delete-notebook path) (ein:notebooklist-delete-notebook ein:%notebooklist% url-or-port path)
(cl-loop with fullpath = (concat (file-name-as-directory ein:testing-jupyter-server-root) path) (cl-loop with fullpath = (concat (file-name-as-directory ein:testing-jupyter-server-root) path)
repeat 10 repeat 10
for extant = (file-exists-p fullpath) for extant = (file-exists-p fullpath)
until (not extant) until (not extant)
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 delete %s" path)))))))
(aif (ein:notebook-opened-notebooks) (aif (ein:notebook-opened-notebooks)
(cl-loop for nb in it (cl-loop for nb in it
for path = (ein:$notebook-notebook-path nb) for path = (ein:$notebook-notebook-path nb)

View file

@ -519,7 +519,7 @@ Return language name as a string or `nil' when not defined.
(when (and (not (slot-value cell 'collapsed)) (when (and (not (slot-value cell 'collapsed))
(= index ein:cell-max-num-outputs) (= index ein:cell-max-num-outputs)
(> (point) (point-at-bol))) (> (point) (point-at-bol)))
;; The first output which exceeds `ein:cell-max-num-outputs'. ;; The first output which exceeds `ein:cell-max-num-outputs'.
(ein:insert-read-only "\n")) (ein:insert-read-only "\n"))
(ein:insert-read-only ".")) (ein:insert-read-only "."))
(let ((out (nth index (slot-value cell 'outputs)))) (let ((out (nth index (slot-value cell 'outputs))))
@ -819,7 +819,6 @@ If END is non-`nil', return the location of next element."
(cl-defmethod ein:cell-actually-append-output ((cell ein:codecell) json) (cl-defmethod ein:cell-actually-append-output ((cell ein:codecell) json)
(ein:cell-expand cell) (ein:cell-expand cell)
;; (ein:flush-clear-timeout)
(setf (slot-value cell 'outputs) (setf (slot-value cell 'outputs)
(append (slot-value cell 'outputs) (list json))) (append (slot-value cell 'outputs) (list json)))
(let* ((inhibit-read-only t) (let* ((inhibit-read-only t)
@ -840,7 +839,9 @@ If END is non-`nil', return the location of next element."
"Insert pyout type output in the buffer. "Insert pyout type output in the buffer.
Called from ewoc pretty printer via `ein:cell-insert-output'." Called from ewoc pretty printer via `ein:cell-insert-output'."
(ein:insert-read-only (format "Out [%s]:" (ein:insert-read-only (format "Out [%s]:"
(or (plist-get json :prompt_number) " ")) (or (plist-get json :prompt_number)
(plist-get json :execution_count)
" "))
'font-lock-face 'ein:cell-output-prompt) 'font-lock-face 'ein:cell-output-prompt)
(ein:insert-read-only "\n") (ein:insert-read-only "\n")
(ein:cell-append-mime-type json) (ein:cell-append-mime-type json)
@ -951,8 +952,7 @@ Called from ewoc pretty printer via `ein:cell-insert-output'."
(metadata (slot-value cell 'metadata))) (metadata (slot-value cell 'metadata)))
`((source . ,(ein:cell-get-text cell)) `((source . ,(ein:cell-get-text cell))
(cell_type . "code") (cell_type . "code")
,@(when execute-count (execution_count . ,execute-count)
`((execution_count . ,execute-count)))
(outputs . ,(apply #'vector (slot-value cell 'outputs))) (outputs . ,(apply #'vector (slot-value cell 'outputs)))
(metadata . ,(plist-put metadata :collapsed (if (slot-value cell 'collapsed) t (metadata . ,(plist-put metadata :collapsed (if (slot-value cell 'collapsed) t
json-false)))))) json-false))))))
@ -1010,8 +1010,7 @@ Called from ewoc pretty printer via `ein:cell-insert-output'."
:clear_output (cons #'ein:cell--handle-clear-output cell) :clear_output (cons #'ein:cell--handle-clear-output cell)
:set_next_input (cons #'ein:cell--handle-set-next-input cell))) :set_next_input (cons #'ein:cell--handle-set-next-input cell)))
(cl-defmethod ein:cell--handle-execute-reply ((cell ein:codecell) content (cl-defmethod ein:cell--handle-execute-reply ((cell ein:codecell) content metadata)
metadata)
(run-hook-with-args 'ein:on-execute-reply-functions cell content metadata) (run-hook-with-args 'ein:on-execute-reply-functions cell content metadata)
(ein:cell-set-input-prompt cell (plist-get content :execution_count)) (ein:cell-set-input-prompt cell (plist-get content :execution_count))
(ein:cell-running-set cell nil) (ein:cell-running-set cell nil)
@ -1027,14 +1026,31 @@ Called from ewoc pretty printer via `ein:cell-insert-output'."
(list :cell cell :text text)) (list :cell cell :text text))
(ein:events-trigger events 'maybe_reset_undo.Worksheet cell))) (ein:events-trigger events 'maybe_reset_undo.Worksheet cell)))
(cl-defmethod ein:cell--handle-output ((cell ein:codecell) msg-type content meta) (cl-defmethod ein:cell--handle-output ((cell ein:codecell) msg-type content _metadata)
;; (ein:output-area-convert-mime-types content (plist-get content :data)) (let ((json `(:output_type ,msg-type)))
(ein:cell-append-output cell (cl-macrolet ((copy-props
(plist-put (src tgt props)
(plist-put content :output_type msg-type) `(mapc (lambda (kw)
:metadata meta)) (let ((val (plist-get ,src kw)))
;; (setf (slot-value cell 'dirty) t) (when (and (null val) (plist-member ,src kw))
(ein:events-trigger (slot-value cell 'events) 'maybe_reset_undo.Worksheet cell)) (setq val (make-hash-table)))
(setq ,tgt (plist-put ,tgt kw val))))
,props)))
(ein:case-equal msg-type
(("stream")
(copy-props content json '(:name :text)))
(("display_data")
(copy-props content json '(:data :metadata)))
(("execute_result" "pyout")
(copy-props content json '(:execution_count :data :metadata)))
(("error" "pyerr")
(copy-props content json '(:ename :evalue :traceback)))
(t
(ein:log 'error "ein:cell--handle-output: unhandled msg_type '%s'" msg-type)
(setq json nil))))
(when json
(ein:cell-append-output cell json)
(ein:events-trigger (slot-value cell 'events) 'maybe_reset_undo.Worksheet cell))))
(cl-defmethod ein:cell--handle-clear-output ((cell ein:codecell) content (cl-defmethod ein:cell--handle-clear-output ((cell ein:codecell) content
_metadata) _metadata)

View file

@ -179,7 +179,6 @@
(metadata :initarg :metadata :initform nil :accessor ein:worksheet--metadata) (metadata :initarg :metadata :initform nil :accessor ein:worksheet--metadata)
(events :initarg :events :accessor ein:worksheet--events))) (events :initarg :events :accessor ein:worksheet--events)))
;;; Kernel ;;; Kernel
(defstruct ein:$kernelspec (defstruct ein:$kernelspec
"Kernel specification as return by the Jupyter notebook server. "Kernel specification as return by the Jupyter notebook server.

View file

@ -141,13 +141,13 @@
(cl-defun ein:kernel-restart-session (kernel) (cl-defun ein:kernel-restart-session (kernel)
"Server side delete of KERNEL session and subsequent restart with all new state" "Server side delete of KERNEL session and subsequent restart with all new state"
(ein:kernel-delete-session (ein:kernel-delete-session
kernel
(lambda (kernel) (lambda (kernel)
(ein:events-trigger (ein:$kernel-events kernel) 'status_restarting.Kernel) (ein:events-trigger (ein:$kernel-events kernel) 'status_restarting.Kernel)
(ein:kernel-retrieve-session kernel 0 (ein:kernel-retrieve-session kernel 0
(lambda (kernel) (lambda (kernel)
(ein:events-trigger (ein:$kernel-events kernel) (ein:events-trigger (ein:$kernel-events kernel)
'status_restarted.Kernel)))))) 'status_restarted.Kernel))))
:kernel kernel))
(cl-defun ein:kernel-retrieve-session (kernel &optional iteration callback) (cl-defun ein:kernel-retrieve-session (kernel &optional iteration callback)
"Formerly ein:kernel-start, but that was misnomer because 1. the server really starts a session (and an accompanying kernel), and 2. it may not even start a session if one exists for the same path. "Formerly ein:kernel-start, but that was misnomer because 1. the server really starts a session (and an accompanying kernel), and 2. it may not even start a session if one exists for the same path.
@ -533,33 +533,36 @@ Example::
:success (lambda (&rest ignore) :success (lambda (&rest ignore)
(ein:log 'info "Sent interruption command."))))) (ein:log 'info "Sent interruption command.")))))
(defun ein:kernel-delete--from-session-id (url session-id &optional callback) (cl-defun ein:kernel-delete-session (&optional callback
"Stop/delete a running kernel from a session id. May also specify a callback function of 0 args to be called once oepration is complete. &key url-or-port path kernel
&aux (session-id))
We need this to have proper behavior for the 'Stop' command in the ein:notebooklist buffer."
(ein:query-singleton-ajax
(ein:url url "api/sessions" session-id)
:success (apply-partially #'ein:kernel-delete--from-session-complete session-id callback)
:error (apply-partially #'ein:kernel-delete--from-session-error session-id)
:type "DELETE"))
(defun ein:kernel-delete--from-session-complete (session-id callback &rest _)
(ein:log 'info "Deleted session %s and its associated kernel process." session-id)
(when callback
(funcall callback)))
(defun ein:kernel-delete--from-session-error (session-id &rest _)
(ein:log 'info "Error, could not delete session %s." session-id))
(defun ein:kernel-delete-session (kernel &optional callback)
"Regardless of success or error, we clear all state variables of kernel and funcall CALLBACK (kernel)" "Regardless of success or error, we clear all state variables of kernel and funcall CALLBACK (kernel)"
(ein:and-let* ((session-id (ein:$kernel-session-id kernel))) (cond (kernel
(ein:query-singleton-ajax (setq url-or-port (ein:$kernel-url-or-port kernel))
(ein:url (ein:$kernel-url-or-port kernel) "api/sessions" session-id) (setq path (ein:$kernel-path kernel))
:type "DELETE" (setq session-id (ein:$kernel-session-id kernel)))
:complete (apply-partially #'ein:kernel-delete-session--complete kernel session-id callback) ((and url-or-port path)
:error (apply-partially #'ein:kernel-delete-session--error session-id callback) (aif (ein:notebook-get-opened-notebook url-or-port path)
:success (apply-partially #'ein:kernel-delete-session--success session-id callback)))) (progn
(setq kernel (ein:$notebook-kernel it))
(setq session-id (ein:$kernel-session-id kernel)))
(let ((ein:force-sync t))
(ein:content-query-sessions
url-or-port
(lambda (session-hash)
(setq session-id (car (gethash path session-hash))))
nil))))
(t (error "ein:kernel-delete-session: need kernel, or url-or-port and path")))
(if session-id
(ein:query-singleton-ajax
(ein:url url-or-port "api/sessions" session-id)
:type "DELETE"
:complete (apply-partially #'ein:kernel-delete-session--complete kernel session-id callback)
:error (apply-partially #'ein:kernel-delete-session--error session-id callback)
:success (apply-partially #'ein:kernel-delete-session--success session-id callback))
(ein:log 'verbose "ein:kernel-delete-session: no sessions found for %s" path)
(when callback
(funcall callback kernel))))
(cl-defun ein:kernel-delete-session--error (session-id callback (cl-defun ein:kernel-delete-session--error (session-id callback
&key response error-thrown &key response error-thrown
@ -577,7 +580,8 @@ We need this to have proper behavior for the 'Stop' command in the ein:notebookl
&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:kernel-delete-session--complete %s" resp-string) (ein:log 'debug "ein:kernel-delete-session--complete %s" resp-string)
(ein:kernel-disconnect kernel) (when kernel
(ein:kernel-disconnect kernel))
(when callback (funcall callback kernel))) (when callback (funcall callback kernel)))
;; Reply handlers. ;; Reply handlers.
@ -669,7 +673,7 @@ We need this to have proper behavior for the 'Stop' command in the ein:notebookl
msg-type msg-id) 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")
(aif (plist-get callbacks :output) (aif (plist-get callbacks :output) ;; ein:cell--handle-output
(ein:funcall-packed it msg-type content metadata) (ein:funcall-packed it msg-type content metadata)
(ein:log 'warn (concat "ein:kernel--handle-iopub-reply: " (ein:log 'warn (concat "ein:kernel--handle-iopub-reply: "
"No :output callback for msg_id=%s") "No :output callback for msg_id=%s")

View file

@ -830,18 +830,16 @@ as usual."
(declare (indent defun)) (declare (indent defun))
(interactive (list (ein:notebook--get-nb-or-error) nil)) (interactive (list (ein:notebook--get-nb-or-error) nil))
(unless callback1 (setq callback1 #'ignore)) (unless callback1 (setq callback1 #'ignore))
(lexical-let ((callback1 callback1)) (let* ((kernel (ein:$notebook-kernel notebook))
(let ((kernel (ein:$notebook-kernel notebook)) (callback (apply-partially
(callback (apply-partially (lambda (notebook* cb* kernel*)
(lambda (notebook* kernel*) (ein:notebook-close notebook*)
(ein:notebook-close notebook*) (funcall cb* kernel*))
(funcall callback1 kernel*)) notebook callback1)))
notebook))) (if (ein:kernel-live-p kernel)
(if (ein:kernel-live-p kernel) (ein:message-whir "Ending session" callback
(ein:message-whir "Ending session" (ein:kernel-delete-session callback :kernel kernel))
(add-function :before callback done-callback) (funcall callback nil))))
(ein:kernel-delete-session kernel callback))
(funcall callback nil)))))
(defun ein:fast-content-from-notebook (notebook) (defun ein:fast-content-from-notebook (notebook)
"Quickly generate a basic content structure from notebook. This "Quickly generate a basic content structure from notebook. This

View file

@ -406,34 +406,36 @@ This function is called via `ein:notebook-after-rename-hook'."
name)) name))
(ein:notebooklist-new-notebook url-or-port kernelspec callback no-pop)) (ein:notebooklist-new-notebook url-or-port kernelspec callback no-pop))
(defun ein:notebooklist-delete-notebook-ask (path) (defun ein:notebooklist-delete-notebook (notebooklist url-or-port path &optional callback)
(when (y-or-n-p (format "Delete notebook %s?" path))
(ein:notebooklist-delete-notebook path)))
(defun ein:notebooklist-delete-notebook (path &optional callback)
"CALLBACK with no arguments, e.g., semaphore" "CALLBACK with no arguments, e.g., semaphore"
(lexical-let* ((path path) (declare (indent defun))
(notebooklist ein:%notebooklist%) (unless callback (setq callback #'ignore))
(callback callback) (dolist (buf (seq-filter (lambda (b)
(url-or-port (ein:$notebooklist-url-or-port notebooklist))) (with-current-buffer b
(unless callback (aif (ein:get-notebook)
(setq callback (apply-partially #'ein:notebooklist-reload notebooklist))) (string= path (ein:$notebook-notebook-path it)))))
(dolist (buf (seq-filter (lambda (b) (buffer-list)))
(with-current-buffer b (cl-letf (((symbol-function 'y-or-n-p) (lambda (&rest _args) nil)))
(aif (ein:get-notebook) (kill-buffer buf)))
(string= path (ein:$notebook-notebook-path it))))) (if (ein:notebook-opened-notebooks (lambda (nb)
(buffer-list))) (string= path
(kill-buffer buf)) (ein:$notebook-notebook-path nb))))
(if (ein:notebook-opened-notebooks (ein:log 'error "ein:notebooklist-delete-notebook: cannot close %s" path)
(lambda (nb) (let ((delete-nb
(string= path (ein:$notebook-notebook-path nb)))) (apply-partially
(ein:log 'error "ein:notebooklist-delete-notebook: cannot close %s" path) (lambda (url* settings* _kernel)
(ein:query-singleton-ajax (apply #'ein:query-singleton-ajax url* settings*))
(ein:notebook-url-from-url-and-id (ein:notebook-url-from-url-and-id
url-or-port (ein:$notebooklist-api-version notebooklist) path) url-or-port (ein:$notebooklist-api-version notebooklist) path)
:type "DELETE" (list :type "DELETE"
:complete (apply-partially #'ein:notebooklist-delete-notebook--complete :complete (apply-partially
(ein:url url-or-port path) callback))))) #'ein:notebooklist-delete-notebook--complete
(ein:url url-or-port path) callback)))))
(ein:message-whir
"Ending session" delete-nb
(ein:kernel-delete-session delete-nb
:url-or-port url-or-port
:path path)))))
(cl-defun ein:notebooklist-delete-notebook--complete (cl-defun ein:notebooklist-delete-notebook--complete
(url callback (url callback
@ -556,7 +558,10 @@ This function is called via `ein:notebook-after-rename-hook'."
(ein:make-sorting-widget "Sort by" ein:notebooklist-sort-field) (ein:make-sorting-widget "Sort by" ein:notebooklist-sort-field)
(ein:make-sorting-widget "In Order" ein:notebooklist-sort-order) (ein:make-sorting-widget "In Order" ein:notebooklist-sort-order)
(widget-insert "\n") (widget-insert "\n")
(cl-loop for note in (ein:notebooklist--order-data (cl-loop with reloader = (apply-partially (lambda (nblist _kernel)
(ein:notebooklist-reload nblist))
ein:%notebooklist%)
for note in (ein:notebooklist--order-data
(ein:$notebooklist-data ein:%notebooklist%) (ein:$notebooklist-data ein:%notebooklist%)
ein:notebooklist-sort-field ein:notebooklist-sort-field
ein:notebooklist-sort-order) ein:notebooklist-sort-order)
@ -602,28 +607,41 @@ This function is called via `ein:notebook-after-rename-hook'."
if (string= type "notebook") if (string= type "notebook")
do (progn (widget-create do (progn (widget-create
'link 'link
:notify (lexical-let ((url-or-port url-or-port) :notify (apply-partially
(path path)) (lambda (url-or-port* path* reloader* &rest _args)
(lambda (&rest _ignore) (ein:notebook-open url-or-port* path* nil reloader*))
(run-at-time 3 nil #'ein:notebooklist-reload) url-or-port path
(ein:notebook-open url-or-port path))) (apply-partially (lambda (reloader* &rest _args)
(funcall reloader* nil))
reloader))
"Open") "Open")
(widget-insert " ") (widget-insert " ")
(if (gethash path sessions) (if (gethash path sessions)
(widget-create (widget-create
'link 'link
:notify (lexical-let ((url url-or-port) :notify
(session (car (gethash path sessions)))) (apply-partially
(lambda (&rest _ignore) (lambda (callback* url-or-port* path* &rest _ignore)
(ein:kernel-delete--from-session-id url session #'ein:notebooklist-reload))) (ein:message-whir
"Ending session" callback*
(ein:kernel-delete-session callback*
:url-or-port url-or-port*
:path path*)))
reloader url-or-port path)
"Stop") "Stop")
(widget-insert "------")) (widget-insert "------"))
(widget-insert " ") (widget-insert " ")
(widget-create (widget-create
'link 'link
:notify (lexical-let ((path path)) :notify (apply-partially
(lambda (&rest _ignore) (lambda (notebooklist* url-or-port* path* callback*
(ein:notebooklist-delete-notebook-ask path))) &rest _args)
(when (or noninteractive
(y-or-n-p (format "Delete notebook %s?" path*)))
(ein:notebooklist-delete-notebook
notebooklist* url-or-port* path*
(apply-partially callback* nil))))
ein:%notebooklist% url-or-port path reloader)
"Delete") "Delete")
(widget-insert " : " (ein:format-nbitem-data name last-modified)) (widget-insert " : " (ein:format-nbitem-data name last-modified))
(widget-insert "\n")) (widget-insert "\n"))

View file

@ -226,9 +226,6 @@ at point, i.e. any word before then \"(\", if it is present."
See: http://api.jquery.com/jQuery.ajax/" See: http://api.jquery.com/jQuery.ajax/"
(concat url (format-time-string "?_=%s"))) (concat url (format-time-string "?_=%s")))
;;; HTML utils
(defun ein:html-get-data-in-body-tag (key) (defun ein:html-get-data-in-body-tag (key)
"Very ad-hoc parser to get data in body tag." "Very ad-hoc parser to get data in body tag."
(ignore-errors (ignore-errors
@ -238,9 +235,6 @@ See: http://api.jquery.com/jQuery.ajax/"
(search-forward-regexp (format "%s=\\([^[:space:]\n]+\\)" key)) (search-forward-regexp (format "%s=\\([^[:space:]\n]+\\)" key))
(match-string 1)))) (match-string 1))))
;;; JSON utils
(defmacro ein:with-json-setting (&rest body) (defmacro ein:with-json-setting (&rest body)
`(let ((json-object-type 'plist) `(let ((json-object-type 'plist)
(json-array-type 'list)) (json-array-type 'list))
@ -288,9 +282,6 @@ See: http://api.jquery.com/jQuery.ajax/"
;; (setq ad-return-value "{}") ;; (setq ad-return-value "{}")
;; ad-do-it)) ;; ad-do-it))
;;; EWOC
(defun ein:ewoc-create (pretty-printer &optional header footer nosep) (defun ein:ewoc-create (pretty-printer &optional header footer nosep)
"Do nothing wrapper of `ewoc-create' to provide better error message." "Do nothing wrapper of `ewoc-create' to provide better error message."
(condition-case nil (condition-case nil
@ -392,7 +383,6 @@ Adapted from twittering-mode.el's `case-string'."
,@body))) ,@body)))
clauses))) clauses)))
;;; Text manipulation on buffer ;;; Text manipulation on buffer
(defun ein:find-leftmost-column (beg end) (defun ein:find-leftmost-column (beg end)
@ -604,14 +594,16 @@ otherwise it should be a function, which is called on `time'."
(string (format-time-string format time)) (string (format-time-string format time))
(function (funcall format time)))) (function (funcall format time))))
;;; Emacs utilities ;;; Emacs utilities
(defmacro ein:message-whir (mesg &rest body) (defmacro ein:message-whir (mesg callback &rest body)
"Display MESG with a modest animation until ASYNC-CALL completes." "Display MESG with a modest animation until ASYNC-CALL completes."
`(lexical-let* (done-p `(lexical-let* (done-p
(done-callback (lambda (&rest ignore) (setf done-p t))) (done-callback (lambda (&rest _args) (setf done-p t)))
(errback (lambda (&rest ignore) (setf done-p 'error)))) (errback (lambda (&rest _args) (setf done-p 'error))))
(ein:message-whir-subr ,mesg (lambda () done-p)) ;; again, how can done-callback remove itself after running?
(add-function :before ,callback done-callback)
(unless noninteractive
(ein:message-whir-subr ,mesg (lambda () done-p)))
,@body)) ,@body))
(defun ein:message-whir-subr (mesg doneback) (defun ein:message-whir-subr (mesg doneback)
@ -626,7 +618,7 @@ DONEBACK returns t or 'error when calling process is done, and nil if not done."
;; "complicated timings of macro expansion lexical-let, deferred:lambda" ;; "complicated timings of macro expansion lexical-let, deferred:lambda"
;; using deferred:loop instead ;; using deferred:loop instead
(deferred:$ (deferred:$
(deferred:loop (cl-loop for i from 1 below 30 by 1 collect i) (deferred:loop (cl-loop for i from 1 below 60 by 1 collect i)
(lambda () (lambda ()
(deferred:$ (deferred:$
(deferred:next (deferred:next

View file

@ -343,7 +343,8 @@ if necessary. Install CALLBACK (i.e., cell execution) upon notebook retrieval."
do (sleep-for 0 500) do (sleep-for 0 500)
finally do (if extant finally do (if extant
(ein:display-warning (ein:display-warning
(format "cannot del path=%s nbpath=%s" fullpath nbpath)) (format "cannot delete path=%s nbpath=%s"
fullpath nbpath))
(ob-ein--initiate-session session kernelspec callback)))) (ob-ein--initiate-session session kernelspec callback))))
(notebook (funcall callback notebook)) (notebook (funcall callback notebook))
((string= (url-host parsed-url) ein:url-localhost) ((string= (url-host parsed-url) ein:url-localhost)

View file

@ -54,17 +54,18 @@
(dummy-response (make-request-response)) (dummy-response (make-request-response))
got-url) got-url)
(cl-letf (((symbol-function 'request) (cl-letf (((symbol-function 'request)
(lambda (url &rest ignore) (setq got-url url) dummy-response)) (lambda (url &rest _ignore) (setq got-url url) dummy-response))
((symbol-function 'set-process-query-on-exit-flag) #'ignore) ((symbol-function 'set-process-query-on-exit-flag) #'ignore)
((symbol-function 'ein:kernel-stop-channels) #'ignore) ((symbol-function 'ein:kernel-stop-channels) #'ignore)
((symbol-function 'ein:websocket) (lambda (&rest ignore) (make-ein:$websocket :ws nil :kernel kernel :closed-by-client nil))) ((symbol-function 'ein:websocket)
((symbol-function 'ein:websocket-open-p) (lambda (&rest ignore) t))) (lambda (&rest ignore) (make-ein:$websocket :ws nil :kernel kernel
:closed-by-client nil)))
((symbol-function 'ein:websocket-open-p) (lambda (&rest _ignore) t)))
(ein:kernel-retrieve-session--success (ein:kernel-retrieve-session--success
kernel nil :data (list :ws_url "ws://127.0.0.1:8888" :id kernel-id)) kernel nil :data (list :ws_url "ws://127.0.0.1:8888" :id kernel-id))
(ein:kernel-delete-session kernel)) (ein:kernel-delete-session nil :kernel kernel))
(should (equal got-url desired-url)))) (should (equal got-url desired-url))))
;;; Test `ein:kernel-construct-help-string' ;;; Test `ein:kernel-construct-help-string'
(ert-deftest ein:kernel-construct-help-string-when-found () (ert-deftest ein:kernel-construct-help-string-when-found ()

View file

@ -924,7 +924,8 @@ defined."
(let ((buffer (current-buffer)) (let ((buffer (current-buffer))
(notebook ein:%notebook%)) (notebook ein:%notebook%))
(cl-letf (((symbol-function 'ein:kernel-live-p) (lambda (&rest args) t)) (cl-letf (((symbol-function 'ein:kernel-live-p) (lambda (&rest args) t))
((symbol-function 'ein:kernel-delete-session) (lambda (kernel callback) (funcall callback kernel)))) ((symbol-function 'ein:kernel-delete-session)
(cl-function (lambda (callback &key kernel) (funcall callback kernel)))))
(call-interactively #'ein:notebook-kill-kernel-then-close-command)) (call-interactively #'ein:notebook-kill-kernel-then-close-command))
(ein:testing-notebook-should-be-closed notebook buffer)))) (ein:testing-notebook-should-be-closed notebook buffer))))