mirror of
https://github.com/VSCodeVim/Vim.git
synced 2024-09-11 12:25:59 +03:00
Pull some tests out of extremely bloated modeNormal.test.ts
into dedicated files
This commit is contained in:
parent
15cb5ecde6
commit
e38d60b6af
@ -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'],
|
||||
|
281
test/number/incrementDecrement.test.ts
Normal file
281
test/number/incrementDecrement.test.ts
Normal 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,
|
||||
});
|
||||
});
|
@ -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
162
test/search/search.test.ts
Normal 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,
|
||||
});
|
||||
});
|
359
test/search/searchTextObject.test.ts
Normal file
359
test/search/searchTextObject.test.ts
Normal 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,
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user