Skip to content

Commit

Permalink
Merge pull request #1663 from Chillee/1634
Browse files Browse the repository at this point in the history
Fixes #1400, #612, #1632, #1634, #1531, #1458: Tab isn't handled properly for insert and visualblockinsert modes
  • Loading branch information
johnfn authored May 13, 2017
2 parents eec98d1 + 8229850 commit b7c533b
Show file tree
Hide file tree
Showing 11 changed files with 155 additions and 228 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@
{
"key": "tab",
"command": "extension.vim_tab",
"when": "editorFocus && vim.active && vim.mode == 'Normal' && !inDebugRepl"
"when": "editorFocus && vim.active && !inDebugRepl"
},
{
"key": "ctrl+r",
Expand Down
250 changes: 80 additions & 170 deletions src/actions/commands/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { SearchState, SearchDirection } from './../../state/searchState';
import { ReplaceState } from './../../state/replaceState';
import { VisualBlockMode } from './../../mode/modeVisualBlock';
import { ModeName } from './../../mode/mode';
import { VisualBlockInsertionType } from './../../mode/modeVisualBlock';
import { Range } from './../../common/motion/range';
import { TextEditor, EditorScrollByUnit, EditorScrollDirection } from './../../textEditor';
import { Register, RegisterMode } from './../../register/register';
Expand Down Expand Up @@ -416,7 +415,6 @@ class CommandEsc extends BaseCommand {
modes = [
ModeName.Visual,
ModeName.VisualLine,
ModeName.VisualBlockInsertMode,
ModeName.VisualBlock,
ModeName.Normal,
ModeName.SearchInProgressMode,
Expand Down Expand Up @@ -444,11 +442,7 @@ class CommandEsc extends BaseCommand {
// as that is handled for you by the state machine. ESC is
// a special case since runsOnceForEveryCursor is false.

for (let i = 0; i < vimState.allCursors.length; i++) {
vimState.allCursors[i] = vimState.allCursors[i].withNewStop(
vimState.allCursors[i].stop.getLeft()
);
}
vimState.allCursors = vimState.allCursors.map(x => x.withNewStop(x.stop.getLeft()));
}

if (vimState.currentMode === ModeName.SearchInProgressMode) {
Expand Down Expand Up @@ -517,7 +511,6 @@ class CommandCtrlOpenBracket extends CommandEsc {
ModeName.Insert,
ModeName.Visual,
ModeName.VisualLine,
ModeName.VisualBlockInsertMode,
ModeName.VisualBlock,
ModeName.Replace
];
Expand Down Expand Up @@ -2012,19 +2005,30 @@ class CommandInsertAtLineEnd extends BaseCommand {
class CommandInsertNewLineAbove extends BaseCommand {
modes = [ModeName.Normal];
keys = ["O"];
runsOnceForEveryCursor() { return true; }
runsOnceForEveryCursor() { return false; }

public async exec(position: Position, vimState: VimState): Promise<VimState> {
let indentationWidth = TextEditor.getIndentationLevel(TextEditor.getLineAt(position).text);
public async execCount(position: Position, vimState: VimState): Promise<VimState> {
vimState.currentMode = ModeName.Insert;
let count = vimState.recordedState.count || 1;
// Why do we do this? Who fucking knows??? If the cursor is at the
// beginning of the line, then editor.action.insertLineBefore does some
// weird things with following paste command. Refer to
// https://github.com/VSCodeVim/Vim/pull/1663#issuecomment-300573129 for
// more details.
const tPos = Position.FromVSCodePosition(vscode.window.activeTextEditor!.selection.active).getRight();
vscode.window.activeTextEditor!.selection = new vscode.Selection(tPos, tPos);
for (let i = 0; i < count; i++) {
await vscode.commands.executeCommand('editor.action.insertLineBefore');
}

vimState.recordedState.transformations.push({
type: "insertText",
text: TextEditor.setIndentationLevel("V", indentationWidth).replace("V", "\n"),
position: new Position(vimState.cursorPosition.line, 0),
diff: new PositionDiff(-1, indentationWidth),
});

vimState.allCursors = await allowVSCodeToPropagateCursorUpdatesAndReturnThem();
for (let i = 0; i < count; i++) {
const newPos = new Position(vimState.allCursors[0].start.line + i, vimState.allCursors[0].start.character);
vimState.allCursors.push(new Range(newPos, newPos));
}
vimState.allCursors = vimState.allCursors.reverse();
vimState.isFakeMultiCursor = true;
vimState.isMultiCursor = true;
return vimState;
}
}
Expand All @@ -2035,12 +2039,31 @@ class CommandInsertNewLineBefore extends BaseCommand {
keys = ["o"];
runsOnceForEveryCursor() { return false; }

public async exec(position: Position, vimState: VimState): Promise<VimState> {
public async execCount(position: Position, vimState: VimState): Promise<VimState> {
vimState.currentMode = ModeName.Insert;
await vscode.commands.executeCommand('editor.action.insertLineAfter');
let count = vimState.recordedState.count || 1;

for (let i = 0; i < count; i++) {
await vscode.commands.executeCommand('editor.action.insertLineAfter');
}
vimState.allCursors = await allowVSCodeToPropagateCursorUpdatesAndReturnThem();
for (let i = 1; i < count; i++) {
const newPos = new Position(vimState.allCursors[0].start.line - i, vimState.allCursors[0].start.character);
vimState.allCursors.push(new Range(newPos, newPos));

// Ahhhhhh. We have to manually set cursor position here as we need text
// transformations AND to set multiple cursors.
vimState.recordedState.transformations.push({
type: "insertText",
text: TextEditor.setIndentationLevel("", newPos.character),
position: newPos,
cursorIndex: i,
manuallySetCursorPositions: true
});
}
vimState.allCursors = vimState.allCursors.reverse();
vimState.isFakeMultiCursor = true;
vimState.isMultiCursor = true;
return vimState;
}
}
Expand Down Expand Up @@ -2966,73 +2989,33 @@ class ActionShiftDVisualBlock extends BaseCommand {
}
}

@RegisterAction
class ActionSVisualBlock extends BaseCommand {
modes = [ModeName.VisualBlock];
keys = [["s"], ["S"]];
canBeRepeatedWithDot = true;
runsOnceForEveryCursor() { return false; }

public async exec(position: Position, vimState: VimState): Promise<VimState> {
for (const { start, end } of Position.IterateLine(vimState)) {
vimState.recordedState.transformations.push({
type : "deleteRange",
range : new Range(start, end),
manuallySetCursorPositions: true,
});
}

vimState.currentMode = ModeName.VisualBlockInsertMode;
vimState.recordedState.visualBlockInsertionType = VisualBlockInsertionType.Insert;

// Make sure the cursor position is at the beginning since we are inserting not appending
if (vimState.cursorPosition.character > vimState.cursorStartPosition.character) {
[vimState.cursorPosition, vimState.cursorStartPosition] =
[vimState.cursorStartPosition, vimState.cursorPosition];
}

// Make sure we are in the TOP left
if (vimState.cursorPosition.line > vimState.cursorStartPosition.line) {
let lineStart = vimState.cursorStartPosition.line;
vimState.cursorStartPosition = new Position(vimState.cursorPosition.line, vimState.cursorStartPosition.character);
vimState.cursorPosition = new Position(lineStart, vimState.cursorPosition.character);
}

return vimState;
}
}

@RegisterAction
class ActionGoToInsertVisualBlockMode extends BaseCommand {
modes = [ModeName.VisualBlock];
keys = ["I"];
runsOnceForEveryCursor() { return false; }

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

// Make sure the cursor position is at the beginning since we are inserting not appending
if (vimState.cursorPosition.character > vimState.cursorStartPosition.character) {
[vimState.cursorPosition, vimState.cursorStartPosition] =
[vimState.cursorStartPosition, vimState.cursorPosition];
}

// Make sure we are in the TOP left
if (vimState.cursorPosition.line > vimState.cursorStartPosition.line) {
let lineStart = vimState.cursorStartPosition.line;
vimState.cursorStartPosition = new Position(vimState.cursorPosition.line, vimState.cursorStartPosition.character);
vimState.cursorPosition = new Position(lineStart, vimState.cursorPosition.character);
for (const {line, start} of Position.IterateLine(vimState)) {
if (line === "" && start.character !== 0) {
continue;
}
vimState.allCursors.push(new Range(start, start));
}

vimState.allCursors = vimState.allCursors.slice(1);
return vimState;
}
}

@RegisterAction
class ActionChangeInVisualBlockMode extends BaseCommand {
modes = [ModeName.VisualBlock];
keys = ["c"];
keys = [["c"], ["s"]];
runsOnceForEveryCursor() { return false; }

public async exec(position: Position, vimState: VimState): Promise<VimState> {
Expand All @@ -3044,32 +3027,23 @@ class ActionChangeInVisualBlockMode extends BaseCommand {
});
}

vimState.currentMode = ModeName.VisualBlockInsertMode;
vimState.recordedState.visualBlockInsertionType = VisualBlockInsertionType.Insert;

// Make sure the cursor position is at the beginning since we are inserting not appending
if (vimState.cursorPosition.character > vimState.cursorStartPosition.character) {
[vimState.cursorPosition, vimState.cursorStartPosition] =
[vimState.cursorStartPosition, vimState.cursorPosition];
}
vimState.currentMode = ModeName.Insert;
vimState.isMultiCursor = true;
vimState.isFakeMultiCursor = true;

// Make sure we are in the TOP left
if (vimState.cursorPosition.line > vimState.cursorStartPosition.line) {
let lineStart = vimState.cursorStartPosition.line;
vimState.cursorStartPosition = new Position(vimState.cursorPosition.line, vimState.cursorStartPosition.character);
vimState.cursorPosition = new Position(lineStart, vimState.cursorPosition.character);
for (const {start} of Position.IterateLine(vimState)) {
vimState.allCursors.push(new Range(start, start));
}
vimState.allCursors = vimState.allCursors.slice(1);

return vimState;
}
}

// TODO - this is basically a duplicate of the above command

@RegisterAction
class ActionChangeToEOLInVisualBlockMode extends BaseCommand {
modes = [ModeName.VisualBlock];
keys = ["C"];
keys = [["C"], ["S"]];
runsOnceForEveryCursor() { return false; }

public async exec(position: Position, vimState: VimState): Promise<VimState> {
Expand All @@ -3081,23 +3055,14 @@ class ActionChangeToEOLInVisualBlockMode extends BaseCommand {
});
}

vimState.currentMode = ModeName.VisualBlockInsertMode;
vimState.recordedState.visualBlockInsertionType = VisualBlockInsertionType.Insert;

// Make sure the cursor position is at the end since we are appending
if (vimState.cursorPosition.character < vimState.cursorStartPosition.character) {
[vimState.cursorPosition, vimState.cursorStartPosition] =
[vimState.cursorStartPosition, vimState.cursorPosition];
}
vimState.currentMode = ModeName.Insert;
vimState.isMultiCursor = true;
vimState.isFakeMultiCursor = true;

// Make sure we are in the TOP right
if (vimState.cursorPosition.line > vimState.cursorStartPosition.line) {
let lineStart = vimState.cursorStartPosition.line;
vimState.cursorStartPosition = new Position(vimState.cursorPosition.line, vimState.cursorStartPosition.character);
vimState.cursorPosition = new Position(lineStart, vimState.cursorPosition.character);
for (const {end} of Position.IterateLine(vimState)) {
vimState.allCursors.push(new Range(end, end));
}

vimState.cursorPosition = vimState.cursorPosition.getRight();
vimState.allCursors = vimState.allCursors.slice(1);

return vimState;
}
Expand All @@ -3110,84 +3075,29 @@ class ActionGoToInsertVisualBlockModeAppend extends BaseCommand {
runsOnceForEveryCursor() { return false; }

public async exec(position: Position, vimState: VimState): Promise<VimState> {
vimState.currentMode = ModeName.VisualBlockInsertMode;
vimState.recordedState.visualBlockInsertionType = VisualBlockInsertionType.Append;

// Make sure the cursor position is at the end since we are appending
if (vimState.cursorPosition.character < vimState.cursorStartPosition.character) {
[vimState.cursorPosition, vimState.cursorStartPosition] =
[vimState.cursorStartPosition, vimState.cursorPosition];
}

// Make sure we are in the TOP right
if (vimState.cursorPosition.line > vimState.cursorStartPosition.line) {
let lineStart = vimState.cursorStartPosition.line;
vimState.cursorStartPosition = new Position(vimState.cursorPosition.line, vimState.cursorStartPosition.character);
vimState.cursorPosition = new Position(lineStart, vimState.cursorPosition.character);
}

vimState.cursorPosition = vimState.cursorPosition.getRight();

return vimState;
}
}



@RegisterAction
class InsertInInsertVisualBlockMode extends BaseCommand {
modes = [ModeName.VisualBlockInsertMode];
keys = ["<any>"];
runsOnceForEveryCursor() { return false; }

public async exec(position: Position, vimState: VimState): Promise<VimState> {
let char = this.keysPressed[0];
let insertAtStart = vimState.recordedState.visualBlockInsertionType === VisualBlockInsertionType.Insert;

if (char === '\n') {
return vimState;
}

if (char === '<BS>' && vimState.topLeft.character === 0) {
return vimState;
}

for (const { start, end } of Position.IterateLine(vimState)) {
const insertPos = insertAtStart ? start : end;

// Skip line if starting position does not have content (don't insert on blank lines for example)
if (end.isBefore(start)) {
continue;
}

if (char === '<BS>') {
vimState.recordedState.transformations.push({
type : "deleteText",
position : insertPos,
diff : new PositionDiff(0, -1),
});
} else {
let positionToInsert: Position;

if (vimState.recordedState.visualBlockInsertionType === VisualBlockInsertionType.Append) {
positionToInsert = insertPos.getLeft();
} else {
positionToInsert = insertPos;
}
vimState.currentMode = ModeName.Insert;
vimState.isMultiCursor = true;
vimState.isFakeMultiCursor = true;

for (const {line, end} of Position.IterateLine(vimState)) {
if (line.trim() === "") {
vimState.recordedState.transformations.push({
type : "insertText",
text : char,
position: positionToInsert,
diff : new PositionDiff(0, 1),
type: "replaceText",
text: TextEditor.setIndentationLevel(line, end.character),
start: new Position(end.line, 0),
end: new Position(end.line, end.character),
position: new Position(end.line, 0)
});
}
vimState.allCursors.push(new Range(end, end));
}

vimState.allCursors = vimState.allCursors.slice(1);
return vimState;
}
}



@RegisterAction
class ActionDeleteLineVisualMode extends BaseCommand {
modes = [ModeName.Visual, ModeName.VisualLine];
Expand Down
Loading

0 comments on commit b7c533b

Please sign in to comment.