Fixes #85712

上级 5bfd23cd
......@@ -122,17 +122,19 @@ export class ReplaceCommandThatPreservesSelection implements ICommand {
private readonly _range: Range;
private readonly _text: string;
private readonly _initialSelection: Selection;
private readonly _forceMoveMarkers: boolean;
private _selectionId: string | null;
constructor(editRange: Range, text: string, initialSelection: Selection) {
constructor(editRange: Range, text: string, initialSelection: Selection, forceMoveMarkers: boolean = false) {
this._range = editRange;
this._text = text;
this._initialSelection = initialSelection;
this._forceMoveMarkers = forceMoveMarkers;
this._selectionId = null;
}
public getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {
builder.addEditOperation(this._range, this._text);
builder.addTrackedEditOperation(this._range, this._text, this._forceMoveMarkers);
this._selectionId = builder.trackSelection(this._initialSelection);
}
......
......@@ -727,7 +727,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
case H.Paste:
cursorChangeReason = CursorChangeReason.Paste;
this._paste(<string>payload.text, <boolean>payload.pasteOnNewLine, <string[]>payload.multicursorText);
this._paste(<string>payload.text, <boolean>payload.pasteOnNewLine, <string[]>payload.multicursorText || []);
break;
case H.Cut:
......@@ -1000,7 +1000,7 @@ class CommandExecutor {
let operations: IIdentifiedSingleEditOperation[] = [];
let operationMinor = 0;
const addEditOperation = (selection: Range, text: string | null) => {
const addEditOperation = (selection: Range, text: string | null, forceMoveMarkers: boolean = false) => {
if (selection.isEmpty() && text === '') {
// This command wants to add a no-op => no thank you
return;
......@@ -1012,15 +1012,15 @@ class CommandExecutor {
},
range: selection,
text: text,
forceMoveMarkers: false,
forceMoveMarkers: forceMoveMarkers,
isAutoWhitespaceEdit: command.insertsAutoWhitespace
});
};
let hadTrackedEditOperation = false;
const addTrackedEditOperation = (selection: Range, text: string | null) => {
const addTrackedEditOperation = (selection: Range, text: string | null, forceMoveMarkers?: boolean) => {
hadTrackedEditOperation = true;
addEditOperation(selection, text);
addEditOperation(selection, text, forceMoveMarkers);
};
const trackSelection = (selection: Selection, trackPreviousOnEmpty?: boolean) => {
......
......@@ -94,7 +94,7 @@ export class TypeOperations {
if (pasteOnNewLine) {
// Paste entire line at the beginning of line
let typeSelection = new Range(position.lineNumber, 1, position.lineNumber, 1);
commands[i] = new ReplaceCommandThatPreservesSelection(typeSelection, text, selection);
commands[i] = new ReplaceCommandThatPreservesSelection(typeSelection, text, selection, true);
} else {
commands[i] = new ReplaceCommand(selection, text);
}
......
......@@ -22,7 +22,7 @@ export interface IEditOperationBuilder {
* @param range The range to replace (delete). May be empty to represent a simple insert.
* @param text The text to replace with. May be null to represent a simple delete.
*/
addEditOperation(range: Range, text: string | null): void;
addEditOperation(range: Range, text: string | null, forceMoveMarkers?: boolean): void;
/**
* Add a new edit operation (a replace operation).
......@@ -30,7 +30,7 @@ export interface IEditOperationBuilder {
* @param range The range to replace (delete). May be empty to represent a simple insert.
* @param text The text to replace with. May be null to represent a simple delete.
*/
addTrackedEditOperation(range: Range, text: string | null): void;
addTrackedEditOperation(range: Range, text: string | null, forceMoveMarkers?: boolean): void;
/**
* Track `selection` when applying edit operations.
......
......@@ -22,7 +22,8 @@ import { EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions'
export function createSingleEditOp(text: string, positionLineNumber: number, positionColumn: number, selectionLineNumber: number = positionLineNumber, selectionColumn: number = positionColumn): IIdentifiedSingleEditOperation {
return {
range: new Range(selectionLineNumber, selectionColumn, positionLineNumber, positionColumn),
text: text
text: text,
forceMoveMarkers: false
};
}
......
......@@ -28,7 +28,8 @@ function createInsertDeleteSingleEditOp(text: string | null, positionLineNumber:
export function createSingleEditOp(text: string | null, positionLineNumber: number, positionColumn: number, selectionLineNumber: number = positionLineNumber, selectionColumn: number = positionColumn): IIdentifiedSingleEditOperation {
return {
range: new Range(selectionLineNumber, selectionColumn, positionLineNumber, positionColumn),
text: text
text: text,
forceMoveMarkers: false
};
}
......
......@@ -2279,6 +2279,30 @@ suite('Editor Controller - Regression tests', () => {
model.dispose();
});
test('issue #85712: Paste line moves cursor to start of current line rather than start of next line', () => {
let model = createTextModel(
[
'abc123',
''
].join('\n')
);
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
editor.setSelections([
new Selection(2, 1, 2, 1)
]);
cursorCommand(cursor, H.Paste, { text: 'something\n', pasteOnNewLine: true });
assert.equal(model.getValue(), [
'abc123',
'something',
''
].join('\n'));
assertCursor(cursor, new Position(3, 1));
});
model.dispose();
});
});
suite('Editor Controller - Cursor Configuration', () => {
......@@ -2636,7 +2660,7 @@ suite('Editor Controller - Cursor Configuration', () => {
'',
' }',
].join('\n'));
assertCursor(cursor, new Position(4, 1));
assertCursor(cursor, new Position(5, 1));
});
model.dispose();
......
......@@ -50,17 +50,19 @@ export function testCommand(
export function getEditOperation(model: ITextModel, command: ICommand): IIdentifiedSingleEditOperation[] {
let operations: IIdentifiedSingleEditOperation[] = [];
let editOperationBuilder: IEditOperationBuilder = {
addEditOperation: (range: Range, text: string) => {
addEditOperation: (range: Range, text: string, forceMoveMarkers: boolean = false) => {
operations.push({
range: range,
text: text
text: text,
forceMoveMarkers: forceMoveMarkers
});
},
addTrackedEditOperation: (range: Range, text: string) => {
addTrackedEditOperation: (range: Range, text: string, forceMoveMarkers: boolean = false) => {
operations.push({
range: range,
text: text
text: text,
forceMoveMarkers: forceMoveMarkers
});
},
......
......@@ -1906,14 +1906,14 @@ declare namespace monaco.editor {
* @param range The range to replace (delete). May be empty to represent a simple insert.
* @param text The text to replace with. May be null to represent a simple delete.
*/
addEditOperation(range: Range, text: string | null): void;
addEditOperation(range: Range, text: string | null, forceMoveMarkers?: boolean): void;
/**
* Add a new edit operation (a replace operation).
* The inverse edits will be accessible in `ICursorStateComputerData.getInverseEditOperations()`
* @param range The range to replace (delete). May be empty to represent a simple insert.
* @param text The text to replace with. May be null to represent a simple delete.
*/
addTrackedEditOperation(range: Range, text: string | null): void;
addTrackedEditOperation(range: Range, text: string | null, forceMoveMarkers?: boolean): void;
/**
* Track `selection` when applying edit operations.
* A best effort will be made to not grow/expand the selection.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册