remove multilang

This commit is contained in:
dickmao 2020-01-07 16:44:22 -05:00
parent 8d33f3293c
commit 5de0c8b8a4
16 changed files with 125 additions and 606 deletions

View file

@ -41,11 +41,11 @@ Scenario: kernel reconnect succeeds
And I switch to log expr "ein:log-all-buffer-name"
Then I should see "WS closed unexpectedly"
And I switch to buffer like "Untitled"
And header says "Kernel requires reconnect \<ein:notebook-mode-map>\[ein:notebook-reconnect-session-command]"
And header says "Kernel requires reconnect \<ein:notebook-mode-map>\[ein:notebook-reconnect-session-command-km]"
And I clear log expr "ein:log-all-buffer-name"
And I press "C-c C-r"
And I wait for the smoke to clear
And header does not say "Kernel requires reconnect \<ein:notebook-mode-map>\[ein:notebook-reconnect-session-command]"
And header does not say "Kernel requires reconnect \<ein:notebook-mode-map>\[ein:notebook-reconnect-session-command-km]"
And I switch to log expr "ein:log-all-buffer-name"
Then I should not see "[warn]"
And I should not see "[error]"
@ -55,10 +55,10 @@ Scenario: kernel reconnect succeeds
And I switch to log expr "ein:log-all-buffer-name"
Then I should see "WS closed unexpectedly"
And I switch to buffer like "Untitled"
And header says "Kernel requires reconnect \<ein:notebook-mode-map>\[ein:notebook-reconnect-session-command]"
And header says "Kernel requires reconnect \<ein:notebook-mode-map>\[ein:notebook-reconnect-session-command-km]"
And I clear log expr "ein:log-all-buffer-name"
And I wait for cell to execute
And header does not say "Kernel requires reconnect \<ein:notebook-mode-map>\[ein:notebook-reconnect-session-command]"
And header does not say "Kernel requires reconnect \<ein:notebook-mode-map>\[ein:notebook-reconnect-session-command-km]"
And I switch to log expr "ein:log-all-buffer-name"
Then I should not see "[warn]"
And I should not see "[error]"
@ -72,7 +72,7 @@ Scenario: kernel reconnect succeeds
And I should see "ein:kernel-retrieve-session--complete"
And I switch to buffer like "Untitled"
And I kill kernel
And header says "Kernel requires reconnect \<ein:notebook-mode-map>\[ein:notebook-reconnect-session-command]"
And header says "Kernel requires reconnect \<ein:notebook-mode-map>\[ein:notebook-reconnect-session-command-km]"
And I clear log expr "ein:log-all-buffer-name"
And my reconnect is questioned

View file

@ -113,7 +113,7 @@ Scenario: Specific port, portless localhost refers to same, concurrent execution
And I should not see "[....]"
@org
Scenario: portless url with path, image, C-c ' lets you C-c C-c as well
Scenario: portless url with path, image
When I open temp file "path.org"
And I call "org-mode"
And I type "<s"
@ -134,18 +134,8 @@ Scenario: portless url with path, image, C-c ' lets you C-c C-c as well
And I press "RET"
And I type "import matplotlib.pyplot as plt ; import numpy as np ; x = np.linspace(0, 1, 100) ; y = np.random.rand(100,1) ; plt.plot(x,y)"
And I ctrl-c-ctrl-c
And I press "M->"
And I type "<s"
And I press "TAB"
And I type "ein :session localhost :results raw drawer"
And I press "RET"
And I insert percent sign
And I type "matplotlib inline"
And I press "RET"
And I type "import matplotlib.pyplot as plt ; import numpy as np ; x = np.linspace(0, 1, 100) ; y = np.random.rand(100,1) ; plt.plot(x,y)"
And I ctrl-c-ctrl-c
And I dump buffer
And I wait for buffer to say "file:ein-image"
And I dump buffer
@export
Scenario: Test ob-exp captures code and results.

View file

