Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read key remappings from .vimrc #3908

Merged
merged 10 commits into from
Nov 10, 2019
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ VSCodeVim is a Vim emulator for [Visual Studio Code](https://code.visualstudio.c

VSCodeVim is automatically enabled following [installation](https://marketplace.visualstudio.com/items?itemName=vscodevim.vim) and reloading of VS Code.

> :warning: Vimscript is _not_ supported; therefore, we are _not_ able to load your `.vimrc` or use `.vim` plugins. You have to replicate these using our [Settings](#settings) and [Emulated plugins](#-emulated-plugins).

### Mac

To enable key-repeating execute the following in your Terminal and restart VS Code:
Expand Down Expand Up @@ -365,6 +363,12 @@ Configuration settings that have been copied from vim. Vim settings are loaded i
| vim.whichwrap | Controls wrapping at beginning and end of line. Comma-separated set of keys that should wrap to next/previous line. Arrow keys are represented by `[` and `]` in insert mode, `<` and `>` in normal and visual mode. To wrap "everything", set this to `h,l,<,>,[,]`. | String | `` |
| vim.report | Threshold for reporting number of lines changed. | Number | 2 |

## .vimrc support

> :warning: .vimrc support is currently experimental. Only remaps are supported, and you may experience bugs. Please [report them](https://github.com/VSCodeVim/Vim/issues/new?template=bug_report.md)!

Set `vim.vimrc.enable` to `true` and set `vim.vimrc.path` appropriately.

## 🖱️ Multi-Cursor Mode

> :warning: Multi-Cursor mode is experimental. Please report issues in our [feedback thread.](https://github.com/VSCodeVim/Vim/issues/824)
Expand Down
2 changes: 1 addition & 1 deletion build/CHANGELOG.base.md
Original file line number Diff line number Diff line change
Expand Up @@ -2848,4 +2848,4 @@ The first commit to this project was a little over 3 years ago, and what a journ
- add gulp + tslint [\#6](https://github.com/VSCodeVim/Vim/pull/6) ([jpoon](https://github.com/jpoon))
- command line mode refactoring [\#5](https://github.com/VSCodeVim/Vim/pull/5) ([guillermooo](https://github.com/guillermooo))
- Navigation mode [\#4](https://github.com/VSCodeVim/Vim/pull/4) ([jpoon](https://github.com/jpoon))
- Add ex mode [\#3](https://github.com/VSCodeVim/Vim/pull/3) ([guillermooo](https://github.com/guillermooo))
- Add ex mode [\#3](https://github.com/VSCodeVim/Vim/pull/3) ([guillermooo](https://github.com/guillermooo))
18 changes: 18 additions & 0 deletions extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import './src/actions/include-all';

import * as vscode from 'vscode';
import * as path from 'path';

import { CompositionState } from './src/state/compositionState';
import { EditorIdentity } from './src/editorIdentity';
Expand All @@ -24,6 +25,7 @@ import { configuration } from './src/configuration/configuration';
import { globalState } from './src/state/globalState';
import { taskQueue } from './src/taskQueue';
import { Register } from './src/register/register';
import { vimrc } from './src/configuration/vimrc';

let extensionContext: vscode.ExtensionContext;
let previousActiveEditorId: EditorIdentity | null = null;
Expand Down Expand Up @@ -87,6 +89,7 @@ async function loadConfiguration() {
}
}
}

export async function activate(context: vscode.ExtensionContext) {
// before we do anything else,
// we need to load the configuration first
Expand Down Expand Up @@ -207,6 +210,16 @@ export async function activate(context: vscode.ExtensionContext) {
false
);

registerEventListener(context, vscode.workspace.onDidSaveTextDocument, async document => {
if (
configuration.vimrc.enable &&
path.relative(document.fileName, configuration.vimrc.path) === ''
) {
await configuration.load();
vscode.window.showInformationMessage('Sourced new .vimrc');
}
});

// window events
registerEventListener(
context,
Expand Down Expand Up @@ -391,6 +404,11 @@ export async function activate(context: vscode.ExtensionContext) {
toggleExtension(configuration.disableExtension, compositionState);
});

registerCommand(context, 'vim.editVimrc', async () => {
const document = await vscode.workspace.openTextDocument(configuration.vimrc.path);
await vscode.window.showTextDocument(document);
});

for (const boundKey of configuration.boundKeyCombinations) {
registerCommand(context, boundKey.command, () => handleKeyEvent(`${boundKey.key}`));
}
Expand Down
25 changes: 8 additions & 17 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 16 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@
{
"command": "vim.showQuickpickCmdLine",
"title": "Vim: Show Command Line"
},
{
"command": "vim.editVimrc",
"title": "Vim: Edit .vimrc"
}
],
"keybindings": [
Expand Down Expand Up @@ -750,6 +754,15 @@
"default": "",
"scope": "machine-overridable"
},
"vim.vimrc.enable": {
"type": "boolean",
"description": "Use key mappings from a .vimrc file.",
"default": "true"
},
"vim.vimrc.path": {
"type": "string",
"description": "Path to a Vim configuration file. If unset, it will check for $HOME/.vimrc or $HOME/_vimrc."
},
"vim.substituteGlobalFlag": {
"type": "boolean",
"markdownDescription": "Automatically apply the global flag, `/g`, to substitute commands. When set to true, use `/g` to mean only first match should be replaced.",
Expand Down Expand Up @@ -897,7 +910,8 @@
},
"dependencies": {
"diff-match-patch": "1.0.4",
"lodash.escaperegexp": "4.1.2",
"fs": "0.0.1-security",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you mentioned, vscode.workspace.fs seems to be preferred

"lodash": "^4.17.15",
"neovim": "4.5.0",
"untildify": "4.0.0",
"winston": "3.2.1",
Expand All @@ -907,7 +921,7 @@
"devDependencies": {
"@types/diff": "4.0.2",
"@types/diff-match-patch": "1.0.32",
"@types/lodash.escaperegexp": "4.1.6",
"@types/lodash": "^4.14.144",
"@types/mocha": "5.2.7",
"@types/node": "12.12.7",
"@types/sinon": "7.5.0",
Expand Down
6 changes: 5 additions & 1 deletion src/cmd_line/subparsers/sort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ export function parseSortCommandArgs(args: string): node.SortCommand {
return new node.SortCommand({ reverse: false, ignoreCase: false, unique: false });
}

let scannedArgs: node.ISortCommandArguments = { reverse: false, ignoreCase: false, unique: false };
let scannedArgs: node.ISortCommandArguments = {
reverse: false,
ignoreCase: false,
unique: false,
};
let scanner = new Scanner(args);
const c = scanner.next();
scannedArgs.reverse = c === '!';
Expand Down
8 changes: 4 additions & 4 deletions src/common/motion/position.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { VimState } from '../../state/vimState';
import { configuration } from './../../configuration/configuration';
import { VisualBlockMode } from './../../mode/modes';
import { TextEditor } from './../../textEditor';
import escapeRegExp = require('lodash.escaperegexp');
import * as _ from 'lodash';

enum PositionDiffType {
Offset,
Expand Down Expand Up @@ -874,7 +874,7 @@ export class Position extends vscode.Position {
}

private static makeWordRegex(characterSet: string): RegExp {
let escaped = characterSet && escapeRegExp(characterSet).replace(/-/g, '\\-');
let escaped = characterSet && _.escapeRegExp(characterSet).replace(/-/g, '\\-');
let segments: string[] = [];

segments.push(`([^\\s${escaped}]+)`);
Expand All @@ -886,7 +886,7 @@ export class Position extends vscode.Position {
}

private static makeCamelCaseWordRegex(characterSet: string): RegExp {
const escaped = characterSet && escapeRegExp(characterSet).replace(/-/g, '\\-');
const escaped = characterSet && _.escapeRegExp(characterSet).replace(/-/g, '\\-');
const segments: string[] = [];

// old versions of VSCode before 1.31 will crash when trying to parse a regex with a lookbehind
Expand Down Expand Up @@ -1028,7 +1028,7 @@ export class Position extends vscode.Position {

// Symbols in vim.iskeyword or editor.wordSeparators
// are treated as CharKind.Punctuation
const escapedKeywordChars = escapeRegExp(keywordChars).replace(/-/g, '\\-');
const escapedKeywordChars = _.escapeRegExp(keywordChars).replace(/-/g, '\\-');
codePointRangePatterns[Number(CharKind.Punctuation)].push(escapedKeywordChars);

const codePointRanges = codePointRangePatterns.map(patterns => patterns.join(''));
Expand Down
10 changes: 10 additions & 0 deletions src/configuration/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ValidatorResults } from './iconfigurationValidator';
import { VsCodeContext } from '../util/vscode-context';
import { configurationValidator } from './configurationValidator';
import { decoration } from './decoration';
import { vimrc } from './vimrc';
import {
IConfiguration,
IKeyRemapping,
Expand Down Expand Up @@ -86,6 +87,10 @@ class Configuration implements IConfiguration {
}
}

if (this.vimrc.enable) {
vimrc.load(this);
}

this.leader = Notation.NormalizeKey(this.leader, this.leaderDefault);

const validatorResults = await configurationValidator.validate(configuration);
Expand Down Expand Up @@ -303,6 +308,11 @@ class Configuration implements IConfiguration {
enableNeovim = false;
neovimPath = '';

vimrc = {
enable: false,
path: '',
};

digraphs = {};

gdefault = false;
Expand Down
2 changes: 2 additions & 0 deletions src/configuration/configurationValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { IConfigurationValidator, ValidatorResults } from './iconfigurationValid
import { InputMethodSwitcherConfigurationValidator } from './validators/inputMethodSwitcherValidator';
import { NeovimValidator } from './validators/neovimValidator';
import { RemappingValidator } from './validators/remappingValidator';
import { VimrcValidator } from './validators/vimrcValidator';

class ConfigurationValidator {
private _validators: IConfigurationValidator[];
Expand All @@ -12,6 +13,7 @@ class ConfigurationValidator {
new InputMethodSwitcherConfigurationValidator(),
new NeovimValidator(),
new RemappingValidator(),
new VimrcValidator(),
];
}

Expand Down
14 changes: 14 additions & 0 deletions src/configuration/iconfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ export interface IKeyRemapping {
before: string[];
after?: string[];
commands?: ({ command: string; args: any[] } | string)[];
source?: 'vscode' | 'vimrc';
}

export interface IVimrcKeyRemapping {
keyRemapping: IKeyRemapping;
keyRemappingType: string;
}

export interface IAutoSwitchInputMethod {
Expand Down Expand Up @@ -287,6 +293,14 @@ export interface IConfiguration {
enableNeovim: boolean;
neovimPath: string;

/**
* .vimrc
*/
vimrc: {
enable: boolean;
path: string;
};

/**
* Automatically apply the `/g` flag to substitute commands.
*/
Expand Down
2 changes: 1 addition & 1 deletion src/configuration/iconfigurationValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,5 @@ export class ValidatorResults {

export interface IConfigurationValidator {
validate(config: IConfiguration): Promise<ValidatorResults>;
disable(config: IConfiguration);
disable(config: IConfiguration): void;
}
23 changes: 23 additions & 0 deletions src/configuration/validators/vimrcValidator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as fs from 'fs';
import { IConfiguration } from '../iconfiguration';
import { IConfigurationValidator, ValidatorResults } from '../iconfigurationValidator';
import { vimrc } from '../vimrc';

export class VimrcValidator implements IConfigurationValidator {
async validate(config: IConfiguration): Promise<ValidatorResults> {
const result = new ValidatorResults();

if (config.vimrc.enable && !fs.existsSync(vimrc.vimrcPath)) {
result.append({
level: 'error',
message: `.vimrc not found at ${config.vimrc.path}`,
});
}

return result;
}

disable(config: IConfiguration): void {
// no-op
}
}
Loading