C-c C-q improved visual feedback

As `ein:notebok-kill-kernel-then-close-cmmand` must wait for the
server to delete the session, the buffer wouldn't disappear right
away, leaving the user nonplussed whether the `C-c C-q` took.  Display
a status message "Ending session" with a modest animation instead.

Also add a "Stop" test for notebooklist.  Sorry about breaking "Stop"
in ee3b0f0
This commit is contained in:
dickmao 2018-11-09 13:02:43 -05:00
parent 6f19d8bf83
commit 6ca6752319
9 changed files with 56 additions and 37 deletions

View file

@ -20,9 +20,7 @@ autoloads:
.PHONY: clean .PHONY: clean
clean: clean:
cask clean-elc cask clean-elc
rm -rf test/test-install
env-ipy.%:
tools/makeenv.sh env/ipy.$* tools/requirement-ipy.$*.txt
.PHONY: test-compile .PHONY: test-compile
test-compile: clean autoloads test-compile: clean autoloads

View file

@ -19,6 +19,18 @@ Scenario: Resync
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 "kernelspecs--complete" Then I should see "kernelspecs--complete"
@stop
Scenario: Stop after closing notebook
Given I am in notebooklist buffer
And I click on "New Notebook"
And I switch to buffer like "Untitled"
And I press "C-x k"
And I am in notebooklist buffer
And I keep clicking "Resync" until "Stop"
And I click on "Stop"
And I switch to log expr "ein:log-all-buffer-name"
Then I should see "Deleted session"
@login @login
Scenario: No token server Scenario: No token server
Given I start the server configured "c.NotebookApp.token = u''\n" Given I start the server configured "c.NotebookApp.token = u''\n"

View file

