Absorb displaying widgets into jupyter-repl-insert-data

This commit is contained in:
Nathaniel Nicandro 2018-05-27 22:37:30 -05:00
parent d7a064cae5
commit 382aa9999c

View file

@ -523,10 +523,16 @@ image."
(defun jupyter-repl-insert-data (data metadata) (defun jupyter-repl-insert-data (data metadata)
"Insert DATA into the REPL buffer in order of decreasing richness. "Insert DATA into the REPL buffer in order of decreasing richness.
DATA should be plist mapping mimetypes to their content. Attempt DATA is a plist mapping mimetypes to their content. METADATA is a
to insert a recognized mimetype, trying each one in order of plist similar to data, but with values describing extra
decreasing richness of the mimetype. The current order is information for inserting each kind of mimetype. For example the
value of `image/png' can be a plist with the keys `:width',
`:height'.
Attempt to insert a recognized mimetype, trying each one in order
of decreasing richness of the mimetype. The current order is
- application/vnd.jupyter.widget-view+json
- text/html - text/html
- text/markdown (only if `markdown-mode' is available) - text/markdown (only if `markdown-mode' is available)
- text/latex - text/latex
@ -534,12 +540,12 @@ decreasing richness of the mimetype. The current order is
- image/svg+xml - image/svg+xml
- text/plain - text/plain
When no valid mimetype is present in DATA, a warning is shown. As a special case, since Emacs is currently unable to embed a web
browser in a sufficient way, inserting a widget does not actually
insert it into the buffer. Instead the widget is displayed in a
browser.
METADATA is a plist similar to data, but with values describing When no valid mimetype is present in DATA, a warning is shown."
extra information for inserting each kind of mimetype. For
example the value of `image/png' can be a plist with the keys
`:width', `:height'."
(let ((mimetypes (cl-loop (let ((mimetypes (cl-loop
for (k d) on data by #'cddr for (k d) on data by #'cddr
when when
@ -548,6 +554,11 @@ example the value of `image/png' can be a plist with the keys
(not (memq k jupyter-repl-graphic-mimetypes)))) (not (memq k jupyter-repl-graphic-mimetypes))))
collect k))) collect k)))
(cond (cond
((memq :application/vnd.jupyter.widget-view+json mimetypes)
(jupyter-widgets-display-model
jupyter-repl-current-client
(plist-get (plist-get data :application/vnd.jupyter.widget-view+json)
:model_id)))
((and (memq :text/html mimetypes) ((and (memq :text/html mimetypes)
(functionp 'libxml-parse-html-region)) (functionp 'libxml-parse-html-region))
(let ((html (plist-get data :text/html))) (let ((html (plist-get data :text/html)))
@ -584,18 +595,23 @@ example the value of `image/png' can be a plist with the keys
(defun jupyter-repl-insert-data-with-id (display-id data metadata) (defun jupyter-repl-insert-data-with-id (display-id data metadata)
"Associate DISPLAY-ID with DATA when inserting DATA. "Associate DISPLAY-ID with DATA when inserting DATA.
DATA and METADATA have the same meaning as in DATA and METADATA have the same meaning as in
`jupyter-repl-insert-data'." `jupyter-repl-insert-data'.
Currently there is no support for associating a DISPLAY-ID if
DATA is displayed as a widget."
(unless jupyter-repl-display-ids (unless jupyter-repl-display-ids
(setq-local jupyter-repl-display-ids (setq-local jupyter-repl-display-ids
(make-hash-table :test #'equal (make-hash-table :test #'equal
:weakness 'value))) :weakness 'value)))
(let ((beg (point)) (let ((beg (point))
(id (gethash display-id jupyter-repl-display-ids))) (id (gethash display-id jupyter-repl-display-ids))
(or id (setq id (puthash display-id (widget-p (memq :application/vnd.jupyter.widget-view+json data)))
display-id (or id widget-p (setq id (puthash display-id
jupyter-repl-display-ids))) display-id
jupyter-repl-display-ids)))
(jupyter-repl-insert-data data metadata) (jupyter-repl-insert-data data metadata)
(put-text-property beg (point) 'jupyter-display id))) (unless widget-p
(put-text-property beg (point) 'jupyter-display id))))
;;; Prompt ;;; Prompt
@ -1101,48 +1117,32 @@ found."
transient) transient)
(let ((clear (prog1 (oref client wait-to-clear) (let ((clear (prog1 (oref client wait-to-clear)
(oset client wait-to-clear nil))) (oset client wait-to-clear nil)))
widget) (req (if (eq (jupyter-message-parent-type
(cond (jupyter-request-last-message req))
((setq widget (plist-get data :application/vnd.jupyter.widget-view+json)) :comm-msg)
(jupyter-widgets-display-model client (plist-get widget :model_id))) ;; For comm messages which produce a `:display-data' message,
;; ((eq (jupyter-message-parent-message-type ;; the request is assumed to be the most recently completed
;; (jupyter-request-last-message req)) ;; one.
;; :comm-msg) (with-jupyter-repl-buffer client
;; (with-current-buffer (get-buffer-create "*jupyter-repl-output*") (save-excursion
;; (when clear (erase-buffer)) (goto-char (point-max))
;; (jupyter-repl-insert-data data) (jupyter-repl-previous-cell 2)
;; (pop-to-buffer (current-buffer)))) (jupyter-repl-cell-request)))
(t req)))
(let ((req (if (eq (jupyter-message-parent-type (jupyter-repl-do-at-request client req
(jupyter-request-last-message req)) (cl-destructuring-bind (&key display_id &allow-other-keys)
:comm-msg) transient
;; For comm messages which produce a display_data, the (if display_id
;; request is assumed to be the most recently completed (jupyter-repl-insert-data-with-id display_id data metadata)
;; one. (let ((inhibit-redisplay t))
;; (when clear
;; TODO: Handle display_id, display_id is supposed to be (jupyter-repl-clear-last-cell-output client)
;; used such that any individual output produced by a cell ;; Prevent slight flickering of prompt margin and text, this is
;; can be referenced whereas the output of the whole cell ;; needed in addition to `inhibit-redisplay'. It also seems that
;; is referenced by the request msg_id. ;; it can be placed anywhere within this let and it will prevent
(with-jupyter-repl-buffer client ;; flickering.
(save-excursion (sit-for 0.1 t))
(goto-char (point-max)) (jupyter-repl-insert-data data metadata)))))))
(jupyter-repl-previous-cell 2)
(jupyter-repl-cell-request)))
req)))
(jupyter-repl-do-at-request client req
(cl-destructuring-bind (&key display_id &allow-other-keys)
transient
(if display_id
(jupyter-repl-insert-data-with-id display_id data metadata)
(let ((inhibit-redisplay t))
(when clear (jupyter-repl-clear-last-cell-output client))
(jupyter-repl-insert-data data metadata)
;; Prevent slight flickering of prompt margin and text, this is
;; needed in addition to `inhibit-redisplay'. It also seems
;; that it can be placed anywhere within this let and it will
;; prevent flickering.
(sit-for 0.1 t))))))))))
(cl-defmethod jupyter-handle-update-display-data ((client jupyter-repl-client) (cl-defmethod jupyter-handle-update-display-data ((client jupyter-repl-client)
_req _req