Add jupyter-pop-up-frame

Closes #34
This commit is contained in:
Nathaniel Nicandro 2019-02-20 23:58:29 -06:00
parent 541e5dbe6d
commit bdc52c485d
No known key found for this signature in database
GPG key ID: C34814B309DD06B8
2 changed files with 72 additions and 33 deletions

View file

@ -98,6 +98,28 @@ directory is where kernel connection files are written to."
:group 'jupyter
:type 'string)
(defcustom jupyter-pop-up-frame nil
"Whether or not buffers should be displayed in a new frame by default.
Note, this variable is only considered when evaluating code
interactively with functions like `jupyter-eval-line-or-region'.
If equal to nil, frames will never be popped up. When equal to t,
pop-up frames instead of windows.
`jupyter-pop-up-frame' can also be a list of message type
keywords for messages which will cause frames to be used. For any
message type not in the list, windows will be used instead.
Currently only `:execute-result', `:error', and `:stream'
messages consider this variable."
:group 'jupyter
:type '(choice (const :tag "Pop up frames" t)
(const :tag "Pop up windows" nil)
;; TODO: These are the only ones where `jupyter-pop-up-frame'
;; is checked at the moment.
(set (const :execute-result)
(const :error)
(const :stream))))
(defconst jupyter-root (file-name-directory load-file-name)
"Root directory containing emacs-jupyter.")
@ -313,23 +335,36 @@ the output buffer."
(goto-char jupyter-display-buffer-marker)
(jupyter-with-control-code-handling ,@body))))))
(defun jupyter-display-current-buffer-reuse-window (&optional alist &rest actions)
(defun jupyter-display-current-buffer-reuse-window (&optional msg-type alist &rest actions)
"Convenience function to call `display-buffer' on the `current-buffer'.
If a window showing the current buffer is already available,
re-use it. Otherwise pop-up a new window. If ALIST is non-nil it
is used as the ACTION alist of `display-buffer'. The rest of the
arguments are display ACTIONS tried after attempting to re-use a
window and before attempting to pop-up a new window."
(let ((display-buffer-base-action
(cons
(append '(display-buffer-reuse-window)
actions
'(display-buffer-pop-up-window))
(cl-list*
'(pop-up-windows . t)
alist))))
re-use it.
If ALIST is non-nil it is used as the ACTION alist of
`display-buffer'.
If MSG-TYPE is specified, it should be one of the keywords in
`jupyter-message-types' and is used in setting `pop-up-frames'
and `pop-up-windows'. See `jupyter-pop-up-frame'.
The rest of the arguments are display ACTIONS tried after
attempting to re-use a window and before attempting to pop-up a
new window or frame."
(let* ((jupyter-pop-up-frame (jupyter-pop-up-frame-p msg-type))
(pop-up-frames (and jupyter-pop-up-frame 'graphic-only))
(pop-up-windows (not jupyter-pop-up-frame))
(display-buffer-base-action
(cons
(append '(display-buffer-reuse-window)
(delq nil actions))
alist)))
(display-buffer (current-buffer))))
(defun jupyter-pop-up-frame-p (msg-type)
"Return non-nil if a frame should be popped up for MSG-TYPE."
(or (eq jupyter-pop-up-frame t)
(memq msg-type jupyter-pop-up-frame)))
;;; Signing functions/UUID
(defun jupyter-sha256 (object)

View file

@ -985,24 +985,26 @@ Methods that extend this generic function should
;; Prefer to display the markdown representation if available. The
;; IJulia kernel will return both plain text and markdown.
(md text/markdown))
(cond
((or md (null res))
(jupyter-with-display-buffer "result" 'reset
(jupyter-with-message-content msg (data metadata)
(jupyter-insert data metadata))
(goto-char (point-min))
(jupyter-display-current-buffer-reuse-window)))
(res
(setq res (ansi-color-apply res))
(if (cl-loop
with nlines = 0
for c across res when (eq c ?\n) do (cl-incf nlines)
thereis (> nlines jupyter-eval-short-result-max-lines))
(jupyter-with-display-buffer "result" 'reset
(insert res)
(goto-char (point-min))
(jupyter-display-current-buffer-reuse-window))
(funcall jupyter-eval-short-result-display-function (format "%s" res)))))))
(let ((jupyter-pop-up-frame
(jupyter-pop-up-frame-p :execute-result)))
(cond
((or md (null res))
(jupyter-with-display-buffer "result" 'reset
(jupyter-with-message-content msg (data metadata)
(jupyter-insert data metadata))
(goto-char (point-min))
(jupyter-display-current-buffer-reuse-window)))
(res
(setq res (ansi-color-apply res))
(if (cl-loop
with nlines = 0
for c across res when (eq c ?\n) do (cl-incf nlines)
thereis (> nlines jupyter-eval-short-result-max-lines))
(jupyter-with-display-buffer "result" 'reset
(insert res)
(goto-char (point-min))
(jupyter-display-current-buffer-reuse-window))
(funcall jupyter-eval-short-result-display-function (format "%s" res))))))))
(defun jupyter-eval (code &optional mime)
"Send an execute request for CODE, wait for the execute result.
@ -1078,7 +1080,8 @@ to the above explanation."
req
(jupyter-insert-ansi-coded-text text)
(jupyter-display-current-buffer-reuse-window
nil #'display-buffer-below-selected))))
:stream nil (unless (jupyter-pop-up-frame-p :stream)
#'display-buffer-below-selected)))))
req))
(defun jupyter-eval-region (beg end &optional cb)
@ -2019,7 +2022,8 @@ If RESTART is non-nil, request a restart instead of a complete shutdown."
(jupyter-insert-ansi-coded-text traceback)
(goto-char (point-min))
(jupyter-display-current-buffer-reuse-window
nil #'display-buffer-below-selected)))
:error nil (unless (jupyter-pop-up-frame-p :error)
#'display-buffer-below-selected))))
(cl-defgeneric jupyter-handle-error ((_client jupyter-kernel-client)
_req