diff --git a/features/step-definitions/ein-steps.el b/features/step-definitions/ein-steps.el index dbcc37b..00297e2 100644 --- a/features/step-definitions/ein-steps.el +++ b/features/step-definitions/ein-steps.el @@ -300,9 +300,14 @@ (When "^dump diagnostic" (lambda () (let ((fill (- (length buffer-undo-list) (length ein:%which-cell%)))) - (message "Undo failure diagnostic %s %s | %s" + (message "Undo inspect diagnostic %s %s | %s" buffer-undo-list ein:%which-cell% fill)))) +(When "^I add fake cursor to undo list$" + (lambda () + (push '(apply deactivate-cursor-after-undo 20) buffer-undo-list) + (push '(apply activate-cursor-for-undo 20) buffer-undo-list))) + (When "^eval \"\\(.*\\)\"$" (lambda (command) (eval (car (read-from-string command))))) diff --git a/features/support/env.el b/features/support/env.el index 79afb60..e8411fe 100644 --- a/features/support/env.el +++ b/features/support/env.el @@ -37,6 +37,9 @@ (!cons "content" ecukes-exclude-tags) (!cons "svg" ecukes-exclude-tags)) +(defalias 'activate-cursor-for-undo #'ignore) +(defalias 'deactivate-cursor-after-undo #'ignore) + (defvar ein:testing-jupyter-server-root (f-parent (f-dirname load-file-name))) (defun ein:testing-after-scenario () diff --git a/features/undo.feature b/features/undo.feature index 13ca4e0..59f2a04 100644 --- a/features/undo.feature +++ b/features/undo.feature @@ -86,9 +86,10 @@ Scenario: Test the conflagrative commands Then the cursor should be at point "22" @undo -Scenario: Clear output doesn't break undo +Scenario: Clear output doesn't break undo, throw in multiple-cursors Given I enable "ein:worksheet-enable-undo" Given new python notebook + And I clear log expr "ein:log-all-buffer-name" When I type "from time import sleep" And I press "RET" And I press "C-c C-b" @@ -99,6 +100,7 @@ Scenario: Clear output doesn't break undo And I type "print("abba\nabba")" And I press "RET" And I type "1.618" + And I add fake cursor to undo list And I wait for cell to execute And I press "C-" And I press "C-n" @@ -109,6 +111,8 @@ Scenario: Clear output doesn't break undo Then the cursor should be at point "74" And I undo again Then the cursor should be at point "53" + And I switch to log expr "ein:log-all-buffer-name" + Then I should see "multiple-cursors-mode exception" @undo Scenario: Moving cells doesn't break undo @@ -133,7 +137,7 @@ Scenario: Moving cells doesn't break undo And I press "C-/" Then the cursor should be at point "67" -@forlorn +@undo Scenario: Split and merge don't break undo Given I enable "ein:worksheet-enable-undo" Given new python notebook diff --git a/lisp/ein-worksheet.el b/lisp/ein-worksheet.el index abd0963..67bc31c 100644 --- a/lisp/ein-worksheet.el +++ b/lisp/ein-worksheet.el @@ -173,35 +173,47 @@ Normalize `buffer-undo-list' by removing extraneous details, and update the ein: (defun ein:worksheet--jigger-undo-list (&optional change-cell-id) (cl-assert (listp buffer-undo-list)) - (when (/= (length buffer-undo-list) (length ein:%which-cell%)) - (ein:log 'debug "jig %s to %s: %S %S" - (length ein:%which-cell%) (length buffer-undo-list) - buffer-undo-list ein:%which-cell%)) - (-when-let* ((old-cell-id (car change-cell-id)) - (new-cell-id (cdr change-cell-id)) - (changed-p (not (eq old-cell-id new-cell-id)))) - (setq ein:%which-cell% (-replace old-cell-id new-cell-id ein:%which-cell%))) - (let ((fill (- (length buffer-undo-list) (length ein:%which-cell%)))) - (cond ((> (abs fill) 1) - (let ((msg (format "Undo failure diagnostic %s %s | %s" - buffer-undo-list ein:%which-cell% fill)) - (pm-allow-post-command-hook nil)) - (setq ein:worksheet-enable-undo nil) - (ein:worksheet-undo-setup ein:%worksheet%) - (when pm/polymode - (dolist (b (eieio-oref pm/polymode '-buffers)) - (when (buffer-live-p b) - (poly-ein-copy-state (ein:worksheet--get-buffer ein:%worksheet%) b)))) - (ein:display-warning msg :error) - (error "ein:worksheet--jigger-undo-list: aborting"))) - ((< fill 0) - (setq ein:%which-cell% (nthcdr (- fill) ein:%which-cell%))) - ((> fill 0) - (setq ein:%which-cell% (nconc (make-list fill (car ein:%which-cell%)) - ein:%which-cell%))))) - (cl-assert (= (length buffer-undo-list) (length ein:%which-cell%)) t - "ein:worksheet--jigger-undo-list %d != %d" - (length buffer-undo-list) (length ein:%which-cell%))) + (let ((len-buffer-undo-list (length buffer-undo-list)) + (len-which-cell (length ein:%which-cell%))) + (when (/= len-buffer-undo-list len-which-cell) + (ein:log 'debug "jig %s to %s: %S %S" + len-which-cell len-buffer-undo-list + buffer-undo-list ein:%which-cell%)) + (-when-let* ((old-cell-id (car change-cell-id)) + (new-cell-id (cdr change-cell-id)) + (changed-p (not (eq old-cell-id new-cell-id)))) + (setq ein:%which-cell% (-replace old-cell-id new-cell-id ein:%which-cell%))) + (let ((multiple-cursors-p + (cl-some (lambda (entry) + (cl-flet ((check (entry bogey) (and (listp entry) + (not (atom (cdr entry))) + (eq (nth 1 entry) bogey)))) + (or (check entry 'activate-cursor-for-undo) + (check entry 'deactivate-cursor-after-undo)))) + (cl-subseq buffer-undo-list 0 (min (length buffer-undo-list) 30)))) + (fill (- len-buffer-undo-list len-which-cell))) + (cond ((and (not multiple-cursors-p) (> (abs fill) 1)) + (let ((msg (format "Undo failure diagnostic %s %s | %s" + buffer-undo-list ein:%which-cell% fill)) + (pm-allow-post-command-hook nil)) + (setq ein:worksheet-enable-undo nil) + (ein:worksheet-undo-setup ein:%worksheet%) + (when pm/polymode + (dolist (b (eieio-oref pm/polymode '-buffers)) + (when (buffer-live-p b) + (poly-ein-copy-state (ein:worksheet--get-buffer ein:%worksheet%) b)))) + (ein:display-warning msg :error) + (error "ein:worksheet--jigger-undo-list: aborting"))) + ((< fill 0) + (setq ein:%which-cell% (nthcdr (- fill) ein:%which-cell%))) + ((> fill 0) + (when (and (> fill 1) multiple-cursors-p) + (ein:log 'debug "multiple-cursors-mode exception fill %s" fill)) + (setq ein:%which-cell% (nconc (make-list fill (car ein:%which-cell%)) + ein:%which-cell%))))) + (cl-assert (= (length buffer-undo-list) (length ein:%which-cell%)) t + "ein:worksheet--jigger-undo-list %d != %d" + (length buffer-undo-list) (length ein:%which-cell%)))) (defun ein:worksheet--unshift-undo-list (cell &optional exogenous-input old-cell) "Adjust `buffer-undo-list' for adding CELL. diff --git a/lisp/poly-ein.el b/lisp/poly-ein.el index ffbb9b2..3c719c1 100644 --- a/lisp/poly-ein.el +++ b/lisp/poly-ein.el @@ -28,7 +28,6 @@ (require 'jit-lock) (require 'display-line-numbers nil t) (require 'undo-tree nil t) -(require 'multiple-cursors nil t) (declare-function ein:get-notebook "ein-notebook") (declare-function ein:notebook-mode "ein-notebook") @@ -271,9 +270,6 @@ TYPE can be 'body, nil." (undo-tree-mode -1))) (when visual-line-mode (visual-line-mode -1)) - (when (ein:eval-if-bound 'multiple-cursors-mode) - (when (fboundp 'multiple-cursors-mode) - (multiple-cursors-mode -1))) (if (eq type 'host) (setq syntax-propertize-function nil) (aif pm--syntax-propertize-function-original