Skip to content
This repository has been archived by the owner on Mar 3, 2023. It is now read-only.

Restore selectionsMarkerLayer of different editor #16564

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
105 changes: 105 additions & 0 deletions spec/text-editor-spec.js
Expand Up @@ -5193,6 +5193,111 @@ describe('TextEditor', () => {
})
})

describe('undo/redo restore selections of editor which initiated original change', () => {
let editor1, editor2

beforeEach(async () => {
editor1 = editor
editor2 = new TextEditor({buffer: editor1.buffer})

editor1.setText(dedent `
aaaaaa
bbbbbb
cccccc
dddddd
eeeeee
`)
})

it('[editor.transact] restore selection of change-initiated-editor', () => {
editor1.setCursorBufferPosition([0, 0]); editor1.transact(() => editor1.insertText('1'))
editor2.setCursorBufferPosition([1, 0]); editor2.transact(() => editor2.insertText('2'))
editor1.setCursorBufferPosition([2, 0]); editor1.transact(() => editor1.insertText('3'))
editor2.setCursorBufferPosition([3, 0]); editor2.transact(() => editor2.insertText('4'))

expect(editor1.getText()).toBe(dedent `
1aaaaaa
2bbbbbb
3cccccc
4dddddd
eeeeee
`)

editor2.setCursorBufferPosition([4, 0])
editor1.undo(); expect(editor1.getCursorBufferPosition()).toEqual([3, 0])
editor1.undo(); expect(editor1.getCursorBufferPosition()).toEqual([2, 0])
editor1.undo(); expect(editor1.getCursorBufferPosition()).toEqual([1, 0])
editor1.undo(); expect(editor1.getCursorBufferPosition()).toEqual([0, 0])
expect(editor2.getCursorBufferPosition()).toEqual([4, 0]) // remain unchanged

editor1.redo(); expect(editor1.getCursorBufferPosition()).toEqual([0, 1])
editor1.redo(); expect(editor1.getCursorBufferPosition()).toEqual([1, 1])
editor1.redo(); expect(editor1.getCursorBufferPosition()).toEqual([2, 1])
editor1.redo(); expect(editor1.getCursorBufferPosition()).toEqual([3, 1])
expect(editor2.getCursorBufferPosition()).toEqual([4, 0]) // remain unchanged

editor1.setCursorBufferPosition([4, 0])
editor2.undo(); expect(editor2.getCursorBufferPosition()).toEqual([3, 0])
editor2.undo(); expect(editor2.getCursorBufferPosition()).toEqual([2, 0])
editor2.undo(); expect(editor2.getCursorBufferPosition()).toEqual([1, 0])
editor2.undo(); expect(editor2.getCursorBufferPosition()).toEqual([0, 0])
expect(editor1.getCursorBufferPosition()).toEqual([4, 0]) // remain unchanged

editor2.redo(); expect(editor2.getCursorBufferPosition()).toEqual([0, 1])
editor2.redo(); expect(editor2.getCursorBufferPosition()).toEqual([1, 1])
editor2.redo(); expect(editor2.getCursorBufferPosition()).toEqual([2, 1])
editor2.redo(); expect(editor2.getCursorBufferPosition()).toEqual([3, 1])
expect(editor1.getCursorBufferPosition()).toEqual([4, 0]) // remain unchanged
})

it('[manually group checkpoint] restore selection of change-initiated-editor', () => {
const transact = (editor, fn) => {
const checkpoint = editor.createCheckpoint()
fn()
editor.groupChangesSinceCheckpoint(checkpoint)
}

editor1.setCursorBufferPosition([0, 0]); transact(editor1, () => editor1.insertText('1'))
editor2.setCursorBufferPosition([1, 0]); transact(editor2, () => editor2.insertText('2'))
editor1.setCursorBufferPosition([2, 0]); transact(editor1, () => editor1.insertText('3'))
editor2.setCursorBufferPosition([3, 0]); transact(editor2, () => editor2.insertText('4'))

expect(editor1.getText()).toBe(dedent `
1aaaaaa
2bbbbbb
3cccccc
4dddddd
eeeeee
`)

editor2.setCursorBufferPosition([4, 0])
editor1.undo(); expect(editor1.getCursorBufferPosition()).toEqual([3, 0])
editor1.undo(); expect(editor1.getCursorBufferPosition()).toEqual([2, 0])
editor1.undo(); expect(editor1.getCursorBufferPosition()).toEqual([1, 0])
editor1.undo(); expect(editor1.getCursorBufferPosition()).toEqual([0, 0])
expect(editor2.getCursorBufferPosition()).toEqual([4, 0]) // remain unchanged

editor1.redo(); expect(editor1.getCursorBufferPosition()).toEqual([0, 1])
editor1.redo(); expect(editor1.getCursorBufferPosition()).toEqual([1, 1])
editor1.redo(); expect(editor1.getCursorBufferPosition()).toEqual([2, 1])
editor1.redo(); expect(editor1.getCursorBufferPosition()).toEqual([3, 1])
expect(editor2.getCursorBufferPosition()).toEqual([4, 0]) // remain unchanged

editor1.setCursorBufferPosition([4, 0])
editor2.undo(); expect(editor2.getCursorBufferPosition()).toEqual([3, 0])
editor2.undo(); expect(editor2.getCursorBufferPosition()).toEqual([2, 0])
editor2.undo(); expect(editor2.getCursorBufferPosition()).toEqual([1, 0])
editor2.undo(); expect(editor2.getCursorBufferPosition()).toEqual([0, 0])
expect(editor1.getCursorBufferPosition()).toEqual([4, 0]) // remain unchanged

editor2.redo(); expect(editor2.getCursorBufferPosition()).toEqual([0, 1])
editor2.redo(); expect(editor2.getCursorBufferPosition()).toEqual([1, 1])
editor2.redo(); expect(editor2.getCursorBufferPosition()).toEqual([2, 1])
editor2.redo(); expect(editor2.getCursorBufferPosition()).toEqual([3, 1])
expect(editor1.getCursorBufferPosition()).toEqual([4, 0]) // remain unchanged
})
})

