mirror of
https://github.com/vale981/emacs-ipython-notebook
synced 2025-03-05 17:11:41 -05:00
:image/png not :png
This commit is contained in:
parent
ce4252d2af
commit
702f04064a
20 changed files with 184 additions and 656 deletions
|
@ -37,9 +37,7 @@
|
||||||
(!cons "memory" ecukes-exclude-tags)
|
(!cons "memory" ecukes-exclude-tags)
|
||||||
(!cons "content" ecukes-exclude-tags)
|
(!cons "content" ecukes-exclude-tags)
|
||||||
(when (eq system-type 'darwin)
|
(when (eq system-type 'darwin)
|
||||||
(!cons "julia" ecukes-exclude-tags)))
|
(!cons "julia" ecukes-exclude-tags))
|
||||||
|
|
||||||
(unless (fboundp 'libxml-parse-xml-region)
|
|
||||||
(!cons "svg" ecukes-exclude-tags))
|
(!cons "svg" ecukes-exclude-tags))
|
||||||
|
|
||||||
(defvar ein:testing-jupyter-server-root (f-parent (f-dirname load-file-name)))
|
(defvar ein:testing-jupyter-server-root (f-parent (f-dirname load-file-name)))
|
||||||
|
|
|
@ -220,7 +220,8 @@ Scenario: Undo needs to at least work for reopened notebooks
|
||||||
And I press "C-/"
|
And I press "C-/"
|
||||||
And I undo again
|
And I undo again
|
||||||
And I undo again
|
And I undo again
|
||||||
Then the cursor should be at point "106"
|
And I undo again
|
||||||
|
Then the cursor should be at point "124"
|
||||||
|
|
||||||
@undo
|
@undo
|
||||||
Scenario: Toggling between markdown and codecell does not break undo
|
Scenario: Toggling between markdown and codecell does not break undo
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
;;; ein-cell-output.el --- Cell module
|
|
||||||
|
|
||||||
;; (C) 2015- John M. Miller
|
|
||||||
|
|
||||||
;; Author: John M. Miller (millejoh at mac dot com)
|
|
||||||
|
|
||||||
;; This file is NOT part of GNU Emacs.
|
|
||||||
|
|
||||||
;; ein-cell-output.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-cell-output.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-cell-output.el. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
;;; Commentary:
|
|
||||||
|
|
||||||
;; Because wiriting cell outputs to nbformat v4.0 json is complicated
|
|
||||||
;; enought that it warrants a file all to its own.
|
|
||||||
|
|
||||||
;;; Code:
|
|
||||||
|
|
||||||
(require 'ein-cell)
|
|
||||||
|
|
||||||
(defvar ein:output-type-map
|
|
||||||
'((:svg . :image/svg+xml) (:png . :image/png) (:jpeg . :image/jpeg)
|
|
||||||
(:text . :text/plain)
|
|
||||||
(:html . :text/html) (:latex . :text/latex) (:javascript . :text/javascript)))
|
|
||||||
|
|
||||||
(defun ein:output-property (maybe-property)
|
|
||||||
(cdr (assoc maybe-property ein:output-type-map)))
|
|
||||||
|
|
||||||
;;; Dealing with Code cell outputs
|
|
||||||
(defun ein:cell-stream-output-to-json (output)
|
|
||||||
`((output_type . "stream")
|
|
||||||
(name . ,(plist-get output :stream))
|
|
||||||
(text . ,(plist-get output :text))))
|
|
||||||
|
|
||||||
(defun ein:cell-error-output-to-json (output)
|
|
||||||
`((output_type . "error")
|
|
||||||
(ename . ,(plist-get output :ename))
|
|
||||||
(evalue . ,(plist-get output :evalue))
|
|
||||||
(traceback . ,(plist-get output :traceback))))
|
|
||||||
|
|
||||||
(defun ein:cell-execute-result-output-to-json (output)
|
|
||||||
(let ((data (aif (plist-get output :text)
|
|
||||||
`("text/plain" . ,it)
|
|
||||||
(plist-get output :data))))
|
|
||||||
`((output_type . "execute_result")
|
|
||||||
(metadata . ,(make-hash-table))
|
|
||||||
(execution_count . ,(or (plist-get output :prompt_number)
|
|
||||||
(plist-get output :execution_count)))
|
|
||||||
(data . (,data)))))
|
|
||||||
|
|
||||||
(defun ein:maybe-get-output-mime-data (output)
|
|
||||||
(cl-loop for type in '(:svg :png :jpeg :html :latex :javascript :text)
|
|
||||||
if (plist-get output type)
|
|
||||||
collecting (cons (ein:output-property type) (plist-get output type))))
|
|
||||||
|
|
||||||
(defun ein:cell-display-data-output-to-json (output)
|
|
||||||
(let ((data (or (ein:maybe-get-output-mime-data output)
|
|
||||||
(plist-get output :data))))
|
|
||||||
`((output_type . "display_data")
|
|
||||||
(data . ,data)
|
|
||||||
(metadata . ,(make-hash-table)))))
|
|
||||||
|
|
||||||
(defun ein:find-and-make-outputs (output-plist)
|
|
||||||
(cl-loop for prop in ein:output-type-map
|
|
||||||
when (plist-get output-plist (cdr prop))
|
|
||||||
collect (list (cdr prop) (plist-get output-plist (cdr prop)))))
|
|
||||||
|
|
||||||
(provide 'ein-cell-output)
|
|
253
lisp/ein-cell.el
253
lisp/ein-cell.el
|
@ -113,36 +113,6 @@ Delete current text first, thus effecting a \"refresh\"."
|
||||||
"Face for cell output area errors"
|
"Face for cell output area errors"
|
||||||
:group 'ein)
|
:group 'ein)
|
||||||
|
|
||||||
(defface ein:cell-heading-1
|
|
||||||
'((t :height 1.1 :inherit ein:cell-heading-2))
|
|
||||||
"Face for level 1 heading."
|
|
||||||
:group 'ein)
|
|
||||||
|
|
||||||
(defface ein:cell-heading-2
|
|
||||||
'((t :height 1.1 :inherit ein:cell-heading-3))
|
|
||||||
"Face for level 2 heading."
|
|
||||||
:group 'ein)
|
|
||||||
|
|
||||||
(defface ein:cell-heading-3
|
|
||||||
'((t :height 1.1 :inherit ein:cell-heading-4))
|
|
||||||
"Face for level 3 heading."
|
|
||||||
:group 'ein)
|
|
||||||
|
|
||||||
(defface ein:cell-heading-4
|
|
||||||
'((t :height 1.1 :inherit ein:cell-heading-5))
|
|
||||||
"Face for level 4 heading."
|
|
||||||
:group 'ein)
|
|
||||||
|
|
||||||
(defface ein:cell-heading-5
|
|
||||||
'((t :height 1.1 :inherit ein:cell-heading-6))
|
|
||||||
"Face for level 5 heading."
|
|
||||||
:group 'ein)
|
|
||||||
|
|
||||||
(defface ein:cell-heading-6
|
|
||||||
'((t :weight bold :inherit (variable-pitch ein:cell-input-area)))
|
|
||||||
"Face for level 6 heading."
|
|
||||||
:group 'ein)
|
|
||||||
|
|
||||||
(defface ein:cell-output-prompt
|
(defface ein:cell-output-prompt
|
||||||
'((t :inherit header-line))
|
'((t :inherit header-line))
|
||||||
"Face for cell output prompt"
|
"Face for cell output prompt"
|
||||||
|
@ -280,7 +250,6 @@ a number will limit the number of lines in a cell output."
|
||||||
(("html") 'ein:htmlcell)
|
(("html") 'ein:htmlcell)
|
||||||
(("markdown") 'ein:markdowncell)
|
(("markdown") 'ein:markdowncell)
|
||||||
(("raw") 'ein:rawcell)
|
(("raw") 'ein:rawcell)
|
||||||
(("heading") 'ein:headingcell)
|
|
||||||
(("shared-output") 'ein:shared-output-cell)
|
(("shared-output") 'ein:shared-output-cell)
|
||||||
(t (error "No cell type called %S" type))))
|
(t (error "No cell type called %S" type))))
|
||||||
|
|
||||||
|
@ -318,12 +287,6 @@ a number will limit the number of lines in a cell output."
|
||||||
(setf (slot-value cell 'input) it))
|
(setf (slot-value cell 'input) it))
|
||||||
cell)
|
cell)
|
||||||
|
|
||||||
(cl-defmethod ein:cell-init ((cell ein:headingcell) data) ;; FIXME: Was :after method
|
|
||||||
(cl-call-next-method)
|
|
||||||
(aif (plist-get data :level)
|
|
||||||
(setf (slot-value cell 'level) it))
|
|
||||||
cell)
|
|
||||||
|
|
||||||
(cl-defmethod ein:cell-convert ((cell ein:basecell) type)
|
(cl-defmethod ein:cell-convert ((cell ein:basecell) type)
|
||||||
(let ((new (ein:cell-from-type type)))
|
(let ((new (ein:cell-from-type type)))
|
||||||
;; copy attributes
|
;; copy attributes
|
||||||
|
@ -345,12 +308,6 @@ a number will limit the number of lines in a cell output."
|
||||||
(setf (slot-value new 'kernel) (slot-value cell 'kernel)))
|
(setf (slot-value new 'kernel) (slot-value cell 'kernel)))
|
||||||
new))
|
new))
|
||||||
|
|
||||||
(cl-defmethod ein:cell-convert ((cell ein:headingcell) type)
|
|
||||||
(let ((new (cl-call-next-method)))
|
|
||||||
(when (ein:headingcell-p new)
|
|
||||||
(setf (slot-value new 'level) (slot-value cell 'level)))
|
|
||||||
new))
|
|
||||||
|
|
||||||
(cl-defmethod ein:cell-copy ((cell ein:basecell))
|
(cl-defmethod ein:cell-copy ((cell ein:basecell))
|
||||||
(ein:cell-convert cell (slot-value cell 'cell-type)))
|
(ein:cell-convert cell (slot-value cell 'cell-type)))
|
||||||
|
|
||||||
|
@ -385,16 +342,6 @@ a number will limit the number of lines in a cell output."
|
||||||
do (ein:cell--ewoc-invalidate ewoc en)))
|
do (ein:cell--ewoc-invalidate ewoc en)))
|
||||||
new))
|
new))
|
||||||
|
|
||||||
(cl-defmethod ein:cell-change-level ((cell ein:headingcell) level)
|
|
||||||
(assert (integerp level))
|
|
||||||
(let ((inhibit-read-only t)
|
|
||||||
(buffer-undo-list t)) ; disable undo recording
|
|
||||||
(setf (slot-value cell 'level) level)
|
|
||||||
;; draw ewoc node
|
|
||||||
(cl-loop with ewoc = (slot-value cell 'ewoc)
|
|
||||||
for en in (ein:cell-all-element cell)
|
|
||||||
do (ein:cell--ewoc-invalidate ewoc en))))
|
|
||||||
|
|
||||||
;;; Getter/setter
|
;;; Getter/setter
|
||||||
|
|
||||||
(cl-defmethod ein:cell-num-outputs ((cell ein:codecell))
|
(cl-defmethod ein:cell-num-outputs ((cell ein:codecell))
|
||||||
|
@ -534,11 +481,6 @@ Return language name as a string or `nil' when not defined.
|
||||||
(format "%s:" (slot-value cell 'cell-type))
|
(format "%s:" (slot-value cell 'cell-type))
|
||||||
'font-lock-face 'ein:cell-input-prompt))
|
'font-lock-face 'ein:cell-input-prompt))
|
||||||
|
|
||||||
(cl-defmethod ein:cell-insert-prompt ((cell ein:headingcell))
|
|
||||||
(ein:insert-read-only
|
|
||||||
(format "h%s:" (slot-value cell 'level))
|
|
||||||
'font-lock-face 'ein:cell-input-prompt))
|
|
||||||
|
|
||||||
(cl-defmethod ein:cell-insert-input ((cell ein:basecell))
|
(cl-defmethod ein:cell-insert-input ((cell ein:basecell))
|
||||||
"Insert input of the CELL in the buffer.
|
"Insert input of the CELL in the buffer.
|
||||||
Called from ewoc pretty printer via `ein:cell-pp'."
|
Called from ewoc pretty printer via `ein:cell-pp'."
|
||||||
|
@ -557,9 +499,6 @@ Return language name as a string or `nil' when not defined.
|
||||||
"Return the face (symbol) for input area."
|
"Return the face (symbol) for input area."
|
||||||
'ein:cell-input-area)
|
'ein:cell-input-area)
|
||||||
|
|
||||||
(cl-defmethod ein:cell-get-input-area-face ((cell ein:headingcell))
|
|
||||||
(intern (format "ein:cell-heading-%d" (slot-value cell 'level))))
|
|
||||||
|
|
||||||
(cl-defmethod ein:cell-get-output-area-face-for-output-type (output-type)
|
(cl-defmethod ein:cell-get-output-area-face-for-output-type (output-type)
|
||||||
"Return the face (symbol) for output area."
|
"Return the face (symbol) for output area."
|
||||||
(ein:case-equal output-type
|
(ein:case-equal output-type
|
||||||
|
@ -956,27 +895,24 @@ Called from ewoc pretty printer via `ein:cell-insert-output'."
|
||||||
|
|
||||||
(make-obsolete-variable 'ein:output-type-preference nil "0.17.0")
|
(make-obsolete-variable 'ein:output-type-preference nil "0.17.0")
|
||||||
|
|
||||||
(defun ein:cell-output-type (mime-type)
|
(defun ein:cell-extract-image-format (mime-type)
|
||||||
"Investigate why :image/svg+xml to :svg and :text/plain to :text"
|
"From :image/svg+xml to \"svg\"."
|
||||||
(let* ((mime-str (if (symbolp mime-type) (symbol-name mime-type) mime-type))
|
(let* ((mime-str (if (symbolp mime-type) (symbol-name mime-type) mime-type))
|
||||||
(minor-kw (car (nreverse (split-string mime-str "/"))))
|
(minor-kw (car (nreverse (split-string mime-str "/"))))
|
||||||
(minor (car (nreverse (split-string minor-kw ":")))))
|
(minor (car (nreverse (split-string minor-kw ":")))))
|
||||||
(intern (concat ":"
|
(cl-subseq minor 0 (cl-search "+" minor))))
|
||||||
(cond ((string= minor "plain") "text")
|
|
||||||
(t (cl-subseq minor 0 (cl-search "+" minor))))))))
|
|
||||||
|
|
||||||
(defun ein:cell-append-mime-type (json)
|
(defun ein:cell-append-mime-type (json)
|
||||||
(ein:output-area-case-type
|
(ein:output-area-case-type
|
||||||
json
|
json
|
||||||
(cl-case type
|
(cl-case type
|
||||||
((:html)
|
((:text/html)
|
||||||
(funcall (ein:output-area-get-html-renderer) value))
|
(funcall (ein:output-area-get-html-renderer) value))
|
||||||
((:svg :png :jpeg)
|
((:image/svg+xml :image/png :image/jpeg)
|
||||||
(let ((image (create-image (condition-case nil
|
(let ((image (create-image (condition-case nil
|
||||||
(base64-decode-string value)
|
(base64-decode-string value)
|
||||||
(error value))
|
(error value))
|
||||||
(intern (car (nreverse
|
(intern-soft (ein:cell-extract-image-format type))
|
||||||
(split-string (symbol-name type) ":"))))
|
|
||||||
t)))
|
t)))
|
||||||
(if ein:output-area-inlined-images
|
(if ein:output-area-inlined-images
|
||||||
(ein:insert-image image)
|
(ein:insert-image image)
|
||||||
|
@ -999,124 +935,38 @@ Called from ewoc pretty printer via `ein:cell-insert-output'."
|
||||||
text)
|
text)
|
||||||
(format "Error: %S" err)))))
|
(format "Error: %S" err)))))
|
||||||
|
|
||||||
(cl-defmethod ein:cell-to-json ((cell ein:codecell) &optional discard-output)
|
(cl-defmethod ein:cell-to-json ((cell ein:codecell))
|
||||||
"Return json-ready alist."
|
"Return json-ready alist."
|
||||||
`((input . ,(ein:cell-get-text cell))
|
`((input . ,(ein:cell-get-text cell))
|
||||||
(cell_type . "code")
|
(cell_type . "code")
|
||||||
,@(aif (ein:oref-safe cell 'input-prompt-number)
|
,@(aif (ein:oref-safe cell 'input-prompt-number)
|
||||||
`((prompt_number . ,it)))
|
`((prompt_number . ,it)))
|
||||||
(outputs . ,(if discard-output [] (apply #'vector (slot-value cell 'outputs))))
|
(outputs . ,(apply #'vector (slot-value cell 'outputs)))
|
||||||
(language . ,(or (ein:cell-language cell) "python"))
|
(language . ,(or (ein:cell-language cell) "python"))
|
||||||
(collapsed . ,(if (slot-value cell 'collapsed) t json-false))))
|
(collapsed . ,(if (slot-value cell 'collapsed) t json-false))))
|
||||||
|
|
||||||
(defvar ein:output-type-map
|
(cl-defmethod ein:cell-to-nb4-json ((cell ein:codecell) wsidx)
|
||||||
'((:svg . :image/svg+xml) (:png . :image/png) (:jpeg . :image/jpeg)
|
(let ((execute-count (aif (ein:oref-safe cell 'input-prompt-number)
|
||||||
(:text . :text/plain)
|
(and (numberp it) it)))
|
||||||
(:html . :text/html) (:latex . :text/latex) (:javascript . :text/javascript)))
|
(metadata (slot-value cell 'metadata)))
|
||||||
|
|
||||||
(defun ein:output-property-p (maybe-property)
|
|
||||||
(assoc maybe-property ein:output-type-map))
|
|
||||||
|
|
||||||
(cl-defmethod ein:cell-to-nb4-json ((cell ein:codecell) wsidx &optional discard-output)
|
|
||||||
(let* ((metadata (slot-value cell 'metadata))
|
|
||||||
(outputs (if discard-output []
|
|
||||||
(slot-value cell 'outputs)))
|
|
||||||
(renamed-outputs '())
|
|
||||||
(execute-count (aif (ein:oref-safe cell 'input-prompt-number)
|
|
||||||
(and (numberp it) it))))
|
|
||||||
(setq metadata (plist-put metadata :collapsed (if (slot-value cell 'collapsed) t json-false)))
|
|
||||||
(setq metadata (plist-put metadata :autoscroll json-false))
|
|
||||||
(setq metadata (plist-put metadata :ein.tags (format "worksheet-%s" wsidx)))
|
|
||||||
(unless discard-output
|
|
||||||
(dolist (output outputs)
|
|
||||||
(let ((otype (plist-get output :output_type)))
|
|
||||||
(ein:log 'debug "Saving output of type %S" otype)
|
|
||||||
(if (and (or (equal otype "display_data")
|
|
||||||
(equal otype "execute_result"))
|
|
||||||
(null (plist-get output :metadata)))
|
|
||||||
(plist-put output :metadata (make-hash-table)))
|
|
||||||
(setq renamed-outputs
|
|
||||||
(append renamed-outputs
|
|
||||||
(list (let ((ocopy (cl-copy-list output))
|
|
||||||
(new-output '()))
|
|
||||||
(cl-loop while ocopy
|
|
||||||
do (let ((prop (pop ocopy))
|
|
||||||
(value (pop ocopy)))
|
|
||||||
(ein:log 'debug "Checking property %s for output type '%s'"
|
|
||||||
prop otype)
|
|
||||||
(cond
|
|
||||||
((equal prop :stream) (progn (push value new-output)
|
|
||||||
(push :name new-output)))
|
|
||||||
|
|
||||||
((and (or (equal otype "display_data")
|
|
||||||
(equal otype "execute_result"))
|
|
||||||
(ein:output-property-p prop))
|
|
||||||
(let ((new-prop (cdr (ein:output-property-p prop))))
|
|
||||||
(if (plist-member new-output :data)
|
|
||||||
(setq new-output (plist-put new-output :data
|
|
||||||
(append (plist-get new-output :data)
|
|
||||||
(list new-prop (list value))
|
|
||||||
)))
|
|
||||||
(push (list new-prop (list value)) new-output)
|
|
||||||
(push :data new-output))
|
|
||||||
))
|
|
||||||
|
|
||||||
((and (equal otype "display_data")
|
|
||||||
(equal prop :text))
|
|
||||||
(ein:log 'debug "SAVE-NOTEBOOK: Skipping unnecessary :text data."))
|
|
||||||
|
|
||||||
;; ((and (equal otype "execute_result")
|
|
||||||
;; (ein:output-property-p prop)
|
|
||||||
;; ;; (or (equal prop :text)
|
|
||||||
;; ;; (equal prop :html)
|
|
||||||
;; ;; (equal prop :latex))
|
|
||||||
;; )
|
|
||||||
;; (ein:log 'debug "Fixing execute_result (%s?)." otype)
|
|
||||||
;; (let ((new-prop (cdr (ein:output-property-p prop))))
|
|
||||||
;; (push (list new-prop (list value)) new-output)
|
|
||||||
;; (push :data new-output)))
|
|
||||||
|
|
||||||
|
|
||||||
((and (equal otype "execute_result")
|
|
||||||
(equal prop :prompt_number))
|
|
||||||
(ein:log 'debug "SAVE-NOTEBOOK: Fixing prompt_number property.")
|
|
||||||
(push value new-output)
|
|
||||||
(push :execution_count new-output))
|
|
||||||
|
|
||||||
(t (progn (push value new-output) (push prop new-output)))))
|
|
||||||
finally return new-output))))
|
|
||||||
))))
|
|
||||||
`((source . ,(ein:cell-get-text cell))
|
`((source . ,(ein:cell-get-text cell))
|
||||||
(cell_type . "code")
|
(cell_type . "code")
|
||||||
,@(if execute-count
|
,@(when execute-count
|
||||||
`((execution_count . ,execute-count))
|
`((execution_count . ,execute-count)))
|
||||||
`((execution_count)))
|
(outputs . ,(apply #'vector (slot-value cell 'outputs)))
|
||||||
(outputs . ,(apply #'vector (or renamed-outputs outputs)))
|
(metadata . ,(plist-put metadata :collapsed (if (slot-value cell 'collapsed) t
|
||||||
(metadata . ,metadata))))
|
json-false))))))
|
||||||
|
|
||||||
|
|
||||||
(cl-defmethod ein:cell-to-json ((cell ein:textcell) &optional discard-output)
|
(cl-defmethod ein:cell-to-json ((cell ein:textcell))
|
||||||
`((cell_type . ,(slot-value cell 'cell-type))
|
`((cell_type . ,(slot-value cell 'cell-type))
|
||||||
(source . ,(ein:cell-get-text cell))))
|
(source . ,(ein:cell-get-text cell))))
|
||||||
|
|
||||||
(cl-defmethod ein:cell-to-nb4-json ((cell ein:textcell) wsidx &optional discard-output)
|
(cl-defmethod ein:cell-to-nb4-json ((cell ein:textcell) wsidx)
|
||||||
(let ((metadata (slot-value cell 'metadata)))
|
(let ((metadata (slot-value cell 'metadata)))
|
||||||
(setq metadata (plist-put metadata :ein.tags (format "worksheet-%s" wsidx)))
|
|
||||||
`((cell_type . ,(slot-value cell 'cell-type))
|
`((cell_type . ,(slot-value cell 'cell-type))
|
||||||
(source . ,(ein:cell-get-text cell))
|
(source . ,(ein:cell-get-text cell))
|
||||||
(metadata . ,metadata))))
|
(metadata . ,(plist-put metadata :collapsed json-false)))))
|
||||||
|
|
||||||
(cl-defmethod ein:cell-to-nb4-json ((cell ein:headingcell) wsidx &optional discard-output)
|
|
||||||
(let ((metadata (slot-value cell 'metadata))
|
|
||||||
(header (make-string (slot-value cell 'level) ?#)))
|
|
||||||
(setq metadata (plist-put metadata :ein.tags (format "worksheet-%s" wsidx)))
|
|
||||||
`((cell_type . "markdown")
|
|
||||||
(source . ,(format "%s %s" header (ein:cell-get-text cell)))
|
|
||||||
(metadata . ,metadata))))
|
|
||||||
|
|
||||||
(cl-defmethod ein:cell-to-json ((cell ein:headingcell) &optional discard-output)
|
|
||||||
(let ((json (cl-call-next-method)))
|
|
||||||
(append json `((level . ,(slot-value cell 'level))))))
|
|
||||||
|
|
||||||
(cl-defmethod ein:cell-next ((cell ein:basecell))
|
(cl-defmethod ein:cell-next ((cell ein:basecell))
|
||||||
"Return next cell of the given CELL or nil if CELL is the last one."
|
"Return next cell of the given CELL or nil if CELL is the last one."
|
||||||
|
@ -1175,48 +1025,16 @@ Called from ewoc pretty printer via `ein:cell-insert-output'."
|
||||||
(let ((events (slot-value cell 'events)))
|
(let ((events (slot-value cell 'events)))
|
||||||
(ein:events-trigger events 'set_next_input.Worksheet
|
(ein:events-trigger events 'set_next_input.Worksheet
|
||||||
(list :cell cell :text text))
|
(list :cell cell :text text))
|
||||||
(ein:events-trigger events 'maybe_reset_undo.Worksheet cell)
|
(ein:events-trigger events 'maybe_reset_undo.Worksheet cell)))
|
||||||
))
|
|
||||||
|
|
||||||
|
(cl-defmethod ein:cell--handle-output ((cell ein:codecell) msg-type content meta)
|
||||||
;;; Output area
|
;; (ein:output-area-convert-mime-types content (plist-get content :data))
|
||||||
|
(ein:cell-append-output cell
|
||||||
;; These function should go to ein-output-area.el. But as cell and
|
(plist-put
|
||||||
;; EWOC is connected in complicated way, I will leave them in
|
(plist-put content :output_type msg-type)
|
||||||
;; ein-cell.el.
|
:metadata meta))
|
||||||
|
|
||||||
(cl-defmethod ein:cell--handle-output ((cell ein:codecell) msg-type content
|
|
||||||
_metadata)
|
|
||||||
(let* ((json (list :output_type msg-type)))
|
|
||||||
(ein:case-equal msg-type
|
|
||||||
(("stream")
|
|
||||||
(plist-put json :text (or (plist-get content :data)
|
|
||||||
(plist-get content :text))) ;; Horrible hack to deal with version 5.0 of messaging protocol.
|
|
||||||
(plist-put json :stream (plist-get content :name)))
|
|
||||||
(("display_data" "pyout" "execute_result") ;; in v4 nbformat execute_result == pyout
|
|
||||||
(when (or (equal msg-type "pyout")
|
|
||||||
(equal msg-type "execute_result"))
|
|
||||||
(plist-put json :prompt_number (plist-get content :execution_count)))
|
|
||||||
(setq json (ein:output-area-convert-mime-types json (plist-get content :data))))
|
|
||||||
(("pyerr" "error")
|
|
||||||
(plist-put json :ename (plist-get content :ename))
|
|
||||||
(plist-put json :evalue (plist-get content :evalue))
|
|
||||||
(plist-put json :traceback (plist-get content :traceback))))
|
|
||||||
(ein:cell-append-output cell json)
|
|
||||||
;; (setf (slot-value cell 'dirty) t)
|
;; (setf (slot-value cell 'dirty) t)
|
||||||
(ein:events-trigger (slot-value cell 'events) 'maybe_reset_undo.Worksheet cell)))
|
(ein:events-trigger (slot-value cell 'events) 'maybe_reset_undo.Worksheet cell))
|
||||||
|
|
||||||
(defun ein:output-area-convert-mime-types (json data)
|
|
||||||
(let ((known-mimes (cl-remove-if-not
|
|
||||||
#'identity
|
|
||||||
(mapcar (lambda (x) (intern-soft (concat ":" x)))
|
|
||||||
(mailcap-mime-types)))))
|
|
||||||
(mapc (lambda (x)
|
|
||||||
(-when-let* ((mime-val (plist-get data x))
|
|
||||||
(minor-kw (ein:cell-output-type x)))
|
|
||||||
(setq json (plist-put json minor-kw mime-val))))
|
|
||||||
known-mimes)
|
|
||||||
json))
|
|
||||||
|
|
||||||
(cl-defmethod ein:cell--handle-clear-output ((cell ein:codecell) content
|
(cl-defmethod ein:cell--handle-clear-output ((cell ein:codecell) content
|
||||||
_metadata)
|
_metadata)
|
||||||
|
@ -1230,18 +1048,15 @@ Called from ewoc pretty printer via `ein:cell-insert-output'."
|
||||||
|
|
||||||
;;; Misc.
|
;;; Misc.
|
||||||
|
|
||||||
(cl-defmethod ein:cell-has-image-ouput-p ((cell ein:codecell))
|
(cl-defmethod ein:cell-has-image-output-p ((cell ein:codecell))
|
||||||
"Return `t' if given cell has image output, `nil' otherwise."
|
"Return `t' if given cell has image output, `nil' otherwise."
|
||||||
(cl-loop for out in (slot-value cell 'outputs)
|
(seq-some (lambda (out)
|
||||||
when (or (plist-member out :svg)
|
(or (plist-member out :image/svg+xml)
|
||||||
(plist-member out :image/svg+xml)
|
|
||||||
(plist-member out :png)
|
|
||||||
(plist-member out :image/png)
|
(plist-member out :image/png)
|
||||||
(plist-member out :jpeg)
|
(plist-member out :image/jpeg)))
|
||||||
(plist-member out :image/jpeg))
|
(slot-value cell 'outputs)))
|
||||||
return t))
|
|
||||||
|
|
||||||
(cl-defmethod ein:cell-has-image-ouput-p ((cell ein:textcell))
|
(cl-defmethod ein:cell-has-image-output-p ((cell ein:textcell))
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
(cl-defmethod ein:cell-get-tb-data ((cell ein:codecell))
|
(cl-defmethod ein:cell-get-tb-data ((cell ein:codecell))
|
||||||
|
|
|
@ -166,10 +166,6 @@
|
||||||
((nbformat :initarg :nbformat :type integer)
|
((nbformat :initarg :nbformat :type integer)
|
||||||
(get-notebook-name :initarg :get-notebook-name :type cons
|
(get-notebook-name :initarg :get-notebook-name :type cons
|
||||||
:accessor ein:worksheet--notebook-name)
|
:accessor ein:worksheet--notebook-name)
|
||||||
;; This slot introduces too much complexity so therefore must be
|
|
||||||
;; removed later. This is here only for backward compatible
|
|
||||||
;; reason.
|
|
||||||
(discard-output-p :initarg :discard-output-p :accessor ein:worksheet--discard-output-p)
|
|
||||||
(saved-cells :initarg :saved-cells :initform nil
|
(saved-cells :initarg :saved-cells :initform nil
|
||||||
:accessor ein:worksheet--saved-cells
|
:accessor ein:worksheet--saved-cells
|
||||||
:documentation
|
:documentation
|
||||||
|
@ -251,7 +247,7 @@
|
||||||
(input :initarg :input :type string
|
(input :initarg :input :type string
|
||||||
:documentation "Place to hold data until it is rendered via `ewoc'.")
|
:documentation "Place to hold data until it is rendered via `ewoc'.")
|
||||||
(outputs :initarg :outputs :initform nil :type list)
|
(outputs :initarg :outputs :initform nil :type list)
|
||||||
(metadata :initarg :metadata :initform nil :type list :accessor ein:cell-metadata) ;; For nbformat >= 4
|
(metadata :initarg :metadata :initform nil :type list :accessor ein:cell-metadata)
|
||||||
(events :initarg :events :type ein:events)
|
(events :initarg :events :type ein:events)
|
||||||
(cell-id :initarg :cell-id :initform (ein:utils-uuid) :type string
|
(cell-id :initarg :cell-id :initform (ein:utils-uuid) :type string
|
||||||
:accessor ein:cell-id))
|
:accessor ein:cell-id))
|
||||||
|
@ -290,11 +286,6 @@ auto-execution mode flag in the connected buffer is `t'.")))
|
||||||
(defclass ein:rawcell (ein:textcell)
|
(defclass ein:rawcell (ein:textcell)
|
||||||
((cell-type :initarg :cell-type :initform "raw")))
|
((cell-type :initarg :cell-type :initform "raw")))
|
||||||
|
|
||||||
(defclass ein:headingcell (ein:textcell)
|
|
||||||
((cell-type :initarg :cell-type :initform "heading")
|
|
||||||
(level :initarg :level :initform 1)))
|
|
||||||
|
|
||||||
|
|
||||||
;;; Notifications
|
;;; Notifications
|
||||||
|
|
||||||
(defclass ein:notification-status ()
|
(defclass ein:notification-status ()
|
||||||
|
@ -331,9 +322,9 @@ auto-execution mode flag in the connected buffer is `t'.")))
|
||||||
(ein:notification-status
|
(ein:notification-status
|
||||||
"NotebookStatus"
|
"NotebookStatus"
|
||||||
:s2m
|
:s2m
|
||||||
'((notebook_saving.Notebook . "Saving Notebook...")
|
'((notebook_saving.Notebook . "Saving notebook...")
|
||||||
(notebook_saved.Notebook . "Notebook is saved")
|
(notebook_saved.Notebook . "Notebook saved")
|
||||||
(notebook_save_failed.Notebook . "Failed to save Notebook!")))
|
(notebook_save_failed.Notebook . "Failed saving notebook!")))
|
||||||
:type ein:notification-status)
|
:type ein:notification-status)
|
||||||
(kernel
|
(kernel
|
||||||
:initarg :kernel
|
:initarg :kernel
|
||||||
|
@ -342,7 +333,7 @@ auto-execution mode flag in the connected buffer is `t'.")))
|
||||||
"KernelStatus"
|
"KernelStatus"
|
||||||
:s2m
|
:s2m
|
||||||
'((status_idle.Kernel . nil)
|
'((status_idle.Kernel . nil)
|
||||||
(status_busy.Kernel . "Kernel is busy...")
|
(status_busy.Kernel . "Kernel busy...")
|
||||||
(status_restarting.Kernel . "Kernel restarting...")
|
(status_restarting.Kernel . "Kernel restarting...")
|
||||||
(status_restarted.Kernel . "Kernel restarted")
|
(status_restarted.Kernel . "Kernel restarted")
|
||||||
(status_dead.Kernel . "Kernel requires restart \\<ein:notebook-mode-map>\\[ein:notebook-restart-session-command-km]")
|
(status_dead.Kernel . "Kernel requires restart \\<ein:notebook-mode-map>\\[ein:notebook-restart-session-command-km]")
|
||||||
|
@ -352,7 +343,6 @@ auto-execution mode flag in the connected buffer is `t'.")))
|
||||||
:type ein:notification-status))
|
:type ein:notification-status))
|
||||||
"Notification widget for Notebook.")
|
"Notification widget for Notebook.")
|
||||||
|
|
||||||
|
|
||||||
;;; Events
|
;;; Events
|
||||||
|
|
||||||
(defclass ein:events ()
|
(defclass ein:events ()
|
||||||
|
|
|
@ -296,9 +296,11 @@ global setting. For global setting and more information, see
|
||||||
:type "PUT"
|
:type "PUT"
|
||||||
:headers '(("Content-Type" . "application/json"))
|
:headers '(("Content-Type" . "application/json"))
|
||||||
:timeout ein:content-query-timeout
|
:timeout ein:content-query-timeout
|
||||||
:data (encode-coding-string (ein:content-to-json content) buffer-file-coding-system)
|
:data (encode-coding-string (ein:content-to-json content)
|
||||||
|
buffer-file-coding-system)
|
||||||
:success (apply-partially #'ein:content-save-success callback cbargs)
|
:success (apply-partially #'ein:content-save-success callback cbargs)
|
||||||
:error (apply-partially #'ein:content-save-error (ein:content-url content) errcb errcbargs))
|
:error (apply-partially #'ein:content-save-error
|
||||||
|
(ein:content-url content) errcb errcbargs))
|
||||||
(ein:content-save-legacy content callback cbargs)))
|
(ein:content-save-legacy content callback cbargs)))
|
||||||
|
|
||||||
(cl-defun ein:content-save-success (callback cbargs &key status response &allow-other-keys)
|
(cl-defun ein:content-save-success (callback cbargs &key status response &allow-other-keys)
|
||||||
|
|
|
@ -211,7 +211,7 @@ CALLBACK of arity 1, the kernel.
|
||||||
(let ((session-id (plist-get data :id)))
|
(let ((session-id (plist-get data :id)))
|
||||||
(if (plist-get data :kernel)
|
(if (plist-get data :kernel)
|
||||||
(setq data (plist-get data :kernel)))
|
(setq data (plist-get data :kernel)))
|
||||||
(destructuring-bind (&key id &allow-other-keys) data
|
(cl-destructuring-bind (&key id &allow-other-keys) data
|
||||||
(ein:log 'verbose "ein:kernel-retrieve-session--success: kernel-id=%s session-id=%s"
|
(ein:log 'verbose "ein:kernel-retrieve-session--success: kernel-id=%s session-id=%s"
|
||||||
id session-id)
|
id session-id)
|
||||||
(setf (ein:$kernel-kernel-id kernel) id)
|
(setf (ein:$kernel-kernel-id kernel) id)
|
||||||
|
@ -308,7 +308,6 @@ See https://github.com/ipython/ipython/pull/3307"
|
||||||
(ein:log 'info "Kernel connect_request_reply received."))
|
(ein:log 'info "Kernel connect_request_reply received."))
|
||||||
|
|
||||||
(defun ein:kernel-run-after-start-hook (kernel)
|
(defun ein:kernel-run-after-start-hook (kernel)
|
||||||
(ein:log 'debug "EIN:KERNEL-RUN-AFTER-START-HOOK")
|
|
||||||
(mapc #'ein:funcall-packed
|
(mapc #'ein:funcall-packed
|
||||||
(ein:$kernel-after-start-hook kernel)))
|
(ein:$kernel-after-start-hook kernel)))
|
||||||
|
|
||||||
|
@ -331,15 +330,6 @@ delete the kernel on the server side"
|
||||||
(ein:log 'verbose "Kernel %s unavailable" (ein:$kernel-kernel-id kernel))
|
(ein:log 'verbose "Kernel %s unavailable" (ein:$kernel-kernel-id kernel))
|
||||||
(ein:kernel-reconnect-session kernel callback)))
|
(ein:kernel-reconnect-session kernel callback)))
|
||||||
|
|
||||||
;;; Main public methods
|
|
||||||
|
|
||||||
;; NOTE: The argument CALLBACKS for the following functions is almost
|
|
||||||
;; same as the JS implementation in IPython. However, as Emacs
|
|
||||||
;; lisp does not support closure, value is "packed" using
|
|
||||||
;; `cons': `car' is the actual callback function and `cdr' is
|
|
||||||
;; its first argument. It's like using `cons' instead of
|
|
||||||
;; `$.proxy'.
|
|
||||||
|
|
||||||
(defun ein:kernel-object-info-request (kernel objname callbacks &optional cursor-pos detail-level)
|
(defun ein:kernel-object-info-request (kernel objname callbacks &optional cursor-pos detail-level)
|
||||||
"Send object info request of OBJNAME to KERNEL.
|
"Send object info request of OBJNAME to KERNEL.
|
||||||
|
|
||||||
|
@ -385,63 +375,18 @@ http://ipython.org/ipython-doc/dev/development/messaging.html#object-information
|
||||||
(stop-on-error nil))
|
(stop-on-error nil))
|
||||||
"Execute CODE on KERNEL.
|
"Execute CODE on KERNEL.
|
||||||
|
|
||||||
When calling this method pass a CALLBACKS structure of the form:
|
The CALLBACKS plist looks like:
|
||||||
|
|
||||||
(:execute_reply EXECUTE-REPLY-CALLBACK
|
(:execute_reply EXECUTE-REPLY-CALLBACK
|
||||||
:output OUTPUT-CALLBACK
|
:output OUTPUT-CALLBACK
|
||||||
:clear_output CLEAR-OUTPUT-CALLBACK
|
:clear_output CLEAR-OUTPUT-CALLBACK
|
||||||
:set_next_input SET-NEXT-INPUT)
|
:set_next_input SET-NEXT-INPUT)
|
||||||
|
|
||||||
Right hand sides ending -CALLBACK above must cons a FUNCTION and its
|
Right hand sides ending -CALLBACK above are of the form (FUNCTION ARG1 ... ARGN).
|
||||||
`packed' ARGUMENT which is a sublist of args:
|
(Hindsight: this was all much better implemented using `apply-partially')
|
||||||
|
|
||||||
(FUNCTION . ARGUMENT)
|
Return randomly generated MSG-ID tag uniquely identifying expectation of a kernel response.
|
||||||
|
|
||||||
Call signature
|
|
||||||
--------------
|
|
||||||
::
|
|
||||||
|
|
||||||
(`funcall' EXECUTE-REPLY-CALLBACK ARGUMENT CONTENT METADATA)
|
|
||||||
(`funcall' OUTPUT-CALLBACK ARGUMENT MSG-TYPE CONTENT METADATA)
|
|
||||||
(`funcall' CLEAR-OUTPUT-CALLBACK ARGUMENT CONTENT METADATA)
|
|
||||||
(`funcall' SET-NEXT-INPUT ARGUMENT TEXT)
|
|
||||||
|
|
||||||
* Both CONTENT and METADATA objects are plist.
|
|
||||||
* The MSG-TYPE argument for OUTPUT-CALLBACK is a string
|
|
||||||
(one of `stream', `display_data', `pyout' and `pyerr').
|
|
||||||
* The CONTENT object for CLEAR-OUTPUT-CALLBACK has
|
|
||||||
`stdout', `stderr' and `other' fields that are booleans.
|
|
||||||
* The SET-NEXT-INPUT callback will be passed the `set_next_input' payload,
|
|
||||||
which is a string.
|
|
||||||
See `ein:kernel--handle-shell-reply' for how the callbacks are called.
|
|
||||||
|
|
||||||
Links
|
|
||||||
-----
|
|
||||||
* For general description of CONTENT and METADATA:
|
|
||||||
http://ipython.org/ipython-doc/dev/development/messaging.html#general-message-format
|
|
||||||
* `execute_reply' message is documented here:
|
|
||||||
http://ipython.org/ipython-doc/dev/development/messaging.html#execute
|
|
||||||
* Output type messages is documented here:
|
|
||||||
http://ipython.org/ipython-doc/dev/development/messaging.html#messages-on-the-pub-sub-socket
|
|
||||||
|
|
||||||
Sample implementations
|
|
||||||
----------------------
|
|
||||||
* `ein:cell--handle-execute-reply'
|
|
||||||
* `ein:cell--handle-output'
|
|
||||||
* `ein:cell--handle-clear-output'
|
|
||||||
* `ein:cell--handle-set-next-input'
|
|
||||||
"
|
"
|
||||||
;; FIXME: Consider changing callback to use `&key'.
|
|
||||||
;; Otherwise, adding new arguments to callback requires
|
|
||||||
;; backward incompatible changes (hence a big diff), unlike
|
|
||||||
;; Javascript. Downside of this is that there is no short way
|
|
||||||
;; to write anonymous callback because there is no `lambda*'.
|
|
||||||
;; You can use `function*', but that's bit long...
|
|
||||||
|
|
||||||
;; FIXME: Consider allowing a list of fixed argument so that the
|
|
||||||
;; call signature becomes something like:
|
|
||||||
;; (funcall FUNCTION [ARG ...] CONTENT METADATA)
|
|
||||||
|
|
||||||
(assert (ein:kernel-live-p kernel) nil "execute_reply: Kernel is not active.")
|
(assert (ein:kernel-live-p kernel) nil "execute_reply: Kernel is not active.")
|
||||||
(let* ((content (list
|
(let* ((content (list
|
||||||
:code code
|
:code code
|
||||||
|
@ -452,7 +397,7 @@ Sample implementations
|
||||||
:stop_on_error (or stop-on-error json-false)))
|
:stop_on_error (or stop-on-error json-false)))
|
||||||
(msg (ein:kernel--get-msg kernel "execute_request" content))
|
(msg (ein:kernel--get-msg kernel "execute_request" content))
|
||||||
(msg-id (plist-get (plist-get msg :header) :msg_id)))
|
(msg-id (plist-get (plist-get msg :header) :msg_id)))
|
||||||
(ein:log 'debug "KERNEL-EXECUTE: code=%s msg_id=%s" code msg-id)
|
(ein:log 'debug "ein:kernel-execute: code=%s msg_id=%s" code msg-id)
|
||||||
(run-hook-with-args 'ein:pre-kernel-execute-functions msg)
|
(run-hook-with-args 'ein:pre-kernel-execute-functions msg)
|
||||||
(ein:websocket-send-shell-channel kernel msg)
|
(ein:websocket-send-shell-channel kernel msg)
|
||||||
(ein:kernel-set-callbacks-for-msg kernel msg-id callbacks)
|
(ein:kernel-set-callbacks-for-msg kernel msg-id callbacks)
|
||||||
|
@ -577,36 +522,6 @@ Example::
|
||||||
(ein:kernel-set-callbacks-for-msg kernel msg-id callbacks)
|
(ein:kernel-set-callbacks-for-msg kernel msg-id callbacks)
|
||||||
msg-id))
|
msg-id))
|
||||||
|
|
||||||
(defun ein:kernel-kernel-info-request (kernel callbacks)
|
|
||||||
"Request core information of KERNEL.
|
|
||||||
|
|
||||||
When calling this method pass a CALLBACKS structure of the form::
|
|
||||||
|
|
||||||
(:kernel_info_reply (FUNCTION . ARGUMENT))
|
|
||||||
|
|
||||||
Call signature::
|
|
||||||
|
|
||||||
(`funcall' FUNCTION ARGUMENT CONTENT METADATA)
|
|
||||||
|
|
||||||
CONTENT and METADATA are given by `kernel_info_reply' message.
|
|
||||||
|
|
||||||
`kernel_info_reply' message is documented here:
|
|
||||||
http://ipython.org/ipython-doc/dev/development/messaging.html#kernel-info
|
|
||||||
|
|
||||||
Example::
|
|
||||||
|
|
||||||
(ein:kernel-kernel-info-request
|
|
||||||
(ein:get-kernel)
|
|
||||||
'(:kernel_info_reply (message . \"CONTENT: %S\\nMETADATA: %S\")))
|
|
||||||
"
|
|
||||||
(assert (ein:kernel-live-p kernel) nil "kernel_info_reply: Kernel is not active.")
|
|
||||||
(ein:log 'debug "EIN:KERNEL-KERNEL-INFO-REQUEST: Sending request.")
|
|
||||||
(let* ((msg (ein:kernel--get-msg kernel "kernel_info_request" nil))
|
|
||||||
(msg-id (plist-get (plist-get msg :header) :msg_id)))
|
|
||||||
(ein:websocket-send-shell-channel kernel msg)
|
|
||||||
(ein:kernel-set-callbacks-for-msg kernel msg-id callbacks)
|
|
||||||
msg-id))
|
|
||||||
|
|
||||||
(defun ein:kernel-interrupt (kernel)
|
(defun ein:kernel-interrupt (kernel)
|
||||||
(when (ein:kernel-live-p kernel)
|
(when (ein:kernel-live-p kernel)
|
||||||
(ein:log 'info "Interrupting kernel")
|
(ein:log 'info "Interrupting kernel")
|
||||||
|
@ -670,17 +585,18 @@ We need this to have proper behavior for the 'Stop' command in the ein:notebookl
|
||||||
(gethash msg-id (ein:$kernel-msg-callbacks kernel)))
|
(gethash msg-id (ein:$kernel-msg-callbacks kernel)))
|
||||||
|
|
||||||
(defun ein:kernel-set-callbacks-for-msg (kernel msg-id callbacks)
|
(defun ein:kernel-set-callbacks-for-msg (kernel msg-id callbacks)
|
||||||
|
"Set up promise for MSG-ID."
|
||||||
(puthash msg-id callbacks (ein:$kernel-msg-callbacks kernel)))
|
(puthash msg-id callbacks (ein:$kernel-msg-callbacks kernel)))
|
||||||
|
|
||||||
(defun ein:kernel--handle-stdin-reply (kernel packet)
|
(defun ein:kernel--handle-stdin-reply (kernel packet)
|
||||||
(setf (ein:$kernel-stdin-activep kernel) t)
|
(setf (ein:$kernel-stdin-activep kernel) t)
|
||||||
(destructuring-bind
|
(cl-destructuring-bind
|
||||||
(&key header parent_header metadata content &allow-other-keys)
|
(&key header parent_header metadata content &allow-other-keys)
|
||||||
(ein:json-read-from-string packet)
|
(ein:json-read-from-string packet)
|
||||||
(let ((msg-type (plist-get header :msg_type))
|
(let ((msg-type (plist-get header :msg_type))
|
||||||
(msg-id (plist-get header :msg_id))
|
(msg-id (plist-get header :msg_id))
|
||||||
(password (plist-get content :password)))
|
(password (plist-get content :password)))
|
||||||
(ein:log 'debug "KERNEL--HANDLE-STDIN-REPLY: msg_type=%s msg_id=%s"
|
(ein:log 'debug "ein:kernel--handle-stdin-reply: msg_type=%s msg_id=%s"
|
||||||
msg-type msg-id)
|
msg-type msg-id)
|
||||||
(cond ((string-equal msg-type "input_request")
|
(cond ((string-equal msg-type "input_request")
|
||||||
(if (not (eql password :json-false))
|
(if (not (eql password :json-false))
|
||||||
|
@ -697,33 +613,10 @@ We need this to have proper behavior for the 'Stop' command in the ein:notebookl
|
||||||
(ein:websocket-send-stdin-channel kernel msg)
|
(ein:websocket-send-stdin-channel kernel msg)
|
||||||
(setf (ein:$kernel-stdin-activep kernel) nil))))))))))
|
(setf (ein:$kernel-stdin-activep kernel) nil))))))))))
|
||||||
|
|
||||||
(defun ein:kernel--handle-shell-reply (kernel packet)
|
|
||||||
(destructuring-bind
|
|
||||||
(&key header content metadata parent_header &allow-other-keys)
|
|
||||||
(ein:json-read-from-string packet)
|
|
||||||
(let* ((msg-type (plist-get header :msg_type))
|
|
||||||
(msg-id (plist-get parent_header :msg_id))
|
|
||||||
(callbacks (ein:kernel-get-callbacks-for-msg kernel msg-id))
|
|
||||||
(cb (plist-get callbacks (intern (format ":%s" msg-type)))))
|
|
||||||
(ein:log 'debug "KERNEL--HANDLE-SHELL-REPLY: msg_type=%s msg_id=%s"
|
|
||||||
msg-type msg-id)
|
|
||||||
(run-hook-with-args 'ein:on-shell-reply-functions msg-type header content metadata)
|
|
||||||
(aif cb (ein:funcall-packed it content metadata))
|
|
||||||
(aif (plist-get content :payload)
|
|
||||||
(ein:kernel--handle-payload kernel callbacks it))
|
|
||||||
(let ((events (ein:$kernel-events kernel)))
|
|
||||||
(ein:case-equal msg-type
|
|
||||||
(("execute_reply")
|
|
||||||
(aif (plist-get content :execution_count)
|
|
||||||
;; It can be `nil' for silent execution
|
|
||||||
(ein:events-trigger events 'execution_count.Kernel it))))))))
|
|
||||||
|
|
||||||
(defun ein:kernel--handle-payload (kernel callbacks payload)
|
(defun ein:kernel--handle-payload (kernel callbacks payload)
|
||||||
(cl-loop with events = (ein:$kernel-events kernel)
|
(cl-loop with events = (ein:$kernel-events kernel)
|
||||||
for p in payload
|
for p in payload
|
||||||
for text = (or (plist-get p :text)
|
for text = (or (plist-get p :text) (plist-get (plist-get p :data) :text/plain))
|
||||||
(plist-get (plist-get p :data)
|
|
||||||
:text/plain))
|
|
||||||
for source = (plist-get p :source)
|
for source = (plist-get p :source)
|
||||||
if (member source '("IPython.kernel.zmq.page.page"
|
if (member source '("IPython.kernel.zmq.page.page"
|
||||||
"IPython.zmq.page.page"
|
"IPython.zmq.page.page"
|
||||||
|
@ -740,24 +633,47 @@ We need this to have proper behavior for the 'Stop' command in the ein:notebookl
|
||||||
do (let ((cb (plist-get callbacks :set_next_input)))
|
do (let ((cb (plist-get callbacks :set_next_input)))
|
||||||
(when cb (ein:funcall-packed cb text)))))
|
(when cb (ein:funcall-packed cb text)))))
|
||||||
|
|
||||||
|
(defun ein:kernel--handle-shell-reply (kernel packet)
|
||||||
|
(cl-destructuring-bind
|
||||||
|
(&key header content metadata parent_header &allow-other-keys)
|
||||||
|
(ein:json-read-from-string packet)
|
||||||
|
(let* ((msg-type (plist-get header :msg_type))
|
||||||
|
(msg-id (plist-get parent_header :msg_id))
|
||||||
|
(callbacks (ein:kernel-get-callbacks-for-msg kernel msg-id)))
|
||||||
|
(ein:log 'debug "ein:kernel--handle-shell-reply: msg_type=%s msg_id=%s"
|
||||||
|
msg-type msg-id)
|
||||||
|
(run-hook-with-args 'ein:on-shell-reply-functions msg-type header content metadata)
|
||||||
|
(aif (plist-get callbacks (intern-soft (format ":%s" msg-type)))
|
||||||
|
(ein:funcall-packed it content metadata)
|
||||||
|
(ein:log 'info "ein:kernel--handle-shell-reply: No :%s callback for msg_id=%s"
|
||||||
|
msg-type msg-id))
|
||||||
|
(aif (plist-get content :payload)
|
||||||
|
(ein:kernel--handle-payload kernel callbacks it))
|
||||||
|
(let ((events (ein:$kernel-events kernel)))
|
||||||
|
(ein:case-equal msg-type
|
||||||
|
(("execute_reply")
|
||||||
|
(aif (plist-get content :execution_count)
|
||||||
|
(ein:events-trigger events 'execution_count.Kernel it))))))))
|
||||||
|
|
||||||
(defun ein:kernel--handle-iopub-reply (kernel packet)
|
(defun ein:kernel--handle-iopub-reply (kernel packet)
|
||||||
(if (ein:$kernel-stdin-activep kernel)
|
(if (ein:$kernel-stdin-activep kernel)
|
||||||
(ein:ipdb--handle-iopub-reply kernel packet)
|
(ein:ipdb--handle-iopub-reply kernel packet)
|
||||||
(destructuring-bind
|
(cl-destructuring-bind
|
||||||
(&key content metadata parent_header header &allow-other-keys)
|
(&key content metadata parent_header header &allow-other-keys)
|
||||||
(ein:json-read-from-string packet)
|
(ein:json-read-from-string packet)
|
||||||
(let* ((msg-type (plist-get header :msg_type))
|
(let* ((msg-type (plist-get header :msg_type))
|
||||||
(msg-id (plist-get parent_header :msg_id))
|
(msg-id (plist-get parent_header :msg_id))
|
||||||
(callbacks (ein:kernel-get-callbacks-for-msg kernel msg-id))
|
(callbacks (ein:kernel-get-callbacks-for-msg kernel msg-id))
|
||||||
(events (ein:$kernel-events kernel)))
|
(events (ein:$kernel-events kernel)))
|
||||||
(ein:log 'debug "KERNEL--HANDLE-IOPUB-REPLY: msg_type=%s msg_id=%s"
|
(ein:log 'debug "ein:kernel--handle-iopub-reply: msg_type=%s msg_id=%s"
|
||||||
msg-type msg-id)
|
msg-type msg-id)
|
||||||
(if (and (not (equal msg-type "status")) (null callbacks))
|
|
||||||
(ein:log 'verbose "Not processing msg_type=%s msg_id=%s" msg-type msg-id)
|
|
||||||
(ein:case-equal msg-type
|
(ein:case-equal msg-type
|
||||||
(("stream" "display_data" "pyout" "pyerr" "error" "execute_result")
|
(("stream" "display_data" "pyout" "pyerr" "error" "execute_result")
|
||||||
(aif (plist-get callbacks :output)
|
(aif (plist-get callbacks :output)
|
||||||
(ein:funcall-packed it msg-type content metadata)))
|
(ein:funcall-packed it msg-type content metadata)
|
||||||
|
(ein:log 'warn (concat "ein:kernel--handle-iopub-reply: "
|
||||||
|
"No :output callback for msg_id=%s")
|
||||||
|
msg-id)))
|
||||||
(("status")
|
(("status")
|
||||||
(ein:case-equal (plist-get content :execution_state)
|
(ein:case-equal (plist-get content :execution_state)
|
||||||
(("busy")
|
(("busy")
|
||||||
|
@ -767,12 +683,13 @@ We need this to have proper behavior for the 'Stop' command in the ein:notebookl
|
||||||
(("dead")
|
(("dead")
|
||||||
(ein:kernel-disconnect kernel))))
|
(ein:kernel-disconnect kernel))))
|
||||||
(("data_pub")
|
(("data_pub")
|
||||||
(ein:log 'verbose (format "Received data_pub message w/content %s" packet)))
|
(ein:log 'verbose "ein:kernel--handle-iopub-reply: data_pub %S" packet))
|
||||||
(("clear_output")
|
(("clear_output")
|
||||||
(aif (plist-get callbacks :clear_output)
|
(aif (plist-get callbacks :clear_output)
|
||||||
(ein:funcall-packed it content metadata)))))))))
|
(ein:funcall-packed it content metadata)
|
||||||
|
(ein:log 'info (concat "ein:kernel--handle-iopub-reply: "
|
||||||
;;; Utility functions
|
"No :clear_output callback for msg_id=%s")
|
||||||
|
msg-id))))))))
|
||||||
|
|
||||||
(defun ein:kernel-filename-to-python (kernel filename)
|
(defun ein:kernel-filename-to-python (kernel filename)
|
||||||
"See: `ein:filename-to-python'."
|
"See: `ein:filename-to-python'."
|
||||||
|
@ -792,7 +709,6 @@ Used in `ein:pytools-finish-tooltip', etc."
|
||||||
(defun ein:kernel-construct-help-string (content)
|
(defun ein:kernel-construct-help-string (content)
|
||||||
"Construct help string from CONTENT of ``:object_info_reply``.
|
"Construct help string from CONTENT of ``:object_info_reply``.
|
||||||
Used in `ein:pytools-finish-tooltip', etc."
|
Used in `ein:pytools-finish-tooltip', etc."
|
||||||
(ein:log 'debug "KERNEL-CONSTRUCT-HELP-STRING")
|
|
||||||
(let* ((defstring (ein:aand
|
(let* ((defstring (ein:aand
|
||||||
(ein:kernel-construct-defstring content)
|
(ein:kernel-construct-defstring content)
|
||||||
(ansi-color-apply it)
|
(ansi-color-apply it)
|
||||||
|
@ -807,7 +723,6 @@ Used in `ein:pytools-finish-tooltip', etc."
|
||||||
(help (ein:aand
|
(help (ein:aand
|
||||||
(delete nil (list defstring docstring))
|
(delete nil (list defstring docstring))
|
||||||
(ein:join-str "\n" it))))
|
(ein:join-str "\n" it))))
|
||||||
(ein:log 'debug "KERNEL-CONSTRUCT-HELP-STRING: help=%s" help)
|
|
||||||
help))
|
help))
|
||||||
|
|
||||||
(defun ein:kernel-request-stream (kernel code func &optional args)
|
(defun ein:kernel-request-stream (kernel code func &optional args)
|
||||||
|
|
|
@ -44,7 +44,6 @@
|
||||||
(require 'ein-kernel)
|
(require 'ein-kernel)
|
||||||
(require 'ein-kernelinfo)
|
(require 'ein-kernelinfo)
|
||||||
(require 'ein-cell)
|
(require 'ein-cell)
|
||||||
(require 'ein-cell-output)
|
|
||||||
(require 'ein-worksheet)
|
(require 'ein-worksheet)
|
||||||
(require 'ein-iexec)
|
(require 'ein-iexec)
|
||||||
(require 'ein-scratchsheet)
|
(require 'ein-scratchsheet)
|
||||||
|
@ -65,47 +64,19 @@
|
||||||
|
|
||||||
;;; Configuration
|
;;; Configuration
|
||||||
|
|
||||||
(defcustom ein:notebook-discard-output-on-save 'no
|
|
||||||
"Configure if the output part of the cell should be saved or not.
|
|
||||||
|
|
||||||
.. warning:: This configuration is obsolete now.
|
|
||||||
Use nbconvert (https://github.com/ipython/nbconvert) to
|
|
||||||
strip output.
|
|
||||||
|
|
||||||
`no' : symbol
|
|
||||||
Save output. This is the default.
|
|
||||||
`yes' : symbol
|
|
||||||
Always discard output.
|
|
||||||
a function
|
|
||||||
This function takes two arguments, notebook and cell. Return
|
|
||||||
`t' to discard output and return `nil' to save. For example,
|
|
||||||
if you don't want to save image output but other kind of
|
|
||||||
output, use `ein:notebook-cell-has-image-output-p'.
|
|
||||||
"
|
|
||||||
:type '(choice (const :tag "No" 'no)
|
|
||||||
(const :tag "Yes" 'yes)
|
|
||||||
)
|
|
||||||
:group 'ein)
|
|
||||||
(make-obsolete-variable 'ein:use-smartrep nil "0.17.0")
|
(make-obsolete-variable 'ein:use-smartrep nil "0.17.0")
|
||||||
|
|
||||||
(defvar *ein:notebook--pending-query* (make-hash-table :test 'equal)
|
|
||||||
"A map: (URL-OR-PORT . PATH) => t/nil")
|
|
||||||
|
|
||||||
(make-obsolete-variable 'ein:notebook-autosave-frequency nil "0.17.0")
|
(make-obsolete-variable 'ein:notebook-autosave-frequency nil "0.17.0")
|
||||||
|
|
||||||
(make-obsolete-variable 'ein:notebook-create-checkpoint-on-save nil "0.17.0")
|
(make-obsolete-variable 'ein:notebook-create-checkpoint-on-save nil "0.17.0")
|
||||||
|
|
||||||
(make-obsolete-variable 'ein:notebook-discard-output-on-save nil "0.17.0")
|
(make-obsolete-variable 'ein:notebook-discard-output-on-save nil "0.17.0")
|
||||||
|
|
||||||
(defun ein:notebook-cell-has-image-output-p (-ignore- cell)
|
(defvar *ein:notebook--pending-query* (make-hash-table :test 'equal)
|
||||||
(ein:cell-has-image-ouput-p cell))
|
"A map: (URL-OR-PORT . PATH) => t/nil")
|
||||||
|
|
||||||
(defun ein:notebook-discard-output-p (notebook cell)
|
(defun ein:notebook-cell-has-image-output-p (_ignore cell)
|
||||||
"Return non-`nil' if the output must be discarded, otherwise save."
|
(ein:cell-has-image-output-p cell))
|
||||||
(case ein:notebook-discard-output-on-save
|
|
||||||
(no nil)
|
|
||||||
(yes t)
|
|
||||||
(t (funcall ein:notebook-discard-output-on-save notebook cell))))
|
|
||||||
|
|
||||||
;; As opening/saving notebook treats possibly huge data, define these
|
;; As opening/saving notebook treats possibly huge data, define these
|
||||||
;; timeouts separately:
|
;; timeouts separately:
|
||||||
|
@ -548,9 +519,6 @@ This is equivalent to do ``C-c`` in the console program."
|
||||||
(funcall func
|
(funcall func
|
||||||
(ein:$notebook-nbformat notebook)
|
(ein:$notebook-nbformat notebook)
|
||||||
(ein:notebook-name-getter notebook)
|
(ein:notebook-name-getter notebook)
|
||||||
(cons (lambda (notebook cell)
|
|
||||||
(ein:notebook-discard-output-p notebook cell))
|
|
||||||
notebook)
|
|
||||||
(ein:$notebook-kernel notebook)
|
(ein:$notebook-kernel notebook)
|
||||||
(ein:$notebook-events notebook)))
|
(ein:$notebook-events notebook)))
|
||||||
|
|
||||||
|
@ -761,8 +729,8 @@ This is equivalent to do ``C-c`` in the console program."
|
||||||
(cl-defun ein:notebook-save-notebook-error (notebook &key symbol-status
|
(cl-defun ein:notebook-save-notebook-error (notebook &key symbol-status
|
||||||
&allow-other-keys)
|
&allow-other-keys)
|
||||||
(if (eq symbol-status 'user-cancel)
|
(if (eq symbol-status 'user-cancel)
|
||||||
(ein:log 'info "Cancel saving notebook.")
|
(ein:log 'info "Cancelled save.")
|
||||||
(ein:log 'info "Failed to save notebook!")
|
(ein:log 'warn "Failed saving notebook!")
|
||||||
(ein:events-trigger (ein:$notebook-events notebook)
|
(ein:events-trigger (ein:$notebook-events notebook)
|
||||||
'notebook_save_failed.Notebook)))
|
'notebook_save_failed.Notebook)))
|
||||||
|
|
||||||
|
@ -1437,19 +1405,12 @@ watch the fireworks!"
|
||||||
(aif ein:anything-kernel-history-search-key
|
(aif ein:anything-kernel-history-search-key
|
||||||
(ein:notebook--define-key ein:notebook-mode-map it anything-ein-kernel-history))
|
(ein:notebook--define-key ein:notebook-mode-map it anything-ein-kernel-history))
|
||||||
(setq indent-tabs-mode nil) ;; Being T causes problems with Python code.
|
(setq indent-tabs-mode nil) ;; Being T causes problems with Python code.
|
||||||
(ein:worksheet-imenu-setup)))
|
))
|
||||||
|
|
||||||
;; To avoid MuMaMo to discard `ein:notebook-mode', make it
|
;; To avoid MuMaMo to discard `ein:notebook-mode', make it
|
||||||
;; permanent local.
|
;; permanent local.
|
||||||
(put 'ein:notebook-mode 'permanent-local t)
|
(put 'ein:notebook-mode 'permanent-local t)
|
||||||
|
|
||||||
(define-derived-mode ein:notebook-plain-mode fundamental-mode "EIN[plain]"
|
|
||||||
"IPython notebook mode without fancy coloring."
|
|
||||||
(font-lock-mode))
|
|
||||||
|
|
||||||
(define-derived-mode ein:notebook-python-mode python-mode "EIN[python]"
|
|
||||||
"Use `python-mode' for whole notebook buffer.")
|
|
||||||
|
|
||||||
(defun ein:notebook-open-in-browser (&optional print)
|
(defun ein:notebook-open-in-browser (&optional print)
|
||||||
"Open current notebook in web browser.
|
"Open current notebook in web browser.
|
||||||
When the prefix argument (``C-u``) is given, print page is opened.
|
When the prefix argument (``C-u``) is given, print page is opened.
|
||||||
|
|
|
@ -125,13 +125,34 @@ Usage::
|
||||||
(ein:xml-replace-attributes dom 'a 'href replace-p replacer)
|
(ein:xml-replace-attributes dom 'a 'href replace-p replacer)
|
||||||
(ein:xml-replace-attributes dom 'img 'src replace-p replacer)))
|
(ein:xml-replace-attributes dom 'img 'src replace-p replacer)))
|
||||||
|
|
||||||
|
(defun ein:output-area-type (mime-type)
|
||||||
|
"Investigate why :image/svg+xml to :svg and :text/plain to :text"
|
||||||
|
(let* ((mime-str (if (symbolp mime-type) (symbol-name mime-type) mime-type))
|
||||||
|
(minor-kw (car (nreverse (split-string mime-str "/"))))
|
||||||
|
(minor (car (nreverse (split-string minor-kw ":")))))
|
||||||
|
(intern (concat ":"
|
||||||
|
(cond ((string= minor "plain") "text")
|
||||||
|
(t (cl-subseq minor 0 (cl-search "+" minor))))))))
|
||||||
|
|
||||||
|
(defun ein:output-area-convert-mime-types (json data)
|
||||||
|
(let ((known-mimes (cl-remove-if-not
|
||||||
|
#'identity
|
||||||
|
(mapcar (lambda (x) (intern-soft (concat ":" x)))
|
||||||
|
(mailcap-mime-types)))))
|
||||||
|
(mapc (lambda (x)
|
||||||
|
(-when-let* ((mime-val (plist-get data x))
|
||||||
|
(minor-kw (ein:output-area-type x)))
|
||||||
|
(setq json (plist-put json minor-kw mime-val))))
|
||||||
|
known-mimes)
|
||||||
|
json))
|
||||||
|
|
||||||
(defmacro ein:output-area-case-type (json &rest case-body)
|
(defmacro ein:output-area-case-type (json &rest case-body)
|
||||||
`(progn (aif (plist-get ,json :data) (setq ,json it)) ;; nbformat v4 ???
|
`(progn (aif (plist-get ,json :data) (setq ,json it))
|
||||||
(seq-some (lambda (type)
|
(seq-some (lambda (type)
|
||||||
(when-let ((value (plist-get ,json type)))
|
(when-let ((value (plist-get ,json type)))
|
||||||
,@case-body
|
,@case-body
|
||||||
t))
|
t))
|
||||||
(list :svg :png :jpeg :text :html :latex :javascript))))
|
(list :image/svg+xml :image/png :image/jpeg :text/plain :text/html :application/latex :application/tex :application/javascript))))
|
||||||
|
|
||||||
(provide 'ein-output-area)
|
(provide 'ein-output-area)
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,7 @@ working."
|
||||||
(lambda (name msg-type content -metadata-not-used-)
|
(lambda (name msg-type content -metadata-not-used-)
|
||||||
(ein:case-equal msg-type
|
(ein:case-equal msg-type
|
||||||
(("stream" "display_data")
|
(("stream" "display_data")
|
||||||
(ein:pytools-finish-tooltip name (ein:json-read-from-string (plist-get content :text)) nil))))
|
(ein:pytools-finish-tooltip name (ein:json-read-from-string (or (plist-get content :text) (plist-get (plist-get content :data) :text/plain))) nil))))
|
||||||
func)))
|
func)))
|
||||||
(ein:kernel-object-info-request
|
(ein:kernel-object-info-request
|
||||||
kernel func (list :object_info_reply
|
kernel func (list :object_info_reply
|
||||||
|
@ -178,7 +178,7 @@ pager buffer. You can explicitly specify the object by selecting it."
|
||||||
(ein:log 'debug "object[[%s]] other-window[[%s]]" object other-window)
|
(ein:log 'debug "object[[%s]] other-window[[%s]]" object other-window)
|
||||||
(ein:case-equal msg-type
|
(ein:case-equal msg-type
|
||||||
(("stream" "display_data")
|
(("stream" "display_data")
|
||||||
(aif (or (plist-get content :text) (plist-get content :data))
|
(aif (or (plist-get content :text) (plist-get (plist-get content :data) :text/plain))
|
||||||
(if (string-match ein:pytools-jump-to-source-not-found-regexp it)
|
(if (string-match ein:pytools-jump-to-source-not-found-regexp it)
|
||||||
(ein:log 'info
|
(ein:log 'info
|
||||||
"Jumping to the source of %s...Not found" object)
|
"Jumping to the source of %s...Not found" object)
|
||||||
|
@ -231,7 +231,7 @@ is defined."
|
||||||
(destructuring-bind (kernel object callback) packed
|
(destructuring-bind (kernel object callback) packed
|
||||||
(if (or (string= msg-type "stream")
|
(if (or (string= msg-type "stream")
|
||||||
(string= msg-type "display_data"))
|
(string= msg-type "display_data"))
|
||||||
(aif (or (plist-get content :text) (plist-get content :data))
|
(aif (or (plist-get content :text) (plist-get (plist-get content :data) :text/plain))
|
||||||
(if (string-match ein:pytools-jump-to-source-not-found-regexp it)
|
(if (string-match ein:pytools-jump-to-source-not-found-regexp it)
|
||||||
(ein:log 'info
|
(ein:log 'info
|
||||||
"Source of %s not found" object)
|
"Source of %s not found" object)
|
||||||
|
|
|
@ -37,11 +37,10 @@
|
||||||
:documentation
|
:documentation
|
||||||
"Worksheet without needs for saving.")
|
"Worksheet without needs for saving.")
|
||||||
|
|
||||||
(defun ein:scratchsheet-new (nbformat get-notebook-name discard-output-p
|
(defun ein:scratchsheet-new (nbformat get-notebook-name kernel events &rest args)
|
||||||
kernel events &rest args)
|
|
||||||
(apply #'make-instance 'ein:scratchsheet
|
(apply #'make-instance 'ein:scratchsheet
|
||||||
:nbformat nbformat :get-notebook-name get-notebook-name
|
:nbformat nbformat :get-notebook-name get-notebook-name
|
||||||
:discard-output-p discard-output-p :kernel kernel :events events
|
:kernel kernel :events events
|
||||||
args))
|
args))
|
||||||
|
|
||||||
(cl-defmethod ein:worksheet--buffer-name ((ws ein:scratchsheet))
|
(cl-defmethod ein:worksheet--buffer-name ((ws ein:scratchsheet))
|
||||||
|
|
|
@ -293,11 +293,10 @@ Normalize `buffer-undo-list' by removing extraneous details, and update the ein:
|
||||||
|
|
||||||
;;; Initialization of object and buffer
|
;;; Initialization of object and buffer
|
||||||
|
|
||||||
(defun ein:worksheet-new (nbformat get-notebook-name discard-output-p
|
(defun ein:worksheet-new (nbformat get-notebook-name kernel events &rest args)
|
||||||
kernel events &rest args)
|
|
||||||
(apply #'make-instance 'ein:worksheet
|
(apply #'make-instance 'ein:worksheet
|
||||||
:nbformat nbformat :get-notebook-name get-notebook-name
|
:nbformat nbformat :get-notebook-name get-notebook-name
|
||||||
:discard-output-p discard-output-p :kernel kernel :events events
|
:kernel kernel :events events
|
||||||
args))
|
args))
|
||||||
|
|
||||||
(cl-defmethod ein:worksheet-bind-events ((ws ein:worksheet))
|
(cl-defmethod ein:worksheet-bind-events ((ws ein:worksheet))
|
||||||
|
@ -463,21 +462,17 @@ Normalize `buffer-undo-list' by removing extraneous details, and update the ein:
|
||||||
"Convert worksheet WS into JSON ready alist.
|
"Convert worksheet WS into JSON ready alist.
|
||||||
It sets buffer internally so that caller doesn not have to set
|
It sets buffer internally so that caller doesn not have to set
|
||||||
current buffer."
|
current buffer."
|
||||||
(let* ((discard-output-p (ein:worksheet--discard-output-p ws))
|
(let* ((cells (ein:with-possibly-killed-buffer (ein:worksheet-buffer ws)
|
||||||
(cells (ein:with-possibly-killed-buffer (ein:worksheet-buffer ws)
|
|
||||||
(mapcar (lambda (c)
|
(mapcar (lambda (c)
|
||||||
(ein:cell-to-json
|
(ein:cell-to-json c))
|
||||||
c (ein:funcall-packed discard-output-p c)))
|
|
||||||
(ein:worksheet-get-cells ws)))))
|
(ein:worksheet-get-cells ws)))))
|
||||||
`((cells . ,(apply #'vector cells))
|
`((cells . ,(apply #'vector cells))
|
||||||
,@(ein:aand (ein:worksheet--metadata ws) `((metadata . ,it))))))
|
,@(ein:aand (ein:worksheet--metadata ws) `((metadata . ,it))))))
|
||||||
|
|
||||||
(cl-defmethod ein:worksheet-to-nb4-json ((ws ein:worksheet) wsidx)
|
(cl-defmethod ein:worksheet-to-nb4-json ((ws ein:worksheet) wsidx)
|
||||||
(let* ((discard-output-p (slot-value ws 'discard-output-p))
|
(let* ((cells (ein:with-possibly-killed-buffer (ein:worksheet-buffer ws)
|
||||||
(cells (ein:with-possibly-killed-buffer (ein:worksheet-buffer ws)
|
|
||||||
(mapcar (lambda (c)
|
(mapcar (lambda (c)
|
||||||
(ein:cell-to-nb4-json
|
(ein:cell-to-nb4-json c wsidx))
|
||||||
c wsidx (ein:funcall-packed discard-output-p c)))
|
|
||||||
(ein:worksheet-get-cells ws)))))
|
(ein:worksheet-get-cells ws)))))
|
||||||
cells))
|
cells))
|
||||||
|
|
||||||
|
@ -613,7 +608,7 @@ If you really want use this command, you can do something like this
|
||||||
t))
|
t))
|
||||||
(ein:worksheet--shift-undo-list cell)
|
(ein:worksheet--shift-undo-list cell)
|
||||||
(let ((inhibit-read-only t)
|
(let ((inhibit-read-only t)
|
||||||
(buffer-undo-list t)) ; disable undo recording
|
(buffer-undo-list t))
|
||||||
(apply #'ewoc-delete
|
(apply #'ewoc-delete
|
||||||
(slot-value ws 'ewoc)
|
(slot-value ws 'ewoc)
|
||||||
(ein:cell-all-element cell)))
|
(ein:cell-all-element cell)))
|
||||||
|
@ -772,13 +767,12 @@ directly."
|
||||||
(when focus (ein:cell-goto new relpos))
|
(when focus (ein:cell-goto new relpos))
|
||||||
(ein:worksheet--unshift-undo-list new nil cell))))
|
(ein:worksheet--unshift-undo-list new nil cell))))
|
||||||
|
|
||||||
(defun ein:worksheet-change-cell-type (ws cell type &optional level focus)
|
(defun ein:worksheet-change-cell-type (ws cell type &optional focus)
|
||||||
"Change the cell type of the current cell.
|
"Change the cell type of the current cell.
|
||||||
Prompt will appear in the minibuffer.
|
Prompt will appear in the minibuffer.
|
||||||
|
|
||||||
When used in as a Lisp function, TYPE (string) should be chose
|
When used in as a Lisp function, TYPE (string) should be chose
|
||||||
from \"code\", \"markdown\", \"raw\" and \"heading\". LEVEL is
|
from \"code\", \"markdown\", \"raw\" and \"heading\"."
|
||||||
an integer used only when the TYPE is \"heading\"."
|
|
||||||
(interactive
|
(interactive
|
||||||
(let* ((ws (ein:worksheet--get-ws-or-error))
|
(let* ((ws (ein:worksheet--get-ws-or-error))
|
||||||
(cell (ein:worksheet-get-current-cell))
|
(cell (ein:worksheet-get-current-cell))
|
||||||
|
@ -791,18 +785,12 @@ an integer used only when the TYPE is \"heading\"."
|
||||||
(type (case key
|
(type (case key
|
||||||
(?c "code")
|
(?c "code")
|
||||||
(?m "markdown")
|
(?m "markdown")
|
||||||
(?r "raw")
|
(?r "raw"))))
|
||||||
(t "heading")))
|
(list ws cell type t)))
|
||||||
(level (when (equal type "heading")
|
|
||||||
(string-to-number (char-to-string key)))))
|
|
||||||
(list ws cell type level t)))
|
|
||||||
|
|
||||||
(let ((relpos (ein:cell-relative-point cell))
|
(let ((relpos (ein:cell-relative-point cell))
|
||||||
(new (ein:cell-convert-inplace cell type)))
|
(new (ein:cell-convert-inplace cell type)))
|
||||||
(when (ein:codecell-p new)
|
(when (ein:codecell-p new)
|
||||||
(setf (slot-value new 'kernel) (slot-value ws 'kernel)))
|
(setf (slot-value new 'kernel) (slot-value ws 'kernel)))
|
||||||
(when level
|
|
||||||
(ein:cell-change-level new level))
|
|
||||||
(ein:worksheet--unshift-undo-list cell)
|
(ein:worksheet--unshift-undo-list cell)
|
||||||
(when focus (ein:cell-goto new relpos))))
|
(when focus (ein:cell-goto new relpos))))
|
||||||
|
|
||||||
|
@ -819,10 +807,7 @@ argument \(C-u)."
|
||||||
(head (buffer-substring beg pos))
|
(head (buffer-substring beg pos))
|
||||||
(new (ein:worksheet-insert-cell-above ws
|
(new (ein:worksheet-insert-cell-above ws
|
||||||
(slot-value cell 'cell-type)
|
(slot-value cell 'cell-type)
|
||||||
cell))
|
cell)))
|
||||||
)
|
|
||||||
(when (ein:headingcell-p cell)
|
|
||||||
(ein:cell-change-level new (slot-value cell 'level)))
|
|
||||||
(undo-boundary)
|
(undo-boundary)
|
||||||
(delete-region beg pos)
|
(delete-region beg pos)
|
||||||
(unless no-trim
|
(unless no-trim
|
||||||
|
@ -1253,26 +1238,6 @@ function."
|
||||||
(ein:worksheet-get-cells ws))))))
|
(ein:worksheet-get-cells ws))))))
|
||||||
ws (current-buffer)))))
|
ws (current-buffer)))))
|
||||||
|
|
||||||
|
|
||||||
;;; Imenu
|
|
||||||
|
|
||||||
(defun ein:worksheet-imenu-create-index ()
|
|
||||||
"`imenu-create-index-function' for notebook buffer."
|
|
||||||
;; As Imenu does not provide the way to represent level *and*
|
|
||||||
;; position, use #'s to do that.
|
|
||||||
(cl-loop for cell in (when (ein:worksheet-p ein:%worksheet%)
|
|
||||||
(seq-filter #'ein:headingcell-p
|
|
||||||
(ein:worksheet-get-cells ein:%worksheet%)))
|
|
||||||
for sharps = (cl-loop repeat (slot-value cell 'level) collect "#")
|
|
||||||
for text = (ein:cell-get-text cell)
|
|
||||||
for name = (ein:join-str "" (append sharps (list " " text)))
|
|
||||||
collect (cons name (ein:cell-input-pos-min cell))))
|
|
||||||
|
|
||||||
(defun ein:worksheet-imenu-setup ()
|
|
||||||
"Called via notebook mode hooks."
|
|
||||||
(setq imenu-create-index-function #'ein:worksheet-imenu-create-index))
|
|
||||||
|
|
||||||
|
|
||||||
;;; Workarounds
|
;;; Workarounds
|
||||||
|
|
||||||
(defadvice fill-paragraph (around ein:worksheet-fill-paragraph activate)
|
(defadvice fill-paragraph (around ein:worksheet-fill-paragraph activate)
|
||||||
|
|
|
@ -120,8 +120,7 @@
|
||||||
(ein:output-area-case-type
|
(ein:output-area-case-type
|
||||||
json
|
json
|
||||||
(cl-case type
|
(cl-case type
|
||||||
((:svg :png :jpeg)
|
((:image/svg+xml :image/png :image/jpeg)
|
||||||
(message "got here %s" type)
|
|
||||||
(let ((file (or explicit-file (ob-ein--inline-image-info value))))
|
(let ((file (or explicit-file (ob-ein--inline-image-info value))))
|
||||||
(ob-ein--write-base64-image value file)
|
(ob-ein--write-base64-image value file)
|
||||||
(setq result (format "[[file:%s]]" file))))
|
(setq result (format "[[file:%s]]" file))))
|
||||||
|
|
|
@ -67,10 +67,6 @@ To make OUTPUTS data, use `ein:testing-codecell-pyout-data'."
|
||||||
(defun ein:testing-htmlcell-data (&optional source)
|
(defun ein:testing-htmlcell-data (&optional source)
|
||||||
(ein:testing-textcell-data source "html"))
|
(ein:testing-textcell-data source "html"))
|
||||||
|
|
||||||
(defun ein:testing-headingcell-data (&optional source level)
|
|
||||||
(append (ein:testing-textcell-data source "heading")
|
|
||||||
(list :level (or level 1))))
|
|
||||||
|
|
||||||
(provide 'ein-testing-cell)
|
(provide 'ein-testing-cell)
|
||||||
|
|
||||||
;;; ein-testing-cell.el ends here
|
;;; ein-testing-cell.el ends here
|
||||||
|
|
|
@ -128,47 +128,47 @@ some input
|
||||||
,regexp-display-data)))))
|
,regexp-display-data)))))
|
||||||
|
|
||||||
(eintest:gene-test-cell-insert-output-pyout-and-display-data
|
(eintest:gene-test-cell-insert-output-pyout-and-display-data
|
||||||
text ("some output") ((:data (:text "some output"))))
|
text ("some output") ((:data (:text/plain "some output"))))
|
||||||
|
|
||||||
(eintest:gene-test-cell-insert-output-pyout-and-display-data
|
(eintest:gene-test-cell-insert-output-pyout-and-display-data
|
||||||
latex
|
latex
|
||||||
("some output \\\\LaTeX")
|
("some output \\\\LaTeX")
|
||||||
((:data (:latex "some output \\LaTeX"))))
|
((:data (:application/latex "some output \\LaTeX"))))
|
||||||
|
|
||||||
(when (image-type-available-p 'svg)
|
(when (image-type-available-p 'svg)
|
||||||
(eintest:gene-test-cell-insert-output-pyout-and-display-data
|
(eintest:gene-test-cell-insert-output-pyout-and-display-data
|
||||||
svg
|
svg
|
||||||
("\\.")
|
("\\.")
|
||||||
((:data (:text "some output text" :svg ein:testing-example-svg)))))
|
((:data (:text/plain "some output text" :image/svg+xml ein:testing-example-svg)))))
|
||||||
|
|
||||||
(eintest:gene-test-cell-insert-output-pyout-and-display-data
|
(eintest:gene-test-cell-insert-output-pyout-and-display-data
|
||||||
html
|
html
|
||||||
("some output text")
|
("some output text")
|
||||||
((:data (:text "some output text" :html "<b>not shown</b>"))))
|
((:data (:text/plain "some output text" :text/html "<b>not shown</b>"))))
|
||||||
|
|
||||||
(eintest:gene-test-cell-insert-output-pyout-and-display-data
|
(eintest:gene-test-cell-insert-output-pyout-and-display-data
|
||||||
javascript
|
javascript
|
||||||
("some output text")
|
("some output text")
|
||||||
((:data (:text "some output text" :javascript "$.do.something()"))))
|
((:data (:text/plain "some output text" :application/javascript "$.do.something()"))))
|
||||||
|
|
||||||
(eintest:gene-test-cell-insert-output-pyout-and-display-data
|
(eintest:gene-test-cell-insert-output-pyout-and-display-data
|
||||||
text-two
|
text-two
|
||||||
("first output text" "second output text")
|
("first output text" "second output text")
|
||||||
((:data (:text "first output text")) (:data (:text "second output text"))))
|
((:data (:text/plain "first output text")) (:data (:text/plain "second output text"))))
|
||||||
|
|
||||||
(eintest:gene-test-cell-insert-output-pyout-and-display-data
|
(eintest:gene-test-cell-insert-output-pyout-and-display-data
|
||||||
text-javascript
|
text-javascript
|
||||||
("first output text" "second output text")
|
("first output text" "second output text")
|
||||||
((:data (:text "first output text"))
|
((:data (:text/plain "first output text"))
|
||||||
(:data (:text "second output text" :javascript "$.do.something()"))))
|
(:data (:text/plain "second output text" :application/javascript "$.do.something()"))))
|
||||||
|
|
||||||
(when (image-type-available-p 'svg)
|
(when (image-type-available-p 'svg)
|
||||||
(eintest:gene-test-cell-insert-output-pyout-and-display-data
|
(eintest:gene-test-cell-insert-output-pyout-and-display-data
|
||||||
text-latex-svg
|
text-latex-svg
|
||||||
("first output text" "second output \\\\LaTeX")
|
("first output text" "second output \\\\LaTeX")
|
||||||
((:data (:text "first output text"))
|
((:data (:text/plain "first output text"))
|
||||||
(:data (:latex "second output \\LaTeX"))
|
(:data (:application/latex "second output \\LaTeX"))
|
||||||
(:data (:text "some output text" :svg ein:testing-example-svg)))))
|
(:data (:text/plain "some output text" :image/svg+xml ein:testing-example-svg)))))
|
||||||
|
|
||||||
;; Insert pyerr
|
;; Insert pyerr
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,7 @@
|
||||||
(input (ein:join-str "\n" '("first input" "second input")))
|
(input (ein:join-str "\n" '("first input" "second input")))
|
||||||
(output-0 (list :output_type "execute_result"
|
(output-0 (list :output_type "execute_result"
|
||||||
:prompt_number output-prompt-number
|
:prompt_number output-prompt-number
|
||||||
:text (list "first output"
|
:text (list "first output" "second output")))
|
||||||
"second output")))
|
|
||||||
(data (ein:testing-codecell-data
|
(data (ein:testing-codecell-data
|
||||||
input input-prompt-number (list output-0)))
|
input input-prompt-number (list output-0)))
|
||||||
(cell (eintest:cell-from-json data)))
|
(cell (eintest:cell-from-json data)))
|
||||||
|
@ -62,21 +61,13 @@
|
||||||
(should (ein:rawcell-p cell))
|
(should (ein:rawcell-p cell))
|
||||||
(should (equal (oref cell :input) input))))
|
(should (equal (oref cell :input) input))))
|
||||||
|
|
||||||
(ert-deftest ein:cell-from-json-heading ()
|
|
||||||
(let* ((input (ein:join-str "\n" '("first input" "second input")))
|
|
||||||
(data (list :cell_type "heading" :source input))
|
|
||||||
(cell (eintest:cell-from-json data)))
|
|
||||||
(should (ein:headingcell-p cell))
|
|
||||||
(should (equal (oref cell :input) input))))
|
|
||||||
|
|
||||||
|
|
||||||
;; ein:cell-to-json
|
;; ein:cell-to-json
|
||||||
|
|
||||||
(defun eintest:cell-to-json (cell input &optional discard-output)
|
(defun eintest:cell-to-json (cell input)
|
||||||
(mocker-let ((ein:cell-get-text
|
(mocker-let ((ein:cell-get-text
|
||||||
(cell)
|
(cell)
|
||||||
((:input (list cell) :output input))))
|
((:input (list cell) :output input))))
|
||||||
(ein:cell-to-json cell discard-output)))
|
(ein:cell-to-json cell)))
|
||||||
|
|
||||||
(ert-deftest ein:cell-to-json-code ()
|
(ert-deftest ein:cell-to-json-code ()
|
||||||
(let* ((input-prompt-number 111)
|
(let* ((input-prompt-number 111)
|
||||||
|
@ -96,24 +87,6 @@
|
||||||
(should (equal (cdr (assq 'language alist)) "python"))
|
(should (equal (cdr (assq 'language alist)) "python"))
|
||||||
(should (equal (cdr (assq 'collapsed alist)) json-false))))
|
(should (equal (cdr (assq 'collapsed alist)) json-false))))
|
||||||
|
|
||||||
(ert-deftest ein:cell-to-json-code-discard-output ()
|
|
||||||
(let* ((input-prompt-number 111)
|
|
||||||
(output-prompt-number 222)
|
|
||||||
(input (ein:join-str "\n" '("first input" "second input")))
|
|
||||||
(output-0 (list :output_type "execute_result"
|
|
||||||
:prompt_number output-prompt-number
|
|
||||||
:text (list "first output"
|
|
||||||
"second output")))
|
|
||||||
(data (ein:testing-codecell-data
|
|
||||||
input input-prompt-number (list output-0)))
|
|
||||||
(cell (eintest:cell-from-json data))
|
|
||||||
(alist (eintest:cell-to-json cell input t)))
|
|
||||||
(should (equal (cdr (assq 'input alist)) "first input\nsecond input"))
|
|
||||||
(should (equal (cdr (assq 'cell_type alist)) "code"))
|
|
||||||
(should (equal (cdr (assq 'outputs alist)) []))
|
|
||||||
(should (equal (cdr (assq 'language alist)) "python"))
|
|
||||||
(should (equal (cdr (assq 'collapsed alist)) json-false))))
|
|
||||||
|
|
||||||
(ert-deftest ein:cell-to-json-text ()
|
(ert-deftest ein:cell-to-json-text ()
|
||||||
(let* ((input (ein:join-str "\n" '("first input" "second input")))
|
(let* ((input (ein:join-str "\n" '("first input" "second input")))
|
||||||
(data (list :cell_type "text" :source input))
|
(data (list :cell_type "text" :source input))
|
||||||
|
@ -146,16 +119,6 @@
|
||||||
(should (equal (cdr (assq 'cell_type alist)) "raw"))
|
(should (equal (cdr (assq 'cell_type alist)) "raw"))
|
||||||
(should (equal (cdr (assq 'source alist)) "first input\nsecond input"))))
|
(should (equal (cdr (assq 'source alist)) "first input\nsecond input"))))
|
||||||
|
|
||||||
(ert-deftest ein:cell-to-json-heading ()
|
|
||||||
(let* ((input (ein:join-str "\n" '("first input" "second input")))
|
|
||||||
(data (list :cell_type "heading" :source input))
|
|
||||||
(cell (eintest:cell-from-json data))
|
|
||||||
(alist (eintest:cell-to-json cell input)))
|
|
||||||
(should (equal (cdr (assq 'cell_type alist)) "heading"))
|
|
||||||
(should (equal (cdr (assq 'source alist)) "first input\nsecond input"))
|
|
||||||
(should (equal (cdr (assq 'level alist)) 1))))
|
|
||||||
|
|
||||||
|
|
||||||
;;; ein:cell-convert/copy
|
;;; ein:cell-convert/copy
|
||||||
|
|
||||||
(ert-deftest ein:cell-convert-code-to-markdown ()
|
(ert-deftest ein:cell-convert-code-to-markdown ()
|
||||||
|
@ -206,7 +169,7 @@
|
||||||
(should (equal (oref new :input) input))))
|
(should (equal (oref new :input) input))))
|
||||||
|
|
||||||
(ert-deftest ein:cell-copy-text-types ()
|
(ert-deftest ein:cell-copy-text-types ()
|
||||||
(cl-loop for cell-type in '("text" "html" "markdown" "raw" "heading")
|
(cl-loop for cell-type in '("text" "html" "markdown" "raw")
|
||||||
for cell-p = (intern (format "ein:%scell-p" cell-type))
|
for cell-p = (intern (format "ein:%scell-p" cell-type))
|
||||||
do
|
do
|
||||||
(let* ((input (ein:join-str "\n" '("first input" "second input")))
|
(let* ((input (ein:join-str "\n" '("first input" "second input")))
|
||||||
|
|
|
@ -86,7 +86,7 @@
|
||||||
(ein:kernel--handle-shell-reply kernel (json-encode packet))))
|
(ein:kernel--handle-shell-reply kernel (json-encode packet))))
|
||||||
|
|
||||||
(defun eintest:kernel-fake-stream (kernel msg-id data)
|
(defun eintest:kernel-fake-stream (kernel msg-id data)
|
||||||
(let* ((content (list :data data
|
(let* ((content (list :text data
|
||||||
:name "stdout"))
|
:name "stdout"))
|
||||||
(packet (list :header (list :msg_type "stream")
|
(packet (list :header (list :msg_type "stream")
|
||||||
:parent_header (list :msg_id msg-id)
|
:parent_header (list :msg_id msg-id)
|
||||||
|
@ -143,16 +143,11 @@ is not found."
|
||||||
(list (ein:testing-codecell-data "import numpy")
|
(list (ein:testing-codecell-data "import numpy")
|
||||||
(ein:testing-markdowncell-data "*markdown* text")
|
(ein:testing-markdowncell-data "*markdown* text")
|
||||||
(ein:testing-rawcell-data "`raw` cell text")
|
(ein:testing-rawcell-data "`raw` cell text")
|
||||||
(ein:testing-htmlcell-data "<b>HTML</b> text")
|
(ein:testing-htmlcell-data "<b>HTML</b> text")))
|
||||||
(ein:testing-headingcell-data "Heading 1" 1)
|
|
||||||
(ein:testing-headingcell-data "Heading 2" 2)
|
|
||||||
(ein:testing-headingcell-data "Heading 3" 3)
|
|
||||||
(ein:testing-headingcell-data "Heading 4" 4)
|
|
||||||
(ein:testing-headingcell-data "Heading 5" 5)
|
|
||||||
(ein:testing-headingcell-data "Heading 6" 6)))
|
|
||||||
(should (ein:$notebook-p ein:%notebook%))
|
(should (ein:$notebook-p ein:%notebook%))
|
||||||
(should (equal (ein:$notebook-notebook-name ein:%notebook%) ein:testing-notebook-dummy-name))
|
(should (equal (ein:$notebook-notebook-name ein:%notebook%)
|
||||||
(should (equal (ein:worksheet-ncells ein:%worksheet%) 10))
|
ein:testing-notebook-dummy-name))
|
||||||
|
(should (equal (ein:worksheet-ncells ein:%worksheet%) 4))
|
||||||
(let ((cells (ein:worksheet-get-cells ein:%worksheet%)))
|
(let ((cells (ein:worksheet-get-cells ein:%worksheet%)))
|
||||||
(should (ein:codecell-p (nth 0 cells)))
|
(should (ein:codecell-p (nth 0 cells)))
|
||||||
(should (ein:markdowncell-p (nth 1 cells)))
|
(should (ein:markdowncell-p (nth 1 cells)))
|
||||||
|
@ -161,16 +156,8 @@ is not found."
|
||||||
(should (equal (ein:cell-get-text (nth 0 cells)) "import numpy"))
|
(should (equal (ein:cell-get-text (nth 0 cells)) "import numpy"))
|
||||||
(should (equal (ein:cell-get-text (nth 1 cells)) "*markdown* text"))
|
(should (equal (ein:cell-get-text (nth 1 cells)) "*markdown* text"))
|
||||||
(should (equal (ein:cell-get-text (nth 2 cells)) "`raw` cell text"))
|
(should (equal (ein:cell-get-text (nth 2 cells)) "`raw` cell text"))
|
||||||
(should (equal (ein:cell-get-text (nth 3 cells)) "<b>HTML</b> text"))
|
(should (equal (ein:cell-get-text (nth 3 cells)) "<b>HTML</b> text")))))
|
||||||
(cl-loop for i from 4 to 9
|
|
||||||
for level from 1
|
|
||||||
for cell = (nth i cells)
|
|
||||||
do (should (ein:headingcell-p cell))
|
|
||||||
do (should (equal (ein:cell-get-text cell)
|
|
||||||
(format "Heading %s" level)))
|
|
||||||
do (should (= (oref cell :level) level))))))
|
|
||||||
|
|
||||||
|
|
||||||
;;; Destructor
|
;;; Destructor
|
||||||
|
|
||||||
(defvar ein:testing-notebook-del-args-log 'nolog)
|
(defvar ein:testing-notebook-del-args-log 'nolog)
|
||||||
|
@ -340,7 +327,6 @@ some text
|
||||||
(when (< (ein:$notebook-nbformat ein:%notebook%) 4)
|
(when (< (ein:$notebook-nbformat ein:%notebook%) 4)
|
||||||
;; toggle to heading
|
;; toggle to heading
|
||||||
(call-interactively #'ein:worksheet-toggle-cell-type)
|
(call-interactively #'ein:worksheet-toggle-cell-type)
|
||||||
(should (ein:headingcell-p (ein:worksheet-get-current-cell)))
|
|
||||||
(should (looking-back "some text"))
|
(should (looking-back "some text"))
|
||||||
;; toggle to code
|
;; toggle to code
|
||||||
(call-interactively #'ein:worksheet-toggle-cell-type)
|
(call-interactively #'ein:worksheet-toggle-cell-type)
|
||||||
|
@ -356,11 +342,11 @@ some text
|
||||||
(should (ein:codecell-p (ein:worksheet-get-current-cell)))
|
(should (ein:codecell-p (ein:worksheet-get-current-cell)))
|
||||||
(should (slot-boundp (ein:worksheet-get-current-cell) :kernel))
|
(should (slot-boundp (ein:worksheet-get-current-cell) :kernel))
|
||||||
(let ((check
|
(let ((check
|
||||||
(lambda (type &optional level)
|
(lambda (type)
|
||||||
(let ((cell-p (intern (format "ein:%scell-p" type)))
|
(let ((cell-p (intern (format "ein:%scell-p" type)))
|
||||||
(cell (ein:worksheet-get-current-cell)))
|
(cell (ein:worksheet-get-current-cell)))
|
||||||
(ein:worksheet-change-cell-type ein:%worksheet% cell
|
(ein:worksheet-change-cell-type ein:%worksheet% cell
|
||||||
type level t)
|
type t)
|
||||||
(let ((new (ein:worksheet-get-current-cell)))
|
(let ((new (ein:worksheet-get-current-cell)))
|
||||||
(should-not (eq new cell))
|
(should-not (eq new cell))
|
||||||
(should (funcall cell-p new)))
|
(should (funcall cell-p new)))
|
||||||
|
@ -368,9 +354,6 @@ some text
|
||||||
;; change type: code (no change) -> markdown -> raw
|
;; change type: code (no change) -> markdown -> raw
|
||||||
(cl-loop for type in '("code" "markdown" "raw")
|
(cl-loop for type in '("code" "markdown" "raw")
|
||||||
do (funcall check type))
|
do (funcall check type))
|
||||||
;; change level: 1 to 6
|
|
||||||
(cl-loop for level from 1 to 6
|
|
||||||
do (funcall check "heading" level))
|
|
||||||
;; back to code
|
;; back to code
|
||||||
(funcall check "code")
|
(funcall check "code")
|
||||||
(should (slot-boundp (ein:worksheet-get-current-cell) :kernel)))))
|
(should (slot-boundp (ein:worksheet-get-current-cell) :kernel)))))
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
(oset ein:%notification% :tab (ein:testing-notification-tab-mock))
|
(oset ein:%notification% :tab (ein:testing-notification-tab-mock))
|
||||||
(ein:notification-status-set kernel
|
(ein:notification-status-set kernel
|
||||||
'status_busy.Kernel)
|
'status_busy.Kernel)
|
||||||
(should (string-prefix-p "IP[y]: Kernel is busy... | /1\\ /2\\ /3\\ [+]"
|
(should (string-prefix-p "IP[y]: Kernel busy... | /1\\ /2\\ /3\\ [+]"
|
||||||
(ein:header-line)))))
|
(ein:header-line)))))
|
||||||
|
|
||||||
(ert-deftest ein:header-line-notebook-status-busy ()
|
(ert-deftest ein:header-line-notebook-status-busy ()
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
(oset ein:%notification% :tab (ein:testing-notification-tab-mock))
|
(oset ein:%notification% :tab (ein:testing-notification-tab-mock))
|
||||||
(ein:notification-status-set notebook
|
(ein:notification-status-set notebook
|
||||||
'notebook_saved.Notebook)
|
'notebook_saved.Notebook)
|
||||||
(should (string-prefix-p "IP[y]: Notebook is saved | /1\\ /2\\ /3\\ [+]"
|
(should (string-prefix-p "IP[y]: Notebook saved | /1\\ /2\\ /3\\ [+]"
|
||||||
(ein:header-line)))))
|
(ein:header-line)))))
|
||||||
|
|
||||||
(ert-deftest ein:header-line-notebook-complex ()
|
(ert-deftest ein:header-line-notebook-complex ()
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
(ein:notification-status-set notebook
|
(ein:notification-status-set notebook
|
||||||
'notebook_saving.Notebook)
|
'notebook_saving.Notebook)
|
||||||
(should (string-prefix-p
|
(should (string-prefix-p
|
||||||
(concat "IP[y]: Saving Notebook... | "
|
(concat "IP[y]: Saving notebook... | "
|
||||||
(substitute-command-keys "Kernel requires restart \\<ein:notebook-mode-map>\\[ein:notebook-restart-session-command-km] | ")
|
(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 | "
|
;;"Kernel requires restart C-c C-x C-r | "
|
||||||
"/1\\ /2\\ /3\\ [+]") (ein:header-line)))))
|
"/1\\ /2\\ /3\\ [+]") (ein:header-line)))))
|
||||||
|
|
|
@ -7,12 +7,10 @@
|
||||||
(list (ein:testing-codecell-data "code example input")
|
(list (ein:testing-codecell-data "code example input")
|
||||||
(ein:testing-markdowncell-data "markdown example input")
|
(ein:testing-markdowncell-data "markdown example input")
|
||||||
(ein:testing-rawcell-data "raw example input")
|
(ein:testing-rawcell-data "raw example input")
|
||||||
(ein:testing-htmlcell-data "html example input")
|
(ein:testing-htmlcell-data "html example input")))
|
||||||
(ein:testing-headingcell-data "heading example input")))
|
|
||||||
|
|
||||||
(defun ein:testing-worksheet-new ()
|
(defun ein:testing-worksheet-new ()
|
||||||
(make-instance 'ein:worksheet
|
(make-instance 'ein:worksheet))
|
||||||
:discard-output-p (cons #'ignore nil)))
|
|
||||||
|
|
||||||
(defun ein:testing-worksheet-to-json (cells &optional metadata)
|
(defun ein:testing-worksheet-to-json (cells &optional metadata)
|
||||||
(let* ((ws-0 (ein:worksheet-from-json (ein:testing-worksheet-new)
|
(let* ((ws-0 (ein:worksheet-from-json (ein:testing-worksheet-new)
|
||||||
|
|
Loading…
Add table
Reference in a new issue