Skip to content

Commit beecd58

Browse files
committed
Use a more reasonable start selection for the inverse of applied history events
... when they have no stored selections after them. FIX: Move the selection to a less surprising place when undoing, moving the selection, redoing, then undoing again. Closes codemirror/dev#1668
1 parent 0587e5d commit beecd58

File tree

2 files changed

+19
-4
lines changed

2 files changed

+19
-4
lines changed

src/history.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,8 @@ class HistoryState {
355355
pop(side: BranchName, state: EditorState, onlySelection: boolean): Transaction | null {
356356
let branch = side == BranchName.Done ? this.done : this.undone
357357
if (branch.length == 0) return null
358-
let event = branch[branch.length - 1], selection = event.selectionsAfter[0] || state.selection
358+
let event = branch[branch.length - 1], selection = event.selectionsAfter[0] ||
359+
(event.startSelection ? event.startSelection.map(event.changes!.invertedDesc, 1) : state.selection)
359360
if (onlySelection && event.selectionsAfter.length) {
360361
return state.update({
361362
selection: event.selectionsAfter[event.selectionsAfter.length - 1],

test/test-history.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,21 @@ describe("history", () => {
7070
ist(state.selection.main.head, 4)
7171
})
7272

73+
it("restores selection on undo-redo-undo", () => {
74+
let state = mkState({}, "1\n2\n3")
75+
state = state.update({selection: {anchor: 5}}).state
76+
state = state.update({changes: {from: 5, insert: "."}, selection: {anchor: 6}}).state
77+
state = state.update({selection: {anchor: 0}}).state
78+
state = command(state, undo)
79+
ist(state.selection.main.head, 5)
80+
state = state.update({selection: {anchor: 0}}).state
81+
state = command(state, redo)
82+
ist(state.selection.main.head, 6)
83+
state = state.update({selection: {anchor: 0}}).state
84+
state = command(state, undo)
85+
ist(state.selection.main.head, 5)
86+
})
87+
7388
it("tracks multiple levels of history", () => {
7489
let state = mkState({}, "one")
7590
state = type(state, "new")
@@ -249,7 +264,7 @@ describe("history", () => {
249264
state = state.update({annotations: isolateHistory.of("before")}).state
250265
state = state.update({selection: {anchor: 0, head: 2}}).state
251266
const selection = state.selection
252-
state = state.update(state.replaceSelection("hello")).state
267+
state = state.update({changes: [{from: 0, to: 2}, {from: 0, insert: "hello"}]}).state
253268
const selection2 = state.selection
254269
state = command(state, undo)
255270
ist(state.selection.eq(selection))
@@ -466,11 +481,10 @@ describe("history", () => {
466481
state = command(state, redoSelection)
467482
ist(state.selection.eq(selection2))
468483
state = state.update(state.replaceSelection("hello")).state
469-
const selection3 = state.selection
470484
state = command(state, undoSelection)
471485
ist(state.selection.eq(selection2))
472486
state = command(state, redo)
473-
ist(state.selection.eq(selection3))
487+
ist(state.selection.main.head, 5)
474488
})
475489

476490
it("can undo a selection through remote changes", () => {

0 commit comments

Comments
 (0)