diff --git a/jupyter-client.el b/jupyter-client.el index 0cbd7b9..d654bcc 100644 --- a/jupyter-client.el +++ b/jupyter-client.el @@ -931,7 +931,7 @@ Methods that extend this generic function should (lambda () (setq jupyter-current-client client) ;; TODO: Enable the kernel languages mode using - ;; `jupyter-repl-language-mode', but there are + ;; `jupyter-kernel-language-mode', but there are ;; issues with enabling a major mode. (add-hook 'completion-at-point-functions 'jupyter-completion-at-point nil t) @@ -1794,7 +1794,12 @@ snippet text property, if any, and if `yasnippet' is available." ;;;; Kernel info -(cl-defmethod jupyter-kernel-info ((client jupyter-kernel-client)) +(defvar jupyter-kernel-language-mode-properties nil + "An association list mapping language names to major mode properties. +The lists contain the cached information returned by the +`jupyter-kernel-language-mode-properties' function.") + +(defun jupyter-kernel-info (client) "Return the kernel info plist of CLIENT. Return CLIENT's kernel-info slot if non-nil. Otherwise send a `:kernel-info-request' to CLIENT's kernel, set CLIENT's @@ -1803,6 +1808,7 @@ return it. If the kernel CLIENT is connected to does not respond to a `:kernel-info-request', raise an error." + (cl-check-type client jupyter-kernel-client) (or (oref client kernel-info) (let* ((jupyter-inhibit-handlers t) (req (jupyter-send-kernel-info-request client)) @@ -1812,14 +1818,45 @@ If the kernel CLIENT is connected to does not respond to a (error "Kernel did not respond to kernel-info request")) (oset client kernel-info (jupyter-message-content msg))))) -(cl-defmethod jupyter-kernel-language ((client jupyter-kernel-client)) +(defun jupyter-kernel-language-mode-properties (client) + "Get the `major-mode' info of CLIENT's kernel language. +Return a list + + (MODE SYNTAX-TABLE) + +Where MODE is the `major-mode' to use for syntax highlighting +purposes and SYNTAX-TABLE is the syntax table of MODE." + (cl-check-type client jupyter-kernel-client) + (cl-destructuring-bind (&key name file_extension &allow-other-keys) + (plist-get (jupyter-kernel-info client) :language_info) + (cdr (or (assoc name jupyter-kernel-language-mode-properties) + (with-temp-buffer + (let ((buffer-file-name + (concat "jupyter-repl-lang" file_extension))) + (delay-mode-hooks (set-auto-mode))) + (let ((item (cons name (list major-mode (syntax-table))))) + (prog1 item + (push item jupyter-kernel-language-mode-properties)))))))) + +(defun jupyter-kernel-language (client) "Return the language of the kernel CLIENT is connected to." + (cl-check-type client jupyter-kernel-client) (plist-get (plist-get (jupyter-kernel-info client) :language_info) :name)) +(defun jupyter-kernel-language-mode (client) + "Return the `major-mode' used for CLIENT's kernel language." + (cl-check-type client jupyter-kernel-client) + (nth 0 (jupyter-kernel-language-mode-properties client))) + +(defun jupyter-kernel-language-syntax-table (client) + "Return the `syntax-table' used for CLIENT's kernel language." + (cl-check-type client jupyter-kernel-client) + (nth 1 (jupyter-kernel-language-mode-properties client))) + (defun jupyter-load-language-support (client) "Load language support definitions for CLIENT. CLIENT is a kernel client." - (cl-assert (object-of-class-p client 'jupyter-kernel-client)) + (cl-check-type client jupyter-kernel-client) (let* ((lang (jupyter-kernel-language client)) (support (intern (concat "jupyter-" lang)))) (require support nil t))) diff --git a/jupyter-repl.el b/jupyter-repl.el index b0f5372..604e27c 100644 --- a/jupyter-repl.el +++ b/jupyter-repl.el @@ -222,13 +222,6 @@ The cell is narrowed to the region between and including (jupyter-repl-cell-code-end-position)) ,@body))) -;;; Convenience functions - -(defun jupyter-repl-language-mode (client) - "Return the `major-mode' of CLIENT's kernel language." - (jupyter-with-repl-buffer client - jupyter-repl-lang-mode)) - ;;; Text insertion (defun jupyter-repl-insert (&rest args) @@ -1371,7 +1364,7 @@ in the appropriate direction, to the saved element." 9 nil nil "…")))) (unless (get-buffer name) (with-current-buffer (get-buffer-create name) - (funcall (jupyter-repl-language-mode client)) + (funcall (jupyter-kernel-language-mode client)) (jupyter-repl-associate-buffer client) (insert (substitute-command-keys @@ -1410,11 +1403,10 @@ in the appropriate direction, to the saved element." ;; language. This will be used for indentation and to capture font lock ;; properties. (let* ((info (jupyter-kernel-info jupyter-current-client)) - (language-info (plist-get info :language_info)) - (language (plist-get language-info :name))) + (language (plist-get (plist-get info :language_info) :name))) (jupyter-load-language-support jupyter-current-client) (cl-destructuring-bind (mode syntax) - (jupyter-repl-kernel-language-mode-properties language-info) + (jupyter-kernel-language-mode-properties jupyter-current-client) (setq jupyter-repl-lang-mode mode) (setq jupyter-repl-lang-buffer (get-buffer-create @@ -1604,8 +1596,9 @@ If CLIENT is a buffer or the name of a buffer, use the (with-current-buffer client jupyter-current-client) client)) - (cl-check-type client jupyter-repl-client) - (unless (eq (jupyter-repl-language-mode client) major-mode) + (unless (object-of-class-p client 'jupyter-repl-client) + (error "Not a REPL client (%s)" client)) + (unless (eq (jupyter-kernel-language-mode client) major-mode) (error "Cannot associate buffer to REPL. Wrong `major-mode'")) (setq-local jupyter-current-client client) (unless jupyter-repl-interaction-mode @@ -1660,7 +1653,7 @@ NOTE: Only intended to be added as advice to `switch-to-buffer', (with-current-buffer buffer (let ((client jupyter-current-client) (mode (if (eq major-mode 'jupyter-repl-mode) - (jupyter-repl-language-mode jupyter-current-client) + (jupyter-kernel-language-mode jupyter-current-client) major-mode))) (with-current-buffer other-buffer (when (and (eq mode major-mode) @@ -1670,7 +1663,8 @@ NOTE: Only intended to be added as advice to `switch-to-buffer', (defun jupyter-repl-interaction-mode-reenable () (when (and (not jupyter-repl-interaction-mode) (jupyter-repl-client-p jupyter-current-client) - (eq (jupyter-repl-language-mode jupyter-current-client) major-mode)) + (eq major-mode + (jupyter-kernel-language-mode jupyter-current-client))) (jupyter-repl-interaction-mode))) (defun jupyter-repl-interaction-mode-line () @@ -1738,25 +1732,6 @@ other buffers switched to that have the same `major-mode' as the ;;; Starting a REPL -(defun jupyter-repl-kernel-language-mode-properties (language-info) - "Get the `major-mode' info of a kernel's language. -LANGUAGE-INFO should be the plist of the `:language_info' key in -a kernel's kernel-info. The `major-mode' is found by consulting -`auto-mode-alist' using the language's file extension found in -LANGUAGE-INFO. Return a list - - (MODE SYNTAX-TABLE) - -Where MODE is the `major-mode' to use for syntax highlighting -purposes and SYNTAX-TABLE is the syntax table of MODE." - (cl-destructuring-bind (&key file_extension &allow-other-keys) - language-info - (with-temp-buffer - (let ((buffer-file-name - (concat "jupyter-repl-lang" file_extension))) - (delay-mode-hooks (set-auto-mode))) - (list major-mode (syntax-table))))) - (defun jupyter-repl--new-repl (client &optional repl-name) "Initialize a new REPL buffer based on CLIENT. CLIENT is a REPL client already connected to its kernel and has a @@ -1833,7 +1808,7 @@ Otherwise, in a non-interactive call, return the ;; mode using `auto-mode-alist'. See ;; `jupyter-repl-kernel-language-mode-properties'. (when (and associate-buffer - (eq major-mode (jupyter-repl-language-mode client))) + (eq major-mode (jupyter-kernel-language-mode client))) (jupyter-repl-associate-buffer client)) (when display (pop-to-buffer (oref client buffer))) @@ -1866,7 +1841,7 @@ called interactively, DISPLAY the new REPL buffer as well." (jupyter-start-channels client) (jupyter-repl--new-repl client repl-name) (when (and associate-buffer - (eq major-mode (jupyter-repl-language-mode client))) + (eq major-mode (jupyter-kernel-language-mode client))) (jupyter-repl-associate-buffer client)) (when display (pop-to-buffer (oref client buffer)))