mirror of
https://github.com/vale981/emacs-jupyter
synced 2025-03-05 07:41:37 -05:00
Add jupyter-message-lambda
This simplifies the writing of message callbacks.
This commit is contained in:
parent
1054dc8857
commit
d709b31a64
4 changed files with 122 additions and 72 deletions
|
@ -978,10 +978,9 @@ text/plain representation."
|
|||
(prog1 req
|
||||
(jupyter-add-callback req
|
||||
:execute-reply
|
||||
(lambda (msg)
|
||||
(jupyter-with-message-content msg (status evalue)
|
||||
(jupyter-message-lambda (status evalue)
|
||||
(unless (equal status "ok")
|
||||
(error "%s" (ansi-color-apply evalue)))))))))))
|
||||
(error "%s" (ansi-color-apply evalue))))))))))
|
||||
(when msg
|
||||
(jupyter-message-data msg (or mime :text/plain)))))
|
||||
|
||||
|
@ -1006,29 +1005,29 @@ to the above explanation."
|
|||
(had-result nil))
|
||||
(jupyter-add-callback req
|
||||
:execute-reply
|
||||
(lambda (msg)
|
||||
(jupyter-with-message-content msg (status ename evalue)
|
||||
(jupyter-message-lambda (status ename evalue)
|
||||
(if (equal status "ok")
|
||||
(unless had-result
|
||||
(message "jupyter: eval done"))
|
||||
(message "%s: %s"
|
||||
(ansi-color-apply ename)
|
||||
(ansi-color-apply evalue)))))
|
||||
(setq ename (ansi-color-apply ename))
|
||||
(setq evalue (ansi-color-apply evalue))
|
||||
(if (string-prefix-p ename evalue)
|
||||
;; Happens in IJulia
|
||||
(message evalue)
|
||||
(message "%s: %s" ename evalue))))
|
||||
:execute-result
|
||||
(or (and (functionp cb) cb)
|
||||
(lambda (msg)
|
||||
(setq had-result t)
|
||||
(jupyter--display-eval-result msg)))
|
||||
:error
|
||||
(lambda (msg)
|
||||
(jupyter-with-message-content msg (traceback)
|
||||
(jupyter-message-lambda (traceback)
|
||||
;; FIXME: Assumes the error in the
|
||||
;; execute-reply is good enough
|
||||
(when (> (apply '+ (mapcar 'length traceback)) 250)
|
||||
(jupyter-display-traceback traceback))))
|
||||
(jupyter-display-traceback traceback)))
|
||||
:stream
|
||||
(lambda (msg)
|
||||
(jupyter-with-message-content msg (name text)
|
||||
(jupyter-message-lambda (name text)
|
||||
(pcase name
|
||||
("stdout"
|
||||
(jupyter-with-display-buffer "output" req
|
||||
|
@ -1039,7 +1038,7 @@ to the above explanation."
|
|||
(jupyter-with-display-buffer "error" req
|
||||
(jupyter-insert-ansi-coded-text text)
|
||||
(display-buffer (current-buffer)
|
||||
'(display-buffer-below-selected))))))))
|
||||
'(display-buffer-below-selected)))))))
|
||||
req))
|
||||
|
||||
(defun jupyter-eval-region (beg end &optional cb)
|
||||
|
@ -1050,8 +1049,22 @@ ignored when called interactively."
|
|||
(interactive "r")
|
||||
(jupyter-eval-string (buffer-substring-no-properties beg end) cb))
|
||||
|
||||
(defun jupyter-eval--insert-result (pos region msg)
|
||||
(jupyter-with-message-data msg ((res text/plain))
|
||||
(defun jupyter-eval-line-or-region (insert)
|
||||
"Evaluate the current line or region with the `jupyter-current-client'.
|
||||
If the current region is active send it using
|
||||
`jupyter-eval-region', otherwise send the current line.
|
||||
|
||||
With a prefix argument, evaluate and INSERT the text/plain
|
||||
representation of the results in the current buffer."
|
||||
(interactive "P")
|
||||
(let ((region (when (use-region-p)
|
||||
(car (region-bounds)))))
|
||||
(funcall #'jupyter-eval-region
|
||||
(or (car region) (line-beginning-position))
|
||||
(or (cdr region) (line-end-position))
|
||||
(when insert
|
||||
(let ((pos (point-marker)))
|
||||
(jupyter-message-lambda ((res text/plain))
|
||||
(when res
|
||||
(setq res (ansi-color-apply res))
|
||||
(with-current-buffer (marker-buffer pos)
|
||||
|
@ -1066,24 +1079,7 @@ ignored when called interactively."
|
|||
(insert "\n")))
|
||||
(set-marker pos nil)
|
||||
(insert res)
|
||||
(when region (push-mark)))))))
|
||||
|
||||
(defun jupyter-eval-line-or-region (insert)
|
||||
"Evaluate the current line or region with the `jupyter-current-client'.
|
||||
If the current region is active send it using
|
||||
`jupyter-eval-region', otherwise send the current line.
|
||||
|
||||
With a prefix argument, evaluate and INSERT the text/plain
|
||||
representation of the results in the current buffer."
|
||||
(interactive "P")
|
||||
(let ((cb (when insert
|
||||
(apply-partially
|
||||
#'jupyter-eval--insert-result
|
||||
(point-marker) (when (use-region-p)
|
||||
(car (region-bounds)))))))
|
||||
(if (use-region-p)
|
||||
(jupyter-eval-region (region-beginning) (region-end) cb)
|
||||
(jupyter-eval-region (line-beginning-position) (line-end-position) cb))))
|
||||
(when region (push-mark)))))))))))
|
||||
|
||||
(defun jupyter-load-file (file)
|
||||
"Send the contents of FILE using `jupyter-current-client'."
|
||||
|
|
|
@ -453,9 +453,11 @@ So to bind the :status key of MSG you would do
|
|||
(jupyter-with-message-content msg (status)
|
||||
BODY)"
|
||||
(declare (indent 2) (debug (form listp body)))
|
||||
(if keys
|
||||
`(cl-destructuring-bind (&key ,@keys &allow-other-keys)
|
||||
(jupyter-message-content ,msg)
|
||||
,@body))
|
||||
,@body)
|
||||
`(progn ,@body)))
|
||||
|
||||
(defmacro jupyter-with-message-data (msg varlist &rest body)
|
||||
"For MSG, bind the mimetypes in VARLIST and evaluate BODY.
|
||||
|
@ -477,8 +479,42 @@ you would do
|
|||
,m ',(if (keywordp (cadr el)) (cadr el)
|
||||
(intern (concat ":" (symbol-name (cadr el))))))))
|
||||
varlist)))
|
||||
`(let* ((,m ,msg) ,@vars)
|
||||
(if vars `(let* ((,m ,msg) ,@vars)
|
||||
,@body)
|
||||
`(progn ,@body))))
|
||||
|
||||
(defmacro jupyter-message-lambda (keys &rest body)
|
||||
"Return a function binding KEYS to fields of a message then evaluating BODY.
|
||||
The returned function takes a single argument which is expected
|
||||
to be a Jupyter message property list.
|
||||
|
||||
The elements of KEYS can either be a symbol, KEY, or a two
|
||||
element list (VAL MIMETYPE). In the former case, KEY will be
|
||||
bound to the corresponding value of KEY in the
|
||||
`jupyter-message-content' of the message argument. In the latter
|
||||
case, VAL will be bound to the value of the MIMETYPE found in the
|
||||
`jupyter-message-data' of the message."
|
||||
(declare (indent defun) (debug ((&rest [&or symbolp (symbolp symbolp)]) body)))
|
||||
(let ((msg (cl-gensym "msg"))
|
||||
content-keys
|
||||
data-keys)
|
||||
(while (car keys)
|
||||
(let ((key (pop keys)))
|
||||
(push key (if (listp key) data-keys content-keys))))
|
||||
`(lambda (,msg)
|
||||
,(cond
|
||||
((and data-keys content-keys)
|
||||
`(jupyter-with-message-content ,msg ,content-keys
|
||||
(jupyter-with-message-data ,msg ,data-keys
|
||||
,@body)))
|
||||
(data-keys
|
||||
`(jupyter-with-message-data ,msg ,data-keys
|
||||
,@body))
|
||||
(content-keys
|
||||
`(jupyter-with-message-content ,msg ,content-keys
|
||||
,@body))
|
||||
(t
|
||||
`(progn ,@body))))))
|
||||
|
||||
(defmacro jupyter--decode-message-part (key msg)
|
||||
"Return a form to decode the value of KEY in MSG.
|
||||
|
|
|
@ -1533,9 +1533,9 @@ it."
|
|||
(req (let ((jupyter-inhibit-handlers t))
|
||||
(jupyter-send-execute-request client :code "" :silent t))))
|
||||
(jupyter-add-callback req
|
||||
:execute-reply (lambda (msg)
|
||||
(oset client execution-count
|
||||
(1+ (jupyter-message-get msg :execution_count)))
|
||||
:execute-reply
|
||||
(jupyter-message-lambda (execution_count)
|
||||
(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
|
||||
|
|
|
@ -406,6 +406,24 @@
|
|||
(should (json-plist-p res))
|
||||
(should (eq (jupyter-message-type res) :shutdown-reply))))))
|
||||
|
||||
(ert-deftest jupyter-message-lambda ()
|
||||
:tags '(messages)
|
||||
(let ((msg (jupyter-test-message
|
||||
(jupyter-request) :execute-reply
|
||||
(list :status "idle" :data (list :text/plain "foo")))))
|
||||
(should (equal (funcall (jupyter-message-lambda (status)
|
||||
status)
|
||||
msg)
|
||||
"idle"))
|
||||
(should (equal (funcall (jupyter-message-lambda ((res text/plain))
|
||||
res)
|
||||
msg)
|
||||
"foo"))
|
||||
(should (equal (funcall (jupyter-message-lambda (status (res text/plain))
|
||||
(cons status res))
|
||||
msg)
|
||||
(cons "idle" "foo")))))
|
||||
|
||||
;;; Channels
|
||||
|
||||
(ert-deftest jupyter-sync-channel ()
|
||||
|
|
Loading…
Add table
Reference in a new issue