Skip to content

Commit

Permalink
Merge pull request #2892 from VSCodeVim/refactor
Browse files Browse the repository at this point in the history
refactor baseaction
  • Loading branch information
jpoon authored Jul 30, 2018
2 parents 47fe944 + 48f5308 commit 4681a0e
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 104 deletions.
182 changes: 86 additions & 96 deletions src/actions/base.ts
Original file line number Diff line number Diff line change
@@ -1,89 +1,7 @@
import { configuration } from './../configuration/configuration';
import { ModeName } from './../mode/mode';
import { VimState } from './../state/vimState';

const is2DArray = function<T>(x: any): x is T[][] {
return Array.isArray(x[0]);
};

export let compareKeypressSequence = function(one: string[] | string[][], two: string[]): boolean {
if (is2DArray(one)) {
for (const sequence of one) {
if (compareKeypressSequence(sequence, two)) {
return true;
}
}

return false;
}

if (one.length !== two.length) {
return false;
}

const containsControlKey = (s: string): boolean => {
// We count anything starting with < (e.g. <c-u>) as a control key, but we
// exclude the first 3 because it's more convenient to do so.
s = s.toUpperCase();
return s !== '<BS>' && s !== '<SHIFT+BS>' && s !== '<TAB>' && s.startsWith('<') && s.length > 1;
};

const isSingleNumber: RegExp = /^[0-9]$/;
const isSingleAlpha: RegExp = /^[a-zA-Z]$/;

for (let i = 0, j = 0; i < one.length; i++, j++) {
const left = one[i],
right = two[j];

if (left === '<any>') {
continue;
}
if (right === '<any>') {
continue;
}

if (left === '<number>' && isSingleNumber.test(right)) {
continue;
}
if (right === '<number>' && isSingleNumber.test(left)) {
continue;
}

if (left === '<alpha>' && isSingleAlpha.test(right)) {
continue;
}
if (right === '<alpha>' && isSingleAlpha.test(left)) {
continue;
}

if (left === '<character>' && !containsControlKey(right)) {
continue;
}
if (right === '<character>' && !containsControlKey(left)) {
continue;
}

if (left === '<leader>' && right === configuration.leader) {
continue;
}
if (right === '<leader>' && left === configuration.leader) {
continue;
}

if (left === configuration.leader) {
return false;
}
if (right === configuration.leader) {
return false;
}

if (left !== right) {
return false;
}
}

return true;
};
import { Notation } from '../configuration/notation';

export class BaseAction {
/**
Expand Down Expand Up @@ -121,7 +39,7 @@ export class BaseAction {
return false;
}

if (!compareKeypressSequence(this.keys, keysPressed)) {
if (!BaseAction.CompareKeypressSequence(this.keys, keysPressed)) {
return false;
}

Expand All @@ -143,9 +61,9 @@ export class BaseAction {
return false;
}

const keys2D = is2DArray(this.keys) ? this.keys : [this.keys];
const keys2D = BaseAction.is2DArray(this.keys) ? this.keys : [this.keys];
const keysSlice = keys2D.map(x => x.slice(0, keysPressed.length));
if (!compareKeypressSequence(keysSlice, keysPressed)) {
if (!BaseAction.CompareKeypressSequence(keysSlice, keysPressed)) {
return false;
}

Expand All @@ -159,9 +77,85 @@ export class BaseAction {
return true;
}

public static CompareKeypressSequence(one: string[] | string[][], two: string[]): boolean {
if (BaseAction.is2DArray(one)) {
for (const sequence of one) {
if (BaseAction.CompareKeypressSequence(sequence, two)) {
return true;
}
}

return false;
}

if (one.length !== two.length) {
return false;
}

const isSingleNumber: RegExp = /^[0-9]$/;
const isSingleAlpha: RegExp = /^[a-zA-Z]$/;

for (let i = 0, j = 0; i < one.length; i++, j++) {
const left = one[i],
right = two[j];

if (left === '<any>') {
continue;
}
if (right === '<any>') {
continue;
}

if (left === '<number>' && isSingleNumber.test(right)) {
continue;
}
if (right === '<number>' && isSingleNumber.test(left)) {
continue;
}

if (left === '<alpha>' && isSingleAlpha.test(right)) {
continue;
}
if (right === '<alpha>' && isSingleAlpha.test(left)) {
continue;
}

if (left === '<character>' && !Notation.IsControlKey(right)) {
continue;
}
if (right === '<character>' && !Notation.IsControlKey(left)) {
continue;
}

if (left === '<leader>' && right === configuration.leader) {
continue;
}
if (right === '<leader>' && left === configuration.leader) {
continue;
}

if (left === configuration.leader) {
return false;
}
if (right === configuration.leader) {
return false;
}

if (left !== right) {
return false;
}
}

return true;
}

public toString(): string {
return this.keys.join('');
}

private static is2DArray<T>(x: any): x is T[][] {
return Array.isArray(x[0]);
}
}

export enum KeypressState {
Expand All @@ -173,9 +167,7 @@ export class Actions {
/**
* Every Vim action will be added here with the @RegisterAction decorator.
*/
public static allActions: { type: typeof BaseAction; action: BaseAction }[] = [];

public static actionMap = new Map<ModeName, { type: typeof BaseAction; action: BaseAction }[]>();
public static actionMap = new Map<ModeName, typeof BaseAction[]>();
/**
* Gets the action that should be triggered given a key
* sequence.
Expand All @@ -194,13 +186,11 @@ export class Actions {
let isPotentialMatch = false;

var possibleActionsForMode = Actions.actionMap.get(vimState.currentMode) || [];
for (const possibleAction of possibleActionsForMode) {
const { type, action } = possibleAction!;

for (const actionType of possibleActionsForMode) {
const action = new actionType();
if (action.doesActionApply(vimState, keysPressed)) {
const result = new type();
result.keysPressed = vimState.recordedState.actionKeys.slice(0);
return result;
action.keysPressed = vimState.recordedState.actionKeys.slice(0);
return action;
}

if (action.couldActionApply(vimState, keysPressed)) {
Expand All @@ -226,6 +216,6 @@ export function RegisterAction(action: typeof BaseAction): void {
continue;
}

actions.push({ type: action, action: actionInstance });
actions.push(action);
}
}
8 changes: 4 additions & 4 deletions src/actions/operator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ModeName } from './../mode/mode';
import { Register, RegisterMode } from './../register/register';
import { VimState } from './../state/vimState';
import { TextEditor } from './../textEditor';
import { BaseAction, compareKeypressSequence, RegisterAction } from './base';
import { BaseAction, RegisterAction } from './base';
import { CommandNumber } from './commands/actions';
import { TextObjectMovement } from './textobject';

Expand All @@ -32,7 +32,7 @@ export class BaseOperator extends BaseAction {
if (this.modes.indexOf(vimState.currentMode) === -1) {
return false;
}
if (!compareKeypressSequence(this.keys, keysPressed)) {
if (!BaseAction.CompareKeypressSequence(this.keys, keysPressed)) {
return false;
}
if (
Expand All @@ -52,7 +52,7 @@ export class BaseOperator extends BaseAction {
if (this.modes.indexOf(vimState.currentMode) === -1) {
return false;
}
if (!compareKeypressSequence(this.keys.slice(0, keysPressed.length), keysPressed)) {
if (!BaseAction.CompareKeypressSequence(this.keys.slice(0, keysPressed.length), keysPressed)) {
return false;
}
if (
Expand Down Expand Up @@ -81,7 +81,7 @@ export class BaseOperator extends BaseAction {
// The previous action is the same as the one we're testing
prevAction.constructor === this.constructor &&
// The key pressed is the same as the previous action's last key.
compareKeypressSequence(prevAction.keysPressed.slice(-1), keysPressed)
BaseAction.CompareKeypressSequence(prevAction.keysPressed.slice(-1), keysPressed)
);
}

Expand Down
10 changes: 10 additions & 0 deletions src/configuration/notation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ export class Notation {
'\n': ['<cr>', '<enter>'],
};

public static IsControlKey(key: string): boolean {
key = key.toLocaleUpperCase();
return (
this.isSurroundedByAngleBrackets(key) &&
key !== '<BS>' &&
key !== '<SHIFT+BS>' &&
key !== '<TAB>'
);
}

/**
* Normalizes key to AngleBracketNotation
* (e.g. <ctrl+x>, Ctrl+x, <c-x> normalized to <C-x>)
Expand Down
8 changes: 4 additions & 4 deletions test/actions/baseAction.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import * as assert from 'assert';
import * as vscode from 'vscode';

import * as base from '../../src/actions/base';
import { BaseAction } from '../../src/actions/base';
import { VimState } from '../../src/state/vimState';
import { setupWorkspace, cleanUpWorkspace } from './../testUtils';
import { ModeName } from '../../src/mode/mode';

class TestAction1D extends base.BaseAction {
class TestAction1D extends BaseAction {
keys = ['a', 'b'];
modes = [ModeName.Normal];
}

class TestAction2D extends base.BaseAction {
class TestAction2D extends BaseAction {
keys = [['a', 'b'], ['c', 'd']];
modes = [ModeName.Normal];
}
Expand Down Expand Up @@ -47,7 +47,7 @@ suite('base action', () => {
let right = testCases[test][1];
let expected = testCases[test][2];

let actual = base.compareKeypressSequence(left, right);
let actual = BaseAction.CompareKeypressSequence(left, right);
assert.equal(actual, expected, `${left}. ${right}.`);
}
}
Expand Down

0 comments on commit 4681a0e

Please sign in to comment.