mirror of
https://github.com/vale981/emacs-jupyter
synced 2025-03-04 15:41:37 -05:00
Update code comments and documentation
This commit is contained in:
parent
6a68cb6180
commit
670611ded1
4 changed files with 108 additions and 63 deletions
|
@ -208,8 +208,8 @@ connection is terminated before initializing a new one."
|
|||
(otherwise (error "Wrong channel type")))
|
||||
;; So channels have access to the client's session
|
||||
;;
|
||||
;; See `jupyter-start-channels' for when the :ioloop slot is
|
||||
;; set
|
||||
;; See `jupyter-start-channels' for when the :ioloop slot of
|
||||
;; a channel is set
|
||||
:session session
|
||||
:endpoint (funcall addr port))))))))
|
||||
|
||||
|
@ -271,11 +271,11 @@ this is called."
|
|||
message)
|
||||
"Send a message on CLIENT's CHANNEL.
|
||||
Return a `jupyter-request' representing the sent message. CHANNEL
|
||||
is one of the channel's of CLIENT. TYPE is one of the values in
|
||||
`jupyter-message-types' and is the type of the MESSAGE. If FLAGS
|
||||
is non-nil, it has the same meaning as FLAGS in `zmq-send'. You
|
||||
can manipulate how to handle messages received in response to the
|
||||
sent message, see `jupyter-add-callback' and
|
||||
is one of the channel's of CLIENT. TYPE is one of the
|
||||
`jupyter-message-types'. MESSAGE is the message sent on CHANNEL.
|
||||
|
||||
Note that you can manipulate how to handle messages received in
|
||||
response to the sent message, see `jupyter-add-callback' and
|
||||
`jupyter-request-inhibited-handlers'."
|
||||
(declare (indent 1))
|
||||
(let ((ioloop (oref client ioloop)))
|
||||
|
@ -358,12 +358,13 @@ Any other command sent to the subprocess will be ignored."
|
|||
(signal 'quit nil))
|
||||
(otherwise (error "Unhandled command (%s)" cmd)))))
|
||||
|
||||
;; This may not happen if the parent emacs crashes. One solution is to send the
|
||||
;; process id of the parent emacs and periodically check if the process is
|
||||
;; still alive, then exit the subprocess if the parent process is dead.
|
||||
;; FIXME: The subprocess may not get killed if the parent emacs crashes. One
|
||||
;; solution to this is to send the process id of the parent emacs and
|
||||
;; periodically check if the process is still alive, then exit the subprocess
|
||||
;; if the parent process is dead.
|
||||
;;
|
||||
;; TODO: Fix the problem where lots of display_data messages are coming in, we
|
||||
;; send a request, and wait for the request id to come back with
|
||||
;; FIXME: Fix the problem where lots of display_data messages are coming in,
|
||||
;; then we send a request, and wait for the request id to come back with
|
||||
;; `jupyter-request-id'. `jupyter-request-id' will time out. it looks like the
|
||||
;; poller is not noticing the stdin event in this case.
|
||||
(defun jupyter--ioloop (client)
|
||||
|
@ -423,7 +424,9 @@ Any other command sent to the subprocess will be ignored."
|
|||
;;
|
||||
;; TODO: Drop messages if they are comming too frequently
|
||||
;; to the point where the parent Emacs process would be
|
||||
;; spending too much time handling messages.
|
||||
;; spending too much time handling messages. Or better
|
||||
;; yet, reduce the rate at which messages are being sent
|
||||
;; to the parent process.
|
||||
(when (and messages (or (= idle-count 5)
|
||||
(> (length messages) 10)))
|
||||
(setq messages (nreverse messages))
|
||||
|
@ -527,6 +530,10 @@ by `jupyter--ioloop'."
|
|||
;;; Starting the channel subprocess
|
||||
|
||||
(defun jupyter-ioloop-wait-until (event ioloop &optional timeout)
|
||||
"Wait until EVENT occurs in IOLOOP.
|
||||
Currently EVENT can be :start or :quit and this function will
|
||||
blocks for TIMEOUT seconds until IOLOOP starts or quits depending
|
||||
on EVENT. If TIMEOUT is nil it defaults to 1 s."
|
||||
(or timeout (setq timeout 1))
|
||||
(with-timeout (timeout nil)
|
||||
(while (null (process-get ioloop event))
|
||||
|
@ -534,6 +541,7 @@ by `jupyter--ioloop'."
|
|||
t))
|
||||
|
||||
(defun jupyter--start-ioloop (client)
|
||||
"Start CLIENT's channels."
|
||||
(unless (oref client ioloop)
|
||||
(oset client ioloop
|
||||
(zmq-start-process
|
||||
|
@ -608,10 +616,10 @@ See `jupyter-add-callback'."
|
|||
|
||||
(defun jupyter--add-callback (req msg-type cb)
|
||||
"Helper function for `jupyter-add-callback'.
|
||||
REQ is a `jupyter-request' object, MSG-TYPE should be one of the
|
||||
REQ is a `jupyter-request' object, MSG-TYPE is one of the
|
||||
keywords corresponding to a received message type in
|
||||
`jupyter-message-types', and CB will be the callback that will be
|
||||
run when MSG-TYPE is received for REQ."
|
||||
`jupyter-message-types', and CB is the callback that will be run
|
||||
when MSG-TYPE is received for REQ."
|
||||
(setq msg-type (or (plist-get jupyter-message-types msg-type)
|
||||
;; A msg-type of t means that FUNCTION is run for all
|
||||
;; messages associated with a request.
|
||||
|
@ -691,8 +699,8 @@ within TIMEOUT. Note that if no TIMEOUT is given, it defaults to
|
|||
|
||||
(defun jupyter-wait-until-received (msg-type req &optional timeout)
|
||||
"Wait until a message of a certain type is received for a request.
|
||||
MSG-TYPE and REQ has the same meaning as their corresponding
|
||||
argument in `jupyter-add-callback'. If no message that matches
|
||||
MSG-TYPE and REQ have the same meaning as their corresponding
|
||||
arguments in `jupyter-add-callback'. If no message that matches
|
||||
MSG-TYPE is received for REQ within TIMEOUT seconds, return nil.
|
||||
Otherwise return the first message that matched MSG-TYPE. Note
|
||||
that if no TIMEOUT is given, it defaults to
|
||||
|
|
|
@ -92,7 +92,7 @@ SLOTS are the slots used to initialize the client with.")
|
|||
(cl-defmethod jupyter-make-client ((manager jupyter-kernel-manager) class &rest slots)
|
||||
"Make a new client from CLASS connected to MANAGER's kernel.
|
||||
CLASS should be a subclass of `jupyter-kernel-client', a new
|
||||
instance of CLASS initialized with SLOTS and configured to
|
||||
instance of CLASS is initialized with SLOTS and configured to
|
||||
connect to MANAGER's kernel."
|
||||
(unless (child-of-class-p class 'jupyter-kernel-client)
|
||||
(signal 'wrong-type-argument (list '(subclass jupyter-kernel-client) class)))
|
||||
|
@ -105,7 +105,8 @@ connect to MANAGER's kernel."
|
|||
"Cleanup resources after kernel shutdown.
|
||||
If MANAGER's KERNEL process terminates, i.e. when EVENT describes
|
||||
an event in which the KERNEL process was killed: kill the process
|
||||
buffer and delete MANAGER's conn-file."
|
||||
buffer and delete MANAGER's connection file from the
|
||||
`jupyter-runtime-directory'."
|
||||
(cond
|
||||
((not (process-live-p kernel))
|
||||
(and (buffer-live-p (process-buffer kernel))
|
||||
|
|
|
@ -26,8 +26,28 @@
|
|||
;; A Jupyter REPL for Emacs.
|
||||
;;
|
||||
;; The main entry points are `run-jupyter-repl' and `connect-jupyter-repl'.
|
||||
;; `run-jupyter-repl' starts a new kernel, connects a `jupyter-repl-client' to
|
||||
;; it, and pops up a REPL buffer when called interactively. Whereas `connect-jupyter-repl'
|
||||
;;
|
||||
;; When called interactively, `run-jupyter-repl' asks for a kernel to start
|
||||
;; (based on the kernels found using `jupyter-available-kernelspecs'), connects
|
||||
;; a `jupyter-repl-client' to the selected kernel, and pops up a REPL buffer.
|
||||
;; On the other hand, if `connect-jupyter-repl' is called interactively, it
|
||||
;; will ask for the JSON file that contains the kernel's connection info.
|
||||
;;
|
||||
;; Additionally, `jupyter-repl-associate-buffer' associates the
|
||||
;; `current-buffer' with a REPL client appropriate for the buffer's
|
||||
;; `major-mode'. Associating a buffer with a REPL client enables the minor mode
|
||||
;; `jupyter-repl-interaction-mode' and, if `company-mode' is installed, enables
|
||||
;; auto-completion using the associated REPL client.
|
||||
;;
|
||||
;; `jupyter-repl-interaction-mode' adds the following keybindings for
|
||||
;; interacing a REPL client:
|
||||
;;
|
||||
;; C-c C-c `jupyter-repl-eval-line-or-region'
|
||||
;; C-c C-l `jupyter-repl-eval-file'
|
||||
;; C-c C-f `jupyter-repl-inspect-at-point'
|
||||
;; C-c C-r `jupyter-repl-restart-kernel'
|
||||
;; C-c C-i `jupyter-repl-interrupt-kernel'
|
||||
;; C-c C-z `jupyter-repl-pop-to-buffer'
|
||||
|
||||
;;; Code:
|
||||
|
||||
|
@ -451,7 +471,8 @@ image."
|
|||
(jupyter-repl-insert tex)
|
||||
(setq end (point))
|
||||
(org-format-latex
|
||||
"jupyter-repl" beg end "jupyter-repl"
|
||||
;; FIXME: Possibly make a resource directory for the REPL
|
||||
"ltx" beg end org-babel-jupyter-resource-directory
|
||||
'overlays "Creating LaTeX image...%s"
|
||||
'forbuffer
|
||||
;; Use the default method for creating image files
|
||||
|
@ -1035,6 +1056,9 @@ buffer to display TEXT."
|
|||
(let ((pos (point)))
|
||||
(jupyter-repl-insert-ansi-coded-text
|
||||
(mapconcat #'identity traceback "\n"))
|
||||
;; TODO: Better way of accessing client kernel's properties
|
||||
;;
|
||||
;; (jupyter-client-property client :kernel-language)
|
||||
(when (eq jupyter-repl-lang-mode 'python-mode)
|
||||
;; Fix spacing between error name and Traceback
|
||||
(save-excursion
|
||||
|
@ -1046,6 +1070,7 @@ buffer to display TEXT."
|
|||
(jupyter-repl-insert
|
||||
(make-string (if (> len 4) len 4) ? )))))))
|
||||
(jupyter-repl-newline)))
|
||||
;; TODO: Probably this shouldn't be here.
|
||||
(jupyter-repl-display-other-output
|
||||
client "stderr" (format "(other client) %s: %s" ename evalue))))
|
||||
|
||||
|
@ -1073,9 +1098,11 @@ REPL buffer."
|
|||
thereis (eq (ring-ref jupyter-repl-history -1) 'jupyter-repl-history)
|
||||
do (ring-insert
|
||||
jupyter-repl-history (ring-remove jupyter-repl-history -1)))
|
||||
;; When the next history element is the sentinel, handle some edge cases
|
||||
(cond
|
||||
((equal (jupyter-repl-cell-code)
|
||||
(ring-ref jupyter-repl-history 0))
|
||||
;; If the cell code is the last history item, erase it
|
||||
(jupyter-repl-replace-cell-code "")
|
||||
(setq no-replace t))
|
||||
((equal (jupyter-repl-cell-code) "")
|
||||
|
@ -1272,8 +1299,9 @@ kernel that the REPL buffer is connected to."
|
|||
(defun jupyter-repl-preserve-window-margins (&optional window)
|
||||
"Ensure that the margins of a REPL window are present.
|
||||
This function is added as a hook to `pre-redisplay-functions' to
|
||||
ensure that a REPL windows margins are present. If WINDOW is
|
||||
showing a REPL buffer and the margins are not set to
|
||||
ensure that a REPL windows margins are present.
|
||||
|
||||
If WINDOW is showing a REPL buffer and the margins are not set to
|
||||
`jupyter-repl-prompt-margin-width', set them to the proper
|
||||
value."
|
||||
(when (and (eq major-mode 'jupyter-repl-mode)
|
||||
|
@ -1287,18 +1315,13 @@ value."
|
|||
|
||||
(defun jupyter-repl-code-context-at-point (type)
|
||||
"Return a cons cell, (CODE . POS), for the context around `point'.
|
||||
Returns the required context depending on TYPE which can be
|
||||
either `inspect' or `complete'. If TYPE is `inspect' return an
|
||||
appropriate context for an inspect request. If TYPE is `complete'
|
||||
return an appropriate context for a completion request. PREFIX
|
||||
should be the prefix of the completion when TYPE is `complete'.
|
||||
PREFIX is unused when TYPE is `inspect'.
|
||||
|
||||
The context also depends on the `major-mode' of the
|
||||
`current-buffer'. If the `current-buffer' is a
|
||||
`jupyter-repl-mode' buffer, CODE is the contents of the entire
|
||||
code cell. Otherwise its either the line up to `point' if TYPE is
|
||||
`complete' or the entire line if TYPE is `inspect'."
|
||||
CODE is the required context for TYPE (either `inspect' or
|
||||
`complete') and POS is the relative position of `point' within
|
||||
CODE. The context also depends on the `major-mode' of the
|
||||
`current-buffer'. If the `major-mode' is `jupyter-repl-mode',
|
||||
CODE is the contents of the entire code cell. Otherwise its
|
||||
either the line up to `point' if TYPE is `complete' or the entire
|
||||
line if TYPE is `inspect'."
|
||||
(unless (memq type '(complete inspect))
|
||||
(error "Type not `complete' or `inspect' (%s)" type))
|
||||
(let (code pos)
|
||||
|
@ -1597,7 +1620,6 @@ A kernel can be interrupted if it was started using a
|
|||
(oref jupyter-repl-current-client manager))))
|
||||
|
||||
;; TODO: Make timeouts configurable
|
||||
;; TODO: Handle all consequences of a shutdown
|
||||
(defun jupyter-repl-restart-kernel (shutdown)
|
||||
"Restart the kernel.
|
||||
With a prefix argument, SHUTDOWN the kernel completely instead."
|
||||
|
@ -2001,7 +2023,7 @@ Otherwise, in a non-interactive call, return the
|
|||
(setq kernel-name (caar (jupyter-find-kernelspecs kernel-name))))
|
||||
(unless kernel-name
|
||||
(error "No kernel found for prefix (%s)" kernel-name))
|
||||
;; The manager is set as the client's parent-instance in
|
||||
;; The manager is set as the client's manager slot in
|
||||
;; `jupyter-start-new-kernel'
|
||||
(cl-destructuring-bind (_manager client info)
|
||||
(jupyter-start-new-kernel kernel-name 'jupyter-repl-client)
|
||||
|
|
|
@ -201,7 +201,7 @@ is used as the extension."
|
|||
(concat (file-name-as-directory dir) (sha1 data) ext)))
|
||||
|
||||
(defun org-babel-jupyter--image-result (data file &optional overwrite base64-encoded)
|
||||
"Possibly write DATA to FILE.
|
||||
"Possibly write image DATA to FILE.
|
||||
If OVERWRITE is non-nil, overwrite FILE if it already exists.
|
||||
Otherwise if FILE already exists, DATA is not written to FILE.
|
||||
|
||||
|
@ -224,7 +224,14 @@ Return the cons cell (\"file\" . FILE), see
|
|||
|
||||
(defun org-babel-jupyter-prepare-result (data metadata params)
|
||||
"Return the rendered DATA.
|
||||
DATA is a plist, (:mimetype1 value1 ...), which is used to render
|
||||
DATA is converted into a representation suitable for display in
|
||||
an `org-mode' buffer depending on
|
||||
|
||||
DATA is a plist, (:mimetype1 value1 ...), containing the
|
||||
different representations of a result returned by a kernel.
|
||||
Preparing a result
|
||||
|
||||
which is used to render
|
||||
a result which can be passed to `org-babel-insert-result'.
|
||||
|
||||
METADATA is the metadata plist used to render DATA with, as
|
||||
|
@ -233,17 +240,18 @@ information such as the size of an image to be rendered. The
|
|||
metadata plist is currently unused.
|
||||
|
||||
PARAMS is the source block parameter list as passed to
|
||||
`org-babel-execute:jupyter'. Currently this is only used to
|
||||
extract the file name of an image file when DATA can be rendered
|
||||
as an image type (either `:image/png' or `:image/svg+xml') when a
|
||||
file name is passed to the code block. If no file name is given
|
||||
one is generated based on DATA and the mimetype, see
|
||||
`org-babel-jupyter-file-name'.
|
||||
`org-babel-execute:jupyter'. Currently this is used to extract
|
||||
the file name of an image file when DATA can be rendered as an
|
||||
image. If no file name is given, one is generated based on the
|
||||
image data and mimetype, see `org-babel-jupyter-file-name'.
|
||||
PARAMS is also used to intelligently choose the rendering
|
||||
parameter used for result insertion.
|
||||
|
||||
This function returns a cons cell (RESULT-PARAM . RESULT) where
|
||||
RESULT-PARAM is either a result parameter, i.e. one of the result
|
||||
paramters of `org-babel-insert-result', or a key value pair which
|
||||
should be appended to the PARAMS list when to render RESULT.
|
||||
This function returns a cons cell (RENDER-PARAM . RESULT) where
|
||||
RENDER-PARAM is either a result parameter, i.e. one of the result
|
||||
parameters of `org-babel-insert-result', or a key value pair
|
||||
which should be appended to the PARAMS list when rendering
|
||||
RESULT.
|
||||
|
||||
For example, if DATA only contains the mimetype `:text/markdown',
|
||||
the RESULT-PARAM will be
|
||||
|
@ -386,20 +394,26 @@ language."
|
|||
|
||||
(defun org-babel-jupyter-insert-results (results params kernel-lang)
|
||||
"Insert RESULTS at the current source block location.
|
||||
RESULTS is either a single pair or a list of pairs, each pair
|
||||
having the form
|
||||
RESULTS is either a single cons cell or a list of such cells,
|
||||
each cell having the form
|
||||
|
||||
(RENDER-PARAM . RESULT)
|
||||
|
||||
i.e. the pairs returned by `org-babel-jupyter-prepare-result'.
|
||||
PARAMS are the parameters passed to `org-babel-execute:jupyter'.
|
||||
KERNEL-LANG is the language of the kernel that produced RESULTS.
|
||||
They should have been collected by previous calls to
|
||||
`org-babel-jupyter-prepare-result'. PARAMS are the parameters
|
||||
passed to `org-babel-execute:jupyter'. KERNEL-LANG is the
|
||||
language of the kernel that produced RESULTS.
|
||||
|
||||
Note that for a list of results, the result which will appear
|
||||
will be the last one in the list unless the source block has an
|
||||
\"append\" or \"prepend\" parameter or some other way that
|
||||
prevents `org-babel-insert-result' from clearing a result when
|
||||
inserting a new one."
|
||||
Note that if RESULTS is a list, the last result in the list will
|
||||
be the one that eventually is shown in the org document. This is
|
||||
due to how `org-babel-insert-result' works. This behavior can be
|
||||
modified if the source block has an \"append\" or \"prepend\"
|
||||
parameter; in this case results will either be appended or
|
||||
prepended.
|
||||
|
||||
The current implementation of `org-babel-execute:jupyter' will
|
||||
automatically add this parameter internally so under normal use
|
||||
it does not need to be added by the user."
|
||||
;; Unless this is a list of results
|
||||
(unless (car-safe (car results))
|
||||
(setq results (list results)))
|
||||
|
@ -418,8 +432,8 @@ inserting a new one."
|
|||
|
||||
(defun org-babel-execute:jupyter (body params)
|
||||
"Execute BODY according to PARAMS.
|
||||
BODY is the code to execute for the current Jupyter `:session' of
|
||||
PARAMS."
|
||||
BODY is the code to execute for the current Jupyter `:session' in
|
||||
the PARAMS alist."
|
||||
(let* ((repl-buffer (org-babel-jupyter-initiate-session
|
||||
(alist-get :session params) params))
|
||||
(client (with-current-buffer repl-buffer
|
||||
|
|
Loading…
Add table
Reference in a new issue