mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
Fix cursor synchronization issue in multi-cursor word left selection (#215523)
Make all cursors behave the same when doing word left (fixes #169904)
This commit is contained in:
@@ -208,7 +208,7 @@ export class WordOperations {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static moveWordLeft(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position, wordNavigationType: WordNavigationType): Position {
|
||||
public static moveWordLeft(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position, wordNavigationType: WordNavigationType, hasMulticursor: boolean): Position {
|
||||
let lineNumber = position.lineNumber;
|
||||
let column = position.column;
|
||||
|
||||
@@ -227,7 +227,8 @@ export class WordOperations {
|
||||
|
||||
if (wordNavigationType === WordNavigationType.WordStartFast) {
|
||||
if (
|
||||
prevWordOnLine
|
||||
!hasMulticursor // avoid having multiple cursors stop at different locations when doing word start
|
||||
&& prevWordOnLine
|
||||
&& prevWordOnLine.wordType === WordType.Separator
|
||||
&& prevWordOnLine.end - prevWordOnLine.start === 1
|
||||
&& prevWordOnLine.nextCharClass === WordCharacterClass.Regular
|
||||
@@ -830,10 +831,10 @@ export class WordPartOperations extends WordOperations {
|
||||
return candidates[0];
|
||||
}
|
||||
|
||||
public static moveWordPartLeft(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position): Position {
|
||||
public static moveWordPartLeft(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position, hasMulticursor: boolean): Position {
|
||||
const candidates = enforceDefined([
|
||||
WordOperations.moveWordLeft(wordSeparators, model, position, WordNavigationType.WordStart),
|
||||
WordOperations.moveWordLeft(wordSeparators, model, position, WordNavigationType.WordEnd),
|
||||
WordOperations.moveWordLeft(wordSeparators, model, position, WordNavigationType.WordStart, hasMulticursor),
|
||||
WordOperations.moveWordLeft(wordSeparators, model, position, WordNavigationType.WordEnd, hasMulticursor),
|
||||
WordOperations._moveWordPartLeft(model, position)
|
||||
]);
|
||||
candidates.sort(Position.compare);
|
||||
|
||||
@@ -48,10 +48,10 @@ export abstract class MoveWordCommand extends EditorCommand {
|
||||
const wordSeparators = getMapForWordSeparators(editor.getOption(EditorOption.wordSeparators), editor.getOption(EditorOption.wordSegmenterLocales));
|
||||
const model = editor.getModel();
|
||||
const selections = editor.getSelections();
|
||||
|
||||
const hasMulticursor = selections.length > 1;
|
||||
const result = selections.map((sel) => {
|
||||
const inPosition = new Position(sel.positionLineNumber, sel.positionColumn);
|
||||
const outPosition = this._move(wordSeparators, model, inPosition, this._wordNavigationType);
|
||||
const outPosition = this._move(wordSeparators, model, inPosition, this._wordNavigationType, hasMulticursor);
|
||||
return this._moveTo(sel, outPosition, this._inSelectionMode);
|
||||
});
|
||||
|
||||
@@ -83,17 +83,17 @@ export abstract class MoveWordCommand extends EditorCommand {
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract _move(wordSeparators: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType): Position;
|
||||
protected abstract _move(wordSeparators: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType, hasMulticursor: boolean): Position;
|
||||
}
|
||||
|
||||
export class WordLeftCommand extends MoveWordCommand {
|
||||
protected _move(wordSeparators: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType): Position {
|
||||
return WordOperations.moveWordLeft(wordSeparators, model, position, wordNavigationType);
|
||||
protected _move(wordSeparators: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType, hasMulticursor: boolean): Position {
|
||||
return WordOperations.moveWordLeft(wordSeparators, model, position, wordNavigationType, hasMulticursor);
|
||||
}
|
||||
}
|
||||
|
||||
export class WordRightCommand extends MoveWordCommand {
|
||||
protected _move(wordSeparators: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType): Position {
|
||||
protected _move(wordSeparators: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType, hasMulticursor: boolean): Position {
|
||||
return WordOperations.moveWordRight(wordSeparators, model, position, wordNavigationType);
|
||||
}
|
||||
}
|
||||
@@ -187,8 +187,8 @@ export class CursorWordAccessibilityLeft extends WordLeftCommand {
|
||||
});
|
||||
}
|
||||
|
||||
protected override _move(wordCharacterClassifier: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType): Position {
|
||||
return super._move(getMapForWordSeparators(EditorOptions.wordSeparators.defaultValue, wordCharacterClassifier.intlSegmenterLocales), model, position, wordNavigationType);
|
||||
protected override _move(wordCharacterClassifier: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType, hasMulticursor: boolean): Position {
|
||||
return super._move(getMapForWordSeparators(EditorOptions.wordSeparators.defaultValue, wordCharacterClassifier.intlSegmenterLocales), model, position, wordNavigationType, hasMulticursor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,8 +202,8 @@ export class CursorWordAccessibilityLeftSelect extends WordLeftCommand {
|
||||
});
|
||||
}
|
||||
|
||||
protected override _move(wordCharacterClassifier: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType): Position {
|
||||
return super._move(getMapForWordSeparators(EditorOptions.wordSeparators.defaultValue, wordCharacterClassifier.intlSegmenterLocales), model, position, wordNavigationType);
|
||||
protected override _move(wordCharacterClassifier: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType, hasMulticursor: boolean): Position {
|
||||
return super._move(getMapForWordSeparators(EditorOptions.wordSeparators.defaultValue, wordCharacterClassifier.intlSegmenterLocales), model, position, wordNavigationType, hasMulticursor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,8 +295,8 @@ export class CursorWordAccessibilityRight extends WordRightCommand {
|
||||
});
|
||||
}
|
||||
|
||||
protected override _move(wordCharacterClassifier: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType): Position {
|
||||
return super._move(getMapForWordSeparators(EditorOptions.wordSeparators.defaultValue, wordCharacterClassifier.intlSegmenterLocales), model, position, wordNavigationType);
|
||||
protected override _move(wordCharacterClassifier: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType, hasMulticursor: boolean): Position {
|
||||
return super._move(getMapForWordSeparators(EditorOptions.wordSeparators.defaultValue, wordCharacterClassifier.intlSegmenterLocales), model, position, wordNavigationType, hasMulticursor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,8 +310,8 @@ export class CursorWordAccessibilityRightSelect extends WordRightCommand {
|
||||
});
|
||||
}
|
||||
|
||||
protected override _move(wordCharacterClassifier: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType): Position {
|
||||
return super._move(getMapForWordSeparators(EditorOptions.wordSeparators.defaultValue, wordCharacterClassifier.intlSegmenterLocales), model, position, wordNavigationType);
|
||||
protected override _move(wordCharacterClassifier: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType, hasMulticursor: boolean): Position {
|
||||
return super._move(getMapForWordSeparators(EditorOptions.wordSeparators.defaultValue, wordCharacterClassifier.intlSegmenterLocales), model, position, wordNavigationType, hasMulticursor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -217,6 +217,40 @@ suite('WordOperations', () => {
|
||||
assert.deepStrictEqual(actual, EXPECTED);
|
||||
});
|
||||
|
||||
test('cursorWordLeft - issue #169904: cursors out of sync', () => {
|
||||
const text = [
|
||||
'.grid1 {',
|
||||
' display: grid;',
|
||||
' grid-template-columns:',
|
||||
' [full-start] minmax(1em, 1fr)',
|
||||
' [main-start] minmax(0, 40em) [main-end]',
|
||||
' minmax(1em, 1fr) [full-end];',
|
||||
'}',
|
||||
'.grid2 {',
|
||||
' display: grid;',
|
||||
' grid-template-columns:',
|
||||
' [full-start] minmax(1em, 1fr)',
|
||||
' [main-start] minmax(0, 40em) [main-end] minmax(1em, 1fr) [full-end];',
|
||||
'}',
|
||||
];
|
||||
withTestCodeEditor(text, {}, (editor) => {
|
||||
editor.setSelections([
|
||||
new Selection(5, 44, 5, 44),
|
||||
new Selection(6, 32, 6, 32),
|
||||
new Selection(12, 44, 12, 44),
|
||||
new Selection(12, 72, 12, 72),
|
||||
]);
|
||||
cursorWordLeft(editor, false);
|
||||
assert.deepStrictEqual(editor.getSelections(), [
|
||||
new Selection(5, 43, 5, 43),
|
||||
new Selection(6, 31, 6, 31),
|
||||
new Selection(12, 43, 12, 43),
|
||||
new Selection(12, 71, 12, 71),
|
||||
]);
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
test('cursorWordLeftSelect - issue #74369: cursorWordLeft and cursorWordLeftSelect do not behave consistently', () => {
|
||||
const EXPECTED = [
|
||||
'|this.|is.|a.|test',
|
||||
|
||||
@@ -68,8 +68,8 @@ export class DeleteWordPartRight extends DeleteWordCommand {
|
||||
}
|
||||
|
||||
export class WordPartLeftCommand extends MoveWordCommand {
|
||||
protected _move(wordSeparators: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType): Position {
|
||||
return WordPartOperations.moveWordPartLeft(wordSeparators, model, position);
|
||||
protected _move(wordSeparators: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType, hasMulticursor: boolean): Position {
|
||||
return WordPartOperations.moveWordPartLeft(wordSeparators, model, position, hasMulticursor);
|
||||
}
|
||||
}
|
||||
export class CursorWordPartLeft extends WordPartLeftCommand {
|
||||
@@ -111,7 +111,7 @@ export class CursorWordPartLeftSelect extends WordPartLeftCommand {
|
||||
CommandsRegistry.registerCommandAlias('cursorWordPartStartLeftSelect', 'cursorWordPartLeftSelect');
|
||||
|
||||
export class WordPartRightCommand extends MoveWordCommand {
|
||||
protected _move(wordSeparators: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType): Position {
|
||||
protected _move(wordSeparators: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType, hasMulticursor: boolean): Position {
|
||||
return WordPartOperations.moveWordPartRight(wordSeparators, model, position);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user