Skip to content

Commit

Permalink
Merge pull request #2993 from axs221/feature/visual-line-mode-insert-…
Browse files Browse the repository at this point in the history
…append

I or A in visual/visual line mode creates multiple cursors #2167
  • Loading branch information
jpoon authored Sep 7, 2018
2 parents 8868b7b + 18a6133 commit de2e2ea
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 2 deletions.
100 changes: 98 additions & 2 deletions src/actions/commands/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2641,7 +2641,7 @@ class CommandInsertAtLastChange extends BaseCommand {

@RegisterAction
export class CommandInsertAtFirstCharacter extends BaseCommand {
modes = [ModeName.Normal, ModeName.Visual];
modes = [ModeName.Normal];
keys = ['I'];

public async exec(position: Position, vimState: VimState): Promise<VimState> {
Expand Down Expand Up @@ -2698,7 +2698,7 @@ export class CommandInsertAfterCursor extends BaseCommand {

@RegisterAction
export class CommandInsertAtLineEnd extends BaseCommand {
modes = [ModeName.Normal, ModeName.Visual];
modes = [ModeName.Normal];
keys = ['A'];

public async exec(position: Position, vimState: VimState): Promise<VimState> {
Expand Down Expand Up @@ -3713,6 +3713,102 @@ class ActionChangeToEOLInVisualBlockMode extends BaseCommand {
}
}

abstract class ActionGoToInsertVisualLineModeCommand extends BaseCommand {
runsOnceForEveryCursor() {
return false;
}

abstract getCursorRangeForLine(
line: vscode.TextLine,
selectionStart: Position,
selectionEnd: Position
): Range;

public async exec(position: Position, vimState: VimState): Promise<VimState> {
vimState.currentMode = ModeName.Insert;
vimState.isMultiCursor = true;
vimState.isFakeMultiCursor = true;

let start = Position.FromVSCodePosition(vimState.editor.selection.start);
let end = Position.FromVSCodePosition(vimState.editor.selection.end);

if (start.isAfter(end)) {
[start, end] = [end, start];
}

vimState.allCursors = [];
for (let i = start.line; i <= end.line; i++) {
const line = TextEditor.getLineAt(new Position(i, 0));

if (line.text.trim() !== '') {
vimState.allCursors.push(this.getCursorRangeForLine(line, start, end));
}
}
return vimState;
}
}

@RegisterAction
export class ActionGoToInsertVisualLineMode extends ActionGoToInsertVisualLineModeCommand {
modes = [ModeName.VisualLine];
keys = ['I'];

getCursorRangeForLine(line: vscode.TextLine): Range {
const startCharacterPosition = new Position(
line.lineNumber,
line.firstNonWhitespaceCharacterIndex
);
return new Range(startCharacterPosition, startCharacterPosition);
}
}

@RegisterAction
export class ActionGoToInsertVisualLineModeAppend extends ActionGoToInsertVisualLineModeCommand {
modes = [ModeName.VisualLine];
keys = ['A'];

getCursorRangeForLine(line: vscode.TextLine): Range {
const endCharacterPosition = new Position(line.lineNumber, line.range.end.character);
return new Range(endCharacterPosition, endCharacterPosition);
}
}

@RegisterAction
export class ActionGoToInsertVisualMode extends ActionGoToInsertVisualLineModeCommand {
modes = [ModeName.Visual];
keys = ['I'];

getCursorRangeForLine(
line: vscode.TextLine,
selectionStart: Position,
selectionEnd: Position
): Range {
const startCharacterPosition =
line.lineNumber === selectionStart.line
? selectionStart
: new Position(line.lineNumber, line.firstNonWhitespaceCharacterIndex);
return new Range(startCharacterPosition, startCharacterPosition);
}
}

@RegisterAction
export class ActionGoToInsertVisualModeAppend extends ActionGoToInsertVisualLineModeCommand {
modes = [ModeName.Visual];
keys = ['A'];

getCursorRangeForLine(
line: vscode.TextLine,
selectionStart: Position,
selectionEnd: Position
): Range {
const endCharacterPosition =
line.lineNumber === selectionEnd.line
? selectionEnd
: new Position(line.lineNumber, line.range.end.character);
return new Range(endCharacterPosition, endCharacterPosition);
}
}

@RegisterAction
class ActionGoToInsertVisualBlockModeAppend extends BaseCommand {
modes = [ModeName.VisualBlock];
Expand Down
46 changes: 46 additions & 0 deletions test/mode/modeVisual.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1296,4 +1296,50 @@ suite('Mode Visual', () => {
assertEqual(selection.end.line, 2);
});
});

suite('can prepend text with I', () => {
newTest({
title: 'multiline insert from bottom up selection',
start: ['111', '222', '333', '4|44', '555'],
keysPressed: 'vkkI_',
end: ['111', '2_|22', '_333', '_444', '555'],
});

newTest({
title: 'multiline insert from top down selection',
start: ['111', '2|22', '333', '444', '555'],
keysPressed: 'vjjI_',
end: ['111', '2_|22', '_333', '_444', '555'],
});

newTest({
title: 'skips blank lines',
start: ['111', '2|22', ' ', '444', '555'],
keysPressed: 'vjjI_',
end: ['111', '2_|22', ' ', '_444', '555'],
});
});

suite('can append text with A', () => {
newTest({
title: 'multiline append from bottom up selection',
start: ['111', '222', '333', '4|44', '555'],
keysPressed: 'vkkA_',
end: ['111', '222_|', '333_', '44_4', '555'],
});

newTest({
title: 'multiline append from top down selection',
start: ['111', '2|22', '333', '444', '555'],
keysPressed: 'vjjA_',
end: ['111', '222_|', '333_', '44_4', '555'],
});

newTest({
title: 'skips blank lines',
start: ['111', '2|22', ' ', '444', '555'],
keysPressed: 'vjjA_',
end: ['111', '222_|', ' ', '44_4', '555'],
});
});
});
46 changes: 46 additions & 0 deletions test/mode/modeVisualLine.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -436,4 +436,50 @@ suite('Mode Visual Line', () => {
assertEqual(selection.end.line, 1);
});
});

suite('can prepend text with I', () => {
newTest({
title: 'multiline insert from bottom up selection',
start: ['111', '222', '333', '4|44', '555'],
keysPressed: 'VkkI_',
end: ['111', '_|222', '_333', '_444', '555'],
});

newTest({
title: 'multiline insert from top down selection',
start: ['111', '2|22', '333', '444', '555'],
keysPressed: 'VjjI_',
end: ['111', '_|222', '_333', '_444', '555'],
});

newTest({
title: 'skips blank lines',
start: ['111', '2|22', ' ', '444', '555'],
keysPressed: 'VjjI_',
end: ['111', '_|222', ' ', '_444', '555'],
});
});

suite('can append text with A', () => {
newTest({
title: 'multiline append from bottom up selection',
start: ['111', '222', '333', '4|44', '555'],
keysPressed: 'VkkA_',
end: ['111', '222_|', '333_', '444_', '555'],
});

newTest({
title: 'multiline append from top down selection',
start: ['111', '2|22', '333', '444', '555'],
keysPressed: 'VjjA_',
end: ['111', '222_|', '333_', '444_', '555'],
});

newTest({
title: 'skips blank lines',
start: ['111', '2|22', ' ', '444', '555'],
keysPressed: 'VjjA_',
end: ['111', '222_|', ' ', '444_', '555'],
});
});
});

0 comments on commit de2e2ea

Please sign in to comment.