@ -40,24 +40,27 @@
(ein:testing-flush-queries)
(with-current-buffer (ein:notebooklist-get-buffer (car (ein:jupyter-server-conn-info)))
(cl-loop for notebook in (ein:notebook-opened-notebooks)
for path = (ein:$notebook-notebook-path notebook)
do (ein:notebook-kill-kernel-then-close-command notebook)
do (cl-loop repeat 16
until (not (ein:notebook-live-p notebook))
do (sleep-for 0 1000)
finally do (when (ein:notebook-live-p notebook)
(ein:display-warning (format "cannot close %s" path))))
do (when (or (ob-ein-anonymous-p path)
(search "Untitled" path)
(search "Renamed" path))
(ein:notebooklist-delete-notebook path)
(cl-loop with fullpath = (concat (file-name-as-directory ein:testing-jupyter-server-root) path)
repeat 10
for extant = (file-exists-p fullpath)
until (not extant)
do (sleep-for 0 1000)
finally do (when extant
(ein:display-warning (format "cannot del %s" path)))))))
for path = (ein:$notebook-notebook-path notebook)
for done-p = nil
do (ein:notebook-kill-kernel-then-close-command
notebook (lambda (_kernel) (setq done-p t)))
do (cl-loop repeat 16
until done-p
do (sleep-for 0 1000)
finally do (if done-p
(message "killed %s" path)
(ein:display-warning (format "cannot close %s" path))))
do (when (or (ob-ein-anonymous-p path)
(search "Untitled" path)
(search "Renamed" path))
(ein:notebooklist-delete-notebook path)
(cl-loop with fullpath = (concat (file-name-as-directory ein:testing-jupyter-server-root) path)
repeat 10
for extant = (file-exists-p fullpath)
until (not extant)
do (sleep-for 0 1000)
finally do (when extant
(ein:display-warning (format "cannot del %s" path)))))))
(aif (ein:notebook-opened-notebooks)
(cl-loop for nb in it
for path = (ein:$notebook-notebook-path nb)

View file

@ -356,10 +356,10 @@ auto-execution mode flag in the connected buffer is `t'.")))
(status_busy.Kernel . "Kernel is busy...")
(status_restarting.Kernel . "Kernel restarting...")
(status_restarted.Kernel . "Kernel restarted")
(status_dead.Kernel . "Kernel requires restart \\<ein:notebook-mode-map>\\[ein:notebook-restart-session-command]")
(status_dead.Kernel . "Kernel requires restart \\<ein:notebook-mode-map>\\[ein:notebook-restart-session-command-km]")
(status_reconnecting.Kernel . "Kernel reconnecting...")
(status_reconnected.Kernel . "Kernel reconnected")
(status_disconnected.Kernel . "Kernel requires reconnect \\<ein:notebook-mode-map>\\[ein:notebook-reconnect-session-command]")))
(status_disconnected.Kernel . "Kernel requires reconnect \\<ein:notebook-mode-map>\\[ein:notebook-reconnect-session-command-km]")))
:type ein:notification-status))
"Notification widget for Notebook.")

View file

@ -184,21 +184,6 @@ callback (`websocket-callback-debug-on-error') is enabled."
(websocket-get-debug-buffer-create
(ein:$websocket-ws channel)))))
(defun ein:dev-notebook-plain-mode ()
"Use `ein:notebook-plain-mode'."
(interactive)
(setq ein:notebook-modes '(ein:notebook-plain-mode)))
(defun ein:dev-notebook-python-mode ()
"Use `ein:notebook-python-mode'."
(interactive)
(setq ein:notebook-modes '(ein:notebook-python-mode)))
(defun ein:dev-notebook-multilang-mode ()
"Use `ein:notebook-multilang-mode'."
(interactive)
(setq ein:notebook-modes '(ein:notebook-multilang-mode)))
(defun ein:dev-sys-info--lib (name)
(let* ((libsym (intern-soft name))
(version-var (cl-loop for fmt in '("%s-version" "%s:version")

View file

@ -109,6 +109,16 @@ with the call to the jupyter notebook."
(defvar *ein:jupyter-server-buffer-name*
(format "*%s*" *ein:jupyter-server-process-name*))
(defun ein:jupyter-get-default-kernel (kernels)
(cond (ein:%notebooklist-new-kernel%
(ein:$kernelspec-name ein:%notebooklist-new-kernel%))
((eq ein:jupyter-default-kernel 'first-alphabetically)
(car (car kernels)))
((stringp ein:jupyter-default-kernel)
ein:jupyter-default-kernel)
(t
(symbol-name ein:jupyter-default-kernel))))
(defun ein:jupyter-process-lines (url-or-port command &rest args)
"If URL-OR-PORT registered as a k8s url, preface COMMAND ARGS with `kubectl exec'."
(condition-case err
@ -197,6 +207,49 @@ our singleton jupyter server process here."
(funcall #'ein:notebooklist-sentinel url-or-port* proc* event))
url-or-port (process-sentinel proc))))
(defun ein:jupyter-crib-token (url-or-port)
"Shell out to jupyter for its credentials knowledge. Return list of (PASSWORD TOKEN)."
(aif (cl-loop for line in
(apply #'ein:jupyter-process-lines url-or-port
ein:jupyter-server-command
(split-string
(format "%s%s %s"
(aif ein:jupyter-server-use-subcommand
(concat it " ") "")
"list" "--json")))
with token0
with password0
when (destructuring-bind
(&key password url token &allow-other-keys)
(ein:json-read-from-string line)
(prog1 (or (equal (ein:url url) url-or-port)
(equal (url-host (url-generic-parse-url url))
"0.0.0.0"))
(setq password0 password) ;; t or :json-false
(setq token0 token)))
return (list password0 token0))
it (list nil nil)))
(defun ein:jupyter-crib-running-servers ()
"Shell out to jupyter for running servers."
(nconc
(cl-loop for line in
(apply #'ein:jupyter-process-lines nil
ein:jupyter-server-command
(split-string
(format "%s%s %s"
(aif ein:jupyter-server-use-subcommand
(concat it " ") "")
"list" "--json")))
collecting (destructuring-bind
(&key url &allow-other-keys)
(ein:json-read-from-string line)
(ein:url url)))
(aif (ein:k8s-service-url-or-port) (list it))))
;;;###autoload
(defun ein:jupyter-server-start (server-command
notebook-directory
@ -277,14 +330,6 @@ server command."
;;;###autoload
(defalias 'ein:stop 'ein:jupyter-server-stop)
(defun ein:undocumented-shutdown (url-or-port)
(ein:query-singleton-ajax
(list 'shutdown-server url-or-port)
(ein:url url-or-port "api/shutdown")
:type "POST"
:timeout 3 ;; content-query-timeout and query-timeout default nil
:sync t))
;;;###autoload
(defun ein:jupyter-server-stop (&optional force log)
(interactive)

View file

@ -43,9 +43,7 @@
(if-let ((contexts (ein:k8s-get-contexts)))
(let ((desired-context
(ein:completing-read "Select context: " contexts nil t)))
(ein:message-whir "Rereading state"
(add-function :before callback1 done-callback)
(ein:kernel-delete-session kernel callback1))
(message "Rereading state...")
(kubernetes-state-clear)
(let ((response
(kubernetes-kubectl-await
@ -82,7 +80,7 @@
(funcall refresh-f))))
(cl-remove-if (apply-partially #'eq 'nodes)
(mapcar #'car kubernetes-overview-views-alist)))
(message "Selected %s" current-name))
(message ""))
(error "ein:k8s-select-context: %s is down" current-name))))
(error "ein:k8s-select-context: use-context returned %s, expected %s"
response desired-context))))

View file

@ -1,78 +0,0 @@
;;; ein-multilang-fontify.el --- Syntax highlighting for multiple-languages
;; Copyright (C) 2012 Takafumi Arakaki
;; Author: Takafumi Arakaki <aka.tkf at gmail.com>
;; This file is NOT part of GNU Emacs.
;; ein-multilang-fontify.el 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 of
;; the License, or (at your option) any later version.
;; ein-multilang-fontify.el 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 ein-multilang-fontify.el.
;; If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
;; It would be nice if org-src is available, but this module should
;; work without org-src. Data on `org-src-lang-modes' is used
;; if this variable is bound.
(require 'org-src nil t)
(defun ein:mlf-get-lang-mode (lang)
"Return major mode for LANG.
Modified version of `org-src-get-lang-mode'."
(when (symbolp lang)
(setq lang (symbol-name lang)))
(intern
(format "%s-mode"
(or (and (bound-and-true-p org-src-lang-modes)
(cdr (assoc lang org-src-lang-modes)))
lang))))
(defun ein:mlf-font-lock-fontify-block (lang start end)
"Patched version of `org-src-font-lock-fontify-block'."
(let ((lang-mode (ein:mlf-get-lang-mode lang)))
(if (fboundp lang-mode)
(let ((string (buffer-substring-no-properties start end))
(modified (buffer-modified-p))
(orig-buffer (current-buffer))
pos
next)
(remove-text-properties start end '(face nil))
(with-current-buffer
(get-buffer-create
(concat " ein:mlf-fontification:" (symbol-name lang-mode)))
(delete-region (point-min) (point-max))
(insert string)
(unless (eq major-mode lang-mode) (funcall lang-mode))
(font-lock-ensure)
(setq pos (point-min))
(cl-loop for next = (next-single-property-change pos 'face nil (point-max))
do (put-text-property
;; `font-lock-face' property is used instead of `font'.
;; This is the only difference from org-src.
(+ start (1- pos)) (+ start next) 'font-lock-face
(get-text-property pos 'face) orig-buffer)
do (setq pos next)
until (eq pos (point-max))))
(add-text-properties
start end
'(font-lock-fontified t fontified t font-lock-multiline t))
(set-buffer-modified-p modified)))))
(provide 'ein-multilang-fontify)
;;; ein-multilang-fontify.el ends here

View file

@ -1,354 +0,0 @@
;;; ein-multilang.el --- Notebook mode with multiple language fontification
;; Copyright (C) 2012 Takafumi Arakaki
;; Author: Takafumi Arakaki <aka.tkf at gmail.com>
;; This file is NOT part of GNU Emacs.
;; ein-multilang.el 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 of the License, or
;; (at your option) any later version.
;; ein-multilang.el 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 ein-multilang.el.
;; If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(eval-when-compile (defvar markdown-mode-map))
(require 'ein-worksheet)
(require 'ein-multilang-fontify)
(require 'python)
(declare-function ess-indent-line "ess")
(declare-function ess-r-eldoc-function "ess-r-completion")
(declare-function ess-setq-vars-local "ess-utils")
(declare-function julia-indent-line "julia-mode")
(defun ein:ml-fontify (limit)
"Fontify next input area comes after the current point then
return `t' or `nil' if not found.
See info node `(elisp) Search-based Fontification'."
(ein:log-ignore-errors
(ein:ml-fontify-1 limit)))
(defun ein:ml-current-or-next-input-cell (ewoc-node)
"Almost identical to `ein:worksheet-next-input-cell' but return
the current cell if EWOC-NODE is the input area node."
(let* ((ewoc-data (ewoc-data ewoc-node))
(cell (ein:$node-data ewoc-data))
(path (ein:$node-path ewoc-data))
(element (nth 1 path)))
(if (memql element '(prompt input))
cell
(ein:cell-next cell))))
(defun ein:ml-fontify-1 (limit)
"Actual implementation of `ein:ml-fontify'.
This function may raise an error."
(ein:and-let* ((pos (point))
(node (ein:worksheet-get-nearest-cell-ewoc-node pos limit))
(cell (ein:ml-current-or-next-input-cell node))
(start (ein:cell-input-pos-min cell))
(end (ein:cell-input-pos-max cell))
((<= end limit))
((< start end))
(lang (ein:cell-language cell)))
(let ((inhibit-read-only t))
(ein:mlf-font-lock-fontify-block lang start end)
;; Emacs fontification mechanism requires the function to move
;; the point. Do *not* use `(goto-char end)'. As END is in the
;; input area, fontification falls into an infinite loop.
(ewoc-goto-node (slot-value cell 'ewoc) (ein:cell-element-get cell :footer)))
t))
(defun ein:ml-back-to-prev-node ()
(ein:aand (ein:worksheet-get-ewoc) (ewoc-goto-prev it 1)))
(defvar ein:ml-font-lock-keywords
'((ein:ml-fontify))
"Default `font-lock-keywords' for `ein:notebook-multilang-mode'.")
(defun ein:ml-set-font-lock-defaults ()
(setq-local font-lock-defaults
'(ein:ml-font-lock-keywords
;; The following are adapted from org-mode but I am not sure
;; if I need them:
t nil nil
ein:ml-back-to-prev-node)))
;;;###autoload
(define-derived-mode ein:notebook-multilang-mode prog-mode "EIN"
"A mode for fontifying multiple languages.
\\{ein:notebook-multilang-mode-map}
"
(setq-local beginning-of-defun-function
'ein:worksheet-beginning-of-cell-input)
(setq-local end-of-defun-function
'ein:worksheet-end-of-cell-input)
(ein:ml-set-font-lock-defaults))
;;; Language setup functions
(defun ein:ml-narrow-to-cell ()
"Narrow to the current cell."
(ein:and-let* ((pos (point))
(node (ein:worksheet-get-nearest-cell-ewoc-node pos))
(cell (ein:ml-current-or-next-input-cell node))
(start (ein:cell-input-pos-min cell))
(end (ein:cell-input-pos-max cell))
((< start end)))
(narrow-to-region start end)))
(defun ein:ml-indent-line-function (lang-func)
(save-restriction
(ein:ml-narrow-to-cell)
(funcall lang-func)))
(defun ein:ml-indent-region (lang-func start end)
(save-restriction
(ein:ml-narrow-to-cell)
(funcall lang-func start end)))
(defun ein:ml-lang-setup-python ()
"Presumably tkf had good reasons to choose only these forms from `python-mode'."
(setq-local mode-name "EIN[Py]")
(setq-local comment-start "# ")
(setq-local comment-start-skip "#+\\s-*")
(setq-local parse-sexp-lookup-properties t)
(setq-local indent-line-function
(apply-partially #'ein:ml-indent-line-function #'python-indent-line-function))
(setq-local indent-region-function
(apply-partially #'ein:ml-indent-region #'python-indent-region))
(set-syntax-table python-mode-syntax-table)
(set-keymap-parent ein:notebook-multilang-mode-map python-mode-map))
(defun ein:ml-lang-setup-julia ()
(require 'julia-mode nil t)
(when (featurep 'julia-mode)
(setq-local mode-name "EIN[julia]")
(setq-local comment-start "# ")
(setq-local comment-start-skip "#+\\s-*")
(setq-local indent-line-function
(apply-partially #'ein:ml-indent-line-function #'julia-indent-line))
(when (boundp 'julia-mode-syntax-table)
(set-syntax-table julia-mode-syntax-table))
(when (boundp 'julia-mode-map)
(set-keymap-parent ein:notebook-multilang-mode-map julia-mode-map))))
(defun ein:ml-lang-setup-R ()
(require 'ess-r-mode nil t)
(require 'ess-custom nil t)
(when (and (featurep 'ess-r-mode) (featurep 'ess-custom))
(setq-local mode-name "EIN[R]")
(when (boundp 'ess-r-customize-alist)
(ess-setq-vars-local ess-r-customize-alist))
(setq-local paragraph-start (concat "\\s-*$\\|" page-delimiter))
(setq-local paragraph-separate (concat "\\s-*$\\|" page-delimiter))
(setq-local paragraph-ignore-fill-prefix t)
(setq-local indent-line-function
(apply-partially #'ein:ml-indent-line-function #'ess-indent-line))
(when (and (boundp 'ess-style) (boundp 'ess-default-style))
(setq-local ess-style ess-default-style))
(when (and (boundp 'prettify-symbols-alist) (boundp 'ess-r-prettify-symbols))
(setq-local prettify-symbols-alist ess-r-prettify-symbols))
(when (boundp 'ess-r-mode-syntax-table)
(set-syntax-table ess-r-mode-syntax-table))
(when (boundp 'ess-r-mode-map)
(set-keymap-parent ein:notebook-multilang-mode-map ess-r-mode-map))))
(defun ein:ml-lang-setup (kernelspec)
(let ((setup-func (intern (concat "ein:ml-lang-setup-" (ein:$kernelspec-language kernelspec)))))
(if (fboundp setup-func)
(funcall setup-func)
(error "ein:ml-lang-setup: kernelspec language '%s' unsupported" (ein:$kernelspec-language kernelspec)))))
;; (defun ein:ml-lang-setup-markdown ()
;; "Use `markdown-mode-map'. NOTE: This function is not used now."
;; (when (featurep 'markdown-mode)
;; (set-keymap-parent ein:notebook-multilang-mode-map markdown-mode-map)))
;;; yasnippet
(defvar ein:ml-yasnippet-parents '(python-mode markdown-mode)
"Parent modes for `ein:notebook-multilang-mode' to register in yasnippet.")
(defun ein:ml-setup-yasnippet ()
(cl-loop for define-parents in '(yas/define-parents
yas--define-parents)
when (fboundp define-parents)
do (ignore-errors
;; `let' is for workaround the bug in yasnippet
(let ((mode-sym 'ein:notebook-multilang-mode))
(funcall define-parents
mode-sym
ein:ml-yasnippet-parents)))))
(eval-after-load "yasnippet" '(ein:ml-setup-yasnippet))
;;; Imenu Support
;; Most of this is borrowed from python.el
;; Just replace python with ein in most cases.
(defvar ein:imenu-format-item-label-function
'ein:imenu-format-item-label
"Imenu function used to format an item label.
It must be a function with two arguments: TYPE and NAME.")
(defvar ein:imenu-format-parent-item-label-function
'ein:imenu-format-parent-item-label
"Imenu function used to format a parent item label.
It must be a function with two arguments: TYPE and NAME.")
(defvar ein:imenu-format-parent-item-jump-label-function
'ein:imenu-format-parent-item-jump-label
"Imenu function used to format a parent jump item label.
It must be a function with two arguments: TYPE and NAME.")
(defun ein:imenu-format-item-label (type name)
"Return Imenu label for single node using TYPE and NAME."
(format "%s (%s)" name type))
(defun ein:imenu-format-parent-item-label (type name)
"Return Imenu label for parent node using TYPE and NAME."
(format "%s..." (ein:imenu-format-item-label type name)))
(defun python-imenu-format-parent-item-jump-label (type _name)
"Return Imenu label for parent node jump using TYPE and NAME."
(if (string= type "class")
"*class definition*"
"*function definition*"))
(defun ein:imenu--put-parent (type name pos tree)
"Add the parent with TYPE, NAME and POS to TREE."
(let ((label
(funcall ein:imenu-format-item-label-function type name))
(jump-label
(funcall ein:imenu-format-parent-item-jump-label-function type name)))
(if (not tree)
(cons label pos)
(cons label (cons (cons jump-label pos) tree)))))
(defun ein:imenu--build-tree (&optional min-indent prev-indent tree)
"Recursively build the tree of nested definitions of a node.
Arguments MIN-INDENT, PREV-INDENT and TREE are internal and should
not be passed explicitly unless you know what you are doing."
(setq min-indent (or min-indent 0)
prev-indent (or prev-indent python-indent-offset))
(let* ((pos (python-nav-backward-defun))
(type)
(name (when (and pos (looking-at python-nav-beginning-of-defun-regexp))
(let ((split (split-string (match-string-no-properties 0))))
(setq type (car split))
(cadr split))))
(label (when name
(funcall ein:imenu-format-item-label-function type name)))
(indent (current-indentation))
(children-indent-limit (+ python-indent-offset min-indent)))
(cond ((not pos)
;; Nothing found, probably near to bobp.
nil)
((<= indent min-indent)
;; The current indentation points that this is a parent
;; node, add it to the tree and stop recursing.
(ein:imenu--put-parent type name pos tree))
(t
(ein:imenu--build-tree
min-indent
indent
(if (<= indent children-indent-limit)
;; This lies within the children indent offset range,
;; so it's a normal child of its parent (i.e., not
;; a child of a child).
(cons (cons label pos) tree)
;; Oh no, a child of a child?! Fear not, we
;; know how to roll. We recursively parse these by
;; swapping prev-indent and min-indent plus adding this
;; newly found item to a fresh subtree. This works, I
;; promise.
(cons
(ein:imenu--build-tree
prev-indent indent (list (cons label pos)))
tree)))))))
(defun ein:imenu-create-index ()
"Return tree Imenu alist for the current Python buffer.
Change `ein:imenu-format-item-label-function',
`ein:imenu-format-parent-item-label-function',
`ein:imenu-format-parent-item-jump-label-function' to
customize how labels are formatted."
(goto-char (point-max))
(let ((index)
(tree))
(while (setq tree (ein:imenu--build-tree))
(setq index (cons tree index)))
index))
(defun ein:imenu-create-flat-index (&optional alist prefix)
"Return flat outline of the current Python buffer for Imenu.
Optional argument ALIST is the tree to be flattened; when nil
`ein:imenu-build-index' is used with
`ein:imenu-format-parent-item-jump-label-function'
`ein:imenu-format-parent-item-label-function'
`ein:imenu-format-item-label-function' set to
(lambda (type name) name)
Optional argument PREFIX is used in recursive calls and should
not be passed explicitly.
Converts this:
((\"Foo\" . 103)
(\"Bar\" . 138)
(\"decorator\"
(\"decorator\" . 173)
(\"wrap\"
(\"wrap\" . 353)
(\"wrapped_f\" . 393))))
To this:
((\"Foo\" . 103)
(\"Bar\" . 138)
(\"decorator\" . 173)
(\"decorator.wrap\" . 353)
(\"decorator.wrapped_f\" . 393))"
;; Inspired by imenu--flatten-index-alist removed in revno 21853.
(apply
'nconc
(mapcar
(lambda (item)
(let ((name (if prefix
(concat prefix "." (car item))
(car item)))
(pos (cdr item)))
(cond ((or (numberp pos) (markerp pos))
(list (cons name pos)))
((listp pos)
(cons
(cons name (cdar pos))
(python-imenu-create-flat-index (cddr item) name))))))
(or alist
(let* ((fn (lambda (_type name) name))
(ein:imenu-format-item-label-function fn)
(ein:imenu-format-parent-item-label-function fn)
(ein:imenu-format-parent-item-jump-label-function fn))
(python-imenu-create-index))))))
(provide 'ein-multilang)
;;; ein-multilang.el ends here

View file

@ -61,7 +61,6 @@
(require 'ein-traceback)
(require 'ein-shared-output)
(require 'ein-notebooklist)
(require 'ein-multilang)
(require 'ob-ein)
(require 'poly-ein)
@ -874,21 +873,25 @@ NAME is any non-empty string that does not contain '/' or '\\'.
(apply #'apply-partially callback cbargs)))
(ein:notebook-ask-save notebook callback0)))
(defun ein:notebook-kill-kernel-then-close-command (notebook)
(defun ein:notebook-kill-kernel-then-close-command (notebook &optional callback1)
"Kill kernel and then kill notebook buffer.
To close notebook without killing kernel, just close the buffer
as usual."
(interactive (list (ein:notebook--get-nb-or-error)))
(let ((kernel (ein:$notebook-kernel notebook))
(callback1 (apply-partially
(lambda (notebook* kernel)
(ein:notebook-close notebook*))
notebook)))
(if (ein:kernel-live-p kernel)
(ein:message-whir "Ending session"
(add-function :before callback1 done-callback)
(ein:kernel-delete-session kernel callback1))
(funcall callback1 nil))))
(declare (indent defun))
(interactive (list (ein:notebook--get-nb-or-error) nil))
(unless callback1 (setq callback1 #'ignore))
(lexical-let ((callback1 callback1))
(let ((kernel (ein:$notebook-kernel notebook))
(callback (apply-partially
(lambda (notebook* kernel*)
(ein:notebook-close notebook*)
(funcall callback1 kernel*))
notebook)))
(if (ein:kernel-live-p kernel)
(ein:message-whir "Ending session"
(add-function :before callback done-callback)
(ein:kernel-delete-session kernel callback))
(funcall callback nil)))))
(defun ein:fast-content-from-notebook (notebook)
"Quickly generate a basic content structure from notebook. This
@ -1234,27 +1237,12 @@ associated with current buffer (if any)."
;;; Notebook mode
(defcustom ein:notebook-modes
'(ein:notebook-multilang-mode)
"Obsolete."
:type '(repeat (choice (const :tag "Multi-lang" ein:notebook-multilang-mode)
(const :tag "Only Python" ein:notebook-python-mode)
(const :tag "Plain" ein:notebook-plain-mode)))
:group 'ein)
(defun ein:notebook-choose-mode ()
"Return usable (defined) notebook mode."
(autoload 'ein:notebook-multilang-mode "ein-multilang")
(cl-loop for mode in ein:notebook-modes
if (functionp mode)
return mode))
(defvar ein:notebook-mode-map (make-sparse-keymap))
(defmacro ein:notebook--define-key (keymap key defn)
"Ideally we could override just the keymap binding with a (string . wrapped) cons pair (as opposed to messing with the DEFN itself), but then describe-minor-mode unhelpfully shows ?? for the keymap commands.
"Ideally we could override just the keymap binding with a
(string . wrapped) cons pair (as opposed to messing with the DEFN itself),
but then describe-minor-mode unhelpfully shows ?? for the keymap commands.
Tried add-function: the &rest from :around is an emacs-25 compilation issue."
(let ((km (intern (concat (symbol-name defn) "-km"))))
@ -1557,15 +1545,6 @@ the first argument and CBARGS as the rest of arguments."
"Add \"notebook destructor\" to `kill-buffer-hook'."
(add-hook 'kill-buffer-hook 'ein:notebook-kill-buffer-callback nil t))
(lexical-let* ((the-mode (ein:notebook-choose-mode))
(incompatible-func (lambda ()
(when (boundp 'undo-tree-incompatible-major-modes)
(nconc undo-tree-incompatible-major-modes
(list the-mode))))))
(unless (funcall incompatible-func)
(with-eval-after-load 'undo-tree
(funcall incompatible-func))))
(provide 'ein-notebook)
;;; ein-notebook.el ends here

View file

@ -38,7 +38,11 @@
(require 'dash)
(require 'ido)
(autoload 'ein:jupyterhub-connect "ein-jupyterhub")
(declare-function ein:jupyterhub-connect "ein-jupyterhub")
(declare-function ein:jupyter-crib-token "ein-jupyter")
(declare-function ein:jupyter-server-conn-info "ein-jupyter")
(declare-function ein:jupyter-get-default-kernel "ein-jupyter")
(declare-function ein:jupyter-crib-running-servers "ein-jupyter")
(defcustom ein:notebooklist-login-timeout (truncate (* 6.3 1000))
"Timeout in milliseconds for logging into server"
@ -160,54 +164,13 @@ This function adds NBLIST to `ein:notebooklist-map'."
(get-buffer-create
(format ein:notebooklist-buffer-name-template url-or-port)))
(defun ein:crib-token (url-or-port)
"Shell out to jupyter for its credentials knowledge. Return list of (PASSWORD TOKEN)."
(aif (cl-loop for line in
(apply #'ein:jupyter-process-lines url-or-port
ein:jupyter-server-command
(split-string
(format "%s%s %s"
(aif ein:jupyter-server-use-subcommand
(concat it " ") "")
"list" "--json")))
with token0
with password0
when (destructuring-bind
(&key password url token &allow-other-keys)
(ein:json-read-from-string line)
(prog1 (or (equal (ein:url url) url-or-port)
(equal (url-host (url-generic-parse-url url))
"0.0.0.0"))
(setq password0 password) ;; t or :json-false
(setq token0 token)))
return (list password0 token0))
it (list nil nil)))
(defun ein:crib-running-servers ()
"Shell out to jupyter for running servers."
(nconc
(cl-loop for line in
(apply #'ein:jupyter-process-lines nil
ein:jupyter-server-command
(split-string
(format "%s%s %s"
(aif ein:jupyter-server-use-subcommand
(concat it " ") "")
"list" "--json")))
collecting (destructuring-bind
(&key url &allow-other-keys)
(ein:json-read-from-string line)
(ein:url url)))
(aif (ein:k8s-service-url-or-port) (list it))))
(defun ein:notebooklist-token-or-password (url-or-port)
"Return token or password for URL-OR-PORT.
Jupyter requires one or the other but not both.
Return empty string token if all authentication disabled.
Return nil if unclear what, if any, authentication applies."
(multiple-value-bind (password-p token) (ein:crib-token url-or-port)
(autoload 'ein:jupyter-server-conn-info "ein-jupyter")
(multiple-value-bind (password-p token) (ein:jupyter-crib-token url-or-port)
(multiple-value-bind (my-url-or-port my-token) (ein:jupyter-server-conn-info)
(cond ((eq password-p t) (read-passwd (format "Password for %s: " url-or-port)))
((and (stringp token) (eql password-p :json-false)) token)
@ -226,7 +189,7 @@ Return nil if unclear what, if any, authentication applies."
(if (atom ein:url-or-port)
(list ein:url-or-port)
ein:url-or-port)
(ein:crib-running-servers)))))
(ein:jupyter-crib-running-servers)))))
(url-or-port (let (ido-report-no-match ido-use-faces)
(ein:completing-read "URL or port: "
url-or-port-list
@ -508,7 +471,6 @@ This function is called via `ein:notebook-after-rename-hook'."
(-concat dirs nbs files)))
(defun render-header (url-or-port &rest args)
"Render the header (for ipython>=3)."
(with-current-buffer (ein:notebooklist-get-buffer url-or-port)
(widget-insert
(format "Contents API %s (%s)\n\n"
@ -531,20 +493,11 @@ This function is called via `ein:notebook-after-rename-hook'."
(widget-insert " |\n\n"))
(lexical-let* ((url-or-port url-or-port)
(kernels (ein:list-available-kernels url-or-port)))
(unless ein:%notebooklist-new-kernel%
(setq ein:%notebooklist-new-kernel%
(if (eq ein:jupyter-default-kernel 'first-alphabetically)
(ein:get-kernelspec url-or-port (caar kernels))
(ein:get-kernelspec
url-or-port
(if (stringp ein:jupyter-default-kernel)
ein:jupyter-default-kernel
(symbol-name ein:jupyter-default-kernel))))))
(widget-create
'link
:notify (lambda (&rest _ignore) (ein:notebooklist-new-notebook
url-or-port
ein:%notebooklist-new-kernel%))
url-or-port
ein:%notebooklist-new-kernel%))
"New Notebook")
(widget-insert " ")
(widget-create
@ -571,14 +524,7 @@ This function is called via `ein:notebook-after-rename-hook'."
(ein:$kernelspec-display-name update)))
(setq ein:%notebooklist-new-kernel% update)))))))
(if kernels
(let ((initial (cond (ein:%notebooklist-new-kernel%
(ein:$kernelspec-name ein:%notebooklist-new-kernel%))
((eq ein:jupyter-default-kernel 'first-alphabetically)
(car (car kernels)))
((stringp ein:jupyter-default-kernel)
ein:jupyter-default-kernel)
(t
(symbol-name ein:jupyter-default-kernel)))))
(let ((initial (ein:jupyter-get-default-kernel kernels)))
(dolist (k kernels)
(let ((child (widget-radio-add-item
radio-widget

View file

@ -395,7 +395,7 @@ Adapted from twittering-mode.el's `case-string'."
;;; Text manipulation on buffer
(defun ein:find-leftmot-column (beg end)
(defun ein:find-leftmost-column (beg end)
"Return the leftmost column in region BEG to END."
(save-excursion
(let (mincol)
@ -407,7 +407,7 @@ Adapted from twittering-mode.el's `case-string'."
(min mincol (current-column))
(current-column))))
(unless (= (forward-line 1) 0)
(return-from ein:find-leftmot-column mincol)))
(return-from ein:find-leftmost-column mincol)))
mincol)))
;;; Misc

View file

@ -1180,7 +1180,7 @@ in the history."
(let* ((beg (ein:cell-input-pos-min cell))
(end (ein:cell-input-pos-max cell)))
(indent-rigidly
beg end (- (ein:find-leftmot-column beg end)))))
beg end (- (ein:find-leftmost-column beg end)))))
(defun ein:worksheet--cells-before-cell (ws cell)
(let ((cells (ein:worksheet-get-cells ws)))

View file

@ -12,6 +12,11 @@
(defsubst poly-ein--neuter-markdown-mode ()
"Consolidate fragility here."
(unless (eq 'ein:notebook-mode (caar minor-mode-map-alist))
(when-let ((entry (assq 'ein:notebook-mode minor-mode-map-alist)))
(setf minor-mode-map-alist
(cons entry
(assq-delete-all 'ein:notebook-mode minor-mode-map-alist)))))
(when (eq major-mode 'markdown-mode)
(poly-ein--remove-hook "markdown" after-change-functions)
(poly-ein--remove-hook "markdown" jit-lock-after-change-extend-region-functions)

View file

@ -44,7 +44,7 @@
'notebook_saving.Notebook)
(should (string-prefix-p
(concat "IP[y]: Saving Notebook... | "
(substitute-command-keys "Kernel requires restart \\<ein:notebook-mode-map>\\[ein:notebook-restart-session-command] | ")
(substitute-command-keys "Kernel requires restart \\<ein:notebook-mode-map>\\[ein:notebook-restart-session-command-km] | ")
;;"Kernel requires restart C-c C-x C-r | "
"/1\\ /2\\ /3\\ [+]") (ein:header-line)))))

View file

@ -98,7 +98,7 @@ def func():
;;; Text manipulation on buffer
(ert-deftest ein:find-leftmot-column-simple-cases ()
(ert-deftest ein:find-leftmost-column-simple-cases ()
(cl-loop for (indent text) in
'(;; No indent
(0 "\
@ -123,7 +123,7 @@ def f():
)
do (with-temp-buffer
(insert text)
(should (= (ein:find-leftmot-column (point-min) (point-max))
(should (= (ein:find-leftmost-column (point-min) (point-max))
indent)))))