Skip to content

Commit

Permalink
Add cursorRedo command (Ctrl+Shift+J) (#82620)
Browse files Browse the repository at this point in the history
Add `cursorRedo` command (Ctrl+Shift+J)
  • Loading branch information
alexdima authored Oct 18, 2019
2 parents fca98f0 + a1ff866 commit 259b7bf
Showing 1 changed file with 56 additions and 34 deletions.
90 changes: 56 additions & 34 deletions src/vs/editor/contrib/cursorUndo/cursorUndo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,77 +26,83 @@ class CursorState {
}
}

export class CursorUndoController extends Disposable implements IEditorContribution {
export class CursorUndoRedoController extends Disposable implements IEditorContribution {

public static readonly ID = 'editor.contrib.cursorUndoController';
public static readonly ID = 'editor.contrib.cursorUndoRedoController';

public static get(editor: ICodeEditor): CursorUndoController {
return editor.getContribution<CursorUndoController>(CursorUndoController.ID);
public static get(editor: ICodeEditor): CursorUndoRedoController {
return editor.getContribution<CursorUndoRedoController>(CursorUndoRedoController.ID);
}

private readonly _editor: ICodeEditor;
private _isCursorUndo: boolean;
private _isCursorUndoRedo: boolean;

private _undoStack: CursorState[];
private _redoStack: CursorState[];
private _prevState: CursorState | null;

constructor(editor: ICodeEditor) {
super();
this._editor = editor;
this._isCursorUndo = false;
this._isCursorUndoRedo = false;

this._undoStack = [];
this._prevState = this._readState();
this._redoStack = [];
this._prevState = null;

this._register(editor.onDidChangeModel((e) => {
this._undoStack = [];
this._redoStack = [];
this._prevState = null;
}));
this._register(editor.onDidChangeModelContent((e) => {
this._undoStack = [];
this._redoStack = [];
this._prevState = null;
}));
this._register(editor.onDidChangeCursorSelection((e) => {

if (!this._isCursorUndo && this._prevState) {
this._undoStack.push(this._prevState);
if (this._undoStack.length > 50) {
// keep the cursor undo stack bounded
this._undoStack.shift();
const newState = new CursorState(this._editor.getSelections()!);

if (!this._isCursorUndoRedo && this._prevState) {
const isEqualToLastUndoStack = (this._undoStack.length > 0 && this._undoStack[this._undoStack.length - 1].equals(this._prevState));
if (!isEqualToLastUndoStack) {
this._undoStack.push(this._prevState);
this._redoStack = [];
if (this._undoStack.length > 50) {
// keep the cursor undo stack bounded
this._undoStack.shift();
}
}
}

this._prevState = this._readState();
this._prevState = newState;
}));
}

private _readState(): CursorState | null {
if (!this._editor.hasModel()) {
// no model => no state
return null;
public cursorUndo(): void {
if (!this._editor.hasModel() || this._undoStack.length === 0) {
return;
}

return new CursorState(this._editor.getSelections());
this._redoStack.push(new CursorState(this._editor.getSelections()));
this._applyState(this._undoStack.pop()!);
}

public cursorUndo(): void {
if (!this._editor.hasModel()) {
public cursorRedo(): void {
if (!this._editor.hasModel() || this._redoStack.length === 0) {
return;
}

const currState = new CursorState(this._editor.getSelections());

while (this._undoStack.length > 0) {
const prevState = this._undoStack.pop()!;
this._undoStack.push(new CursorState(this._editor.getSelections()));
this._applyState(this._redoStack.pop()!);
}

if (!prevState.equals(currState)) {
this._isCursorUndo = true;
this._editor.setSelections(prevState.selections);
this._editor.revealRangeInCenterIfOutsideViewport(prevState.selections[0], ScrollType.Smooth);
this._isCursorUndo = false;
return;
}
}
private _applyState(state: CursorState): void {
this._isCursorUndoRedo = true;
this._editor.setSelections(state.selections);
this._editor.revealRangeInCenterIfOutsideViewport(state.selections[0], ScrollType.Smooth);
this._isCursorUndoRedo = false;
}
}

Expand All @@ -116,9 +122,25 @@ export class CursorUndo extends EditorAction {
}

public run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void {
CursorUndoController.get(editor).cursorUndo();
CursorUndoRedoController.get(editor).cursorUndo();
}
}

export class CursorRedo extends EditorAction {
constructor() {
super({
id: 'cursorRedo',
label: nls.localize('cursor.redo', "Soft Redo"),
alias: 'Soft Redo',
precondition: undefined
});
}

public run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void {
CursorUndoRedoController.get(editor).cursorRedo();
}
}

registerEditorContribution(CursorUndoController.ID, CursorUndoController);
registerEditorContribution(CursorUndoRedoController.ID, CursorUndoRedoController);
registerEditorAction(CursorUndo);
registerEditorAction(CursorRedo);

0 comments on commit 259b7bf

Please sign in to comment.