Skip to content

Commit

Permalink
Merge pull request #335 from VSCodeVim/star-and-hash
Browse files Browse the repository at this point in the history
Star and hash
  • Loading branch information
johnfn authored Jun 21, 2016
2 parents c784fb4 + d157f24 commit 4454e8d
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 7 deletions.
95 changes: 92 additions & 3 deletions src/actions/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ export function isIMovement(o: IMovement | Position): o is IMovement {
}

export class BaseAction {
/**
* Can this action be paired with an operator (is it like w in dw)? All
* BaseMovements can be, and some more sophisticated commands also can be.
*/
isMotion = false;

/**
* Modes that this action can be run in.
*/
Expand Down Expand Up @@ -119,6 +125,8 @@ export class BaseAction {
* A movement is something like 'h', 'k', 'w', 'b', 'gg', etc.
*/
export abstract class BaseMovement extends BaseAction {
isMotion = true;

/**
* Whether we should change desiredColumn in VimState.
*/
Expand Down Expand Up @@ -466,6 +474,87 @@ class CommandNextSearchMatch extends BaseMovement {
}
}

@RegisterAction
class CommandStar extends BaseCommand {
modes = [ModeName.Normal, ModeName.Visual, ModeName.VisualLine];
keys = ["*"];
isMotion = true;
canBeRepeated = true;

public static GetWordAtPosition(position: Position): string {
const start = position.getWordLeft(true);
const end = position.getCurrentWordEnd(true).getRight();

return TextEditor.getText(new vscode.Range(start, end));
}

public async exec(position: Position, vimState: VimState): Promise<VimState> {
const currentWord = CommandStar.GetWordAtPosition(position);

vimState.searchString = currentWord;
vimState.searchDirection = 1;

let result: Position;

while (true) {
result = CommandInsertInSearchMode.GetNextSearchMatch(vimState.cursorPosition, currentWord);

if (result === undefined) {
break;
}

vimState.cursorPosition = result;

if (CommandStar.GetWordAtPosition(result) === currentWord) {
break;
}
}

return vimState;
}
}

// TODO - merge both * and # implementations, use regex in GetNextSearchMatch
// rather than this approach
@RegisterAction
class CommandHash extends BaseCommand {
modes = [ModeName.Normal, ModeName.Visual, ModeName.VisualLine];
keys = ["#"];
isMotion = true;
canBeRepeated = true;

public static GetWordAtPosition(position: Position): string {
const start = position.getWordLeft(true);
const end = position.getCurrentWordEnd(true).getRight();

return TextEditor.getText(new vscode.Range(start, end));
}

public async exec(position: Position, vimState: VimState): Promise<VimState> {
const currentWord = CommandStar.GetWordAtPosition(position);

vimState.searchString = currentWord;
vimState.searchDirection = -1;

let result: Position;

while (true) {
result = CommandInsertInSearchMode.GetPreviousSearchMatch(vimState.cursorPosition, currentWord);

if (result === undefined) {
break;
}

vimState.cursorPosition = result;

if (CommandStar.GetWordAtPosition(result) === currentWord) {
break;
}
}

return vimState;
}
}

@RegisterAction
class CommandPreviousSearchMatch extends BaseMovement {
Expand Down Expand Up @@ -527,14 +616,14 @@ class CommandInsertInInsertMode extends BaseCommand {
export class CommandSearchForwards extends BaseCommand {
modes = [ModeName.Normal];
keys = ["/"];
isMotion = true;

public async exec(position: Position, vimState: VimState): Promise<VimState> {
vimState.searchString = "";
vimState.searchDirection = 1;
vimState.searchCursorStartPosition = position;
vimState.nextSearchMatchPosition = undefined;
vimState.currentMode = ModeName.SearchInProgressMode;
// vimState.actionState.actionKeys = []; // ???

return vimState;
}
Expand All @@ -545,14 +634,14 @@ export class CommandSearchForwards extends BaseCommand {
export class CommandSearchBackwards extends BaseCommand {
modes = [ModeName.Normal];
keys = ["?"];
isMotion = true;

public async exec(position: Position, vimState: VimState): Promise<VimState> {
vimState.searchString = "";
vimState.searchDirection = -1;
vimState.searchCursorStartPosition = position;
vimState.nextSearchMatchPosition = undefined;
vimState.currentMode = ModeName.SearchInProgressMode;
// vimState.actionState.actionKeys = []; // ???

return vimState;
}
Expand Down Expand Up @@ -1808,4 +1897,4 @@ class ToggleCaseAndMoveForward extends BaseMovement {

return position.getRight();
}
}
}
5 changes: 1 addition & 4 deletions src/mode/modeHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,7 @@ export class RecordedState {
}

public get hasRunAMovement(): boolean {
return _.filter(this.actionsRun, a =>
a instanceof BaseMovement ||
a instanceof CommandSearchForwards ||
a instanceof CommandSearchBackwards).length > 0;
return _.filter(this.actionsRun, a => a.isMotion).length > 0;
}

/**
Expand Down
36 changes: 36 additions & 0 deletions test/mode/normalModeTests/motions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,4 +255,40 @@ suite("Motions in Normal Mode", () => {
keysPressed: '10l',
end: ['blah blah |blah']
});

newTest({
title: "Can handle *",
start: ['|blah duh blah duh blah'],
keysPressed: '*',
end: ['blah duh |blah duh blah']
});

newTest({
title: "Can handle tricky *",
start: ['|blah blahblah duh blah'],
keysPressed: '*',
end: ['blah blahblah duh |blah']
});

newTest({
title: "Can handle **",
start: ['|blah duh blah duh blah'],
keysPressed: '**',
end: ['blah duh blah duh |blah']
});

newTest({
title: "Can handle #",
start: ['blah duh |blah duh blah'],
keysPressed: '#',
end: ['|blah duh blah duh blah']
});

newTest({
title: "Can handle ##",
start: ['blah duh blah duh |blah'],
keysPressed: '##',
end: ['|blah duh blah duh blah']
});

});

0 comments on commit 4454e8d

Please sign in to comment.