Pull some tests out of extremely bloated modeNormal.test.ts into dedicated files

This commit is contained in:
Jason Fields 2023-03-12 18:59:43 -04:00
parent 15cb5ecde6
commit e38d60b6af
5 changed files with 805 additions and 773 deletions

View File

@ -2129,279 +2129,6 @@ suite('Mode Normal', () => {
end: ['one two| '],
});
newTest({
title: 'can ctrl-a correctly behind a word',
start: ['|one 9'],
keysPressed: '<C-a>',
end: ['one 1|0'],
});
newTest({
title: 'can ctrl-a the right word (always the one AFTER the cursor)',
start: ['1 |one 2'],
keysPressed: '<C-a>',
end: ['1 one |3'],
});
newTest({
title: 'can ctrl-a on word',
start: ['one -|11'],
keysPressed: '<C-a>',
end: ['one -1|0'],
});
newTest({
title: 'can ctrl-a on a hex number',
start: ['|0xf'],
keysPressed: '<C-a>',
end: ['0x1|0'],
});
newTest({
title: 'can ctrl-a on decimal',
start: ['1|1.123'],
keysPressed: '<C-a>',
end: ['1|2.123'],
});
newTest({
title: 'can ctrl-a with numeric prefix',
start: ['|-10'],
keysPressed: '15<C-a>',
end: ['|5'],
});
newTest({
title: 'can ctrl-a on a decimal',
start: ['-10.|1'],
keysPressed: '10<C-a>',
end: ['-10.1|1'],
});
newTest({
title: 'can ctrl-a on an octal ',
start: ['0|7'],
keysPressed: '<C-a>',
end: ['01|0'],
});
newTest({
title: 'Correctly increments in the middle of a number',
start: ['10|1'],
keysPressed: '<C-a>',
end: ['10|2'],
});
newTest({
title: 'can ctrl-a on a hex number behind a word',
start: ['|test0xf'],
keysPressed: '<C-a>',
end: ['test0x1|0'],
});
newTest({
title: 'can ctrl-a distinguish fake hex number',
start: ['|00xf'],
keysPressed: '<C-a>',
end: ['0|1xf'],
});
newTest({
title: 'can ctrl-a can preserve uppercase',
start: ['|0xDEAD'],
keysPressed: '<C-a>',
end: ['0xDEA|E'],
});
newTest({
title: 'can ctrl-a can transform to lowercase',
start: ['|0xDEAd'],
keysPressed: '<C-a>',
end: ['0xdea|e'],
});
newTest({
title: 'can ctrl-a can transform to uppercase 1',
start: ['|0xdeaD'],
keysPressed: '<C-a>',
end: ['0xDEA|E'],
});
newTest({
title: 'can ctrl-a can transform to uppercase 2',
start: ['|0xDeaD1'],
keysPressed: '<C-a>',
end: ['0xDEAD|2'],
});
newTest({
title: 'can ctrl-a preserve leading zeros of octal',
start: ['|000007'],
keysPressed: '<C-a>',
end: ['00001|0'],
});
newTest({
title: 'can ctrl-a trim leading zeros of decimal',
start: ['|000009'],
keysPressed: '<C-a>',
end: ['1|0'],
});
newTest({
title: 'can ctrl-a process `-0x0` correctly',
start: ['|-0x0'],
keysPressed: '<C-a>',
end: ['-0x|1'],
});
newTest({
title: 'can ctrl-a regard `0` as decimal',
start: ['|0'],
keysPressed: '10<C-a>',
end: ['1|0'],
});
newTest({
title: 'can ctrl-a on octal ignore negative sign',
start: ['|test-0116'],
keysPressed: '<C-a>',
end: ['test-011|7'],
});
newTest({
title: 'can ctrl-a on octal ignore positive sign',
start: ['|test+0116'],
keysPressed: '<C-a>',
end: ['test+011|7'],
});
newTest({
title: 'can ctrl-a on hex number ignore negative sign',
start: ['|test-0xf'],
keysPressed: '<C-a>',
end: ['test-0x1|0'],
});
newTest({
title: 'can ctrl-a on hex number ignore positive sign',
start: ['|test+0xf'],
keysPressed: '<C-a>',
end: ['test+0x1|0'],
});
newTest({
title: 'can ctrl-x correctly behind a word',
start: ['|one 10'],
keysPressed: '<C-x>',
end: ['one |9'],
});
newTest({
title: 'can ctrl-a on an number with word before ',
start: ['|test3'],
keysPressed: '<C-a>',
end: ['test|4'],
});
newTest({
title: 'can ctrl-a on an number with word before and after ',
start: ['|test3abc'],
keysPressed: '<C-a>',
end: ['test|4abc'],
});
newTest({
title: 'can ctrl-x on a negative number with word before and after ',
start: ['|test-2abc'],
keysPressed: '<C-x><C-x><C-x>',
end: ['test-|5abc'],
});
newTest({
title: 'can ctrl-a properly on multiple lines',
start: ['id: 1|,', 'someOtherId: 1'],
keysPressed: '<C-a>',
end: ['id: 1|,', 'someOtherId: 1'],
});
newTest({
title: 'can <C-a> on word with multiple numbers (incrementing first number)',
start: ['f|oo1bar2'],
keysPressed: '<C-a>',
end: ['foo|2bar2'],
});
newTest({
title: 'can <C-a> on word with multiple numbers (incrementing second number)',
start: ['foo1|bar2'],
keysPressed: '<C-a>',
end: ['foo1bar|3'],
});
newTest({
title: 'can <C-a> on word with - in front of it',
start: ['-fo|o2'],
keysPressed: '<C-a>',
end: ['-foo|3'],
});
newTest({
title: '<C-a> in visual mode',
start: ['9 9 9', '9| 9 9', '9 9 9', '9 9 9', '9 9 9'],
keysPressed: 'vjj3<C-a>',
end: ['9 9 9', '9| 12 9', '12 9 9', '12 9 9', '9 9 9'],
endMode: Mode.Normal,
});
newTest({
title: '<C-a> in visual line mode',
start: ['9 9 9', '9| 9 9', '9 9 9', '9 9 9', '9 9 9'],
keysPressed: 'Vjj3<C-a>',
end: ['9 9 9', '|12 9 9', '12 9 9', '12 9 9', '9 9 9'],
endMode: Mode.Normal,
});
newTest({
title: '<C-a> in visual block mode',
start: ['9 9 9', '9 |9 9', '9 9 9', '9 9 9', '9 9 9'],
keysPressed: '<C-v>jj3<C-a>',
end: ['9 9 9', '9 |12 9', '9 12 9', '9 12 9', '9 9 9'],
endMode: Mode.Normal,
});
newTest({
title: '<C-a> in visual block mode does not go past selection',
start: ['9 9 9', '9| 9 9', '9 9 9', '9 9 9', '9 9 9'],
keysPressed: '<C-v>jj3<C-a>',
end: ['9 9 9', '9| 9 9', '9 9 9', '9 9 9', '9 9 9'],
endMode: Mode.Normal,
});
newTest({
title: 'g<C-a> in visual mode',
start: ['9 9 9', '9| 9 9', '9 9 9', '9 9 9', '9 9 9'],
keysPressed: 'vjj3g<C-a>',
end: ['9 9 9', '9| 12 9', '15 9 9', '18 9 9', '9 9 9'],
endMode: Mode.Normal,
});
newTest({
title: 'g<C-a> in visual line mode',
start: ['9 9 9', '9| 9 9', '9 9 9', '9 9 9', '9 9 9'],
keysPressed: 'Vjj3g<C-a>',
end: ['9 9 9', '|12 9 9', '15 9 9', '18 9 9', '9 9 9'],
endMode: Mode.Normal,
});
newTest({
title: 'g<C-a> in visual block mode',
start: ['9 9 9', '9 |9 9', '9 9 9', '9 9 9', '9 9 9'],
keysPressed: '<C-v>jj3g<C-a>',
end: ['9 9 9', '9 |12 9', '9 15 9', '9 18 9', '9 9 9'],
endMode: Mode.Normal,
});
newTest({
title: 'can do Y',
start: ['|blah blah'],
@ -2430,160 +2157,6 @@ suite('Mode Normal', () => {
end: [' one', ' |'],
});
newTest({
title: '/ does not affect mark',
start: ['|one', 'twooo', 'thurr'],
keysPressed: "ma/two\n'a",
end: ['|one', 'twooo', 'thurr'],
});
newTest({
title: '/ can search with regex',
start: ['|', 'one two2o'],
keysPressed: '/o\\do\n',
end: ['', 'one tw|o2o'],
});
newTest({
title: '/ can search with newline',
start: ['|asdf', '__asdf', 'asdf'],
keysPressed: '/\\nasdf\n',
end: ['asdf', '__asd|f', 'asdf'],
});
newTest({
title: '/ can search through multiple newlines',
start: ['|asdf', '__asdf', 'asdf', 'abc', ' abc'],
keysPressed: '/asdf\\nasdf\\nabc\n',
end: ['asdf', '__|asdf', 'asdf', 'abc', ' abc'],
});
newTest({
title: '/ with noignorecase, nosmartcase',
config: { ignorecase: false, smartcase: false },
start: ['bl|ah', 'blAh', 'BLAH', 'blah'],
keysPressed: '/blah\n',
end: ['blah', 'blAh', 'BLAH', '|blah'],
});
newTest({
title: '/ with \\%V will search in last selection',
start: ['', 'asdf', '|asdf', 'asdf', 'asdf'],
keysPressed: 'vjj<Esc>gg/\\%Vasdf\n',
end: ['', 'asdf', '|asdf', 'asdf', 'asdf'],
});
newTest({
title: '/ with \\%V will search in last selection, starting from the cursor postion',
start: ['', 'asdf', '|asdf', '', 'asdf', 'asdf'],
keysPressed: 'vjjj<Esc>kk/\\%Vasdf\nn',
end: ['', 'asdf', '|asdf', '', 'asdf', 'asdf'],
});
newTest({
title: '/ matches ^ per line',
start: ['| asdf', 'asasdf', 'asdf', 'asdf'],
keysPressed: '/^asdf\n',
end: [' asdf', 'asasdf', '|asdf', 'asdf'],
});
newTest({
title: '/ matches $ per line',
start: ['|asdfjkl', 'asdf ', 'asdf', 'asdf'],
keysPressed: '/asdf$\n',
end: ['asdfjkl', 'asdf ', '|asdf', 'asdf'],
});
newTest({
title: '/ search $, walk over matches',
start: ['|start', '', '', 'end'],
keysPressed: '/$\nnnn',
end: ['start', '', '', 'en|d'],
});
newTest({
title: '?, match at EOL, walk over matches',
start: ['x end', 'x', 'x', '|start'],
keysPressed: '?x\nnn',
end: ['|x end', 'x', 'x', 'start'],
});
newTest({
title: 'Search for `(`',
start: ['|one (two) three'],
keysPressed: '/(\n',
end: ['one |(two) three'],
});
/**
* The escaped `/` and `?` the next tests are necessary because otherwise they denote a search offset.
*/
newTest({
title: 'Can search for forward slash',
start: ['|One/two/three/four'],
keysPressed: '/\\/\nn',
end: ['One/two|/three/four'],
});
newTest({
title: 'Can search backward for question mark',
start: ['|One?two?three?four'],
keysPressed: '?\\?\nn',
end: ['One?two|?three?four'],
});
newTest({
title: '/\\c forces case insensitive search',
start: ['|__ASDF', 'asdf'],
keysPressed: '/\\casdf\n',
end: ['__|ASDF', 'asdf'],
});
newTest({
title: '/\\C forces case sensitive search',
start: ['|__ASDF', 'asdf'],
keysPressed: '/\\Casdf\n',
end: ['__ASDF', '|asdf'],
});
newTest({
title: '/\\\\c does not trigger case (in)sensitivity',
start: ['|__\\c__'],
keysPressed: '/\\\\c\n',
end: ['__|\\c__'],
});
newTest({
title: '/\\\\\\c triggers case insensitivity',
start: ['|__\\ASDF', 'asdf'],
keysPressed: '/\\\\\\c\n',
end: ['__|\\ASDF', 'asdf'],
});
newTest({
title: '<C-l> adds the next character in the first match to search term',
start: ['|foo', 'bar', 'abcd'],
keysPressed: '/ab<C-l>d\n',
end: ['foo', 'bar', '|abcd'],
endMode: Mode.Normal,
});
newTest({
title: 'Can delete with search forward',
start: ['foo |junk junk bar'],
keysPressed: 'd/bar\n',
end: ['foo |bar'],
endMode: Mode.Normal,
});
newTest({
title: 'Can delete with search backward',
start: ['foo junk garbage trash |bar'],
keysPressed: 'd?junk\n',
end: ['foo |bar'],
endMode: Mode.Normal,
});
newTest({
title: 'Can do C',
start: ['export const options = {', '|', '};'],
@ -3166,349 +2739,6 @@ suite('Mode Normal', () => {
endMode: Mode.Normal,
});
suite('can handle gn', () => {
test(`gn selects the next match text`, async () => {
await modeHandler.handleMultipleKeyEvents('ifoo\nhello world\nhello\nhello'.split(''));
await modeHandler.handleMultipleKeyEvents(['<Esc>', ...'/hello\n'.split('')]);
await modeHandler.handleMultipleKeyEvents('gg'.split(''));
await modeHandler.handleMultipleKeyEvents(['g', 'n']);
assert.strictEqual(modeHandler.currentMode, Mode.Visual);
const selection = modeHandler.vimState.editor.selection;
assert.strictEqual(selection.start.character, 0);
assert.strictEqual(selection.start.line, 1);
assert.strictEqual(selection.end.character, 'hello'.length);
assert.strictEqual(selection.end.line, 1);
});
const gnSelectsCurrentWord = async (jumpCmd: string) => {
await modeHandler.handleMultipleKeyEvents('ifoo\nhello world\nhello\nhello'.split(''));
await modeHandler.handleMultipleKeyEvents(['<Esc>', ...'/hello\n'.split('')]);
await modeHandler.handleMultipleKeyEvents(jumpCmd.split(''));
await modeHandler.handleMultipleKeyEvents(['g', 'n']);
assert.strictEqual(modeHandler.currentMode, Mode.Visual);
const selection = modeHandler.vimState.editor.selection;
assert.strictEqual(selection.start.character, 0);
assert.strictEqual(selection.start.line, 1);
assert.strictEqual(selection.end.character, 'hello'.length);
assert.strictEqual(selection.end.line, 1);
};
test(`gn selects the current word at |hello`, async () => {
await gnSelectsCurrentWord('2gg');
});
test(`gn selects the current word at h|ello`, async () => {
await gnSelectsCurrentWord('2ggl');
});
test(`gn selects the current word at hel|lo`, async () => {
await gnSelectsCurrentWord('2ggeh');
});
test(`gn selects the current word at hell|o`, async () => {
await gnSelectsCurrentWord('2gge');
});
test(`gn selects the next word at hello|`, async () => {
await modeHandler.handleMultipleKeyEvents('ifoo\nhello world\nhello\nhello'.split(''));
await modeHandler.handleMultipleKeyEvents(['<Esc>', ...'/hello\n'.split('')]);
await modeHandler.handleMultipleKeyEvents('2ggel'.split(''));
await modeHandler.handleMultipleKeyEvents(['g', 'n']);
assert.strictEqual(modeHandler.currentMode, Mode.Visual);
const selection = modeHandler.vimState.editor.selection;
assert.strictEqual(selection.start.character, 0);
assert.strictEqual(selection.start.line, 2);
assert.strictEqual(selection.end.character, 'hello'.length);
assert.strictEqual(selection.end.line, 2);
});
});
suite('can handle dgn', () => {
newTest({
title: 'dgn deletes the next match text (from first line)',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\nggdgn',
end: ['foo', '| world', 'hello', 'hello'],
endMode: Mode.Normal,
});
newTest({
title: 'dgn deletes the current word when cursor is at |hello',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\ndgn',
end: ['foo', '| world', 'hello', 'hello'],
endMode: Mode.Normal,
});
newTest({
title: 'dgn deletes the current word when cursor is at h|ello',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\nldgn',
end: ['foo', '| world', 'hello', 'hello'],
endMode: Mode.Normal,
});
newTest({
title: 'dgn deletes the current word when cursor is at hel|lo',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\n3ldgn',
end: ['foo', '| world', 'hello', 'hello'],
endMode: Mode.Normal,
});
newTest({
title: 'dgn deletes the current word when cursor is at hell|o',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\nedgn',
end: ['foo', '| world', 'hello', 'hello'],
endMode: Mode.Normal,
});
newTest({
title: 'dgn deletes the next word when cursor is at hello|',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\neldgn',
end: ['foo', 'hello world', '|', 'hello'],
endMode: Mode.Normal,
});
newTest({
title: 'dgn with single-character match',
start: ['O|ne Two Three Four Five Six'],
keysPressed: '/T\n' + 'e' + 'dgn',
end: ['One Two |hree Four Five Six'],
endMode: Mode.Normal,
});
});
suite('can handle cgn', () => {
newTest({
title: 'cgn deletes the next match text (from first line)',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\nggcgn',
end: ['foo', '| world', 'hello', 'hello'],
endMode: Mode.Insert,
});
newTest({
title: 'cgn deletes the current word when cursor is at |hello',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\ncgn',
end: ['foo', '| world', 'hello', 'hello'],
endMode: Mode.Insert,
});
newTest({
title: 'cgn deletes the current word when cursor is at h|ello',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\nlcgn',
end: ['foo', '| world', 'hello', 'hello'],
endMode: Mode.Insert,
});
newTest({
title: 'cgn deletes the current word when cursor is at hel|lo',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\n3lcgn',
end: ['foo', '| world', 'hello', 'hello'],
endMode: Mode.Insert,
});
newTest({
title: 'cgn deletes the current word when cursor is at hell|o',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\necgn',
end: ['foo', '| world', 'hello', 'hello'],
endMode: Mode.Insert,
});
newTest({
title: 'cgn with single-character match',
start: ['O|ne Two Three Four Five Six'],
keysPressed: '/T\n' + 'e' + 'cgn',
end: ['One Two |hree Four Five Six'],
endMode: Mode.Insert,
});
newTest({
title: '`cgn` can be repeated by dot',
start: ['|', 'one', 'two', 'one', 'three'],
keysPressed: '/one\n' + 'cgn' + 'XYZ' + '<Esc>' + '..',
end: ['', 'XYZ', 'two', 'XY|Z', 'three'],
endMode: Mode.Normal,
});
});
suite('can handle gN', () => {
test(`gN selects the previous match text`, async () => {
await modeHandler.handleMultipleKeyEvents('ihello world\nhello\nhi hello\nfoo'.split(''));
await modeHandler.handleMultipleKeyEvents(['<Esc>', ...'/hello\n'.split('')]);
await modeHandler.handleMultipleKeyEvents(['G']);
await modeHandler.handleMultipleKeyEvents(['g', 'N']);
assert.strictEqual(modeHandler.currentMode, Mode.Visual);
const selection = modeHandler.vimState.editor.selection;
assert.strictEqual(selection.start.character, 'hi '.length);
assert.strictEqual(selection.start.line, 2);
assert.strictEqual(selection.end.character, 'hi hello'.length);
assert.strictEqual(selection.end.line, 2);
});
const gnSelectsCurrentWord = async (jumpCmd: string) => {
await modeHandler.handleMultipleKeyEvents('ihello world\nhello\nhi hello\nfoo'.split(''));
await modeHandler.handleMultipleKeyEvents(['<Esc>', ...'/hello\n'.split('')]);
await modeHandler.handleMultipleKeyEvents(jumpCmd.split(''));
await modeHandler.handleMultipleKeyEvents(['g', 'N']);
assert.strictEqual(modeHandler.currentMode, Mode.Visual);
const selection = modeHandler.vimState.editor.selection;
assert.strictEqual(selection.start.character, 'hi '.length);
assert.strictEqual(selection.start.line, 2);
assert.strictEqual(selection.end.character, 'hi hello'.length);
assert.strictEqual(selection.end.line, 2);
};
test(`gN selects the current word at hell|o`, async () => {
await gnSelectsCurrentWord('3gg7l');
});
test(`gN selects the current word at hel|lo`, async () => {
await gnSelectsCurrentWord('3gg6l');
});
test(`gN selects the current word at h|ello`, async () => {
await gnSelectsCurrentWord('3gg4l');
});
test(`gN selects the current word at |hello`, async () => {
await gnSelectsCurrentWord('3gg3l');
});
test(`gN selects the previous word at | hello`, async () => {
await modeHandler.handleMultipleKeyEvents('ihello world\nhello\nhi hello\nfoo'.split(''));
await modeHandler.handleMultipleKeyEvents(['<Esc>', ...'/hello\n'.split('')]);
await modeHandler.handleMultipleKeyEvents('3gg2l'.split(''));
await modeHandler.handleMultipleKeyEvents(['g', 'N']);
assert.strictEqual(modeHandler.currentMode, Mode.Visual);
const selection = modeHandler.vimState.editor.selection;
assert.strictEqual(selection.start.character, 0);
assert.strictEqual(selection.start.line, 1);
assert.strictEqual(selection.end.character, 'hello'.length);
assert.strictEqual(selection.end.line, 1);
});
});
suite('can handle dgN', () => {
newTest({
title: 'dgN deletes the previous match text (from first line)',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\nGdgN',
end: ['hello world', 'hello', 'hi| ', 'foo'],
endMode: Mode.Normal,
});
newTest({
title: 'dgN deletes the current word when cursor is at hell|o',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\n3gg$dgN',
end: ['hello world', 'hello', 'hi| ', 'foo'],
endMode: Mode.Normal,
});
newTest({
title: 'dgN deletes the current word when cursor is at hel|lo',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\n3gg$hdgN',
end: ['hello world', 'hello', 'hi| ', 'foo'],
endMode: Mode.Normal,
});
newTest({
title: 'dgN deletes the current word when cursor is at h|ello',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\n3ggwldgN',
end: ['hello world', 'hello', 'hi| ', 'foo'],
endMode: Mode.Normal,
});
newTest({
title: 'dgN deletes the current word when cursor is at |hello',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\n3ggwdgN',
end: ['hello world', 'hello', 'hi| ', 'foo'],
endMode: Mode.Normal,
});
newTest({
title: 'dgN deletes the previous word when cursor is at | hello',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\n3ggwhdgN',
end: ['hello world', '|', 'hi hello', 'foo'],
endMode: Mode.Normal,
});
});
suite('can handle cgN', () => {
newTest({
title: 'cgN deletes the previous match text (from first line)',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\nGcgN',
end: ['hello world', 'hello', 'hi |', 'foo'],
endMode: Mode.Insert,
});
newTest({
title: 'cgN deletes the current word when cursor is at hell|o',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\n3gg$cgN',
end: ['hello world', 'hello', 'hi |', 'foo'],
endMode: Mode.Insert,
});
newTest({
title: 'cgN deletes the current word when cursor is at hel|lo',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\n3gg$hcgN',
end: ['hello world', 'hello', 'hi |', 'foo'],
endMode: Mode.Insert,
});
newTest({
title: 'cgN deletes the current word when cursor is at h|ello',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\n3ggwlcgN',
end: ['hello world', 'hello', 'hi |', 'foo'],
endMode: Mode.Insert,
});
newTest({
title: 'cgN deletes the current word when cursor is at |hello',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\n3ggwcgN',
end: ['hello world', 'hello', 'hi |', 'foo'],
endMode: Mode.Insert,
});
newTest({
title: 'cgN deletes the previous word when cursor is at | hello',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\n3ggwhcgN',
end: ['hello world', '|', 'hi hello', 'foo'],
endMode: Mode.Insert,
});
});
newTest({
title: 'can handle <C-u> when first line is visible and starting column is at the beginning',
start: ['\t hello world', 'hello', 'hi hello', '|foo'],

View File

@ -0,0 +1,281 @@
import { Mode } from '../../src/mode/mode';
import { newTest } from '../testSimplifier';
import { setupWorkspace, cleanUpWorkspace } from '../testUtils';
suite('Increment/decrement (<C-a> and <C-x>)', () => {
suiteSetup(setupWorkspace);
suiteTeardown(cleanUpWorkspace);
newTest({
title: 'can ctrl-a correctly behind a word',
start: ['|one 9'],
keysPressed: '<C-a>',
end: ['one 1|0'],
});
newTest({
title: 'can ctrl-a the right word (always the one AFTER the cursor)',
start: ['1 |one 2'],
keysPressed: '<C-a>',
end: ['1 one |3'],
});
newTest({
title: 'can ctrl-a on word',
start: ['one -|11'],
keysPressed: '<C-a>',
end: ['one -1|0'],
});
newTest({
title: 'can ctrl-a on a hex number',
start: ['|0xf'],
keysPressed: '<C-a>',
end: ['0x1|0'],
});
newTest({
title: 'can ctrl-a on decimal',
start: ['1|1.123'],
keysPressed: '<C-a>',
end: ['1|2.123'],
});
newTest({
title: 'can ctrl-a with numeric prefix',
start: ['|-10'],
keysPressed: '15<C-a>',
end: ['|5'],
});
newTest({
title: 'can ctrl-a on a decimal',
start: ['-10.|1'],
keysPressed: '10<C-a>',
end: ['-10.1|1'],
});
newTest({
title: 'can ctrl-a on an octal ',
start: ['0|7'],
keysPressed: '<C-a>',
end: ['01|0'],
});
newTest({
title: 'Correctly increments in the middle of a number',
start: ['10|1'],
keysPressed: '<C-a>',
end: ['10|2'],
});
newTest({
title: 'can ctrl-a on a hex number behind a word',
start: ['|test0xf'],
keysPressed: '<C-a>',
end: ['test0x1|0'],
});
newTest({
title: 'can ctrl-a distinguish fake hex number',
start: ['|00xf'],
keysPressed: '<C-a>',
end: ['0|1xf'],
});
newTest({
title: 'can ctrl-a can preserve uppercase',
start: ['|0xDEAD'],
keysPressed: '<C-a>',
end: ['0xDEA|E'],
});
newTest({
title: 'can ctrl-a can transform to lowercase',
start: ['|0xDEAd'],
keysPressed: '<C-a>',
end: ['0xdea|e'],
});
newTest({
title: 'can ctrl-a can transform to uppercase 1',
start: ['|0xdeaD'],
keysPressed: '<C-a>',
end: ['0xDEA|E'],
});
newTest({
title: 'can ctrl-a can transform to uppercase 2',
start: ['|0xDeaD1'],
keysPressed: '<C-a>',
end: ['0xDEAD|2'],
});
newTest({
title: 'can ctrl-a preserve leading zeros of octal',
start: ['|000007'],
keysPressed: '<C-a>',
end: ['00001|0'],
});
newTest({
title: 'can ctrl-a trim leading zeros of decimal',
start: ['|000009'],
keysPressed: '<C-a>',
end: ['1|0'],
});
newTest({
title: 'can ctrl-a process `-0x0` correctly',
start: ['|-0x0'],
keysPressed: '<C-a>',
end: ['-0x|1'],
});
newTest({
title: 'can ctrl-a regard `0` as decimal',
start: ['|0'],
keysPressed: '10<C-a>',
end: ['1|0'],
});
newTest({
title: 'can ctrl-a on octal ignore negative sign',
start: ['|test-0116'],
keysPressed: '<C-a>',
end: ['test-011|7'],
});
newTest({
title: 'can ctrl-a on octal ignore positive sign',
start: ['|test+0116'],
keysPressed: '<C-a>',
end: ['test+011|7'],
});
newTest({
title: 'can ctrl-a on hex number ignore negative sign',
start: ['|test-0xf'],
keysPressed: '<C-a>',
end: ['test-0x1|0'],
});
newTest({
title: 'can ctrl-a on hex number ignore positive sign',
start: ['|test+0xf'],
keysPressed: '<C-a>',
end: ['test+0x1|0'],
});
newTest({
title: 'can ctrl-x correctly behind a word',
start: ['|one 10'],
keysPressed: '<C-x>',
end: ['one |9'],
});
newTest({
title: 'can ctrl-a on an number with word before ',
start: ['|test3'],
keysPressed: '<C-a>',
end: ['test|4'],
});
newTest({
title: 'can ctrl-a on an number with word before and after ',
start: ['|test3abc'],
keysPressed: '<C-a>',
end: ['test|4abc'],
});
newTest({
title: 'can ctrl-x on a negative number with word before and after ',
start: ['|test-2abc'],
keysPressed: '<C-x><C-x><C-x>',
end: ['test-|5abc'],
});
newTest({
title: 'can ctrl-a properly on multiple lines',
start: ['id: 1|,', 'someOtherId: 1'],
keysPressed: '<C-a>',
end: ['id: 1|,', 'someOtherId: 1'],
});
newTest({
title: 'can <C-a> on word with multiple numbers (incrementing first number)',
start: ['f|oo1bar2'],
keysPressed: '<C-a>',
end: ['foo|2bar2'],
});
newTest({
title: 'can <C-a> on word with multiple numbers (incrementing second number)',
start: ['foo1|bar2'],
keysPressed: '<C-a>',
end: ['foo1bar|3'],
});
newTest({
title: 'can <C-a> on word with - in front of it',
start: ['-fo|o2'],
keysPressed: '<C-a>',
end: ['-foo|3'],
});
newTest({
title: '<C-a> in visual mode',
start: ['9 9 9', '9| 9 9', '9 9 9', '9 9 9', '9 9 9'],
keysPressed: 'vjj3<C-a>',
end: ['9 9 9', '9| 12 9', '12 9 9', '12 9 9', '9 9 9'],
endMode: Mode.Normal,
});
newTest({
title: '<C-a> in visual line mode',
start: ['9 9 9', '9| 9 9', '9 9 9', '9 9 9', '9 9 9'],
keysPressed: 'Vjj3<C-a>',
end: ['9 9 9', '|12 9 9', '12 9 9', '12 9 9', '9 9 9'],
endMode: Mode.Normal,
});
newTest({
title: '<C-a> in visual block mode',
start: ['9 9 9', '9 |9 9', '9 9 9', '9 9 9', '9 9 9'],
keysPressed: '<C-v>jj3<C-a>',
end: ['9 9 9', '9 |12 9', '9 12 9', '9 12 9', '9 9 9'],
endMode: Mode.Normal,
});
newTest({
title: '<C-a> in visual block mode does not go past selection',
start: ['9 9 9', '9| 9 9', '9 9 9', '9 9 9', '9 9 9'],
keysPressed: '<C-v>jj3<C-a>',
end: ['9 9 9', '9| 9 9', '9 9 9', '9 9 9', '9 9 9'],
endMode: Mode.Normal,
});
newTest({
title: 'g<C-a> in visual mode',
start: ['9 9 9', '9| 9 9', '9 9 9', '9 9 9', '9 9 9'],
keysPressed: 'vjj3g<C-a>',
end: ['9 9 9', '9| 12 9', '15 9 9', '18 9 9', '9 9 9'],
endMode: Mode.Normal,
});
newTest({
title: 'g<C-a> in visual line mode',
start: ['9 9 9', '9| 9 9', '9 9 9', '9 9 9', '9 9 9'],
keysPressed: 'Vjj3g<C-a>',
end: ['9 9 9', '|12 9 9', '15 9 9', '18 9 9', '9 9 9'],
endMode: Mode.Normal,
});
newTest({
title: 'g<C-a> in visual block mode',
start: ['9 9 9', '9 |9 9', '9 9 9', '9 9 9', '9 9 9'],
keysPressed: '<C-v>jj3g<C-a>',
end: ['9 9 9', '9 |12 9', '9 15 9', '9 18 9', '9 9 9'],
endMode: Mode.Normal,
});
});

View File

@ -1,6 +1,6 @@
import { Configuration } from './testConfiguration';
import { newTest } from './testSimplifier';
import { cleanUpWorkspace, setupWorkspace } from './testUtils';
import { Configuration } from '../testConfiguration';
import { newTest } from '../testSimplifier';
import { cleanUpWorkspace, setupWorkspace } from '../testUtils';
suite('incsearch motion', () => {
suiteSetup(async () => {

162
test/search/search.test.ts Normal file
View File

@ -0,0 +1,162 @@
import { Mode } from '../../src/mode/mode';
import { newTest } from '../testSimplifier';
import { setupWorkspace, cleanUpWorkspace } from '../testUtils';
suite('Search (/ and ?)', () => {
suiteSetup(setupWorkspace);
suiteTeardown(cleanUpWorkspace);
newTest({
title: '/ does not affect mark',
start: ['|one', 'twooo', 'thurr'],
keysPressed: "ma/two\n'a",
end: ['|one', 'twooo', 'thurr'],
});
newTest({
title: '/ can search with regex',
start: ['|', 'one two2o'],
keysPressed: '/o\\do\n',
end: ['', 'one tw|o2o'],
});
newTest({
title: '/ can search with newline',
start: ['|asdf', '__asdf', 'asdf'],
keysPressed: '/\\nasdf\n',
end: ['asdf', '__asd|f', 'asdf'],
});
newTest({
title: '/ can search through multiple newlines',
start: ['|asdf', '__asdf', 'asdf', 'abc', ' abc'],
keysPressed: '/asdf\\nasdf\\nabc\n',
end: ['asdf', '__|asdf', 'asdf', 'abc', ' abc'],
});
newTest({
title: '/ with noignorecase, nosmartcase',
config: { ignorecase: false, smartcase: false },
start: ['bl|ah', 'blAh', 'BLAH', 'blah'],
keysPressed: '/blah\n',
end: ['blah', 'blAh', 'BLAH', '|blah'],
});
newTest({
title: '/ with \\%V will search in last selection',
start: ['', 'asdf', '|asdf', 'asdf', 'asdf'],
keysPressed: 'vjj<Esc>gg/\\%Vasdf\n',
end: ['', 'asdf', '|asdf', 'asdf', 'asdf'],
});
newTest({
title: '/ with \\%V will search in last selection, starting from the cursor postion',
start: ['', 'asdf', '|asdf', '', 'asdf', 'asdf'],
keysPressed: 'vjjj<Esc>kk/\\%Vasdf\nn',
end: ['', 'asdf', '|asdf', '', 'asdf', 'asdf'],
});
newTest({
title: '/ matches ^ per line',
start: ['| asdf', 'asasdf', 'asdf', 'asdf'],
keysPressed: '/^asdf\n',
end: [' asdf', 'asasdf', '|asdf', 'asdf'],
});
newTest({
title: '/ matches $ per line',
start: ['|asdfjkl', 'asdf ', 'asdf', 'asdf'],
keysPressed: '/asdf$\n',
end: ['asdfjkl', 'asdf ', '|asdf', 'asdf'],
});
newTest({
title: '/ search $, walk over matches',
start: ['|start', '', '', 'end'],
keysPressed: '/$\nnnn',
end: ['start', '', '', 'en|d'],
});
newTest({
title: '?, match at EOL, walk over matches',
start: ['x end', 'x', 'x', '|start'],
keysPressed: '?x\nnn',
end: ['|x end', 'x', 'x', 'start'],
});
newTest({
title: 'Search for `(`',
start: ['|one (two) three'],
keysPressed: '/(\n',
end: ['one |(two) three'],
});
/**
* The escaped `/` and `?` the next tests are necessary because otherwise they denote a search offset.
*/
newTest({
title: 'Can search for forward slash',
start: ['|One/two/three/four'],
keysPressed: '/\\/\nn',
end: ['One/two|/three/four'],
});
newTest({
title: 'Can search backward for question mark',
start: ['|One?two?three?four'],
keysPressed: '?\\?\nn',
end: ['One?two|?three?four'],
});
newTest({
title: '/\\c forces case insensitive search',
start: ['|__ASDF', 'asdf'],
keysPressed: '/\\casdf\n',
end: ['__|ASDF', 'asdf'],
});
newTest({
title: '/\\C forces case sensitive search',
start: ['|__ASDF', 'asdf'],
keysPressed: '/\\Casdf\n',
end: ['__ASDF', '|asdf'],
});
newTest({
title: '/\\\\c does not trigger case (in)sensitivity',
start: ['|__\\c__'],
keysPressed: '/\\\\c\n',
end: ['__|\\c__'],
});
newTest({
title: '/\\\\\\c triggers case insensitivity',
start: ['|__\\ASDF', 'asdf'],
keysPressed: '/\\\\\\c\n',
end: ['__|\\ASDF', 'asdf'],
});
newTest({
title: '<C-l> adds the next character in the first match to search term',
start: ['|foo', 'bar', 'abcd'],
keysPressed: '/ab<C-l>d\n',
end: ['foo', 'bar', '|abcd'],
endMode: Mode.Normal,
});
newTest({
title: 'Can delete with search forward',
start: ['foo |junk junk bar'],
keysPressed: 'd/bar\n',
end: ['foo |bar'],
endMode: Mode.Normal,
});
newTest({
title: 'Can delete with search backward',
start: ['foo junk garbage trash |bar'],
keysPressed: 'd?junk\n',
end: ['foo |bar'],
endMode: Mode.Normal,
});
});

View File

@ -0,0 +1,359 @@
import { strict as assert } from 'assert';
import { getAndUpdateModeHandler } from '../../extensionBase';
import { Mode } from '../../src/mode/mode';
import { ModeHandler } from '../../src/mode/modeHandler';
import { newTest } from '../testSimplifier';
import { cleanUpWorkspace, setupWorkspace } from '../testUtils';
suite('Search text objects (gn and gN)', () => {
let modeHandler: ModeHandler;
setup(async () => {
await setupWorkspace();
modeHandler = (await getAndUpdateModeHandler())!;
});
teardown(cleanUpWorkspace);
suite('can handle gn', () => {
test(`gn selects the next match text`, async () => {
await modeHandler.handleMultipleKeyEvents('ifoo\nhello world\nhello\nhello'.split(''));
await modeHandler.handleMultipleKeyEvents(['<Esc>', ...'/hello\n'.split('')]);
await modeHandler.handleMultipleKeyEvents('gg'.split(''));
await modeHandler.handleMultipleKeyEvents(['g', 'n']);
assert.strictEqual(modeHandler.currentMode, Mode.Visual);
const selection = modeHandler.vimState.editor.selection;
assert.strictEqual(selection.start.character, 0);
assert.strictEqual(selection.start.line, 1);
assert.strictEqual(selection.end.character, 'hello'.length);
assert.strictEqual(selection.end.line, 1);
});
const gnSelectsCurrentWord = async (jumpCmd: string) => {
await modeHandler.handleMultipleKeyEvents('ifoo\nhello world\nhello\nhello'.split(''));
await modeHandler.handleMultipleKeyEvents(['<Esc>', ...'/hello\n'.split('')]);
await modeHandler.handleMultipleKeyEvents(jumpCmd.split(''));
await modeHandler.handleMultipleKeyEvents(['g', 'n']);
assert.strictEqual(modeHandler.currentMode, Mode.Visual);
const selection = modeHandler.vimState.editor.selection;
assert.strictEqual(selection.start.character, 0);
assert.strictEqual(selection.start.line, 1);
assert.strictEqual(selection.end.character, 'hello'.length);
assert.strictEqual(selection.end.line, 1);
};
test(`gn selects the current word at |hello`, async () => {
await gnSelectsCurrentWord('2gg');
});
test(`gn selects the current word at h|ello`, async () => {
await gnSelectsCurrentWord('2ggl');
});
test(`gn selects the current word at hel|lo`, async () => {
await gnSelectsCurrentWord('2ggeh');
});
test(`gn selects the current word at hell|o`, async () => {
await gnSelectsCurrentWord('2gge');
});
test(`gn selects the next word at hello|`, async () => {
await modeHandler.handleMultipleKeyEvents('ifoo\nhello world\nhello\nhello'.split(''));
await modeHandler.handleMultipleKeyEvents(['<Esc>', ...'/hello\n'.split('')]);
await modeHandler.handleMultipleKeyEvents('2ggel'.split(''));
await modeHandler.handleMultipleKeyEvents(['g', 'n']);
assert.strictEqual(modeHandler.currentMode, Mode.Visual);
const selection = modeHandler.vimState.editor.selection;
assert.strictEqual(selection.start.character, 0);
assert.strictEqual(selection.start.line, 2);
assert.strictEqual(selection.end.character, 'hello'.length);
assert.strictEqual(selection.end.line, 2);
});
});
suite('can handle dgn', () => {
newTest({
title: 'dgn deletes the next match text (from first line)',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\nggdgn',
end: ['foo', '| world', 'hello', 'hello'],
endMode: Mode.Normal,
});
newTest({
title: 'dgn deletes the current word when cursor is at |hello',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\ndgn',
end: ['foo', '| world', 'hello', 'hello'],
endMode: Mode.Normal,
});
newTest({
title: 'dgn deletes the current word when cursor is at h|ello',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\nldgn',
end: ['foo', '| world', 'hello', 'hello'],
endMode: Mode.Normal,
});
newTest({
title: 'dgn deletes the current word when cursor is at hel|lo',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\n3ldgn',
end: ['foo', '| world', 'hello', 'hello'],
endMode: Mode.Normal,
});
newTest({
title: 'dgn deletes the current word when cursor is at hell|o',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\nedgn',
end: ['foo', '| world', 'hello', 'hello'],
endMode: Mode.Normal,
});
newTest({
title: 'dgn deletes the next word when cursor is at hello|',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\neldgn',
end: ['foo', 'hello world', '|', 'hello'],
endMode: Mode.Normal,
});
newTest({
title: 'dgn with single-character match',
start: ['O|ne Two Three Four Five Six'],
keysPressed: '/T\n' + 'e' + 'dgn',
end: ['One Two |hree Four Five Six'],
endMode: Mode.Normal,
});
});
suite('can handle cgn', () => {
newTest({
title: 'cgn deletes the next match text (from first line)',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\nggcgn',
end: ['foo', '| world', 'hello', 'hello'],
endMode: Mode.Insert,
});
newTest({
title: 'cgn deletes the current word when cursor is at |hello',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\ncgn',
end: ['foo', '| world', 'hello', 'hello'],
endMode: Mode.Insert,
});
newTest({
title: 'cgn deletes the current word when cursor is at h|ello',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\nlcgn',
end: ['foo', '| world', 'hello', 'hello'],
endMode: Mode.Insert,
});
newTest({
title: 'cgn deletes the current word when cursor is at hel|lo',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\n3lcgn',
end: ['foo', '| world', 'hello', 'hello'],
endMode: Mode.Insert,
});
newTest({
title: 'cgn deletes the current word when cursor is at hell|o',
start: ['|foo', 'hello world', 'hello', 'hello'],
keysPressed: '/hello\necgn',
end: ['foo', '| world', 'hello', 'hello'],
endMode: Mode.Insert,
});
newTest({
title: 'cgn with single-character match',
start: ['O|ne Two Three Four Five Six'],
keysPressed: '/T\n' + 'e' + 'cgn',
end: ['One Two |hree Four Five Six'],
endMode: Mode.Insert,
});
newTest({
title: '`cgn` can be repeated by dot',
start: ['|', 'one', 'two', 'one', 'three'],
keysPressed: '/one\n' + 'cgn' + 'XYZ' + '<Esc>' + '..',
end: ['', 'XYZ', 'two', 'XY|Z', 'three'],
endMode: Mode.Normal,
});
});
suite('can handle gN', () => {
test(`gN selects the previous match text`, async () => {
await modeHandler.handleMultipleKeyEvents('ihello world\nhello\nhi hello\nfoo'.split(''));
await modeHandler.handleMultipleKeyEvents(['<Esc>', ...'/hello\n'.split('')]);
await modeHandler.handleMultipleKeyEvents(['G']);
await modeHandler.handleMultipleKeyEvents(['g', 'N']);
assert.strictEqual(modeHandler.currentMode, Mode.Visual);
const selection = modeHandler.vimState.editor.selection;
assert.strictEqual(selection.start.character, 'hi '.length);
assert.strictEqual(selection.start.line, 2);
assert.strictEqual(selection.end.character, 'hi hello'.length);
assert.strictEqual(selection.end.line, 2);
});
const gnSelectsCurrentWord = async (jumpCmd: string) => {
await modeHandler.handleMultipleKeyEvents('ihello world\nhello\nhi hello\nfoo'.split(''));
await modeHandler.handleMultipleKeyEvents(['<Esc>', ...'/hello\n'.split('')]);
await modeHandler.handleMultipleKeyEvents(jumpCmd.split(''));
await modeHandler.handleMultipleKeyEvents(['g', 'N']);
assert.strictEqual(modeHandler.currentMode, Mode.Visual);
const selection = modeHandler.vimState.editor.selection;
assert.strictEqual(selection.start.character, 'hi '.length);
assert.strictEqual(selection.start.line, 2);
assert.strictEqual(selection.end.character, 'hi hello'.length);
assert.strictEqual(selection.end.line, 2);
};
test(`gN selects the current word at hell|o`, async () => {
await gnSelectsCurrentWord('3gg7l');
});
test(`gN selects the current word at hel|lo`, async () => {
await gnSelectsCurrentWord('3gg6l');
});
test(`gN selects the current word at h|ello`, async () => {
await gnSelectsCurrentWord('3gg4l');
});
test(`gN selects the current word at |hello`, async () => {
await gnSelectsCurrentWord('3gg3l');
});
test(`gN selects the previous word at | hello`, async () => {
await modeHandler.handleMultipleKeyEvents('ihello world\nhello\nhi hello\nfoo'.split(''));
await modeHandler.handleMultipleKeyEvents(['<Esc>', ...'/hello\n'.split('')]);
await modeHandler.handleMultipleKeyEvents('3gg2l'.split(''));
await modeHandler.handleMultipleKeyEvents(['g', 'N']);
assert.strictEqual(modeHandler.currentMode, Mode.Visual);
const selection = modeHandler.vimState.editor.selection;
assert.strictEqual(selection.start.character, 0);
assert.strictEqual(selection.start.line, 1);
assert.strictEqual(selection.end.character, 'hello'.length);
assert.strictEqual(selection.end.line, 1);
});
});
suite('can handle dgN', () => {
newTest({
title: 'dgN deletes the previous match text (from first line)',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\nGdgN',
end: ['hello world', 'hello', 'hi| ', 'foo'],
endMode: Mode.Normal,
});
newTest({
title: 'dgN deletes the current word when cursor is at hell|o',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\n3gg$dgN',
end: ['hello world', 'hello', 'hi| ', 'foo'],
endMode: Mode.Normal,
});
newTest({
title: 'dgN deletes the current word when cursor is at hel|lo',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\n3gg$hdgN',
end: ['hello world', 'hello', 'hi| ', 'foo'],
endMode: Mode.Normal,
});
newTest({
title: 'dgN deletes the current word when cursor is at h|ello',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\n3ggwldgN',
end: ['hello world', 'hello', 'hi| ', 'foo'],
endMode: Mode.Normal,
});
newTest({
title: 'dgN deletes the current word when cursor is at |hello',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\n3ggwdgN',
end: ['hello world', 'hello', 'hi| ', 'foo'],
endMode: Mode.Normal,
});
newTest({
title: 'dgN deletes the previous word when cursor is at | hello',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\n3ggwhdgN',
end: ['hello world', '|', 'hi hello', 'foo'],
endMode: Mode.Normal,
});
});
suite('can handle cgN', () => {
newTest({
title: 'cgN deletes the previous match text (from first line)',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\nGcgN',
end: ['hello world', 'hello', 'hi |', 'foo'],
endMode: Mode.Insert,
});
newTest({
title: 'cgN deletes the current word when cursor is at hell|o',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\n3gg$cgN',
end: ['hello world', 'hello', 'hi |', 'foo'],
endMode: Mode.Insert,
});
newTest({
title: 'cgN deletes the current word when cursor is at hel|lo',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\n3gg$hcgN',
end: ['hello world', 'hello', 'hi |', 'foo'],
endMode: Mode.Insert,
});
newTest({
title: 'cgN deletes the current word when cursor is at h|ello',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\n3ggwlcgN',
end: ['hello world', 'hello', 'hi |', 'foo'],
endMode: Mode.Insert,
});
newTest({
title: 'cgN deletes the current word when cursor is at |hello',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\n3ggwcgN',
end: ['hello world', 'hello', 'hi |', 'foo'],
endMode: Mode.Insert,
});
newTest({
title: 'cgN deletes the previous word when cursor is at | hello',
start: ['hello world', 'hello', 'hi hello', '|foo'],
keysPressed: '/hello\n3ggwhcgN',
end: ['hello world', '|', 'hi hello', 'foo'],
endMode: Mode.Insert,
});
});
});