Skip to content

Commit 2edf7f8

Browse files
committed
feature(vim) add find support with: "/", "n" and "N"
1 parent 3693f6f commit 2edf7f8

File tree

7 files changed

+269
-29
lines changed

7 files changed

+269
-29
lines changed

HELP.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@ When `--vim` option provided, or configuration parameter `vim` set, next hot key
191191
| `y` | copy (selected in visual mode files)
192192
| `p` | paste files
193193
| `Esc` | unselect all
194+
| `/` | find file in current directory
195+
| `n` | navigate to next found file
196+
| `N` | navigate to previous found file
194197

195198
Commands can be joined, for example:
196199
- `5j` will navigate `5` files below current;

client/key/vim/find.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
'use strict';
2+
/* global DOM */
3+
4+
const fullstore = require('fullstore');
5+
const limier = require('limier');
6+
const Info = DOM.CurrentInfo;
7+
8+
const searchStore = fullstore([]);
9+
const searchIndex = fullstore(0);
10+
11+
module.exports.find = (value) => {
12+
const names = Info.files.map(DOM.getCurrentName);
13+
const result = limier(value, names);
14+
15+
searchStore(result);
16+
searchIndex(0);
17+
18+
DOM.setCurrentByName(result[0]);
19+
};
20+
21+
module.exports.findNext = () => {
22+
const names = searchStore();
23+
const index = next(searchIndex(), names.length);
24+
25+
searchIndex(index);
26+
DOM.setCurrentByName(names[searchIndex()]);
27+
};
28+
29+
module.exports.findPrevious = () => {
30+
const names = searchStore();
31+
const index = previous(searchIndex(), names.length);
32+
33+
searchIndex(index);
34+
DOM.setCurrentByName(names[index]);
35+
};
36+
37+
module.exports._next = next;
38+
module.exports._previous = previous;
39+
40+
function next(index, length) {
41+
if (index === length - 1)
42+
return 0;
43+
44+
return ++index;
45+
}
46+
47+
function previous(index, length) {
48+
if (!index)
49+
return length - 1;
50+
51+
return --index;
52+
}
53+

client/key/vim.js renamed to client/key/vim/index.js

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
'use strict';
22
/* global CloudCmd, DOM */
33

4+
const KEY = require('../key');
45
const Info = DOM.CurrentInfo;
5-
const KEY = require('./key');
6+
const Dialog = DOM.Dialog;
67

78
const fullstore = require('fullstore/legacy');
89
const store = fullstore('');
910
const visual = fullstore(false);
11+
const {
12+
find,
13+
findNext,
14+
findPrevious,
15+
} = require('./find');
16+
17+
const TITLE = 'Cloud Commander';
1018

1119
const stopVisual = () => {
1220
visual(false);
@@ -104,6 +112,25 @@ module.exports = (key, event) => {
104112

105113
return end();
106114
}
115+
116+
if (key === '/') {
117+
event.preventDefault();
118+
119+
Dialog.prompt(TITLE, 'Find', '', {cancel: false})
120+
.then(find);
121+
122+
return end();
123+
}
124+
125+
if (key === 'n') {
126+
findNext();
127+
return end();
128+
}
129+
130+
if (key === 'N') {
131+
findPrevious();
132+
return end();
133+
}
107134
};
108135