describe('when the buffer is changed (via its direct api, rather than via than edit session)', () => {
it('moves the cursor so it is in the same relative position of the buffer', () => {
expect(editor.getCursorScreenPosition()).toEqual([0, 0])
Expand Down
22 changes: 16 additions & 6 deletions src/text-editor.js
Expand Up @@ -224,7 +224,7 @@ class TextEditor {

this.defaultMarkerLayer = this.displayLayer.addMarkerLayer()
if (!this.selectionsMarkerLayer) {
this.selectionsMarkerLayer = this.addMarkerLayer({maintainHistory: true, persistent: true})
this.selectionsMarkerLayer = this.addMarkerLayer({maintainHistory: true, persistent: true, role: 'selections'})
}

this.decorationManager = new DecorationManager(this)
Expand Down Expand Up @@ -1808,13 +1808,13 @@ class TextEditor {

// Essential: Undo the last change.
undo () {
this.avoidMergingSelections(() => this.buffer.undo())
this.avoidMergingSelections(() => this.buffer.undo({selectionsMarkerLayer: this.selectionsMarkerLayer}))
this.getLastSelection().autoscroll()
}

// Essential: Redo the last change.
redo () {
this.avoidMergingSelections(() => this.buffer.redo())
this.avoidMergingSelections(() => this.buffer.redo({selectionsMarkerLayer: this.selectionsMarkerLayer}))
this.getLastSelection().autoscroll()
}

Expand All @@ -1831,7 +1831,13 @@ class TextEditor {
// still 'groupable', the two transactions are merged with respect to undo and redo.
// * `fn` A {Function} to call inside the transaction.
transact (groupingInterval, fn) {
return this.buffer.transact(groupingInterval, fn)
const options = {selectionsMarkerLayer: this.selectionsMarkerLayer}
if (typeof groupingInterval === 'function') {
fn = groupingInterval
} else {
options.groupingInterval = groupingInterval
}
return this.buffer.transact(options, fn)
}

// Extended: Abort an open transaction, undoing any operations performed so far
Expand All @@ -1842,7 +1848,9 @@ class TextEditor {
// with {::revertToCheckpoint} and {::groupChangesSinceCheckpoint}.
//
// Returns a checkpoint value.
createCheckpoint () { return this.buffer.createCheckpoint() }
createCheckpoint () {
return this.buffer.createCheckpoint({selectionsMarkerLayer: this.selectionsMarkerLayer})
}

// Extended: Revert the buffer to the state it was in when the given
// checkpoint was created.
Expand All @@ -1866,7 +1874,9 @@ class TextEditor {
// * `checkpoint` The checkpoint from which to group changes.
//
// Returns a {Boolean} indicating whether the operation succeeded.
groupChangesSinceCheckpoint (checkpoint) { return this.buffer.groupChangesSinceCheckpoint(checkpoint) }
groupChangesSinceCheckpoint (checkpoint) {
return this.buffer.groupChangesSinceCheckpoint(checkpoint, {selectionsMarkerLayer: this.selectionsMarkerLayer})
}

/*
Section: TextEditor Coordinates
Expand Down