@ -152,6 +152,14 @@
(ein:testing-flush-queries) (ein:testing-flush-queries)
(And "I wait 1 second"))) ;; eldoc-documentation-function not flushing (And "I wait 1 second"))) ;; eldoc-documentation-function not flushing
(When "^I keep clicking \"\\(.+\\)\" until \"\\(.+\\)\"$"
(lambda (go stop)
(loop repeat 10
until (search stop (buffer-string))
do (And "I click on \"Resync\"")
do (sleep-for 0 1000)
finally do (if (not (search stop (buffer-string))) (assert nil)))))
(When "^I click on \"\\(.+\\)\"$" (When "^I click on \"\\(.+\\)\"$"
(lambda (word) (lambda (word)
;; from espuds "go to word" without the '\\b's ;; from espuds "go to word" without the '\\b's

View file

@ -199,6 +199,12 @@ the log of the running jupyter server."
(if (and (not no-login-p) (ein:jupyter-server-process)) (if (and (not no-login-p) (ein:jupyter-server-process))
(ein:jupyter-server-login-and-open login-callback))))) (ein:jupyter-server-login-and-open login-callback)))))
;;;###autoload
(defalias 'ein:run 'ein:jupyter-server-start)
;;;###autoload
(defalias 'ein:stop 'ein:jupyter-server-stop)
;;;###autoload ;;;###autoload
(defun ein:jupyter-server-stop (&optional force log) (defun ein:jupyter-server-stop (&optional force log)
"Stop a running jupyter notebook server. "Stop a running jupyter notebook server.

View file

@ -645,7 +645,7 @@ We need this to have proper behavior for the 'Stop' command in the ein:notebookl
(ein:log 'info "Error, could not delete session %s." session-id)) (ein:log 'info "Error, could not delete session %s." session-id))
(defun ein:kernel-delete-session (kernel &optional callback) (defun ein:kernel-delete-session (kernel &optional callback)
"Regardless of success or error, we clear all state variables of kernel and funcall CALLBACK of arity 1, the 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))) (ein:and-let* ((session-id (ein:$kernel-session-id kernel)))
(ein:query-singleton-ajax (ein:query-singleton-ajax
(list 'kernel-delete-session session-id) (list 'kernel-delete-session session-id)

View file

@ -884,13 +884,16 @@ To close notebook without killing kernel, just close the buffer
as usual." as usual."
(interactive (list ein:%notebook%)) (interactive (list ein:%notebook%))
(when (or force (ein:notebook-ask-before-kill-buffer)) (when (or force (ein:notebook-ask-before-kill-buffer))
(let ((kernel (ein:$notebook-kernel notebook))) (let ((kernel (ein:$notebook-kernel notebook))
;; If kernel is live, kill it before closing. (callback (apply-partially
(lambda (notebook* kernel)
(ein:notebook-close notebook*))
notebook)))
(if (ein:kernel-live-p kernel) (if (ein:kernel-live-p kernel)
(ein:kernel-delete-session kernel (ein:message-whir "Ending session"
(lambda (kernel) (add-function :before callback done-callback)
(ein:notebook-close notebook))) (ein:kernel-delete-session kernel callback))
(ein:notebook-close notebook))))) (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

@ -848,9 +848,6 @@ See also:
;;;###autoload ;;;###autoload
(defalias 'ein:login 'ein:notebooklist-login) (defalias 'ein:login 'ein:notebooklist-login)
;;;###autoload
(defalias 'ein-login 'ein:notebooklist-login)
(defun ein:notebooklist-ask-one-cookie () (defun ein:notebooklist-ask-one-cookie ()
"If we need more than one cookie, we first need to ask for how many. Returns list of name and content." "If we need more than one cookie, we first need to ask for how many. Returns list of name and content."
(plist-put nil (intern (read-no-blanks-input "Cookie name: ")) (plist-put nil (intern (read-no-blanks-input "Cookie name: "))
@ -874,18 +871,15 @@ CALLBACK takes one argument, the buffer created by ein:notebooklist-open--succes
for line = (mapconcat #'identity (list domain "FALSE" (car (url-path-and-query parsed-url)) (if securep "TRUE" "FALSE") "0" (symbol-name name) (concat content "\n")) "\t") for line = (mapconcat #'identity (list domain "FALSE" (car (url-path-and-query parsed-url)) (if securep "TRUE" "FALSE") "0" (symbol-name name) (concat content "\n")) "\t")
do (write-region line nil (request--curl-cookie-jar) 'append)))) do (write-region line nil (request--curl-cookie-jar) 'append))))
(lexical-let* (done-p (ein:message-whir "Establishing session"
(done-callback (lambda (&rest ignore) (setf done-p t))) (let ((token (ein:notebooklist-token-or-password url-or-port)))
(errback (lambda (&rest ignore) (setf done-p 'error)))
(token (ein:notebooklist-token-or-password url-or-port)))
(add-function :before callback done-callback) (add-function :before callback done-callback)
(ein:message-whir "Establishing session" (lambda () done-p))
(cond ((null token) ;; don't know (cond ((null token) ;; don't know
(ein:notebooklist-login--iteration url-or-port callback errback nil -1 nil)) (ein:notebooklist-login--iteration url-or-port callback errback nil -1 nil))
((string= token "") ;; all authentication disabled ((string= token "") ;; all authentication disabled
(ein:log 'verbose "Skipping login %s" url-or-port) (ein:log 'verbose "Skipping login %s" url-or-port)
(ein:notebooklist-open* url-or-port nil nil callback errback)) (ein:notebooklist-open* url-or-port nil nil callback errback))
(t (ein:notebooklist-login--iteration url-or-port callback errback token 0 nil))))) (t (ein:notebooklist-login--iteration url-or-port callback errback token 0 nil))))))
(defun ein:notebooklist-login--parser () (defun ein:notebooklist-login--parser ()
(goto-char (point-min)) (goto-char (point-min))

View file

@ -604,8 +604,15 @@ otherwise it should be a function, which is called on `time'."
;;; Emacs utilities ;;; Emacs utilities
(defmacro ein:message-whir (mesg &rest body)
"Display MESG with a modest animation until ASYNC-CALL completes."
`(lexical-let* (done-p
(done-callback (lambda (&rest ignore) (setf done-p t)))
(errback (lambda (&rest ignore) (setf done-p 'error))))
(ein:message-whir-subr ,mesg (lambda () done-p))
,@body))
(defun ein:message-whir (mesg doneback) (defun ein:message-whir-subr (mesg doneback)
"Display MESG with a modest animation until done-p returns t. "Display MESG with a modest animation until done-p returns t.
DONEBACK returns t or 'error when calling process is done, and nil if not done." DONEBACK returns t or 'error when calling process is done, and nil if not done."

View file

@ -962,19 +962,10 @@ defined."
(with-current-buffer (ein:testing-notebook-make-new) (with-current-buffer (ein:testing-notebook-make-new)
(let ((buffer (current-buffer)) (let ((buffer (current-buffer))
(notebook ein:%notebook%) (notebook ein:%notebook%)
(kernel (ein:$notebook-kernel ein:%notebook%))
(ein:notebook-kill-buffer-ask nil)) (ein:notebook-kill-buffer-ask nil))
(mocker-let (cl-letf (((symbol-function 'ein:kernel-live-p) (lambda (&rest args) t))
((ein:kernel-live-p ((symbol-function 'ein:kernel-delete-session) (lambda (kernel callback) (funcall callback kernel))))
(kernel)
((:input (list kernel) :output t)))
(ein:kernel-delete-session
(kernel &optional callback)
((:input (list kernel (lambda (kernel) (ein:notebook-close notebook)))))))
(call-interactively #'ein:notebook-kill-kernel-then-close-command)) (call-interactively #'ein:notebook-kill-kernel-then-close-command))
(should (buffer-live-p buffer))
;; Pretend that `ein:notebook-close' is called.
(ein:notebook-close notebook)
(ein:testing-notebook-should-be-closed notebook buffer)))) (ein:testing-notebook-should-be-closed notebook buffer))))
(ert-deftest ein:notebook-kill-kernel-then-close-when-already-dead () (ert-deftest ein:notebook-kill-kernel-then-close-when-already-dead ()