Add new customizable variable jupyter-repl-echo-eval-p

Closes #71
This commit is contained in:
Nathaniel Nicandro 2019-05-21 16:45:44 -05:00 committed by Nathaniel Nicandro
parent 6289e23c61
commit 40ee1ac8b9
3 changed files with 97 additions and 0 deletions

View file

@ -298,6 +298,16 @@ If non-nil, allow inserting a newline in a REPL cell whenever the kernel is
busy. Normally this isn't allowed since the REPL relies on the kernel
responding to messages when =RET= is pressed, but a kernel does not respond to
messages when it is busy.
*** =jupyter-repl-echo-eval-p=
If non-nil, when evaluating code using the =jupyter-eval-*= functions
like =M-x jupyter-eval-line-or-region=, copy the evaluated code as a REPL input
cell and display any output generated in the REPL. When this variable is nil,
copying to the REPL does not occur and output/results are inserted in pop-up
buffers or added to the =*Messages*= buffer according to
=jupyter-eval-short-result-max-lines= and
=jupyter-eval-short-result-display-function=.
*** Widget support
There is also support for Jupyter widgets integrated into the REPL. If any of

View file

@ -142,6 +142,20 @@ send the code to the kernel."
:type 'boolean
:group 'jupyter-repl)
(defcustom jupyter-repl-echo-eval-p nil
"Copy evaluation input to a REPL cell if non-nil.
If non-nil, and when calling the `jupyter-eval-*' functions like
`jupyter-eval-line-or-region', copy the input into a REPL cell.
Otherwise the evaluation request is sent to the kernel without
displaying the code of the request in the REPL.
Note, output generated by requests will always be sent to the
REPL buffer whenever this variable is non-nil. When the REPL
buffer isn't visible, output will also be sent to pop-up buffers
as is done when this variable is nil."
:type 'boolean
:group 'jupyter-repl)
;;; Implementation
(defclass jupyter-repl-client (jupyter-widget-client jupyter-kernel-client)
@ -1409,6 +1423,30 @@ value."
(prog1 ex
(jupyter-repl-history-add ex)))))
(cl-defmethod jupyter-eval-string (str
&context (jupyter-current-client jupyter-repl-client)
&optional cb)
(jupyter-with-repl-buffer jupyter-current-client
(when jupyter-repl-echo-eval-p
(goto-char (point-max))
(jupyter-repl-replace-cell-code str)
(setq str nil))
(let* ((jupyter-inhibit-handlers
;; When copying the input to the REPL we need the handlers to
;; update the REPL state
(unless jupyter-repl-echo-eval-p
'(not :input-request)))
(req (jupyter-send-execute-request jupyter-current-client
:code str
:store-history jupyter-repl-echo-eval-p)))
(prog1 req
;; Add callbacks to display evaluation output in pop-up buffers either
;; when we aren't copying the input to a REPL cell or, if we are, when
;; the REPL buffer isn't visible
(unless (and jupyter-repl-echo-eval-p
(get-buffer-window nil 'visible))
(jupyter-eval-add-callbacks req cb))))))
;;; Kernel management
(defun jupyter-repl-interrupt-kernel ()

View file

@ -1642,6 +1642,55 @@ last element being the newest element added to the history."
(let ((kill-buffer-query-functions nil))
(kill-buffer)))))))
(ert-deftest jupyter-repl-echo-eval-p ()
:tags '(repl)
(jupyter-test-with-python-repl client
(jupyter-ert-info ("Copying input")
(let ((jupyter-repl-echo-eval-p t))
(should (equal (jupyter-repl-cell-code) ""))
(let ((req (jupyter-eval-string "1 + 1")))
(should-not (jupyter-request-inhibited-handlers req))
(jupyter-wait-until-idle req)
(jupyter-repl-goto-cell req)
(should (equal (jupyter-repl-cell-code) "1 + 1")))))
(jupyter-ert-info ("Not copying input")
(let ((jupyter-repl-echo-eval-p nil))
(should (equal (jupyter-repl-cell-code) ""))
(let ((req (jupyter-eval-string "1 + 1")))
(should (jupyter-request-inhibited-handlers req))
(jupyter-wait-until-idle req)
(should-error (jupyter-repl-goto-cell req)))))
(ert-info ("Add callbacks when REPL buffer is invisible")
(cl-letf (((symbol-function #'get-buffer-window)
(lambda (&rest _) nil)))
(ert-info ("`jupyter-repl-echo-eval-p' = t")
(let* ((jupyter-repl-echo-eval-p t)
(req (jupyter-eval-string "1 + 1")))
(should-not (jupyter-request-inhibited-handlers req))
(should (jupyter-request-callbacks req))
(jupyter-wait-until-idle req)))
(ert-info ("`jupyter-repl-echo-eval-p' = nil")
(let* ((jupyter-repl-echo-eval-p nil)
(req (jupyter-eval-string "1 + 1")))
(should (jupyter-request-inhibited-handlers req))
(should (jupyter-request-callbacks req))
(jupyter-wait-until-idle req)))))
(ert-info ("No callbacks when REPL buffer visible")
(cl-letf (((symbol-function #'get-buffer-window)
(lambda (&rest _) (selected-window))))
(ert-info ("`jupyter-repl-echo-eval-p' = t")
(let* ((jupyter-repl-echo-eval-p t)
(req (jupyter-eval-string "1 + 1")))
(should-not (jupyter-request-inhibited-handlers req))
(should-not (jupyter-request-callbacks req))
(jupyter-wait-until-idle req)))
(ert-info ("`jupyter-repl-echo-eval-p' = nil")
(let* ((jupyter-repl-echo-eval-p nil)
(req (jupyter-eval-string "1 + 1")))
(should (jupyter-request-inhibited-handlers req))
(should (jupyter-request-callbacks req))
(jupyter-wait-until-idle req)))))))
;;; `org-mode'
(defvar org-babel-jupyter-resource-directory nil)