73 lines
2.5 KiB
TypeScript
73 lines
2.5 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import { Range } from 'vs/editor/common/core/range';
|
|
import { Selection } from 'vs/editor/common/core/selection';
|
|
import { ICommand, IEditOperationBuilder, ICursorStateComputerData } from 'vs/editor/common/editorCommon';
|
|
import { ITextModel } from 'vs/editor/common/model';
|
|
|
|
interface IEditOperation {
|
|
range: Range;
|
|
text: string;
|
|
}
|
|
|
|
export class ReplaceAllCommand implements ICommand {
|
|
|
|
private readonly _editorSelection: Selection;
|
|
private _trackedEditorSelectionId: string | null;
|
|
private readonly _ranges: Range[];
|
|
private readonly _replaceStrings: string[];
|
|
|
|
constructor(editorSelection: Selection, ranges: Range[], replaceStrings: string[]) {
|
|
this._editorSelection = editorSelection;
|
|
this._ranges = ranges;
|
|
this._replaceStrings = replaceStrings;
|
|
this._trackedEditorSelectionId = null;
|
|
}
|
|
|
|
public getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {
|
|
if (this._ranges.length > 0) {
|
|
// Collect all edit operations
|
|
let ops: IEditOperation[] = [];
|
|
for (let i = 0; i < this._ranges.length; i++) {
|
|
ops.push({
|
|
range: this._ranges[i],
|
|
text: this._replaceStrings[i]
|
|
});
|
|
}
|
|
|
|
// Sort them in ascending order by range starts
|
|
ops.sort((o1, o2) => {
|
|
return Range.compareRangesUsingStarts(o1.range, o2.range);
|
|
});
|
|
|
|
// Merge operations that touch each other
|
|
let resultOps: IEditOperation[] = [];
|
|
let previousOp = ops[0];
|
|
for (let i = 1; i < ops.length; i++) {
|
|
if (previousOp.range.endLineNumber === ops[i].range.startLineNumber && previousOp.range.endColumn === ops[i].range.startColumn) {
|
|
// These operations are one after another and can be merged
|
|
previousOp.range = previousOp.range.plusRange(ops[i].range);
|
|
previousOp.text = previousOp.text + ops[i].text;
|
|
} else {
|
|
resultOps.push(previousOp);
|
|
previousOp = ops[i];
|
|
}
|
|
}
|
|
resultOps.push(previousOp);
|
|
|
|
for (const op of resultOps) {
|
|
builder.addEditOperation(op.range, op.text);
|
|
}
|
|
}
|
|
|
|
this._trackedEditorSelectionId = builder.trackSelection(this._editorSelection);
|
|
}
|
|
|
|
public computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {
|
|
return helper.getTrackedSelection(this._trackedEditorSelectionId!);
|
|
}
|
|
}
|