mirror of
https://github.com/vale981/emacs-jupyter
synced 2025-03-05 23:41:38 -05:00
Add jupyter-reply-message
This commit is contained in:
parent
52847c2f51
commit
c1bff794d0
5 changed files with 121 additions and 131 deletions
|
@ -1182,52 +1182,49 @@ DETAIL is the detail level to use for the request and defaults to
|
|||
(object-of-class-p jupyter-current-client 'jupyter-kernel-client))
|
||||
(error "Need a valid `jupyter-current-client'"))
|
||||
(condition-case nil
|
||||
(jupyter-mlet* ((msgs
|
||||
(jupyter-messages
|
||||
(jupyter-inspect-request
|
||||
:code code
|
||||
:pos pos
|
||||
:detail detail)
|
||||
jupyter-long-timeout)))
|
||||
(when-let* ((msg (jupyter-find-message "inspect_reply" msgs)))
|
||||
(jupyter-with-message-content msg
|
||||
(status found)
|
||||
(if (and (equal status "ok") (eq found t))
|
||||
(let ((inhibit-read-only t))
|
||||
(if (buffer-live-p buffer)
|
||||
(with-current-buffer buffer
|
||||
;; Insert MSG here so that `jupyter-insert'
|
||||
;; has access to the message type. This is
|
||||
;; needed since the python kernel and others
|
||||
;; may use this information.
|
||||
(jupyter-insert msg)
|
||||
(current-buffer))
|
||||
(with-help-window (help-buffer)
|
||||
(with-current-buffer standard-output
|
||||
(setq other-window-scroll-buffer (current-buffer))
|
||||
(setq jupyter-current-client client)
|
||||
(help-setup-xref
|
||||
(list
|
||||
;; Don't capture a strong reference to the
|
||||
;; client object since we don't know when
|
||||
;; this reference will be cleaned up.
|
||||
(let ((ref (jupyter-weak-ref client)))
|
||||
(lambda ()
|
||||
(let ((jupyter-current-client
|
||||
(jupyter-weak-ref-resolve ref)))
|
||||
(if jupyter-current-client
|
||||
(jupyter-inspect code pos nil detail)
|
||||
;; TODO: Skip over this xref, need
|
||||
;; to figure out if going forward or
|
||||
;; backward first.
|
||||
(error "Client has been removed"))))))
|
||||
nil)
|
||||
(jupyter-insert msg)))))
|
||||
(message "Nothing found for %s"
|
||||
(with-temp-buffer
|
||||
(insert code)
|
||||
(goto-char pos)
|
||||
(symbol-at-point)))))))
|
||||
(jupyter-mlet* ((msg (jupyter-reply-message
|
||||
(jupyter-inspect-request
|
||||
:code code
|
||||
:pos pos
|
||||
:detail detail))))
|
||||
(jupyter-with-message-content msg
|
||||
(status found)
|
||||
(if (and (equal status "ok") (eq found t))
|
||||
(let ((inhibit-read-only t))
|
||||
(if (buffer-live-p buffer)
|
||||
(with-current-buffer buffer
|
||||
;; Insert MSG here so that `jupyter-insert'
|
||||
;; has access to the message type. This is
|
||||
;; needed since the python kernel and others
|
||||
;; may use this information.
|
||||
(jupyter-insert msg)
|
||||
(current-buffer))
|
||||
(with-help-window (help-buffer)
|
||||
(with-current-buffer standard-output
|
||||
(setq other-window-scroll-buffer (current-buffer))
|
||||
(setq jupyter-current-client client)
|
||||
(help-setup-xref
|
||||
(list
|
||||
;; Don't capture a strong reference to the
|
||||
;; client object since we don't know when
|
||||
;; this reference will be cleaned up.
|
||||
(let ((ref (jupyter-weak-ref client)))
|
||||
(lambda ()
|
||||
(let ((jupyter-current-client
|
||||
(jupyter-weak-ref-resolve ref)))
|
||||
(if jupyter-current-client
|
||||
(jupyter-inspect code pos nil detail)
|
||||
;; TODO: Skip over this xref, need
|
||||
;; to figure out if going forward or
|
||||
;; backward first.
|
||||
(error "Client has been removed"))))))
|
||||
nil)
|
||||
(jupyter-insert msg)))))
|
||||
(message "Nothing found for %s"
|
||||
(with-temp-buffer
|
||||
(insert code)
|
||||
(goto-char pos)
|
||||
(symbol-at-point))))))
|
||||
(jupyter-timeout-before-idle
|
||||
(message "Inspect timed out"))))
|
||||
|
||||
|
@ -1686,19 +1683,18 @@ name are changed to \"-\" and all uppercase characters lowered."
|
|||
(progn
|
||||
(message "Requesting kernel info...")
|
||||
(let ((jupyter-current-client client))
|
||||
(jupyter-mlet* ((msgs (jupyter-messages
|
||||
(jupyter-kernel-info-request
|
||||
:handlers nil)
|
||||
(* 3 jupyter-long-timeout))))
|
||||
(jupyter-mlet* ((msg (jupyter-reply-message
|
||||
(jupyter-kernel-info-request
|
||||
:handlers nil)
|
||||
(* 3 jupyter-long-timeout))))
|
||||
(message "Requesting kernel info...done")
|
||||
(let ((msg (jupyter-find-message "kernel_info_reply" msgs)))
|
||||
(oset client kernel-info (jupyter-message-content msg))
|
||||
;; Canonicalize language name to a language symbol for
|
||||
;; method dispatching
|
||||
(let* ((info (plist-get (oref client kernel-info) :language_info))
|
||||
(lang (plist-get info :name))
|
||||
(name (jupyter-canonicalize-language-string lang)))
|
||||
(plist-put info :name (intern name))))))
|
||||
(oset client kernel-info (jupyter-message-content msg))
|
||||
;; Canonicalize language name to a language symbol for
|
||||
;; method dispatching
|
||||
(let* ((info (plist-get (oref client kernel-info) :language_info))
|
||||
(lang (plist-get info :name))
|
||||
(name (jupyter-canonicalize-language-string lang)))
|
||||
(plist-put info :name (intern name)))))
|
||||
(oref client kernel-info))))
|
||||
|
||||
(defun jupyter-kernel-language-mode-properties (client)
|
||||
|
|
|
@ -122,19 +122,18 @@ Make the character after `point' invisible."
|
|||
If the Pkg prompt can't be retrieved from the kernel, return
|
||||
nil."
|
||||
(let ((prompt-code "import Pkg; Pkg.REPLMode.promptf()"))
|
||||
(jupyter-mlet* ((msgs
|
||||
(jupyter-messages
|
||||
(jupyter-mlet* ((msg
|
||||
(jupyter-reply-message
|
||||
(jupyter-execute-request
|
||||
:code ""
|
||||
:silent t
|
||||
:user-expressions (list :prompt prompt-code)))))
|
||||
(when-let* ((msg (jupyter-find-message "execute_reply" msgs)))
|
||||
(cl-destructuring-bind (&key prompt &allow-other-keys)
|
||||
(jupyter-message-get msg :user_expressions)
|
||||
(cl-destructuring-bind (&key status data &allow-other-keys)
|
||||
prompt
|
||||
(when (equal status "ok")
|
||||
(plist-get data :text/plain))))))))
|
||||
(cl-destructuring-bind (&key prompt &allow-other-keys)
|
||||
(jupyter-message-get msg :user_expressions)
|
||||
(cl-destructuring-bind (&key status data &allow-other-keys)
|
||||
prompt
|
||||
(when (equal status "ok")
|
||||
(plist-get data :text/plain)))))))
|
||||
|
||||
(cl-defmethod jupyter-repl-after-change ((_type (eql insert)) beg _end
|
||||
&context (jupyter-lang julia))
|
||||
|
|
|
@ -415,12 +415,15 @@ when it is idle."
|
|||
(string= type msg-type)))
|
||||
msgs))
|
||||
|
||||
(defun jupyter-reply-message (msgs)
|
||||
(cl-find-if
|
||||
(lambda (msg)
|
||||
(let ((type (jupyter-message-type msg)))
|
||||
(string-suffix-p "_reply" type)))
|
||||
msgs))
|
||||
(defun jupyter-reply-message (io-req &optional timeout)
|
||||
(make-jupyter-delayed
|
||||
:value (lambda ()
|
||||
(jupyter-mlet* ((msgs (jupyter-messages io-req timeout)))
|
||||
(cl-find-if
|
||||
(lambda (msg)
|
||||
(let ((type (jupyter-message-type msg)))
|
||||
(string-suffix-p "_reply" type)))
|
||||
msgs)))))
|
||||
|
||||
(defun jupyter-message-subscribed (io-req cbs)
|
||||
(make-jupyter-delayed
|
||||
|
|
|
@ -1792,28 +1792,27 @@ it."
|
|||
"Synchronize the `jupyter-current-client's kernel state.
|
||||
Also update the cell count of the current REPL input prompt using
|
||||
the updated state."
|
||||
(jupyter-mlet* ((msgs (jupyter-messages
|
||||
(jupyter-execute-request
|
||||
:code ""
|
||||
:silent t
|
||||
:handlers nil)
|
||||
;; Waiting longer here to account for initial
|
||||
;; startup of the Jupyter kernel. Sometimes
|
||||
;; the idle message won't be received if
|
||||
;; another long running execute request is
|
||||
;; sent right after.
|
||||
jupyter-long-timeout)))
|
||||
(when-let* ((msg (jupyter-find-message "execute_reply" msgs)))
|
||||
(jupyter-with-message-content msg (execution_count)
|
||||
(let ((client jupyter-current-client))
|
||||
(oset client execution-count (1+ execution_count))
|
||||
(unless (equal (jupyter-execution-state client) "busy")
|
||||
;; Set the cell count and update the prompt
|
||||
(jupyter-with-repl-buffer client
|
||||
(save-excursion
|
||||
(goto-char (point-max))
|
||||
(jupyter-repl-update-cell-count
|
||||
(oref client execution-count))))))))))
|
||||
(jupyter-mlet* ((msg (jupyter-reply-message
|
||||
(jupyter-execute-request
|
||||
:code ""
|
||||
:silent t
|
||||
:handlers nil)
|
||||
;; Waiting longer here to account for initial
|
||||
;; startup of the Jupyter kernel. Sometimes
|
||||
;; the idle message won't be received if
|
||||
;; another long running execute request is
|
||||
;; sent right after.
|
||||
jupyter-long-timeout)))
|
||||
(jupyter-with-message-content msg (execution_count)
|
||||
(let ((client jupyter-current-client))
|
||||
(oset client execution-count (1+ execution_count))
|
||||
(unless (equal (jupyter-execution-state client) "busy")
|
||||
;; Set the cell count and update the prompt
|
||||
(jupyter-with-repl-buffer client
|
||||
(save-excursion
|
||||
(goto-char (point-max))
|
||||
(jupyter-repl-update-cell-count
|
||||
(oref client execution-count)))))))))
|
||||
|
||||
;;; `jupyter-repl-interaction-mode'
|
||||
|
||||
|
|
|
@ -382,26 +382,23 @@
|
|||
:tags '(client messages)
|
||||
(jupyter-test-with-python-client client
|
||||
(ert-info ("Kernel info")
|
||||
(jupyter-mlet* ((msgs (jupyter-messages
|
||||
(jupyter-mlet* ((res (jupyter-reply-message
|
||||
(jupyter-kernel-info-request))))
|
||||
(let ((res (jupyter-reply-message msgs)))
|
||||
(should res)
|
||||
(should (json-plist-p res))
|
||||
(should (string= (jupyter-message-type res) "kernel_info_reply")))))
|
||||
(should res)
|
||||
(should (json-plist-p res))
|
||||
(should (string= (jupyter-message-type res) "kernel_info_reply"))))
|
||||
(ert-info ("Comm info")
|
||||
(jupyter-mlet* ((msgs (jupyter-messages
|
||||
(jupyter-comm-info-request))))
|
||||
(let ((res (jupyter-reply-message msgs)))
|
||||
(should-not (null res))
|
||||
(should (json-plist-p res))
|
||||
(should (string= (jupyter-message-type res) "comm_info_reply")))))
|
||||
(jupyter-mlet* ((res (jupyter-reply-message
|
||||
(jupyter-comm-info-request))))
|
||||
(should-not (null res))
|
||||
(should (json-plist-p res))
|
||||
(should (string= (jupyter-message-type res) "comm_info_reply"))))
|
||||
(ert-info ("Execute")
|
||||
(jupyter-mlet* ((msgs (jupyter-messages
|
||||
(jupyter-mlet* ((res (jupyter-reply-message
|
||||
(jupyter-execute-request :code "y = 1 + 2"))))
|
||||
(let ((res (jupyter-reply-message msgs)))
|
||||
(should-not (null res))
|
||||
(should (json-plist-p res))
|
||||
(should (string= (jupyter-message-type res) "execute_reply")))))
|
||||
(should-not (null res))
|
||||
(should (json-plist-p res))
|
||||
(should (string= (jupyter-message-type res) "execute_reply"))))
|
||||
(ert-info ("Input")
|
||||
(cl-letf (((symbol-function 'read-from-minibuffer)
|
||||
(lambda (_prompt &rest _args) "foo")))
|
||||
|
@ -414,40 +411,36 @@
|
|||
(should (string= (jupyter-message-type res) "execute_result"))
|
||||
(should (equal (jupyter-message-data res :text/plain) "'foo'"))))))
|
||||
(ert-info ("Inspect")
|
||||
(jupyter-mlet* ((msgs (jupyter-messages
|
||||
(jupyter-mlet* ((res (jupyter-reply-message
|
||||
(jupyter-inspect-request
|
||||
:code "list((1, 2, 3))"
|
||||
:pos 2
|
||||
:detail 0))))
|
||||
(let ((res (jupyter-reply-message msgs)))
|
||||
(should-not (null res))
|
||||
(should (json-plist-p res))
|
||||
(should (string= (jupyter-message-type res) "inspect_reply")))))
|
||||
(should-not (null res))
|
||||
(should (json-plist-p res))
|
||||
(should (string= (jupyter-message-type res) "inspect_reply"))))
|
||||
(ert-info ("Complete")
|
||||
(jupyter-mlet* ((msgs (jupyter-messages
|
||||
(jupyter-mlet* ((res (jupyter-reply-message
|
||||
(jupyter-complete-request
|
||||
:code "foo = lis"
|
||||
:pos 8))))
|
||||
(let ((res (jupyter-reply-message msgs)))
|
||||
(should-not (null res))
|
||||
(should (json-plist-p res))
|
||||
(should (string= (jupyter-message-type res) "complete_reply")))))
|
||||
(should-not (null res))
|
||||
(should (json-plist-p res))
|
||||
(should (string= (jupyter-message-type res) "complete_reply"))))
|
||||
(ert-info ("History")
|
||||
(jupyter-mlet* ((msgs (jupyter-messages
|
||||
(jupyter-mlet* ((msgs (jupyter-reply-message
|
||||
(jupyter-history-request
|
||||
:hist-access-type "tail" :n 2))))
|
||||
(let ((res (jupyter-reply-message msgs)))
|
||||
(should-not (null res))
|
||||
(should (json-plist-p res))
|
||||
(should (string= (jupyter-message-type res) "history_reply")))))
|
||||
(should-not (null res))
|
||||
(should (json-plist-p res))
|
||||
(should (string= (jupyter-message-type res) "history_reply"))))
|
||||
(ert-info ("Is Complete")
|
||||
(jupyter-mlet* ((msgs (jupyter-messages
|
||||
(jupyter-mlet* ((msgs (jupyter-reply-message
|
||||
(jupyter-is-complete-request
|
||||
:code "for i in range(5):"))))
|
||||
(let ((res (jupyter-reply-message msgs)))
|
||||
(should-not (null res))
|
||||
(should (json-plist-p res))
|
||||
(should (string= (jupyter-message-type res) "is_complete_reply")))))
|
||||
(should-not (null res))
|
||||
(should (json-plist-p res))
|
||||
(should (string= (jupyter-message-type res) "is_complete_reply"))))
|
||||
;; TODO: Why does this fail now?
|
||||
;; (ert-info ("Shutdown")
|
||||
;; (let ((res (jupyter-wait-until-received "shutdown_reply"
|
||||
|
|
Loading…
Add table
Reference in a new issue