109136
module.exports.selectFile = selectFile;

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,8 @@
202202
"version-io": "^2.0.1",
203203
"webpack": "^3.0.0",
204204
"wraptile": "^1.0.0",
205-
"yaspeller": "^4.0.0"
205+
"yaspeller": "^4.0.0",
206+
"limier": "^1.0.1"
206207
},
207208
"engines": {
208209
"node": ">=4.0.0"

test/client/key/vim/find.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
'use strict';
2+
3+
const test = require('tape');
4+
const diff = require('sinon-called-with-diff');
5+
const sinon = diff(require('sinon'));
6+
const dir = '../../../../client/key/vim/';
7+
8+
const {
9+
getDOM,
10+
getCloudCmd,
11+
} = require('./globals');
12+
13+
global.DOM = global.DOM || getDOM();
14+
global.CloudCmd = global.CloudCmd || getCloudCmd();
15+
16+
const DOM = global.DOM
17+
const CloudCmd = global.CloudCmd;
18+
19+
const {
20+
find,
21+
findNext,
22+
findPrevious,
23+
_next,
24+
_previous,
25+
} = require(dir + 'find');
26+
27+
test('cloudcmd: client: vim: find', (t) => {
28+
const setCurrentByName = sinon.stub();
29+
DOM.setCurrentByName = setCurrentByName;
30+
DOM.Dialog.prompt = Promise.resolve.bind(Promise);
31+
32+
find('');
33+
34+
t.ok(setCurrentByName.calledWith(), 'should call setCurrentByName');
35+
t.end();
36+
});
37+
38+
test('cloudcmd: client: vim: findNext', (t) => {
39+
const setCurrentByName = sinon.stub();
40+
DOM.setCurrentByName = setCurrentByName;
41+
42+
findNext();
43+
44+
t.ok(setCurrentByName.calledWith(), 'should call setCurrentByName');
45+
t.end();
46+
});
47+
48+
test('cloudcmd: client: vim: findPrevious', (t) => {
49+
const setCurrentByName = sinon.stub();
50+
DOM.setCurrentByName = setCurrentByName;
51+
52+
findPrevious();
53+
54+
t.ok(setCurrentByName.calledWith(), 'should call setCurrentByName');
55+
t.end();
56+
});
57+
58+
test('cloudcmd: client: vim: _next', (t) => {
59+
const result = _next(1, 2)
60+
61+
t.notOk(result, 'should return 0');
62+
t.end();
63+
});
64+
65+
test('cloudcmd: client: vim: _previous', (t) => {
66+
const result = _previous(0, 2)
67+
68+
t.equal(result, 1, 'should return 1');
69+
t.end();
70+
});
71+
72+
function clean(path) {
73+
delete require.cache[require.resolve(path)];
74+
}
75+
76+
function stub(name, fn) {
77+
require.cache[require.resolve(name)].exports = fn;
78+
}
79+

test/client/key/vim/globals.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
'use strict';
2+
3+
module.exports.getDOM = () => {
4+
const resolve = Promise.resolve.bind(Promise);
5+
const CurrentInfo = {
6+
element: {},
7+
files: [],
8+
};
9+
10+
const noop = () => {};
11+
const Buffer = {
12+
copy: noop,
13+
paste: noop,
14+
};
15+
16+
const Dialog = {
17+
prompt: resolve
18+
};
19+
20+
return {
21+
Buffer,
22+
CurrentInfo,
23+
Dialog,
24+
selectFile: noop,
25+
unselectFile: noop,
26+
unselectFiles: noop,
27+
setCurrentFile: noop,
28+
getCurrentName: noop,
29+
setCurrentByName: noop,
30+
toggleSelectedFile: noop,
31+
};
32+
};
33+
34+
module.exports.getCloudCmd = () => {
35+
const show = () => {};
36+
37+
return {
38+
Operation: {
39+
show
40+
}
41+
};
42+
};
43+

test/client/key/vim.js renamed to test/client/key/vim/index.js

Lines changed: 61 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,16 @@
33
const test = require('tape');
44
const diff = require('sinon-called-with-diff');
55
const sinon = diff(require('sinon'));
6-
const dir = '../../../client/key/';
6+
const dir = '../../../../client/key/';
77
const KEY = require(dir + 'key');
88

9-
initGlobals();
9+
const {
10+
getDOM,
11+
getCloudCmd,
12+
} = require('./globals');
13+
14+
global.DOM = global.DOM || getDOM();
15+
global.CloudCmd = global.CloudCmd || getCloudCmd();
1016

1117
const DOM = global.DOM;
1218
const Buffer = DOM.Buffer;
@@ -349,8 +355,8 @@ test('cloudcmd: client: key: Enter', (t) => {
349355

350356
const setCurrentFile = sinon.stub();
351357

352-
global.DOM.CurrentInfo.element = element;
353-
global.DOM.setCurrentFile = setCurrentFile;
358+
DOM.CurrentInfo.element = element;
359+
DOM.setCurrentFile = setCurrentFile;
354360

355361
vim('', {
356362
keyCode: KEY.ENTER
@@ -363,32 +369,60 @@ test('cloudcmd: client: key: Enter', (t) => {
363369
t.end();
364370
});
365371

366-
function initGlobals() {
367-
const CurrentInfo = {
368-
element: {},
369-
};
372+
test('cloudcmd: client: key: /', (t) => {
373+
const preventDefault = sinon.stub();
374+
const element = {};
370375

371-
const noop = () => {};
372-
const Buffer = {
373-
copy: noop,
374-
};
376+
DOM.CurrentInfo.element = element;
377+
DOM.getCurrentName = () => '';
375378

376-
global.DOM = {
377-
Buffer,
378-
CurrentInfo,
379-
selectFile: noop,
380-
unselectFile: noop,
381-
unselectFiles: noop,
382-
setCurrentFile: noop,
383-
toggleSelectedFile: noop,
384-
};
379+
vim('/', {
380+
preventDefault
381+
});
385382

386-
const show = () => {};
383+
t.ok(preventDefault.calledWith(), 'should call preventDefault');
384+
t.end();
385+
});
386+
387+
test('cloudcmd: client: key: n', (t) => {
388+
const findNext = sinon.stub();
387389

388-
global.CloudCmd = {
389-
Operation: {
390-
show
391-
}
392-
};
390+
clean(dir + 'vim');
391+
stub(dir + 'vim/find', {
392+
findNext
393+
});
394+
395+
const vim = require(dir + 'vim');
396+
const event = {};
397+
398+
vim('n', event);
399+
400+
t.ok(findNext.calledWith(), 'should call findNext');
401+
t.end();
402+
});
403+
404+
test('cloudcmd: client: key: N', (t) => {
405+
const findPrevious = sinon.stub();
406+
407+
clean(dir + 'vim');
408+
stub(dir + 'vim/find', {
409+
findPrevious,
410+
});
411+
412+
const vim = require(dir + 'vim');
413+
const event = {};
414+
415+
vim('N', event);
416+
417+
t.ok(findPrevious.calledWith(), 'should call findPrevious');
418+
t.end();
419+
});
420+
421+
function clean(path) {
422+
delete require.cache[require.resolve(path)];
423+
}
424+
425+
function stub(name, fn) {
426+
require.cache[require.resolve(name)].exports = fn;
393427
}
394428

0 commit comments

Comments
 (0)