mirror of
https://github.com/vale981/emacs-ipython-notebook
synced 2025-03-04 16:51:38 -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 "content" ecukes-exclude-tags)
|
||||
(when (eq system-type 'darwin)
|
||||
(!cons "julia" ecukes-exclude-tags)))
|
||||
|
||||
(unless (fboundp 'libxml-parse-xml-region)
|
||||
(!cons "julia" ecukes-exclude-tags))
|
||||
(!cons "svg" ecukes-exclude-tags))
|
||||
|
||||
(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 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
|
||||
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)
|
257
lisp/ein-cell.el
257
lisp/ein-cell.el
|
@ -113,36 +113,6 @@ Delete current text first, thus effecting a \"refresh\"."
|
|||
"Face for cell output area errors"
|
||||
: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
|
||||
'((t :inherit header-line))
|
||||
"Face for cell output prompt"
|
||||
|
@ -280,7 +250,6 @@ a number will limit the number of lines in a cell output."
|
|||
(("html") 'ein:htmlcell)
|
||||
(("markdown") 'ein:markdowncell)
|
||||
(("raw") 'ein:rawcell)
|
||||
(("heading") 'ein:headingcell)
|
||||
(("shared-output") 'ein:shared-output-cell)
|
||||
(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))
|
||||
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)
|
||||
(let ((new (ein:cell-from-type type)))
|
||||
;; 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)))
|
||||
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))
|
||||
(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)))
|
||||
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
|
||||
|
||||
(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))
|
||||
'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))
|
||||
"Insert input of the CELL in the buffer.
|
||||
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."
|
||||
'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)
|
||||
"Return the face (symbol) for output area."
|
||||
(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")
|
||||
|
||||
(defun ein:cell-output-type (mime-type)
|
||||
"Investigate why :image/svg+xml to :svg and :text/plain to :text"
|
||||
(defun ein:cell-extract-image-format (mime-type)
|
||||
"From :image/svg+xml to \"svg\"."
|
||||
(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))))))))
|
||||
(cl-subseq minor 0 (cl-search "+" minor))))
|
||||
|
||||
(defun ein:cell-append-mime-type (json)
|
||||
(ein:output-area-case-type
|
||||
json
|
||||
(cl-case type
|
||||
((:html)
|
||||
((:text/html)
|
||||
(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
|
||||
(base64-decode-string value)
|
||||
(error value))
|
||||
(intern (car (nreverse
|
||||
(split-string (symbol-name type) ":"))))
|
||||
(intern-soft (ein:cell-extract-image-format type))
|
||||
t)))
|
||||
(if ein:output-area-inlined-images
|
||||
(ein:insert-image image)
|
||||
|
@ -999,124 +935,38 @@ Called from ewoc pretty printer via `ein:cell-insert-output'."
|
|||
text)
|
||||
(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."
|
||||
`((input . ,(ein:cell-get-text cell))
|
||||
(cell_type . "code")
|
||||
,@(aif (ein:oref-safe cell 'input-prompt-number)
|
||||
`((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"))
|
||||
(collapsed . ,(if (slot-value cell 'collapsed) t json-false))))
|
||||
|
||||
(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-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))))
|
||||
))))
|
||||
(cl-defmethod ein:cell-to-nb4-json ((cell ein:codecell) wsidx)
|
||||
(let ((execute-count (aif (ein:oref-safe cell 'input-prompt-number)
|
||||
(and (numberp it) it)))
|
||||
(metadata (slot-value cell 'metadata)))
|
||||
`((source . ,(ein:cell-get-text cell))
|
||||
(cell_type . "code")
|
||||
,@(if execute-count
|
||||
`((execution_count . ,execute-count))
|
||||
`((execution_count)))
|
||||
(outputs . ,(apply #'vector (or renamed-outputs outputs)))
|
||||
(metadata . ,metadata))))
|
||||
,@(when execute-count
|
||||
`((execution_count . ,execute-count)))
|
||||
(outputs . ,(apply #'vector (slot-value cell 'outputs)))
|
||||
(metadata . ,(plist-put metadata :collapsed (if (slot-value cell 'collapsed) t
|
||||
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))
|
||||
(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)))
|
||||
(setq metadata (plist-put metadata :ein.tags (format "worksheet-%s" wsidx)))
|
||||
`((cell_type . ,(slot-value cell 'cell-type))
|
||||
(source . ,(ein:cell-get-text cell))
|
||||
(metadata . ,metadata))))
|
||||
|
||||
(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))))))
|
||||
(metadata . ,(plist-put metadata :collapsed json-false)))))
|
||||
|
||||
(cl-defmethod ein:cell-next ((cell ein:basecell))
|
||||
"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)))
|
||||
(ein:events-trigger events 'set_next_input.Worksheet
|
||||
(list :cell cell :text text))
|
||||
(ein:events-trigger events 'maybe_reset_undo.Worksheet cell)
|
||||
))
|
||||
(ein:events-trigger events 'maybe_reset_undo.Worksheet cell)))
|
||||
|
||||
|
||||
;;; Output area
|
||||
|
||||
;; These function should go to ein-output-area.el. But as cell and
|
||||
;; EWOC is connected in complicated way, I will leave them in
|
||||
;; ein-cell.el.
|
||||
|
||||
(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)
|
||||
(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-output ((cell ein:codecell) msg-type content meta)
|
||||
;; (ein:output-area-convert-mime-types content (plist-get content :data))
|
||||
(ein:cell-append-output cell
|
||||
(plist-put
|
||||
(plist-put content :output_type msg-type)
|
||||
:metadata meta))
|
||||
;; (setf (slot-value cell 'dirty) t)
|
||||
(ein:events-trigger (slot-value cell 'events) 'maybe_reset_undo.Worksheet cell))
|
||||
|
||||
(cl-defmethod ein:cell--handle-clear-output ((cell ein:codecell) content
|
||||
_metadata)
|
||||
|
@ -1230,18 +1048,15 @@ Called from ewoc pretty printer via `ein:cell-insert-output'."
|
|||
|
||||
;;; 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."
|
||||
(cl-loop for out in (slot-value cell 'outputs)
|
||||
when (or (plist-member out :svg)
|
||||
(plist-member out :image/svg+xml)
|
||||
(plist-member out :png)
|
||||
(plist-member out :image/png)
|
||||
(plist-member out :jpeg)
|
||||
(plist-member out :image/jpeg))
|
||||
return t))
|
||||
(seq-some (lambda (out)
|
||||
(or (plist-member out :image/svg+xml)
|
||||
(plist-member out :image/png)
|
||||
(plist-member out :image/jpeg)))
|
||||
(slot-value cell 'outputs)))
|
||||
|
||||
(cl-defmethod ein:cell-has-image-ouput-p ((cell ein:textcell))
|
||||
(cl-defmethod ein:cell-has-image-output-p ((cell ein:textcell))
|
||||
nil)
|
||||
|
||||
(cl-defmethod ein:cell-get-tb-data ((cell ein:codecell))
|
||||
|
|
|
@ -166,10 +166,6 @@
|
|||
((nbformat :initarg :nbformat :type integer)
|
||||
(get-notebook-name :initarg :get-notebook-name :type cons
|
||||
: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
|
||||
:accessor ein:worksheet--saved-cells
|
||||
:documentation
|
||||
|
@ -251,7 +247,7 @@
|
|||
(input :initarg :input :type string
|
||||
:documentation "Place to hold data until it is rendered via `ewoc'.")
|
||||
(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)
|
||||
(cell-id :initarg :cell-id :initform (ein:utils-uuid) :type string
|
||||
:accessor ein:cell-id))
|
||||
|
@ -290,11 +286,6 @@ auto-execution mode flag in the connected buffer is `t'.")))
|
|||
(defclass ein:rawcell (ein:textcell)
|
||||
((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
|
||||
|
||||
(defclass ein:notification-status ()
|
||||
|
@ -331,9 +322,9 @@ auto-execution mode flag in the connected buffer is `t'.")))
|
|||
(ein:notification-status
|
||||
"NotebookStatus"
|
||||
:s2m
|
||||
'((notebook_saving.Notebook . "Saving Notebook...")
|
||||
(notebook_saved.Notebook . "Notebook is saved")
|
||||
(notebook_save_failed.Notebook . "Failed to save Notebook!")))
|
||||
'((notebook_saving.Notebook . "Saving notebook...")
|
||||
(notebook_saved.Notebook . "Notebook saved")
|
||||
(notebook_save_failed.Notebook . "Failed saving notebook!")))
|
||||
:type ein:notification-status)
|
||||
(kernel
|
||||
:initarg :kernel
|
||||
|
@ -342,7 +333,7 @@ auto-execution mode flag in the connected buffer is `t'.")))
|
|||
"KernelStatus"
|
||||
:s2m
|
||||
'((status_idle.Kernel . nil)
|
||||
(status_busy.Kernel . "Kernel is busy...")
|
||||
(status_busy.Kernel . "Kernel 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-km]")
|
||||
|
@ -352,7 +343,6 @@ auto-execution mode flag in the connected buffer is `t'.")))
|
|||
:type ein:notification-status))
|
||||
"Notification widget for Notebook.")
|
||||
|
||||
|
||||
;;; Events
|
||||
|
||||
(defclass ein:events ()
|
||||
|
|
|
@ -296,9 +296,11 @@ global setting. For global setting and more information, see
|
|||
:type "PUT"
|
||||
:headers '(("Content-Type" . "application/json"))
|
||||
: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)
|
||||
: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)))
|
||||
|
||||
(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)))
|
||||
(if (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"
|
||||
id session-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."))
|
||||
|
||||
(defun ein:kernel-run-after-start-hook (kernel)
|
||||
(ein:log 'debug "EIN:KERNEL-RUN-AFTER-START-HOOK")
|
||||
(mapc #'ein:funcall-packed
|
||||
(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: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)
|
||||
"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))
|
||||
"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
|
||||
:output OUTPUT-CALLBACK
|
||||
:clear_output CLEAR-OUTPUT-CALLBACK
|
||||
:set_next_input SET-NEXT-INPUT)
|
||||
|
||||
Right hand sides ending -CALLBACK above must cons a FUNCTION and its
|
||||
`packed' ARGUMENT which is a sublist of args:
|
||||
Right hand sides ending -CALLBACK above are of the form (FUNCTION ARG1 ... ARGN).
|
||||
(Hindsight: this was all much better implemented using `apply-partially')
|
||||
|
||||
(FUNCTION . ARGUMENT)
|
||||
|
||||
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'
|
||||
Return randomly generated MSG-ID tag uniquely identifying expectation of a kernel response.
|
||||
"
|
||||
;; 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.")
|
||||
(let* ((content (list
|
||||
:code code
|
||||
|
@ -452,7 +397,7 @@ Sample implementations
|
|||
:stop_on_error (or stop-on-error json-false)))
|
||||
(msg (ein:kernel--get-msg kernel "execute_request" content))
|
||||
(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)
|
||||
(ein:websocket-send-shell-channel kernel msg)
|
||||
(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)
|
||||
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)
|
||||
(when (ein:kernel-live-p 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)))
|
||||
|
||||
(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)))
|
||||
|
||||
(defun ein:kernel--handle-stdin-reply (kernel packet)
|
||||
(setf (ein:$kernel-stdin-activep kernel) t)
|
||||
(destructuring-bind
|
||||
(cl-destructuring-bind
|
||||
(&key header parent_header metadata content &allow-other-keys)
|
||||
(ein:json-read-from-string packet)
|
||||
(let ((msg-type (plist-get header :msg_type))
|
||||
(msg-id (plist-get header :msg_id))
|
||||
(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)
|
||||
(cond ((string-equal msg-type "input_request")
|
||||
(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)
|
||||
(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)
|
||||
(cl-loop with events = (ein:$kernel-events kernel)
|
||||
for p in payload
|
||||
for text = (or (plist-get p :text)
|
||||
(plist-get (plist-get p :data)
|
||||
:text/plain))
|
||||
for text = (or (plist-get p :text) (plist-get (plist-get p :data) :text/plain))
|
||||
for source = (plist-get p :source)
|
||||
if (member source '("IPython.kernel.zmq.page.page"
|
||||
"IPython.zmq.page.page"
|
||||
|
@ -740,39 +633,63 @@ We need this to have proper behavior for the 'Stop' command in the ein:notebookl
|
|||
do (let ((cb (plist-get callbacks :set_next_input)))
|
||||
(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)
|
||||
(if (ein:$kernel-stdin-activep kernel)
|
||||
(ein:ipdb--handle-iopub-reply kernel packet)
|
||||
(destructuring-bind
|
||||
(cl-destructuring-bind
|
||||
(&key content metadata parent_header 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))
|
||||
(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)
|
||||
(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
|
||||
(("stream" "display_data" "pyout" "pyerr" "error" "execute_result")
|
||||
(aif (plist-get callbacks :output)
|
||||
(ein:funcall-packed it msg-type content metadata)))
|
||||
(("status")
|
||||
(ein:case-equal (plist-get content :execution_state)
|
||||
(("busy")
|
||||
(ein:events-trigger events 'status_busy.Kernel))
|
||||
(("idle")
|
||||
(ein:events-trigger events 'status_idle.Kernel))
|
||||
(("dead")
|
||||
(ein:kernel-disconnect kernel))))
|
||||
(("data_pub")
|
||||
(ein:log 'verbose (format "Received data_pub message w/content %s" packet)))
|
||||
(("clear_output")
|
||||
(aif (plist-get callbacks :clear_output)
|
||||
(ein:funcall-packed it content metadata)))))))))
|
||||
|
||||
;;; Utility functions
|
||||
(ein:case-equal msg-type
|
||||
(("stream" "display_data" "pyout" "pyerr" "error" "execute_result")
|
||||
(aif (plist-get callbacks :output)
|
||||
(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")
|
||||
(ein:case-equal (plist-get content :execution_state)
|
||||
(("busy")
|
||||
(ein:events-trigger events 'status_busy.Kernel))
|
||||
(("idle")
|
||||
(ein:events-trigger events 'status_idle.Kernel))
|
||||
(("dead")
|
||||
(ein:kernel-disconnect kernel))))
|
||||
(("data_pub")
|
||||
(ein:log 'verbose "ein:kernel--handle-iopub-reply: data_pub %S" packet))
|
||||
(("clear_output")
|
||||
(aif (plist-get callbacks :clear_output)
|
||||
(ein:funcall-packed it content metadata)
|
||||
(ein:log 'info (concat "ein:kernel--handle-iopub-reply: "
|
||||
"No :clear_output callback for msg_id=%s")
|
||||
msg-id))))))))
|
||||
|
||||
(defun ein:kernel-filename-to-python (kernel filename)
|
||||
"See: `ein:filename-to-python'."
|
||||
|
@ -792,7 +709,6 @@ Used in `ein:pytools-finish-tooltip', etc."
|
|||
(defun ein:kernel-construct-help-string (content)
|
||||
"Construct help string from CONTENT of ``:object_info_reply``.
|
||||
Used in `ein:pytools-finish-tooltip', etc."
|
||||
(ein:log 'debug "KERNEL-CONSTRUCT-HELP-STRING")
|
||||
(let* ((defstring (ein:aand
|
||||
(ein:kernel-construct-defstring content)
|
||||
(ansi-color-apply it)
|
||||
|
@ -807,7 +723,6 @@ Used in `ein:pytools-finish-tooltip', etc."
|
|||
(help (ein:aand
|
||||
(delete nil (list defstring docstring))
|
||||
(ein:join-str "\n" it))))
|
||||
(ein:log 'debug "KERNEL-CONSTRUCT-HELP-STRING: help=%s" help)
|
||||
help))
|
||||
|
||||
(defun ein:kernel-request-stream (kernel code func &optional args)
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
(require 'ein-kernel)
|
||||
(require 'ein-kernelinfo)
|
||||
(require 'ein-cell)
|
||||
(require 'ein-cell-output)
|
||||
(require 'ein-worksheet)
|
||||
(require 'ein-iexec)
|
||||
(require 'ein-scratchsheet)
|
||||
|
@ -65,47 +64,19 @@
|
|||
|
||||
;;; 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")
|
||||
|
||||
(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-create-checkpoint-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)
|
||||
(ein:cell-has-image-ouput-p cell))
|
||||
(defvar *ein:notebook--pending-query* (make-hash-table :test 'equal)
|
||||
"A map: (URL-OR-PORT . PATH) => t/nil")
|
||||
|
||||
(defun ein:notebook-discard-output-p (notebook cell)
|
||||
"Return non-`nil' if the output must be discarded, otherwise save."
|
||||
(case ein:notebook-discard-output-on-save
|
||||
(no nil)
|
||||
(yes t)
|
||||
(t (funcall ein:notebook-discard-output-on-save notebook cell))))
|
||||
(defun ein:notebook-cell-has-image-output-p (_ignore cell)
|
||||
(ein:cell-has-image-output-p cell))
|
||||
|
||||
;; As opening/saving notebook treats possibly huge data, define these
|
||||
;; timeouts separately:
|
||||
|
@ -548,9 +519,6 @@ This is equivalent to do ``C-c`` in the console program."
|
|||
(funcall func
|
||||
(ein:$notebook-nbformat notebook)
|
||||
(ein:notebook-name-getter notebook)
|
||||
(cons (lambda (notebook cell)
|
||||
(ein:notebook-discard-output-p notebook cell))
|
||||
notebook)
|
||||
(ein:$notebook-kernel 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
|
||||
&allow-other-keys)
|
||||
(if (eq symbol-status 'user-cancel)
|
||||
(ein:log 'info "Cancel saving notebook.")
|
||||
(ein:log 'info "Failed to save notebook!")
|
||||
(ein:log 'info "Cancelled save.")
|
||||
(ein:log 'warn "Failed saving notebook!")
|
||||
(ein:events-trigger (ein:$notebook-events notebook)
|
||||
'notebook_save_failed.Notebook)))
|
||||
|
||||
|
@ -1437,19 +1405,12 @@ watch the fireworks!"
|
|||
(aif ein:anything-kernel-history-search-key
|
||||
(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.
|
||||
(ein:worksheet-imenu-setup)))
|
||||
))
|
||||
|
||||
;; To avoid MuMaMo to discard `ein:notebook-mode', make it
|
||||
;; permanent local.
|
||||
(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)
|
||||
"Open current notebook in web browser.
|
||||
When the prefix argument (``C-u``) is given, print page is opened.
|
||||
|
|
|
@ -752,8 +752,8 @@ and the url-or-port argument of ein:notebooklist-open*."
|
|||
(domain (url-host parsed-url))
|
||||
(securep (string-match "^wss://" url-or-port)))
|
||||
(cl-loop for (name content) on cookie-plist by (function cddr)
|
||||
for line = (mapconcat #'identity (list domain "FALSE" (car (url-path-and-query parsed-url)) (if securep "TRUE" "FALSE") "0" (symbol-name name) (concat content "\n")) "\t")
|
||||
do (write-region line nil (request--curl-cookie-jar) 'append))))
|
||||
for line = (mapconcat #'identity (list domain "FALSE" (car (url-path-and-query parsed-url)) (if securep "TRUE" "FALSE") "0" (symbol-name name) (concat content "\n")) "\t")
|
||||
do (write-region line nil (request--curl-cookie-jar) 'append))))
|
||||
(let ((token (ein:notebooklist-token-or-password url-or-port)))
|
||||
(cond ((null token) ;; don't know
|
||||
(ein:notebooklist-login--iteration url-or-port callback nil nil -1 nil))
|
||||
|
|
|
@ -125,13 +125,34 @@ Usage::
|
|||
(ein:xml-replace-attributes dom 'a 'href 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)
|
||||
`(progn (aif (plist-get ,json :data) (setq ,json it)) ;; nbformat v4 ???
|
||||
`(progn (aif (plist-get ,json :data) (setq ,json it))
|
||||
(seq-some (lambda (type)
|
||||
(when-let ((value (plist-get ,json type)))
|
||||
,@case-body
|
||||
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)
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ working."
|
|||
(lambda (name msg-type content -metadata-not-used-)
|
||||
(ein:case-equal msg-type
|
||||
(("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)))
|
||||
(ein:kernel-object-info-request
|
||||
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:case-equal msg-type
|
||||
(("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)
|
||||
(ein:log 'info
|
||||
"Jumping to the source of %s...Not found" object)
|
||||
|
@ -231,7 +231,7 @@ is defined."
|
|||
(destructuring-bind (kernel object callback) packed
|
||||
(if (or (string= msg-type "stream")
|
||||
(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)
|
||||
(ein:log 'info
|
||||
"Source of %s not found" object)
|
||||
|
|
|
@ -37,11 +37,10 @@
|
|||
:documentation
|
||||
"Worksheet without needs for saving.")
|
||||
|
||||
(defun ein:scratchsheet-new (nbformat get-notebook-name discard-output-p
|
||||
kernel events &rest args)
|
||||
(defun ein:scratchsheet-new (nbformat get-notebook-name kernel events &rest args)
|
||||
(apply #'make-instance 'ein:scratchsheet
|
||||
:nbformat nbformat :get-notebook-name get-notebook-name
|
||||
:discard-output-p discard-output-p :kernel kernel :events events
|
||||
:kernel kernel :events events
|
||||
args))
|
||||
|
||||
(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
|
||||
|
||||
(defun ein:worksheet-new (nbformat get-notebook-name discard-output-p
|
||||
kernel events &rest args)
|
||||
(defun ein:worksheet-new (nbformat get-notebook-name kernel events &rest args)
|
||||
(apply #'make-instance 'ein:worksheet
|
||||
:nbformat nbformat :get-notebook-name get-notebook-name
|
||||
:discard-output-p discard-output-p :kernel kernel :events events
|
||||
:kernel kernel :events events
|
||||
args))
|
||||
|
||||
(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.
|
||||
It sets buffer internally so that caller doesn not have to set
|
||||
current buffer."
|
||||
(let* ((discard-output-p (ein:worksheet--discard-output-p ws))
|
||||
(cells (ein:with-possibly-killed-buffer (ein:worksheet-buffer ws)
|
||||
(let* ((cells (ein:with-possibly-killed-buffer (ein:worksheet-buffer ws)
|
||||
(mapcar (lambda (c)
|
||||
(ein:cell-to-json
|
||||
c (ein:funcall-packed discard-output-p c)))
|
||||
(ein:cell-to-json c))
|
||||
(ein:worksheet-get-cells ws)))))
|
||||
`((cells . ,(apply #'vector cells))
|
||||
,@(ein:aand (ein:worksheet--metadata ws) `((metadata . ,it))))))
|
||||
|
||||
(cl-defmethod ein:worksheet-to-nb4-json ((ws ein:worksheet) wsidx)
|
||||
(let* ((discard-output-p (slot-value ws 'discard-output-p))
|
||||
(cells (ein:with-possibly-killed-buffer (ein:worksheet-buffer ws)
|
||||
(let* ((cells (ein:with-possibly-killed-buffer (ein:worksheet-buffer ws)
|
||||
(mapcar (lambda (c)
|
||||
(ein:cell-to-nb4-json
|
||||
c wsidx (ein:funcall-packed discard-output-p c)))
|
||||
(ein:cell-to-nb4-json c wsidx))
|
||||
(ein:worksheet-get-cells ws)))))
|
||||
cells))
|
||||
|
||||
|
@ -613,7 +608,7 @@ If you really want use this command, you can do something like this
|
|||
t))
|
||||
(ein:worksheet--shift-undo-list cell)
|
||||
(let ((inhibit-read-only t)
|
||||
(buffer-undo-list t)) ; disable undo recording
|
||||
(buffer-undo-list t))
|
||||
(apply #'ewoc-delete
|
||||
(slot-value ws 'ewoc)
|
||||
(ein:cell-all-element cell)))
|
||||
|
@ -772,13 +767,12 @@ directly."
|
|||
(when focus (ein:cell-goto new relpos))
|
||||
(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.
|
||||
Prompt will appear in the minibuffer.
|
||||
|
||||
When used in as a Lisp function, TYPE (string) should be chose
|
||||
from \"code\", \"markdown\", \"raw\" and \"heading\". LEVEL is
|
||||
an integer used only when the TYPE is \"heading\"."
|
||||
from \"code\", \"markdown\", \"raw\" and \"heading\"."
|
||||
(interactive
|
||||
(let* ((ws (ein:worksheet--get-ws-or-error))
|
||||
(cell (ein:worksheet-get-current-cell))
|
||||
|
@ -791,18 +785,12 @@ an integer used only when the TYPE is \"heading\"."
|
|||
(type (case key
|
||||
(?c "code")
|
||||
(?m "markdown")
|
||||
(?r "raw")
|
||||
(t "heading")))
|
||||
(level (when (equal type "heading")
|
||||
(string-to-number (char-to-string key)))))
|
||||
(list ws cell type level t)))
|
||||
|
||||
(?r "raw"))))
|
||||
(list ws cell type t)))
|
||||
(let ((relpos (ein:cell-relative-point cell))
|
||||
(new (ein:cell-convert-inplace cell type)))
|
||||
(when (ein:codecell-p new)
|
||||
(setf (slot-value new 'kernel) (slot-value ws 'kernel)))
|
||||
(when level
|
||||
(ein:cell-change-level new level))
|
||||
(ein:worksheet--unshift-undo-list cell)
|
||||
(when focus (ein:cell-goto new relpos))))
|
||||
|
||||
|
@ -819,10 +807,7 @@ argument \(C-u)."
|
|||
(head (buffer-substring beg pos))
|
||||
(new (ein:worksheet-insert-cell-above ws
|
||||
(slot-value cell 'cell-type)
|
||||
cell))
|
||||
)
|
||||
(when (ein:headingcell-p cell)
|
||||
(ein:cell-change-level new (slot-value cell 'level)))
|
||||
cell)))
|
||||
(undo-boundary)
|
||||
(delete-region beg pos)
|
||||
(unless no-trim
|
||||
|
@ -1253,26 +1238,6 @@ function."
|
|||
(ein:worksheet-get-cells ws))))))
|
||||
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
|
||||
|
||||
(defadvice fill-paragraph (around ein:worksheet-fill-paragraph activate)
|
||||
|
|
|
@ -120,8 +120,7 @@
|
|||
(ein:output-area-case-type
|
||||
json
|
||||
(cl-case type
|
||||
((:svg :png :jpeg)
|
||||
(message "got here %s" type)
|
||||
((:image/svg+xml :image/png :image/jpeg)
|
||||
(let ((file (or explicit-file (ob-ein--inline-image-info value))))
|
||||
(ob-ein--write-base64-image value 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)
|
||||
(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)
|
||||
|
||||
;;; ein-testing-cell.el ends here
|
||||
|
|
|
@ -128,47 +128,47 @@ some input
|
|||
,regexp-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
|
||||
latex
|
||||
("some output \\\\LaTeX")
|
||||
((:data (:latex "some output \\LaTeX"))))
|
||||
((:data (:application/latex "some output \\LaTeX"))))
|
||||
|
||||
(when (image-type-available-p 'svg)
|
||||
(eintest:gene-test-cell-insert-output-pyout-and-display-data
|
||||
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
|
||||
html
|
||||
("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
|
||||
javascript
|
||||
("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
|
||||
text-two
|
||||
("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
|
||||
text-javascript
|
||||
("first output text" "second output text")
|
||||
((:data (:text "first output text"))
|
||||
(:data (:text "second output text" :javascript "$.do.something()"))))
|
||||
((:data (:text/plain "first output text"))
|
||||
(:data (:text/plain "second output text" :application/javascript "$.do.something()"))))
|
||||
|
||||
(when (image-type-available-p 'svg)
|
||||
(eintest:gene-test-cell-insert-output-pyout-and-display-data
|
||||
text-latex-svg
|
||||
("first output text" "second output \\\\LaTeX")
|
||||
((:data (:text "first output text"))
|
||||
(:data (:latex "second output \\LaTeX"))
|
||||
(:data (:text "some output text" :svg ein:testing-example-svg)))))
|
||||
((:data (:text/plain "first output text"))
|
||||
(:data (:application/latex "second output \\LaTeX"))
|
||||
(:data (:text/plain "some output text" :image/svg+xml ein:testing-example-svg)))))
|
||||
|
||||
;; Insert pyerr
|
||||
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
(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")))
|
||||
:text (list "first output" "second output")))
|
||||
(data (ein:testing-codecell-data
|
||||
input input-prompt-number (list output-0)))
|
||||
(cell (eintest:cell-from-json data)))
|
||||
|
@ -62,21 +61,13 @@
|
|||
(should (ein:rawcell-p cell))
|
||||
(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
|
||||
|
||||
(defun eintest:cell-to-json (cell input &optional discard-output)
|
||||
(defun eintest:cell-to-json (cell input)
|
||||
(mocker-let ((ein:cell-get-text
|
||||
(cell)
|
||||
((:input (list cell) :output input))))
|
||||
(ein:cell-to-json cell discard-output)))
|
||||
(ein:cell-to-json cell)))
|
||||
|
||||
(ert-deftest ein:cell-to-json-code ()
|
||||
(let* ((input-prompt-number 111)
|
||||
|
@ -96,24 +87,6 @@
|
|||
(should (equal (cdr (assq 'language alist)) "python"))
|
||||
(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 ()
|
||||
(let* ((input (ein:join-str "\n" '("first input" "second input")))
|
||||
(data (list :cell_type "text" :source input))
|
||||
|
@ -146,16 +119,6 @@
|
|||
(should (equal (cdr (assq 'cell_type alist)) "raw"))
|
||||
(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
|
||||
|
||||
(ert-deftest ein:cell-convert-code-to-markdown ()
|
||||
|
@ -206,7 +169,7 @@
|
|||
(should (equal (oref new :input) input))))
|
||||
|
||||
(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))
|
||||
do
|
||||
(let* ((input (ein:join-str "\n" '("first input" "second input")))
|
||||
|
|
|
@ -86,7 +86,7 @@
|
|||
(ein:kernel--handle-shell-reply kernel (json-encode packet))))
|
||||
|
||||
(defun eintest:kernel-fake-stream (kernel msg-id data)
|
||||
(let* ((content (list :data data
|
||||
(let* ((content (list :text data
|
||||
:name "stdout"))
|
||||
(packet (list :header (list :msg_type "stream")
|
||||
:parent_header (list :msg_id msg-id)
|
||||
|
@ -143,16 +143,11 @@ is not found."
|
|||
(list (ein:testing-codecell-data "import numpy")
|
||||
(ein:testing-markdowncell-data "*markdown* text")
|
||||
(ein:testing-rawcell-data "`raw` cell 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)))
|
||||
(ein:testing-htmlcell-data "<b>HTML</b> text")))
|
||||
(should (ein:$notebook-p ein:%notebook%))
|
||||
(should (equal (ein:$notebook-notebook-name ein:%notebook%) ein:testing-notebook-dummy-name))
|
||||
(should (equal (ein:worksheet-ncells ein:%worksheet%) 10))
|
||||
(should (equal (ein:$notebook-notebook-name ein:%notebook%)
|
||||
ein:testing-notebook-dummy-name))
|
||||
(should (equal (ein:worksheet-ncells ein:%worksheet%) 4))
|
||||
(let ((cells (ein:worksheet-get-cells ein:%worksheet%)))
|
||||
(should (ein:codecell-p (nth 0 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 1 cells)) "*markdown* 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"))
|
||||
(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))))))
|
||||
(should (equal (ein:cell-get-text (nth 3 cells)) "<b>HTML</b> text")))))
|
||||
|
||||
|
||||
;;; Destructor
|
||||
|
||||
(defvar ein:testing-notebook-del-args-log 'nolog)
|
||||
|
@ -340,7 +327,6 @@ some text
|
|||
(when (< (ein:$notebook-nbformat ein:%notebook%) 4)
|
||||
;; toggle to heading
|
||||
(call-interactively #'ein:worksheet-toggle-cell-type)
|
||||
(should (ein:headingcell-p (ein:worksheet-get-current-cell)))
|
||||
(should (looking-back "some text"))
|
||||
;; toggle to code
|
||||
(call-interactively #'ein:worksheet-toggle-cell-type)
|
||||
|
@ -356,21 +342,18 @@ some text
|
|||
(should (ein:codecell-p (ein:worksheet-get-current-cell)))
|
||||
(should (slot-boundp (ein:worksheet-get-current-cell) :kernel))
|
||||
(let ((check
|
||||
(lambda (type &optional level)
|
||||
(lambda (type)
|
||||
(let ((cell-p (intern (format "ein:%scell-p" type)))
|
||||
(cell (ein:worksheet-get-current-cell)))
|
||||
(ein:worksheet-change-cell-type ein:%worksheet% cell
|
||||
type level t)
|
||||
type t)
|
||||
(let ((new (ein:worksheet-get-current-cell)))
|
||||
(should-not (eq new cell))
|
||||
(should (funcall cell-p new)))
|
||||
(should (looking-back "some text"))))))
|
||||
;; change type: code (no change) -> markdown -> raw
|
||||
(cl-loop for type in '("code" "markdown" "raw")
|
||||
do (funcall check type))
|
||||
;; change level: 1 to 6
|
||||
(cl-loop for level from 1 to 6
|
||||
do (funcall check "heading" level))
|
||||
do (funcall check type))
|
||||
;; back to code
|
||||
(funcall check "code")
|
||||
(should (slot-boundp (ein:worksheet-get-current-cell) :kernel)))))
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
(oset ein:%notification% :tab (ein:testing-notification-tab-mock))
|
||||
(ein:notification-status-set 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)))))
|
||||
|
||||
(ert-deftest ein:header-line-notebook-status-busy ()
|
||||
|
@ -30,7 +30,7 @@
|
|||
(oset ein:%notification% :tab (ein:testing-notification-tab-mock))
|
||||
(ein:notification-status-set 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)))))
|
||||
|
||||
(ert-deftest ein:header-line-notebook-complex ()
|
||||
|
@ -43,7 +43,7 @@
|
|||
(ein:notification-status-set notebook
|
||||
'notebook_saving.Notebook)
|
||||
(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] | ")
|
||||
;;"Kernel requires restart C-c C-x C-r | "
|
||||
"/1\\ /2\\ /3\\ [+]") (ein:header-line)))))
|
||||
|
|
|
@ -7,12 +7,10 @@
|
|||
(list (ein:testing-codecell-data "code example input")
|
||||
(ein:testing-markdowncell-data "markdown example input")
|
||||
(ein:testing-rawcell-data "raw example input")
|
||||
(ein:testing-htmlcell-data "html example input")
|
||||
(ein:testing-headingcell-data "heading example input")))
|
||||
(ein:testing-htmlcell-data "html example input")))
|
||||
|
||||
(defun ein:testing-worksheet-new ()
|
||||
(make-instance 'ein:worksheet
|
||||
:discard-output-p (cons #'ignore nil)))
|
||||
(make-instance 'ein:worksheet))
|
||||
|
||||
(defun ein:testing-worksheet-to-json (cells &optional metadata)
|
||||
(let* ((ws-0 (ein:worksheet-from-json (ein:testing-worksheet-new)
|
||||
|
|
Loading…
Add table
Reference in a new issue