diff --git a/features/support/env.el b/features/support/env.el
index ad4bde4..18089be 100644
--- a/features/support/env.el
+++ b/features/support/env.el
@@ -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)))
diff --git a/features/undo.feature b/features/undo.feature
index 71e0b95..62769f1 100644
--- a/features/undo.feature
+++ b/features/undo.feature
@@ -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
diff --git a/lisp/ein-cell-output.el b/lisp/ein-cell-output.el
deleted file mode 100644
index 16038fd..0000000
--- a/lisp/ein-cell-output.el
+++ /dev/null
@@ -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 .
-
-;;; 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)
diff --git a/lisp/ein-cell.el b/lisp/ein-cell.el
index db42966..c42785d 100644
--- a/lisp/ein-cell.el
+++ b/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))
diff --git a/lisp/ein-classes.el b/lisp/ein-classes.el
index 83fdfc6..9660bfe 100644
--- a/lisp/ein-classes.el
+++ b/lisp/ein-classes.el
@@ -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-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 ()
diff --git a/lisp/ein-contents-api.el b/lisp/ein-contents-api.el
index 325a27e..b9086cf 100644
--- a/lisp/ein-contents-api.el
+++ b/lisp/ein-contents-api.el
@@ -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)
diff --git a/lisp/ein-kernel.el b/lisp/ein-kernel.el
index 43d9b2c..ad0c583 100644
--- a/lisp/ein-kernel.el
+++ b/lisp/ein-kernel.el
@@ -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)
diff --git a/lisp/ein-notebook.el b/lisp/ein-notebook.el
index be1215d..85b23c2 100644
--- a/lisp/ein-notebook.el
+++ b/lisp/ein-notebook.el
@@ -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.
diff --git a/lisp/ein-notebooklist.el b/lisp/ein-notebooklist.el
index 8f0f7ac..f61936e 100644
--- a/lisp/ein-notebooklist.el
+++ b/lisp/ein-notebooklist.el
@@ -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))
diff --git a/lisp/ein-output-area.el b/lisp/ein-output-area.el
index 9529e3a..72e1842 100644
--- a/lisp/ein-output-area.el
+++ b/lisp/ein-output-area.el
@@ -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)
diff --git a/lisp/ein-pytools.el b/lisp/ein-pytools.el
index b2fd3f0..2dab141 100644
--- a/lisp/ein-pytools.el
+++ b/lisp/ein-pytools.el
@@ -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)
diff --git a/lisp/ein-scratchsheet.el b/lisp/ein-scratchsheet.el
index c0225f2..d094623 100644
--- a/lisp/ein-scratchsheet.el
+++ b/lisp/ein-scratchsheet.el
@@ -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))
diff --git a/lisp/ein-worksheet.el b/lisp/ein-worksheet.el
index 94dc02d..9b23cdd 100644
--- a/lisp/ein-worksheet.el
+++ b/lisp/ein-worksheet.el
@@ -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)
diff --git a/lisp/ob-ein.el b/lisp/ob-ein.el
index 76191fd..7587308 100644
--- a/lisp/ob-ein.el
+++ b/lisp/ob-ein.el
@@ -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))))
diff --git a/test/ein-testing-cell.el b/test/ein-testing-cell.el
index 9194c8c..fa2465c 100644
--- a/test/ein-testing-cell.el
+++ b/test/ein-testing-cell.el
@@ -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
diff --git a/test/test-ein-cell-notebook.el b/test/test-ein-cell-notebook.el
index 5546ea1..1147af4 100644
--- a/test/test-ein-cell-notebook.el
+++ b/test/test-ein-cell-notebook.el
@@ -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 "not shown"))))
+ ((:data (:text/plain "some output text" :text/html "not shown"))))
(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
diff --git a/test/test-ein-cell.el b/test/test-ein-cell.el
index f58fa6e..7392420 100644
--- a/test/test-ein-cell.el
+++ b/test/test-ein-cell.el
@@ -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")))
diff --git a/test/test-ein-notebook.el b/test/test-ein-notebook.el
index 1bdc421..f4364fe 100644
--- a/test/test-ein-notebook.el
+++ b/test/test-ein-notebook.el
@@ -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 "HTML 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 "HTML 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)) "HTML 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)) "HTML 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)))))
diff --git a/test/test-ein-notification.el b/test/test-ein-notification.el
index 79218f8..837b1b7 100644
--- a/test/test-ein-notification.el
+++ b/test/test-ein-notification.el
@@ -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-restart-session-command-km] | ")
;;"Kernel requires restart C-c C-x C-r | "
"/1\\ /2\\ /3\\ [+]") (ein:header-line)))))
diff --git a/test/test-ein-worksheet.el b/test/test-ein-worksheet.el
index 5065cbe..c501dfc 100644
--- a/test/test-ein-worksheet.el
+++ b/test/test-ein-worksheet.el
@@ -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)