mirror of
https://github.com/vale981/emacs-ipython-notebook
synced 2025-03-06 09:31:39 -05:00
Merge branch 'configurable-undo'
This commit is contained in:
commit
4a7c81869f
7 changed files with 238 additions and 61 deletions
|
@ -2,8 +2,9 @@
|
|||
Emacs IPython Notebook (and more)
|
||||
===================================
|
||||
|
||||
.. warning:: This is **very** early version.
|
||||
Make sure you have backup!
|
||||
.. note:: It is stable enough for my day to day work, but I can't
|
||||
grantee the safety for your notebook data. So please make
|
||||
sure you have backup.
|
||||
|
||||
Screenshot
|
||||
==========
|
||||
|
|
|
@ -239,6 +239,7 @@ Notebook list
|
|||
Notebook
|
||||
^^^^^^^^
|
||||
|
||||
.. el:variable:: ein:notebook-enable-undo
|
||||
.. el:variable:: ein:notebook-discard-output-on-save
|
||||
.. el:variable:: ein:notebook-modes
|
||||
.. el:variable:: ein:notebook-kill-buffer-ask
|
||||
|
|
27
ein-cell.el
27
ein-cell.el
|
@ -543,7 +543,9 @@ Called from ewoc pretty printer via `ein:cell-pp'."
|
|||
|
||||
(defmethod ein:cell-location ((cell ein:basecell) &optional elm end)
|
||||
"Return the starting location of CELL.
|
||||
ELM is a name (keyword) of element in the `:element-names' slot of CELL.
|
||||
ELM is a name (keyword) of element that `ein:cell-element-get'
|
||||
understands. Note that you can't use `:output' since it returns
|
||||
a list. Use `:after-input' instead.
|
||||
If END is non-`nil', return the location of next element."
|
||||
(unless elm (setq elm :prompt))
|
||||
(let ((element (oref cell :element)))
|
||||
|
@ -780,23 +782,27 @@ Called from ewoc pretty printer via `ein:cell-insert-output'."
|
|||
(ein:cell-set-input-prompt cell "*")
|
||||
(ein:cell-running-set cell t)
|
||||
(oset cell :dynamic t)
|
||||
(let* ((callbacks
|
||||
(apply #'ein:kernel-execute kernel code (ein:cell-make-callbacks cell) args))
|
||||
|
||||
(defmethod ein:cell-make-callbacks ((cell ein:codecell))
|
||||
(list
|
||||
:execute_reply (cons #'ein:cell--handle-execute-reply cell)
|
||||
:output (cons #'ein:cell--handle-output cell)
|
||||
:clear_output (cons #'ein:cell--handle-clear-output cell)
|
||||
:set_next_input (cons #'ein:cell--handle-set-next-input cell))))
|
||||
(apply #'ein:kernel-execute kernel code callbacks args)))
|
||||
:set_next_input (cons #'ein:cell--handle-set-next-input cell)))
|
||||
|
||||
(defmethod ein:cell--handle-execute-reply ((cell ein:codecell) content)
|
||||
(ein:cell-set-input-prompt cell (plist-get content :execution_count))
|
||||
(ein:cell-running-set cell nil)
|
||||
(ein:events-trigger
|
||||
(oref cell :events) 'set_dirty.Notebook '(:value t)))
|
||||
(let ((events (oref cell :events)))
|
||||
(ein:events-trigger events 'set_dirty.Notebook '(:value t))
|
||||
(ein:events-trigger events 'maybe_reset_undo.Notebook)))
|
||||
|
||||
(defmethod ein:cell--handle-set-next-input ((cell ein:codecell) text)
|
||||
(ein:events-trigger
|
||||
(oref cell :events) 'set_next_input.Notebook (list :cell cell :text text)))
|
||||
(let ((events (oref cell :events)))
|
||||
(ein:events-trigger events 'set_next_input.Notebook
|
||||
(list :cell cell :text text))
|
||||
(ein:events-trigger events 'maybe_reset_undo.Notebook)))
|
||||
|
||||
|
||||
|
||||
|
@ -823,7 +829,7 @@ Called from ewoc pretty printer via `ein:cell-insert-output'."
|
|||
(plist-put json :traceback (plist-get content :traceback))))
|
||||
(ein:cell-append-output cell json t)
|
||||
;; (oset cell :dirty t)
|
||||
))
|
||||
(ein:events-trigger (oref cell :events) 'maybe_reset_undo.Notebook)))
|
||||
|
||||
|
||||
(defun ein:output-area-convert-mime-types (json data)
|
||||
|
@ -845,7 +851,8 @@ Called from ewoc pretty printer via `ein:cell-insert-output'."
|
|||
(ein:cell-clear-output cell
|
||||
(plist-get content :stdout)
|
||||
(plist-get content :stderr)
|
||||
(plist-get content :other)))
|
||||
(plist-get content :other))
|
||||
(ein:events-trigger (oref cell :events) 'maybe_reset_undo.Notebook))
|
||||
|
||||
|
||||
;;; Misc.
|
||||
|
|
|
@ -62,7 +62,9 @@
|
|||
When EVENT-TYPE is triggered on the event handler EVENTS,
|
||||
CALLBACK is called. CALLBACK must take two arguments:
|
||||
ARG as the first argument and DATA, which is passed via
|
||||
`ein:events-trigger', as the second."
|
||||
`ein:events-trigger', as the second. When calling the function,
|
||||
current buffer is set to the configured buffer. `ein:events-new'
|
||||
is used to configure the buffer."
|
||||
(assert (symbolp event-type))
|
||||
(let* ((table (oref events :callbacks))
|
||||
(cbs (gethash event-type table)))
|
||||
|
|
|
@ -54,6 +54,34 @@
|
|||
|
||||
;;; Configuration
|
||||
|
||||
(defcustom ein:notebook-enable-undo 'yes
|
||||
"Configure undo in notebook buffers.
|
||||
|
||||
`no' : symbol
|
||||
Do not use undo in notebook buffers. It is the safest option.
|
||||
`yes' : symbol
|
||||
Enable undo in notebook buffers. You can't undo after
|
||||
modification of cell (execution, add, remove, etc.). This
|
||||
is default.
|
||||
`full' : symbol
|
||||
Enable full undo in notebook buffers. It is powerful but
|
||||
sometime (typically after the cell specific commands) undo
|
||||
mess up notebook buffer. Use it on your own risk. When the
|
||||
buffer is messed up, you can just redo and continue editing,
|
||||
or save it once and reopen it if you want to be careful.
|
||||
|
||||
You need to reopen the notebook buffer to reflect the change of
|
||||
this value."
|
||||
:type '(choice (const :tag "No" no)
|
||||
(const :tag "Yes" yes)
|
||||
(const :tag "Full" full))
|
||||
:group 'ein)
|
||||
|
||||
(defun ein:notebook-empty-undo-maybe ()
|
||||
"Empty `buffer-undo-list' if `ein:notebook-enable-undo' is `yes'."
|
||||
(when (eq ein:notebook-enable-undo 'yes)
|
||||
(setq buffer-undo-list nil)))
|
||||
|
||||
(defcustom ein:notebook-discard-output-on-save 'no
|
||||
"Configure if the output part of the cell should be saved or not.
|
||||
|
||||
|
@ -295,6 +323,8 @@ See `ein:notebook-open' for more information."
|
|||
(assert ein:notebook) ; make sure in a notebook buffer
|
||||
(ein:notebook-from-json ein:notebook (ein:$notebook-data ein:notebook))
|
||||
(setq buffer-undo-list nil) ; clear undo history
|
||||
(when (eq ein:notebook-enable-undo 'no)
|
||||
(setq buffer-undo-list t))
|
||||
(ein:notebook-mode)
|
||||
(setf (ein:$notebook-notification ein:notebook)
|
||||
(ein:notification-setup (current-buffer)))
|
||||
|
@ -326,6 +356,10 @@ See `ein:notebook-open' for more information."
|
|||
(setf (ein:$notebook-dirty notebook)
|
||||
(plist-get data :value)))
|
||||
notebook)
|
||||
(ein:events-on events
|
||||
'maybe_reset_undo.Notebook
|
||||
(lambda (&rest -ignore-)
|
||||
(ein:notebook-empty-undo-maybe)))
|
||||
;; Bind events for sub components:
|
||||
(mapc (lambda (cell) (oset cell :events (ein:$notebook-events notebook)))
|
||||
(ein:notebook-get-cells notebook))
|
||||
|
@ -385,7 +419,8 @@ See `ein:notebook-open' for more information."
|
|||
(apply #'ewoc-delete
|
||||
(ein:$notebook-ewoc notebook)
|
||||
(ein:cell-all-element cell)))
|
||||
(setf (ein:$notebook-dirty notebook) t))
|
||||
(setf (ein:$notebook-dirty notebook) t)
|
||||
(ein:notebook-empty-undo-maybe))
|
||||
|
||||
(defun ein:notebook-delete-cell-command ()
|
||||
"Delete a cell. \(WARNING: no undo!)
|
||||
|
@ -475,6 +510,7 @@ Prefixes are act same as the normal `yank' command."
|
|||
(ein:cell-insert-below base-cell cell))
|
||||
(t (error (concat "`base-cell' is `nil' but ncells != 0. "
|
||||
"There is something wrong..."))))
|
||||
(ein:notebook-empty-undo-maybe)
|
||||
(ein:cell-goto cell)
|
||||
(setf (ein:$notebook-dirty notebook) t))
|
||||
cell))
|
||||
|
@ -505,6 +541,7 @@ when the prefix argument is given."
|
|||
(ein:cell-enter-first cell))))
|
||||
(t (error (concat "`base-cell' is `nil' but ncells > 1. "
|
||||
"There is something wrong..."))))
|
||||
(ein:notebook-empty-undo-maybe)
|
||||
(ein:cell-goto cell)
|
||||
(setf (ein:$notebook-dirty notebook) t))
|
||||
cell))
|
||||
|
@ -537,6 +574,7 @@ directly."
|
|||
(let ((new (ein:cell-convert-inplace cell type)))
|
||||
(when (ein:codecell-p new)
|
||||
(oset new :kernel (ein:$notebook-kernel ein:notebook)))
|
||||
(ein:notebook-empty-undo-maybe)
|
||||
(ein:cell-goto new)))))
|
||||
|
||||
(defun ein:notebook-change-cell-type ()
|
||||
|
@ -560,7 +598,8 @@ Prompt will appear in the minibuffer."
|
|||
(when (ein:codecell-p new)
|
||||
(oset new :kernel (ein:$notebook-kernel ein:notebook)))
|
||||
(when level
|
||||
(ein:cell-change-level new type))))))
|
||||
(ein:cell-change-level new type))
|
||||
(ein:notebook-empty-undo-maybe)))))
|
||||
|
||||
(defun ein:notebook-split-cell-at-point (&optional no-trim)
|
||||
"Split cell at current position. Newlines at the splitting
|
||||
|
@ -663,6 +702,7 @@ If prefix is given, merge current cell into previous cell."
|
|||
|
||||
(defun ein:notebook-toggle-output (notebook cell)
|
||||
(ein:cell-toggle-output cell)
|
||||
(ein:notebook-empty-undo-maybe)
|
||||
(setf (ein:$notebook-dirty notebook) t))
|
||||
|
||||
(defun ein:notebook-toggle-output-command ()
|
||||
|
@ -676,6 +716,7 @@ This does not alter the actual data stored in the cell."
|
|||
(mapc (lambda (c)
|
||||
(when (ein:codecell-p c) (ein:cell-set-collapsed c collapsed)))
|
||||
(ein:notebook-get-cells notebook))
|
||||
(ein:notebook-empty-undo-maybe)
|
||||
(setf (ein:$notebook-dirty notebook) t))
|
||||
|
||||
(defun ein:notebook-set-collapsed-all-command (&optional show)
|
||||
|
@ -690,7 +731,8 @@ Do not clear input prompt when the prefix argument is given."
|
|||
(ein:notebook-with-cell #'ein:codecell-p
|
||||
(ein:cell-clear-output cell t t t)
|
||||
(unless preserve-input-prompt
|
||||
(ein:cell-set-input-prompt cell))))
|
||||
(ein:cell-set-input-prompt cell))
|
||||
(ein:notebook-empty-undo-maybe)))
|
||||
|
||||
(defun ein:notebook-clear-all-output-command (&optional preserve-input-prompt)
|
||||
"Clear output from all cells.
|
||||
|
@ -701,7 +743,8 @@ Do not clear input prompts when the prefix argument is given."
|
|||
do (when (ein:codecell-p cell)
|
||||
(ein:cell-clear-output cell t t t)
|
||||
(unless preserve-input-prompt
|
||||
(ein:cell-set-input-prompt cell))))
|
||||
(ein:cell-set-input-prompt cell))
|
||||
(ein:notebook-empty-undo-maybe)))
|
||||
(ein:log 'error "Not in notebook buffer!")))
|
||||
|
||||
|
||||
|
|
|
@ -109,8 +109,9 @@
|
|||
ein:@shared-output)))
|
||||
|
||||
(defun ein:shared-output-bind-events (events)
|
||||
(ein:events-on events 'set_dirty.Notebook
|
||||
(lambda (&rest ignore))))
|
||||
"Add dummy event handlers."
|
||||
(ein:events-on events 'set_dirty.Notebook (lambda (&rest ignore)))
|
||||
(ein:events-on events 'maybe_reset_undo.Notebook (lambda (&rest ignore))))
|
||||
|
||||
(defun ein:shared-output-get-cell ()
|
||||
"Get the singleton shared output cell.
|
||||
|
|
|
@ -49,8 +49,7 @@
|
|||
(with-current-buffer (ein:notebook-request-open-callback
|
||||
(ein:notebook-new "DUMMY-URL" notebook-id)
|
||||
:data (ein:json-read-from-string json-string))
|
||||
(let ((events (ein:events-new (current-buffer))))
|
||||
(setf (ein:$notebook-events ein:notebook) events)
|
||||
(let ((events (ein:$notebook-events ein:notebook)))
|
||||
(setf (ein:$notebook-kernel ein:notebook)
|
||||
(ein:kernel-new 8888 "/kernels" events)))
|
||||
(current-buffer))))
|
||||
|
@ -70,6 +69,38 @@
|
|||
(defun eintest:notebook-enable-mode (buffer)
|
||||
(with-current-buffer buffer (ein:notebook-plain-mode) buffer))
|
||||
|
||||
(defun eintest:kernel-fake-execute-reply (kernel msg-id execution-count)
|
||||
(let* ((payload nil)
|
||||
(content (list :execution_count 1 :payload payload))
|
||||
(packet (list :header (list :msg_type "execute_reply")
|
||||
:parent_header (list :msg_id msg-id)
|
||||
:content content)))
|
||||
(ein:kernel--handle-shell-reply kernel (json-encode packet))))
|
||||
|
||||
(defun eintest:kernel-fake-stream (kernel msg-id data)
|
||||
(let* ((content (list :data data
|
||||
:name "stdout"))
|
||||
(packet (list :header (list :msg_type "stream")
|
||||
:parent_header (list :msg_id msg-id)
|
||||
:content content)))
|
||||
(ein:kernel--handle-iopub-reply kernel (json-encode packet))))
|
||||
|
||||
(defun eintest:check-search-forward-from (start string &optional null-string)
|
||||
"Search STRING from START and check it is found.
|
||||
When non-`nil' NULL-STRING is given, it is searched from the
|
||||
position where the search of the STRING ends and check that it
|
||||
is not found."
|
||||
(save-excursion
|
||||
(goto-char start)
|
||||
(should (search-forward string nil t))
|
||||
(when null-string
|
||||
(should-not (search-forward null-string nil t)))))
|
||||
|
||||
(defun eintest:cell-check-output (cell regexp)
|
||||
(save-excursion
|
||||
(goto-char (ein:cell-location cell :after-input))
|
||||
(should (looking-at-p (concat "\\=" regexp "\n")))))
|
||||
|
||||
|
||||
;; from-json
|
||||
|
||||
|
@ -325,23 +356,12 @@ some text
|
|||
|
||||
;; Kernel related things
|
||||
|
||||
(ert-deftest ein:notebook-execute-current-cell ()
|
||||
(with-current-buffer (eintest:notebook-make-empty)
|
||||
(ein:notebook-insert-cell-below-command)
|
||||
(let* ((text "print 'Hello World'")
|
||||
(cell (ein:notebook-get-current-cell))
|
||||
(kernel (ein:$notebook-kernel ein:notebook))
|
||||
(msg-id "DUMMY-MSG-ID")
|
||||
(callbacks
|
||||
(list
|
||||
:execute_reply (cons #'ein:cell--handle-execute-reply cell)
|
||||
:output (cons #'ein:cell--handle-output cell)
|
||||
:clear_output (cons #'ein:cell--handle-clear-output cell)
|
||||
:set_next_input (cons #'ein:cell--handle-set-next-input cell))))
|
||||
(defun eintest:notebook-check-kernel-and-codecell (kernel cell)
|
||||
(should (ein:$kernel-p kernel))
|
||||
(should (ein:codecell-p cell))
|
||||
(should (ein:$kernel-p (oref cell :kernel)))
|
||||
(insert text)
|
||||
(should (ein:$kernel-p (oref cell :kernel))))
|
||||
|
||||
(defun eintest:notebook-fake-execution (kernel text msg-id callbacks)
|
||||
(mocker-let ((ein:kernel-execute
|
||||
(kernel code callbacks kwd-silent silent)
|
||||
((:input (list kernel text callbacks :silent nil))))
|
||||
|
@ -349,34 +369,136 @@ some text
|
|||
(kernel)
|
||||
((:input (list kernel) :output t))))
|
||||
(ein:notebook-execute-current-cell))
|
||||
(ein:kernel-set-callbacks-for-msg kernel msg-id callbacks)
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(should-not (search-forward "In [1]:" nil t)))
|
||||
(let* ((payload nil)
|
||||
(content (list :execution_count 1 :payload payload))
|
||||
(packet (list :header (list :msg_type "execute_reply")
|
||||
:parent_header (list :msg_id msg-id)
|
||||
:content content)))
|
||||
(ein:kernel--handle-shell-reply kernel (json-encode packet)))
|
||||
(ein:kernel-set-callbacks-for-msg kernel msg-id callbacks))
|
||||
|
||||
(ert-deftest ein:notebook-execute-current-cell ()
|
||||
(with-current-buffer (eintest:notebook-make-empty)
|
||||
(ein:notebook-insert-cell-below-command)
|
||||
(let* ((text "print 'Hello World'")
|
||||
(cell (ein:notebook-get-current-cell))
|
||||
(kernel (ein:$notebook-kernel ein:notebook))
|
||||
(msg-id "DUMMY-MSG-ID")
|
||||
(callbacks (ein:cell-make-callbacks cell)))
|
||||
(eintest:notebook-check-kernel-and-codecell kernel cell)
|
||||
;; Execute
|
||||
(insert text)
|
||||
(eintest:notebook-fake-execution kernel text msg-id callbacks)
|
||||
;; Execute reply
|
||||
(should-error (eintest:check-search-forward-from (point-min) "In [1]:"))
|
||||
(eintest:kernel-fake-execute-reply kernel msg-id 1)
|
||||
(should (= (oref cell :input-prompt-number) 1))
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(should (search-forward "In [1]:" nil t)))
|
||||
(let* ((content (list :data "'Hello World'"
|
||||
:name "stdout"))
|
||||
(packet (list :header (list :msg_type "stream")
|
||||
:parent_header (list :msg_id msg-id)
|
||||
:content content)))
|
||||
(ein:kernel--handle-iopub-reply kernel (json-encode packet)))
|
||||
(eintest:check-search-forward-from (point-min) "In [1]:")
|
||||
;; Stream output
|
||||
(eintest:kernel-fake-stream kernel msg-id "Hello World")
|
||||
(should (= (ein:cell-num-outputs cell) 1))
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(should (search-forward "In [1]:" nil t))
|
||||
(should (search-forward "print 'Hello World'" nil t))
|
||||
(should (search-forward "Hello World" nil t)) ; stream output
|
||||
(should (search-forward "\nHello World\n" nil t)) ; stream output
|
||||
(should-not (search-forward "Hello World" nil t))))))
|
||||
|
||||
|
||||
;; Notebook undo
|
||||
|
||||
(defun eintest:notebook-undo-after-execution-1-cell ()
|
||||
(with-current-buffer (eintest:notebook-make-empty)
|
||||
(ein:notebook-insert-cell-below-command)
|
||||
(let* ((text "print 'Hello World'")
|
||||
(output-text "Hello World\n")
|
||||
(cell (ein:notebook-get-current-cell))
|
||||
(kernel (ein:$notebook-kernel ein:notebook))
|
||||
(msg-id "DUMMY-MSG-ID")
|
||||
(callbacks (ein:cell-make-callbacks cell))
|
||||
(check-output
|
||||
(lambda ()
|
||||
(eintest:cell-check-output cell output-text))))
|
||||
(eintest:notebook-check-kernel-and-codecell kernel cell)
|
||||
;; Execute
|
||||
(insert text)
|
||||
(undo-boundary)
|
||||
(eintest:notebook-fake-execution kernel text msg-id callbacks)
|
||||
(ein:kernel-set-callbacks-for-msg kernel msg-id callbacks)
|
||||
;; Stream output
|
||||
(eintest:kernel-fake-stream kernel msg-id output-text)
|
||||
(funcall check-output)
|
||||
;; Undo
|
||||
(should (equal (ein:cell-get-text cell) text))
|
||||
(if (eq ein:notebook-enable-undo 'full)
|
||||
(undo)
|
||||
(should-error (undo)))
|
||||
(when (eq ein:notebook-enable-undo 'full)
|
||||
(should (equal (ein:cell-get-text cell) ""))
|
||||
;; FIXME: Known bug. (it must succeed.)
|
||||
(should-error (funcall check-output))))))
|
||||
|
||||
(defun eintest:notebook-undo-after-execution-2-cells ()
|
||||
(with-current-buffer (eintest:notebook-make-empty)
|
||||
(ein:notebook-insert-cell-below-command)
|
||||
(ein:notebook-insert-cell-above-command)
|
||||
(let* ((text "print 'Hello World\\n' * 10")
|
||||
(next-text "something")
|
||||
(output-text
|
||||
(apply #'concat (loop repeat 10 collect "Hello World\n")))
|
||||
(cell (ein:notebook-get-current-cell))
|
||||
(next-cell (ein:cell-next cell))
|
||||
(kernel (ein:$notebook-kernel ein:notebook))
|
||||
(msg-id "DUMMY-MSG-ID")
|
||||
(callbacks (ein:cell-make-callbacks cell))
|
||||
(check-output
|
||||
(lambda ()
|
||||
(eintest:cell-check-output cell output-text))))
|
||||
(eintest:notebook-check-kernel-and-codecell kernel cell)
|
||||
;; Execute
|
||||
(insert text)
|
||||
(undo-boundary)
|
||||
(let ((pos (point)))
|
||||
;; Do not use `save-excursion' because it does not record undo.
|
||||
(ein:notebook-goto-next-input-command)
|
||||
(insert next-text)
|
||||
(undo-boundary)
|
||||
(goto-char pos))
|
||||
(eintest:notebook-fake-execution kernel text msg-id callbacks)
|
||||
(ein:kernel-set-callbacks-for-msg kernel msg-id callbacks)
|
||||
;; Stream output
|
||||
(eintest:kernel-fake-stream kernel msg-id output-text)
|
||||
(funcall check-output)
|
||||
;; Undo
|
||||
(should (equal (ein:cell-get-text cell) text))
|
||||
(should (equal (ein:cell-get-text next-cell) next-text))
|
||||
(if (eq ein:notebook-enable-undo 'full)
|
||||
(undo)
|
||||
(should-error (undo)))
|
||||
(when (eq ein:notebook-enable-undo 'full)
|
||||
(should (equal (ein:cell-get-text cell) text))
|
||||
;; FIXME: Known bug. (these two must succeed.)
|
||||
(should-error (should (equal (ein:cell-get-text next-cell) "")))
|
||||
(should-error (funcall check-output))))))
|
||||
|
||||
(ert-deftest ein:notebook-undo-after-execution-1-cell/no ()
|
||||
(let ((ein:notebook-enable-undo 'no))
|
||||
(eintest:notebook-undo-after-execution-1-cell)))
|
||||
|
||||
(ert-deftest ein:notebook-undo-after-execution-1-cell/yes ()
|
||||
(let ((ein:notebook-enable-undo 'yes))
|
||||
(eintest:notebook-undo-after-execution-1-cell)))
|
||||
|
||||
(ert-deftest ein:notebook-undo-after-execution-1-cell/full ()
|
||||
(let ((ein:notebook-enable-undo 'full))
|
||||
(eintest:notebook-undo-after-execution-1-cell)))
|
||||
|
||||
(ert-deftest ein:notebook-undo-after-execution-2-cells/no ()
|
||||
(let ((ein:notebook-enable-undo 'no))
|
||||
(eintest:notebook-undo-after-execution-2-cells)))
|
||||
|
||||
(ert-deftest ein:notebook-undo-after-execution-2-cells/yes ()
|
||||
(let ((ein:notebook-enable-undo 'yes))
|
||||
(eintest:notebook-undo-after-execution-2-cells)))
|
||||
|
||||
(ert-deftest ein:notebook-undo-after-execution-2-cells/full ()
|
||||
(let ((ein:notebook-enable-undo 'full))
|
||||
(eintest:notebook-undo-after-execution-2-cells)))
|
||||
|
||||
|
||||
;; Notebook mode
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue