;;; jupyter-zmq-channel-ioloop.el --- IOLoop functions for Jupyter channels -*- lexical-binding: t -*- ;; Copyright (C) 2018-2020 Nathaniel Nicandro ;; Author: Nathaniel Nicandro ;; Created: 08 Nov 2018 ;; This program is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public License as ;; published by the Free Software Foundation; either version 3, or (at ;; your option) any later version. ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;;; Commentary: ;; A `jupyter-channel-ioloop' using `jupyter-zmq-channel' to send and receive ;; messages. Whenever a message is received on a channel an event that looks ;; like the following will be sent back to the parent process ;; ;; (message CHANNEL-TYPE IDENTS . MSG) ;; ;; where CHANNEL-TYPE is the channel on which the message was received (one of ;; `jupyter-socket-types'), IDENTS are ZMQ identities, typically ignored, and ;; MSG is the message plist. ;;; Code: (require 'jupyter-base) (require 'jupyter-channel-ioloop) (require 'jupyter-zmq-channel) (defclass jupyter-zmq-channel-ioloop (jupyter-channel-ioloop) () :documentation "A `jupyter-ioloop' configured for Jupyter channels.") (cl-defmethod initialize-instance ((ioloop jupyter-zmq-channel-ioloop) &optional _slots) (cl-call-next-method) (jupyter-ioloop-add-setup ioloop (require 'jupyter-zmq-channel-ioloop) (push 'jupyter-zmq-channel-ioloop--recv-messages jupyter-ioloop-post-hook) (cl-loop for channel in '(:shell :stdin :iopub) unless (object-assoc channel :type jupyter-channel-ioloop-channels) do (push (jupyter-zmq-channel :session jupyter-channel-ioloop-session :type channel) jupyter-channel-ioloop-channels)))) (defun jupyter-zmq-channel-ioloop--recv-messages (events) "Print the received messages described in EVENTS. EVENTS is a list of socket events as returned by `zmq-poller-wait-all'. If any of the sockets in EVENTS matches one of the sockets in `jupyter-channel-ioloop-channels', receive a message on the channel and print a list with the form (message CHANNEL-TYPE . MSG...) to stdout. CHANNEL-TYPE is the channel on which MSG was received, either :shell, :stdin, or :iopub. MSG is a list as returned by `jupyter-recv'." (let (messages) (dolist (channel jupyter-channel-ioloop-channels) (with-slots (type socket) channel (when (zmq-assoc socket events) (push (cons type (jupyter-recv channel)) messages)))) (when messages ;; Send messages (mapc (lambda (msg) (prin1 (cons 'message msg))) (nreverse messages)) (zmq-flush 'stdout)))) (provide 'jupyter-zmq-channel-ioloop) ;;; jupyter-zmq-channel-ioloop.el ends here