mirror of
https://github.com/VSCodeVim/Vim.git
synced 2024-09-11 20:27:17 +03:00
Add CamelCaseMotion plugin (#3483)
* Add CamelCaseMotion Plugin Fixes https://github.com/VSCodeVim/Vim/issues/1220 * update @node/types * adjust tests to only load config once * nest camelCaseMotion configuration * fix merge error
This commit is contained in:
parent
fa0285dc8d
commit
d8564f90a6
20
README.md
20
README.md
@ -34,6 +34,7 @@ VSCodeVim is a Vim emulator for [Visual Studio Code](https://code.visualstudio.c
|
||||
- [vim-commentary](#vim-commentary)
|
||||
- [vim-indent-object](#vim-indent-object)
|
||||
- [vim-sneak](#vim-sneak)
|
||||
- [CamelCaseMotion](#camelcasemotion)
|
||||
- [Input Method](#input-method)
|
||||
- [VSCodeVim tricks](#-vscodevim-tricks)
|
||||
- [F.A.Q / Troubleshooting](#-faq)
|
||||
@ -505,6 +506,25 @@ Once sneak is active, initiate motions using the following commands. For operato
|
||||
| `<operator>z<char><char>` | Perform `<operator>` forward to the first occurence of `<char><char>` |
|
||||
| `<operator>Z<char><char>` | Perform `<operator>` backward to the first occurence of `<char><char>` |
|
||||
|
||||
### CamelCaseMotion
|
||||
|
||||
Based on [CamelCaseMotion](https://github.com/bkad/CamelCaseMotion), though not an exact emulation. This plugin provides an easier way to move through camelCase and snake_case words.
|
||||
|
||||
| Setting | Description | Type | Default Value |
|
||||
| -------------------------- | ------------------------------ | ------- | ------------- |
|
||||
| vim.camelCaseMotion.enable | Enable/disable CamelCaseMotion | Boolean | false |
|
||||
|
||||
Once CamelCaseMotion is enabled, the following motions are available:
|
||||
|
||||
| Motion Command | Description |
|
||||
| ---------------------- | -------------------------------------------------------------------------- |
|
||||
| `<leader>w` | Move forward to the start of the next camelCase or snake_case word segment |
|
||||
| `<leader>e` | Move forward to the next end of a camelCase or snake_case word segment |
|
||||
| `<leader>b` | Move back to the prior beginning of a camelCase or snake_case word segment |
|
||||
| `<operator>i<leader>w` | Select/change/delete/etc. the current camelCase or snake_case word segment |
|
||||
|
||||
By default, `<leader>` is mapped to `\`, so for example, `d2i\w` would delete the current and next camelCase word segment.
|
||||
|
||||
### Input Method
|
||||
|
||||
Disable input method when exiting Insert Mode.
|
||||
|
@ -1,4 +1,4 @@
|
||||
FROM node:8.15
|
||||
FROM node:10.15
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
|
6
package-lock.json
generated
6
package-lock.json
generated
@ -87,9 +87,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "9.6.42",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.42.tgz",
|
||||
"integrity": "sha512-SpeVQJFekfnEaZZO1yl4je/36upII36L7gOT4DBx51B1GeAB45mmDb3a5OBQB+ZeFxVVOP37r8Owsl940G/fBg==",
|
||||
"version": "10.12.25",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.25.tgz",
|
||||
"integrity": "sha512-IcvnGLGSQFDvC07Bz2I8SX+QKErDZbUdiQq7S2u3XyzTyJfUmT0sWJMbeQkMzpTAkO7/N7sZpW/arUM2jfKsbQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/sinon": {
|
||||
|
@ -449,6 +449,11 @@
|
||||
"description": "Override the 'ignorecase' option if the search pattern contains upper case characters.",
|
||||
"default": true
|
||||
},
|
||||
"vim.camelCaseMotion.enable": {
|
||||
"type": "boolean",
|
||||
"description": "Enable the CamelCaseMotion plugin for Vim.",
|
||||
"default": false
|
||||
},
|
||||
"vim.easymotion": {
|
||||
"type": "boolean",
|
||||
"description": "Enable the EasyMotion plugin for Vim.",
|
||||
@ -711,7 +716,7 @@
|
||||
"@types/diff-match-patch": "1.0.32",
|
||||
"@types/lodash": "4.14.121",
|
||||
"@types/mocha": "5.2.5",
|
||||
"@types/node": "9.6.42",
|
||||
"@types/node": "10.12.25",
|
||||
"@types/sinon": "7.0.5",
|
||||
"gulp": "4.0.0",
|
||||
"gulp-bump": "3.1.3",
|
||||
|
@ -8,6 +8,7 @@ import './commands/insert';
|
||||
import './commands/actions';
|
||||
|
||||
// plugin
|
||||
import './plugins/camelCaseMotion';
|
||||
import './plugins/easymotion/easymotion.cmd';
|
||||
import './plugins/easymotion/registerMoveActions';
|
||||
import './plugins/sneak';
|
||||
|
117
src/actions/plugins/camelCaseMotion.ts
Normal file
117
src/actions/plugins/camelCaseMotion.ts
Normal file
@ -0,0 +1,117 @@
|
||||
import { TextObjectMovement } from '../textobject';
|
||||
import { RegisterAction } from '../base';
|
||||
import { ModeName } from '../../mode/mode';
|
||||
import { Position } from '../../common/motion/position';
|
||||
import { VimState } from '../../state/vimState';
|
||||
import { IMovement, BaseMovement } from '../motion';
|
||||
import { TextEditor } from '../../textEditor';
|
||||
import { configuration } from '../../configuration/configuration';
|
||||
import { ChangeOperator } from '../operator';
|
||||
|
||||
class CamelCaseBaseMovement extends BaseMovement {
|
||||
public doesActionApply(vimState: VimState, keysPressed: string[]) {
|
||||
return configuration.camelCaseMotion.enable && super.doesActionApply(vimState, keysPressed);
|
||||
}
|
||||
|
||||
public couldActionApply(vimState: VimState, keysPressed: string[]) {
|
||||
return configuration.camelCaseMotion.enable && super.couldActionApply(vimState, keysPressed);
|
||||
}
|
||||
}
|
||||
|
||||
class CamelCaseTextObjectMovement extends TextObjectMovement {
|
||||
public doesActionApply(vimState: VimState, keysPressed: string[]) {
|
||||
return configuration.camelCaseMotion.enable && super.doesActionApply(vimState, keysPressed);
|
||||
}
|
||||
|
||||
public couldActionApply(vimState: VimState, keysPressed: string[]) {
|
||||
return configuration.camelCaseMotion.enable && super.couldActionApply(vimState, keysPressed);
|
||||
}
|
||||
}
|
||||
|
||||
// based off of `MoveWordBegin`
|
||||
@RegisterAction
|
||||
class MoveCamelCaseWordBegin extends CamelCaseBaseMovement {
|
||||
keys = ['<leader>', 'w'];
|
||||
|
||||
public async execAction(position: Position, vimState: VimState): Promise<Position> {
|
||||
if (
|
||||
!configuration.changeWordIncludesWhitespace &&
|
||||
vimState.recordedState.operator instanceof ChangeOperator
|
||||
) {
|
||||
// TODO use execForOperator? Or maybe dont?
|
||||
|
||||
// See note for w
|
||||
return position.getCurrentCamelCaseWordEnd().getRight();
|
||||
} else {
|
||||
return position.getCamelCaseWordRight();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// based off of `MoveWordEnd`
|
||||
@RegisterAction
|
||||
class MoveCamelCaseWordEnd extends CamelCaseBaseMovement {
|
||||
keys = ['<leader>', 'e'];
|
||||
|
||||
public async execAction(position: Position, vimState: VimState): Promise<Position> {
|
||||
return position.getCurrentCamelCaseWordEnd();
|
||||
}
|
||||
|
||||
public async execActionForOperator(position: Position, vimState: VimState): Promise<Position> {
|
||||
let end = position.getCurrentCamelCaseWordEnd();
|
||||
|
||||
return new Position(end.line, end.character + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// based off of `MoveBeginningWord`
|
||||
@RegisterAction
|
||||
class MoveBeginningCamelCaseWord extends CamelCaseBaseMovement {
|
||||
keys = ['<leader>', 'b'];
|
||||
|
||||
public async execAction(position: Position, vimState: VimState): Promise<Position> {
|
||||
return position.getCamelCaseWordLeft();
|
||||
}
|
||||
}
|
||||
|
||||
// based off of `SelectInnerWord`
|
||||
@RegisterAction
|
||||
export class SelectInnerCamelCaseWord extends CamelCaseTextObjectMovement {
|
||||
modes = [ModeName.Normal, ModeName.Visual];
|
||||
keys = ['i', '<leader>', 'w'];
|
||||
|
||||
public async execAction(position: Position, vimState: VimState): Promise<IMovement> {
|
||||
let start: Position;
|
||||
let stop: Position;
|
||||
const currentChar = TextEditor.getLineAt(position).text[position.character];
|
||||
|
||||
if (/\s/.test(currentChar)) {
|
||||
start = position.getLastCamelCaseWordEnd().getRight();
|
||||
stop = position.getCamelCaseWordRight().getLeftThroughLineBreaks();
|
||||
} else {
|
||||
start = position.getCamelCaseWordLeft(true);
|
||||
stop = position.getCurrentCamelCaseWordEnd(true);
|
||||
}
|
||||
|
||||
if (
|
||||
vimState.currentMode === ModeName.Visual &&
|
||||
!vimState.cursorStopPosition.isEqual(vimState.cursorStartPosition)
|
||||
) {
|
||||
start = vimState.cursorStartPosition;
|
||||
|
||||
if (vimState.cursorStopPosition.isBefore(vimState.cursorStartPosition)) {
|
||||
// If current cursor postion is before cursor start position, we are selecting words in reverser order.
|
||||
if (/\s/.test(currentChar)) {
|
||||
stop = position.getLastCamelCaseWordEnd().getRight();
|
||||
} else {
|
||||
stop = position.getCamelCaseWordLeft(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
start: start,
|
||||
stop: stop,
|
||||
};
|
||||
}
|
||||
}
|
@ -101,6 +101,7 @@ export class Position extends vscode.Position {
|
||||
|
||||
private _nonWordCharRegex: RegExp;
|
||||
private _nonBigWordCharRegex: RegExp;
|
||||
private _nonCamelCaseWordCharRegex: RegExp;
|
||||
private _sentenceEndRegex: RegExp;
|
||||
private _nonFileNameRegex: RegExp;
|
||||
|
||||
@ -109,6 +110,7 @@ export class Position extends vscode.Position {
|
||||
|
||||
this._nonWordCharRegex = this.makeWordRegex(Position.NonWordCharacters);
|
||||
this._nonBigWordCharRegex = this.makeWordRegex(Position.NonBigWordCharacters);
|
||||
this._nonCamelCaseWordCharRegex = this.makeCamelCaseWordRegex(Position.NonWordCharacters);
|
||||
this._sentenceEndRegex = /[\.!\?]{1}([ \n\t]+|$)/g;
|
||||
this._nonFileNameRegex = this.makeWordRegex(Position.NonFileCharacters);
|
||||
}
|
||||
@ -516,6 +518,10 @@ export class Position extends vscode.Position {
|
||||
return this.getWordLeftWithRegex(this._nonBigWordCharRegex, inclusive);
|
||||
}
|
||||
|
||||
public getCamelCaseWordLeft(inclusive: boolean = false): Position {
|
||||
return this.getWordLeftWithRegex(this._nonCamelCaseWordCharRegex, inclusive);
|
||||
}
|
||||
|
||||
public getFilePathLeft(inclusive: boolean = false): Position {
|
||||
return this.getWordLeftWithRegex(this._nonFileNameRegex, inclusive);
|
||||
}
|
||||
@ -531,6 +537,10 @@ export class Position extends vscode.Position {
|
||||
return this.getWordRightWithRegex(this._nonBigWordCharRegex);
|
||||
}
|
||||
|
||||
public getCamelCaseWordRight(inclusive: boolean = false): Position {
|
||||
return this.getWordRightWithRegex(this._nonCamelCaseWordCharRegex);
|
||||
}
|
||||
|
||||
public getFilePathRight(inclusive: boolean = false): Position {
|
||||
return this.getWordRightWithRegex(this._nonFileNameRegex, inclusive);
|
||||
}
|
||||
@ -543,6 +553,10 @@ export class Position extends vscode.Position {
|
||||
return this.getLastWordEndWithRegex(this._nonBigWordCharRegex);
|
||||
}
|
||||
|
||||
public getLastCamelCaseWordEnd(): Position {
|
||||
return this.getLastWordEndWithRegex(this._nonCamelCaseWordCharRegex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inclusive is true if we consider the current position a valid result, false otherwise.
|
||||
*/
|
||||
@ -557,6 +571,13 @@ export class Position extends vscode.Position {
|
||||
return this.getCurrentWordEndWithRegex(this._nonBigWordCharRegex, inclusive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inclusive is true if we consider the current position a valid result, false otherwise.
|
||||
*/
|
||||
public getCurrentCamelCaseWordEnd(inclusive: boolean = false): Position {
|
||||
return this.getCurrentWordEndWithRegex(this._nonCamelCaseWordCharRegex, inclusive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the boundary position of the section.
|
||||
*/
|
||||
@ -831,6 +852,39 @@ export class Position extends vscode.Position {
|
||||
return result;
|
||||
}
|
||||
|
||||
private makeCamelCaseWordRegex(characterSet: string): RegExp {
|
||||
const escaped = characterSet && _.escapeRegExp(characterSet).replace(/-/g, '\\-');
|
||||
const segments: string[] = [];
|
||||
|
||||
// prettier-ignore
|
||||
const firstSegment =
|
||||
'(' + // OPEN: group for matching camel case words
|
||||
`[^\\s${escaped}]` + // words can start with any word character
|
||||
'(?:' + // OPEN: group for characters after initial char
|
||||
`(?:(?<=[A-Z_])[A-Z](?=[\\sA-Z0-9${escaped}_]))+` + // If first char was a capital
|
||||
// the word can continue with all caps
|
||||
'|' + // OR
|
||||
`(?:(?<=[0-9_])[0-9](?=[\\sA-Z0-9${escaped}_]))+` + // If first char was a digit
|
||||
// the word can continue with all digits
|
||||
'|' + // OR
|
||||
`(?:(?<=[_])[_](?=[\\s${escaped}_]))+` + // Continue with all underscores
|
||||
'|' + // OR
|
||||
`[^\\sA-Z0-9${escaped}_]*` + // Continue with regular characters
|
||||
')' + // END: group for characters after initial char
|
||||
')' + // END: group for matching camel case words
|
||||
'';
|
||||
|
||||
segments.push(firstSegment);
|
||||
segments.push(`[${escaped}]+`);
|
||||
segments.push(`$^`);
|
||||
|
||||
// it can be difficult to grok the behavior of the above regex
|
||||
// feel free to check out https://regex101.com/r/mkVeiH/1 as a live example
|
||||
const result = new RegExp(segments.join('|'), 'g');
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private getAllPositions(line: string, regex: RegExp): number[] {
|
||||
let positions: number[] = [];
|
||||
let result = regex.exec(line);
|
||||
@ -987,7 +1041,7 @@ export class Position extends vscode.Position {
|
||||
.getRightThroughLineBreaks()
|
||||
.compareTo(this);
|
||||
|
||||
return (newPositionBeforeThis && (index < this.character || currentLine < this.line));
|
||||
return newPositionBeforeThis && (index < this.character || currentLine < this.line);
|
||||
});
|
||||
|
||||
if (newCharacter !== undefined) {
|
||||
|
@ -11,6 +11,7 @@ import {
|
||||
IAutoSwitchInputMethod,
|
||||
IDebugConfiguration,
|
||||
Digraph,
|
||||
ICamelCaseMotionConfiguration,
|
||||
} from './iconfiguration';
|
||||
|
||||
const packagejson: {
|
||||
@ -170,6 +171,10 @@ class Configuration implements IConfiguration {
|
||||
|
||||
autoindent = true;
|
||||
|
||||
camelCaseMotion: ICamelCaseMotionConfiguration = {
|
||||
enable: true,
|
||||
};
|
||||
|
||||
sneak = false;
|
||||
sneakUseIgnorecaseAndSmartcase = false;
|
||||
|
||||
|
@ -42,6 +42,13 @@ export interface IDebugConfiguration {
|
||||
loggingLevelForConsole: 'error' | 'warn' | 'info' | 'verbose' | 'debug';
|
||||
}
|
||||
|
||||
export interface ICamelCaseMotionConfiguration {
|
||||
/**
|
||||
* Enable CamelCaseMotion plugin or not
|
||||
*/
|
||||
enable: boolean;
|
||||
}
|
||||
|
||||
export interface IConfiguration {
|
||||
/**
|
||||
* Use the system's clipboard when copying.
|
||||
@ -84,6 +91,11 @@ export interface IConfiguration {
|
||||
*/
|
||||
autoindent: boolean;
|
||||
|
||||
/**
|
||||
* CamelCaseMotion plugin options
|
||||
*/
|
||||
camelCaseMotion: ICamelCaseMotionConfiguration;
|
||||
|
||||
/**
|
||||
* Use EasyMotion plugin?
|
||||
*/
|
||||
|
296
test/plugins/camelCaseMotion.test.ts
Normal file
296
test/plugins/camelCaseMotion.test.ts
Normal file
@ -0,0 +1,296 @@
|
||||
import { getTestingFunctions } from '../testSimplifier';
|
||||
import { cleanUpWorkspace, setupWorkspace, reloadConfiguration } from './../testUtils';
|
||||
import { Configuration } from '../testConfiguration';
|
||||
|
||||
const { newTest } = getTestingFunctions();
|
||||
|
||||
suite('camelCaseMotion plugin if not enabled', () => {
|
||||
setup(async () => {
|
||||
const configuration = new Configuration();
|
||||
configuration.camelCaseMotion.enable = false;
|
||||
await setupWorkspace(configuration);
|
||||
});
|
||||
|
||||
teardown(cleanUpWorkspace);
|
||||
|
||||
newTest({
|
||||
title: "basic motion doesn't work",
|
||||
start: ['|camelWord'],
|
||||
keysPressed: '<leader>w',
|
||||
end: ['|camelWord'],
|
||||
});
|
||||
});
|
||||
|
||||
suite('camelCaseMotion plugin', () => {
|
||||
setup(async () => {
|
||||
const configuration = new Configuration();
|
||||
configuration.camelCaseMotion.enable = true;
|
||||
await setupWorkspace(configuration);
|
||||
});
|
||||
|
||||
teardown(cleanUpWorkspace);
|
||||
|
||||
suite('handles <leader>w for camelCaseText', () => {
|
||||
newTest({
|
||||
title: 'step over whitespace',
|
||||
start: ['|var testCamelVARWithNums555&&&Ops'],
|
||||
keysPressed: '<leader>w',
|
||||
end: ['var |testCamelVARWithNums555&&&Ops'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'step to Camel word',
|
||||
start: ['var |testCamelVARWithNums555&&&Ops'],
|
||||
keysPressed: '<leader>w',
|
||||
end: ['var test|CamelVARWithNums555&&&Ops'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'step to CAP word',
|
||||
start: ['var test|CamelVARWithNums555&&&Ops'],
|
||||
keysPressed: '<leader>w',
|
||||
end: ['var testCamel|VARWithNums555&&&Ops'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'step after CAP word',
|
||||
start: ['var testCamel|VARWithNums555&&&Ops'],
|
||||
keysPressed: '<leader>w',
|
||||
end: ['var testCamelVAR|WithNums555&&&Ops'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'step from middle of word to Camel word',
|
||||
start: ['var testCamelVARW|ithNums555&&&Ops'],
|
||||
keysPressed: '<leader>w',
|
||||
end: ['var testCamelVARWith|Nums555&&&Ops'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'step to number word',
|
||||
start: ['var testCamelVARWith|Nums555&&&Ops'],
|
||||
keysPressed: '<leader>w',
|
||||
end: ['var testCamelVARWithNums|555&&&Ops'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'step to operator word',
|
||||
start: ['var testCamelVARWithNums|555&&&Ops'],
|
||||
keysPressed: '<leader>w',
|
||||
end: ['var testCamelVARWithNums555|&&&Ops'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'step from inside operator word',
|
||||
start: ['var testCamelVARWithNums555&|&&Ops'],
|
||||
keysPressed: '<leader>w',
|
||||
end: ['var testCamelVARWithNums555&&&|Ops'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'step to operator and then over',
|
||||
start: ['|camel.camelWord'],
|
||||
keysPressed: '2<leader>w',
|
||||
end: ['camel.|camelWord'],
|
||||
});
|
||||
});
|
||||
|
||||
suite('handles <leader>w for underscore_var', () => {
|
||||
newTest({
|
||||
title: 'step to _word',
|
||||
start: ['|some_var and_other23_var'],
|
||||
keysPressed: '<leader>w',
|
||||
end: ['some|_var and_other23_var'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'step over whitespace to word',
|
||||
start: ['some|_var and_other23_var'],
|
||||
keysPressed: '<leader>w',
|
||||
end: ['some_var |and_other23_var'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'step from inside word to _word',
|
||||
start: ['some_var a|nd_other23_var'],
|
||||
keysPressed: '<leader>w',
|
||||
end: ['some_var and|_other23_var'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'step form _word to number',
|
||||
start: ['some_var and|_other23_var'],
|
||||
keysPressed: '<leader>w',
|
||||
end: ['some_var and_other|23_var'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'step from nubmer word to _word',
|
||||
start: ['some_var and_other2|3_var'],
|
||||
keysPressed: '<leader>w',
|
||||
end: ['some_var and_other23|_var'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'step from in whitespace to word',
|
||||
start: ['variable | more_vars'],
|
||||
keysPressed: '<leader>w',
|
||||
end: ['variable |more_vars'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'step in ALL_CAPS_WORD',
|
||||
start: ['A|LL_CAPS_WORD'],
|
||||
keysPressed: '2<leader>w',
|
||||
end: ['ALL_CAPS|_WORD'],
|
||||
});
|
||||
});
|
||||
|
||||
suite('handles d<leader>w', () => {
|
||||
newTest({
|
||||
title: 'delete from start of camelWord',
|
||||
start: ['|camelTwoWord'],
|
||||
keysPressed: 'd<leader>w',
|
||||
end: ['|TwoWord'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'delete from middle of camelWord',
|
||||
start: ['ca|melTwoWord'],
|
||||
keysPressed: 'd<leader>w',
|
||||
end: ['ca|TwoWord'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'delete from start of CamelWord',
|
||||
start: ['camel|TwoWord'],
|
||||
keysPressed: 'd<leader>w',
|
||||
end: ['camel|Word'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'delete two words from camelWord',
|
||||
start: ['ca|melTwoWord'],
|
||||
keysPressed: '2d<leader>w',
|
||||
end: ['ca|Word'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'delete from start of underscore_word',
|
||||
start: ['|camel_two_word'],
|
||||
keysPressed: 'd<leader>w',
|
||||
end: ['|_two_word'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'delete from middle of underscore_word',
|
||||
start: ['ca|mel_two_word'],
|
||||
keysPressed: 'd<leader>w',
|
||||
end: ['ca|_two_word'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'delete two words from camel_word',
|
||||
start: ['ca|mel_two_word'],
|
||||
keysPressed: '2d<leader>w',
|
||||
end: ['ca|_word'],
|
||||
});
|
||||
});
|
||||
|
||||
suite('handles di<leader>w', () => {
|
||||
newTest({
|
||||
title: 'delete from start of camelWord',
|
||||
start: ['|camelTwoWord'],
|
||||
keysPressed: 'di<leader>w',
|
||||
end: ['|TwoWord'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'delete from middle of camelWord',
|
||||
start: ['ca|melTwoWord'],
|
||||
keysPressed: 'di<leader>w',
|
||||
end: ['|TwoWord'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'delete from start of CamelWord',
|
||||
start: ['camel|TwoWord'],
|
||||
keysPressed: 'di<leader>w',
|
||||
end: ['camel|Word'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'delete two words from camelWord',
|
||||
start: ['ca|melTwoWord'],
|
||||
keysPressed: '2di<leader>w',
|
||||
end: ['|Word'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'delete from start of underscore_word',
|
||||
start: ['|camel_two_word'],
|
||||
keysPressed: 'di<leader>w',
|
||||
end: ['|_two_word'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'delete from middle of underscore_word',
|
||||
start: ['ca|mel_two_word'],
|
||||
keysPressed: 'di<leader>w',
|
||||
end: ['|_two_word'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'delete two words from camel_word',
|
||||
start: ['ca|mel_two_word'],
|
||||
keysPressed: '2di<leader>w',
|
||||
end: ['|_word'],
|
||||
});
|
||||
});
|
||||
|
||||
suite('handles <leader>b', () => {
|
||||
newTest({
|
||||
title: 'back from middle of word',
|
||||
start: ['camel.camelWord oth|er'],
|
||||
keysPressed: '<leader>b',
|
||||
end: ['camel.camelWord |other'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'back over whitespace to camelWord',
|
||||
start: ['camel.camelWord |other'],
|
||||
keysPressed: '<leader>b',
|
||||
end: ['camel.camel|Word other'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'back twice over operator',
|
||||
start: ['camel.camel|Word other'],
|
||||
keysPressed: '2<leader>b',
|
||||
end: ['camel|.camelWord other'],
|
||||
});
|
||||
});
|
||||
|
||||
suite('handles <leader>e', () => {
|
||||
newTest({
|
||||
title: 'from start to middle of underscore_word',
|
||||
start: ['|foo_bar && camelCase'],
|
||||
keysPressed: '<leader>e',
|
||||
end: ['fo|o_bar && camelCase'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'from middle to end of underscore_word',
|
||||
start: ['fo|o_bar && camelCase'],
|
||||
keysPressed: '<leader>e',
|
||||
end: ['foo_ba|r && camelCase'],
|
||||
});
|
||||
|
||||
newTest({
|
||||
title: 'twice to end of word over operator',
|
||||
start: ['foo_ba|r && camelCase'],
|
||||
keysPressed: '2<leader>e',
|
||||
end: ['foo_bar && came|lCase'],
|
||||
});
|
||||
});
|
||||
});
|
@ -15,6 +15,9 @@ export class Configuration implements IConfiguration {
|
||||
ignorecase = true;
|
||||
smartcase = true;
|
||||
autoindent = true;
|
||||
camelCaseMotion = {
|
||||
enable: false,
|
||||
};
|
||||
sneak = false;
|
||||
sneakUseIgnorecaseAndSmartcase = false;
|
||||
surround = true;
|
||||
|
Loading…
Reference in New Issue
Block a user