mirror of
https://github.com/vale981/emacs-ipython-notebook
synced 2025-03-04 16:51:38 -05:00
remove multilang
This commit is contained in:
parent
8d33f3293c
commit
5de0c8b8a4
16 changed files with 125 additions and 606 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.")
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))))
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)))))
|
||||
|
||||
|
|
|
@ -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)))))
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue