diff --git a/src/configuration/commandValidator.ts b/src/configuration/commandValidator.ts new file mode 100644 index 000000000000..20c5c5e4e8ba --- /dev/null +++ b/src/configuration/commandValidator.ts @@ -0,0 +1,14 @@ +import * as vscode from 'vscode'; + +export class CommandValidator { + private static map: Map; + + public static async IsCommandValid(command: string): Promise { + if (!this.map) { + this.map = new Map( + (await vscode.commands.getCommands(true)).map(x => [x, true] as [string, boolean]) + ); + } + return this.map.get(command) || false; + } +} \ No newline at end of file diff --git a/src/configuration/remapper.ts b/src/configuration/remapper.ts index 3f71a7f91330..20d6d63f6feb 100644 --- a/src/configuration/remapper.ts +++ b/src/configuration/remapper.ts @@ -1,13 +1,14 @@ import * as _ from 'lodash'; import * as vscode from 'vscode'; -import { commandLine } from '../cmd_line/commandLine'; -import { configuration } from '../configuration/configuration'; -import { ModeName } from '../mode/mode'; +import { CommandValidator } from './commandValidator'; +import { IKeyRemapping } from './iconfiguration'; import { ModeHandler } from '../mode/modeHandler'; +import { ModeName } from '../mode/mode'; import { VimState } from './../state/vimState'; -import { IKeyRemapping } from './iconfiguration'; +import { configuration } from '../configuration/configuration'; import { logger } from '../util/logger'; +import { commandLine } from '../cmd_line/commandLine'; interface IRemapper { /** @@ -82,7 +83,7 @@ export class Remapper implements IRemapper { const userDefinedRemappings = this._getRemappings(); let remapping: IKeyRemapping | undefined = Remapper._findMatchingRemap( - userDefinedRemappings, + await userDefinedRemappings, keys, vimState.currentMode ); @@ -174,9 +175,10 @@ export class Remapper implements IRemapper { return false; } - private _getRemappings(): { [key: string]: IKeyRemapping } { + private async _getRemappings(): Promise<{ [key: string]: IKeyRemapping }> { // Create a null object so that there is no __proto__ let remappings: { [key: string]: IKeyRemapping } = Object.create(null); + for (let remapping of configuration[this._configKey] as IKeyRemapping[]) { let debugMsg = `before=${remapping.before}. `; @@ -184,12 +186,25 @@ export class Remapper implements IRemapper { debugMsg += `after=${remapping.after}. `; } + let isCommandValid = true; if (remapping.commands) { for (const command of remapping.commands) { + let cmd: string; + let args: any[]; + if (typeof command === 'string') { - debugMsg += `command=${command}. args=.`; + cmd = command; + args = []; } else { - debugMsg += `command=${command.command}. args=${command.args}.`; + cmd = command.command; + args = command.args; + } + + debugMsg += `command=${cmd}. args=${args}.`; + + if (CommandValidator.IsCommandValid(cmd)) { + isCommandValid = false; + break; } } } @@ -203,6 +218,15 @@ export class Remapper implements IRemapper { continue; } + if (!isCommandValid) { + logger.error( + `Remapper: ${ + this._configKey + }. Invalid configuration. Command does not exist. ${debugMsg}.` + ); + continue; + } + const keys = remapping.before.join(''); if (keys in remappings) { logger.error(`Remapper: ${this._configKey}. Duplicate configuration. ${debugMsg}`);