From 6ca67523191a8dd23f9d898762ee4b8a676daa94 Mon Sep 17 00:00:00 2001 From: dickmao Date: Fri, 9 Nov 2018 13:02:43 -0500 Subject: [PATCH] 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 --- Makefile | 4 +--- features/notebooklist.feature | 12 ++++++++++++ features/step-definitions/ein-steps.el | 8 ++++++++ lisp/ein-jupyter.el | 6 ++++++ lisp/ein-kernel.el | 2 +- lisp/ein-notebook.el | 15 +++++++++------ lisp/ein-notebooklist.el | 24 +++++++++--------------- lisp/ein-utils.el | 9 ++++++++- test/test-ein-notebook.el | 13 ++----------- 9 files changed, 56 insertions(+), 37 deletions(-) diff --git a/Makefile b/Makefile index 2bb4c1c..62e2914 100644 --- a/Makefile +++ b/Makefile @@ -20,9 +20,7 @@ autoloads: .PHONY: clean clean: cask clean-elc - -env-ipy.%: - tools/makeenv.sh env/ipy.$* tools/requirement-ipy.$*.txt + rm -rf test/test-install .PHONY: test-compile test-compile: clean autoloads diff --git a/features/notebooklist.feature b/features/notebooklist.feature index 737264b..e09452e 100644 --- a/features/notebooklist.feature +++ b/features/notebooklist.feature @@ -19,6 +19,18 @@ Scenario: Resync And I switch to log expr "ein:log-all-buffer-name" 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 Scenario: No token server Given I start the server configured "c.NotebookApp.token = u''\n" diff --git a/features/step-definitions/ein-steps.el b/features/step-definitions/ein-steps.el index 12436e9..6e2f11f 100644 --- a/features/step-definitions/ein-steps.el +++ b/features/step-definitions/ein-steps.el @@ -152,6 +152,14 @@ (ein:testing-flush-queries) (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 \"\\(.+\\)\"$" (lambda (word) ;; from espuds "go to word" without the '\\b's diff --git a/lisp/ein-jupyter.el b/lisp/ein-jupyter.el index 6ef3943..e66126b 100644 --- a/lisp/ein-jupyter.el +++ b/lisp/ein-jupyter.el @@ -199,6 +199,12 @@ the log of the running jupyter server." (if (and (not no-login-p) (ein:jupyter-server-process)) (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 (defun ein:jupyter-server-stop (&optional force log) "Stop a running jupyter notebook server. diff --git a/lisp/ein-kernel.el b/lisp/ein-kernel.el index ec9104f..c16968e 100644 --- a/lisp/ein-kernel.el +++ b/lisp/ein-kernel.el @@ -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)) (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:query-singleton-ajax (list 'kernel-delete-session session-id) diff --git a/lisp/ein-notebook.el b/lisp/ein-notebook.el index 63cda46..f88e17a 100644 --- a/lisp/ein-notebook.el +++ b/lisp/ein-notebook.el @@ -884,13 +884,16 @@ To close notebook without killing kernel, just close the buffer as usual." (interactive (list ein:%notebook%)) (when (or force (ein:notebook-ask-before-kill-buffer)) - (let ((kernel (ein:$notebook-kernel notebook))) - ;; If kernel is live, kill it before closing. + (let ((kernel (ein:$notebook-kernel notebook)) + (callback (apply-partially + (lambda (notebook* kernel) + (ein:notebook-close notebook*)) + notebook))) (if (ein:kernel-live-p kernel) - (ein:kernel-delete-session kernel - (lambda (kernel) - (ein:notebook-close notebook))) - (ein:notebook-close notebook))))) + (ein:message-whir "Ending session" + (add-function :before callback done-callback) + (ein:kernel-delete-session kernel callback)) + (funcall callback nil))))) (defun ein:fast-content-from-notebook (notebook) "Quickly generate a basic content structure from notebook. This diff --git a/lisp/ein-notebooklist.el b/lisp/ein-notebooklist.el index 67379f6..4595de1 100644 --- a/lisp/ein-notebooklist.el +++ b/lisp/ein-notebooklist.el @@ -848,9 +848,6 @@ See also: ;;;###autoload (defalias 'ein:login 'ein:notebooklist-login) -;;;###autoload -(defalias 'ein-login 'ein:notebooklist-login) - (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." (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") do (write-region line nil (request--curl-cookie-jar) 'append)))) - (lexical-let* (done-p - (done-callback (lambda (&rest ignore) (setf done-p t))) - (errback (lambda (&rest ignore) (setf done-p 'error))) - (token (ein:notebooklist-token-or-password url-or-port))) - (add-function :before callback done-callback) - (ein:message-whir "Establishing session" (lambda () done-p)) - (cond ((null token) ;; don't know - (ein:notebooklist-login--iteration url-or-port callback errback nil -1 nil)) - ((string= token "") ;; all authentication disabled - (ein:log 'verbose "Skipping login %s" url-or-port) - (ein:notebooklist-open* url-or-port nil nil callback errback)) - (t (ein:notebooklist-login--iteration url-or-port callback errback token 0 nil))))) + (ein:message-whir "Establishing session" + (let ((token (ein:notebooklist-token-or-password url-or-port))) + (add-function :before callback done-callback) + (cond ((null token) ;; don't know + (ein:notebooklist-login--iteration url-or-port callback errback nil -1 nil)) + ((string= token "") ;; all authentication disabled + (ein:log 'verbose "Skipping login %s" url-or-port) + (ein:notebooklist-open* url-or-port nil nil callback errback)) + (t (ein:notebooklist-login--iteration url-or-port callback errback token 0 nil)))))) (defun ein:notebooklist-login--parser () (goto-char (point-min)) diff --git a/lisp/ein-utils.el b/lisp/ein-utils.el index d4a82f7..b7abc9e 100644 --- a/lisp/ein-utils.el +++ b/lisp/ein-utils.el @@ -604,8 +604,15 @@ otherwise it should be a function, which is called on `time'." ;;; 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. DONEBACK returns t or 'error when calling process is done, and nil if not done." diff --git a/test/test-ein-notebook.el b/test/test-ein-notebook.el index 86cfdf1..2330b9d 100644 --- a/test/test-ein-notebook.el +++ b/test/test-ein-notebook.el @@ -962,19 +962,10 @@ defined." (with-current-buffer (ein:testing-notebook-make-new) (let ((buffer (current-buffer)) (notebook ein:%notebook%) - (kernel (ein:$notebook-kernel ein:%notebook%)) (ein:notebook-kill-buffer-ask nil)) - (mocker-let - ((ein:kernel-live-p - (kernel) - ((:input (list kernel) :output t))) - (ein:kernel-delete-session - (kernel &optional callback) - ((:input (list kernel (lambda (kernel) (ein:notebook-close notebook))))))) + (cl-letf (((symbol-function 'ein:kernel-live-p) (lambda (&rest args) t)) + ((symbol-function 'ein:kernel-delete-session) (lambda (kernel callback) (funcall callback kernel)))) (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)))) (ert-deftest ein:notebook-kill-kernel-then-close-when-already-dead ()