mirror of
https://github.com/coderaiser/cloudcmd.git
synced 2026-01-23 10:45:47 +00:00
feature(vim) add find support with: "/", "n" and "N"
This commit is contained in:
parent
3693f6f799
commit
2edf7f8321
7 changed files with 269 additions and 29 deletions
3
HELP.md
3
HELP.md
|
|
@ -191,6 +191,9 @@ When `--vim` option provided, or configuration parameter `vim` set, next hot key
|
|||
| `y` | copy (selected in visual mode files)
|
||||
| `p` | paste files
|
||||
| `Esc` | unselect all
|
||||
| `/` | find file in current directory
|
||||
| `n` | navigate to next found file
|
||||
| `N` | navigate to previous found file
|
||||
|
||||
Commands can be joined, for example:
|
||||
- `5j` will navigate `5` files below current;
|
||||
|
|
|
|||
53
client/key/vim/find.js
Normal file
53
client/key/vim/find.js
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
'use strict';
|
||||
/* global DOM */
|
||||
|
||||
const fullstore = require('fullstore');
|
||||
const limier = require('limier');
|
||||
const Info = DOM.CurrentInfo;
|
||||
|
||||
const searchStore = fullstore([]);
|
||||
const searchIndex = fullstore(0);
|
||||
|
||||
module.exports.find = (value) => {
|
||||
const names = Info.files.map(DOM.getCurrentName);
|
||||
const result = limier(value, names);
|
||||
|
||||
searchStore(result);
|
||||
searchIndex(0);
|
||||
|
||||
DOM.setCurrentByName(result[0]);
|
||||
};
|
||||
|
||||
module.exports.findNext = () => {
|
||||
const names = searchStore();
|
||||
const index = next(searchIndex(), names.length);
|
||||
|
||||
searchIndex(index);
|
||||
DOM.setCurrentByName(names[searchIndex()]);
|
||||
};
|
||||
|
||||
module.exports.findPrevious = () => {
|
||||
const names = searchStore();
|
||||
const index = previous(searchIndex(), names.length);
|
||||
|
||||
searchIndex(index);
|
||||
DOM.setCurrentByName(names[index]);
|
||||
};
|
||||
|
||||
module.exports._next = next;
|
||||
module.exports._previous = previous;
|
||||
|
||||
function next(index, length) {
|
||||
if (index === length - 1)
|
||||
return 0;
|
||||
|
||||
return ++index;
|
||||
}
|
||||
|
||||
function previous(index, length) {
|
||||
if (!index)
|
||||
return length - 1;
|
||||
|
||||
return --index;
|
||||
}
|
||||
|
||||
|
|
@ -1,12 +1,20 @@
|
|||
'use strict';
|
||||
/* global CloudCmd, DOM */
|
||||
|
||||
const KEY = require('../key');
|
||||
const Info = DOM.CurrentInfo;
|
||||
const KEY = require('./key');
|
||||
const Dialog = DOM.Dialog;
|
||||
|
||||
const fullstore = require('fullstore/legacy');
|
||||
const store = fullstore('');
|
||||
const visual = fullstore(false);
|
||||
const {
|
||||
find,
|
||||
findNext,
|
||||
findPrevious,
|
||||
} = require('./find');
|
||||
|
||||
const TITLE = 'Cloud Commander';
|
||||
|
||||
const stopVisual = () => {
|
||||
visual(false);
|
||||
|
|
@ -104,6 +112,25 @@ module.exports = (key, event) => {
|
|||
|
||||
return end();
|
||||
}
|
||||
|
||||
if (key === '/') {
|
||||
event.preventDefault();
|
||||
|
||||
Dialog.prompt(TITLE, 'Find', '', {cancel: false})
|
||||
.then(find);
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
if (key === 'n') {
|
||||
findNext();
|
||||
return end();
|
||||
}
|
||||
|
||||
if (key === 'N') {
|
||||
findPrevious();
|
||||
return end();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.selectFile = selectFile;
|
||||
|
|
@ -202,7 +202,8 @@
|
|||
"version-io": "^2.0.1",
|
||||
"webpack": "^3.0.0",
|
||||
"wraptile": "^1.0.0",
|
||||
"yaspeller": "^4.0.0"
|
||||
"yaspeller": "^4.0.0",
|
||||
"limier": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
|
|
|
|||
79
test/client/key/vim/find.js
Normal file
79
test/client/key/vim/find.js
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
'use strict';
|
||||
|
||||
const test = require('tape');
|
||||
const diff = require('sinon-called-with-diff');
|
||||
const sinon = diff(require('sinon'));
|
||||
const dir = '../../../../client/key/vim/';
|
||||
|
||||
const {
|
||||
getDOM,
|
||||
getCloudCmd,
|
||||
} = require('./globals');
|
||||
|
||||
global.DOM = global.DOM || getDOM();
|
||||
global.CloudCmd = global.CloudCmd || getCloudCmd();
|
||||
|
||||
const DOM = global.DOM
|
||||
const CloudCmd = global.CloudCmd;
|
||||
|
||||
const {
|
||||
find,
|
||||
findNext,
|
||||
findPrevious,
|
||||
_next,
|
||||
_previous,
|
||||
} = require(dir + 'find');
|
||||
|
||||
test('cloudcmd: client: vim: find', (t) => {
|
||||
const setCurrentByName = sinon.stub();
|
||||
DOM.setCurrentByName = setCurrentByName;
|
||||
DOM.Dialog.prompt = Promise.resolve.bind(Promise);
|
||||
|
||||
find('');
|
||||
|
||||
t.ok(setCurrentByName.calledWith(), 'should call setCurrentByName');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: vim: findNext', (t) => {
|
||||
const setCurrentByName = sinon.stub();
|
||||
DOM.setCurrentByName = setCurrentByName;
|
||||
|
||||
findNext();
|
||||
|
||||
t.ok(setCurrentByName.calledWith(), 'should call setCurrentByName');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: vim: findPrevious', (t) => {
|
||||
const setCurrentByName = sinon.stub();
|
||||
DOM.setCurrentByName = setCurrentByName;
|
||||
|
||||
findPrevious();
|
||||
|
||||
t.ok(setCurrentByName.calledWith(), 'should call setCurrentByName');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: vim: _next', (t) => {
|
||||
const result = _next(1, 2)
|
||||
|
||||
t.notOk(result, 'should return 0');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: vim: _previous', (t) => {
|
||||
const result = _previous(0, 2)
|
||||
|
||||
t.equal(result, 1, 'should return 1');
|
||||
t.end();
|
||||
});
|
||||
|
||||
function clean(path) {
|
||||
delete require.cache[require.resolve(path)];
|
||||
}
|
||||
|
||||
function stub(name, fn) {
|
||||
require.cache[require.resolve(name)].exports = fn;
|
||||
}
|
||||
|
||||
43
test/client/key/vim/globals.js
Normal file
43
test/client/key/vim/globals.js
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
'use strict';
|
||||
|
||||
module.exports.getDOM = () => {
|
||||
const resolve = Promise.resolve.bind(Promise);
|
||||
const CurrentInfo = {
|
||||
element: {},
|
||||
files: [],
|
||||
};
|
||||
|
||||
const noop = () => {};
|
||||
const Buffer = {
|
||||
copy: noop,
|
||||
paste: noop,
|
||||
};
|
||||
|
||||
const Dialog = {
|
||||
prompt: resolve
|
||||
};
|
||||
|
||||
return {
|
||||
Buffer,
|
||||
CurrentInfo,
|
||||
Dialog,
|
||||
selectFile: noop,
|
||||
unselectFile: noop,
|
||||
unselectFiles: noop,
|
||||
setCurrentFile: noop,
|
||||
getCurrentName: noop,
|
||||
setCurrentByName: noop,
|
||||
toggleSelectedFile: noop,
|
||||
};
|
||||
};
|
||||
|
||||
module.exports.getCloudCmd = () => {
|
||||
const show = () => {};
|
||||
|
||||
return {
|
||||
Operation: {
|
||||
show
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -3,10 +3,16 @@
|
|||
const test = require('tape');
|
||||
const diff = require('sinon-called-with-diff');
|
||||
const sinon = diff(require('sinon'));
|
||||
const dir = '../../../client/key/';
|
||||
const dir = '../../../../client/key/';
|
||||
const KEY = require(dir + 'key');
|
||||
|
||||
initGlobals();
|
||||
const {
|
||||
getDOM,
|
||||
getCloudCmd,
|
||||
} = require('./globals');
|
||||
|
||||
global.DOM = global.DOM || getDOM();
|
||||
global.CloudCmd = global.CloudCmd || getCloudCmd();
|
||||
|
||||
const DOM = global.DOM;
|
||||
const Buffer = DOM.Buffer;
|
||||
|
|
@ -349,8 +355,8 @@ test('cloudcmd: client: key: Enter', (t) => {
|
|||
|
||||
const setCurrentFile = sinon.stub();
|
||||
|
||||
global.DOM.CurrentInfo.element = element;
|
||||
global.DOM.setCurrentFile = setCurrentFile;
|
||||
DOM.CurrentInfo.element = element;
|
||||
DOM.setCurrentFile = setCurrentFile;
|
||||
|
||||
vim('', {
|
||||
keyCode: KEY.ENTER
|
||||
|
|
@ -363,32 +369,60 @@ test('cloudcmd: client: key: Enter', (t) => {
|
|||
t.end();
|
||||
});
|
||||
|
||||
function initGlobals() {
|
||||
const CurrentInfo = {
|
||||
element: {},
|
||||
};
|
||||
test('cloudcmd: client: key: /', (t) => {
|
||||
const preventDefault = sinon.stub();
|
||||
const element = {};
|
||||
|
||||
const noop = () => {};
|
||||
const Buffer = {
|
||||
copy: noop,
|
||||
};
|
||||
DOM.CurrentInfo.element = element;
|
||||
DOM.getCurrentName = () => '';
|
||||
|
||||
global.DOM = {
|
||||
Buffer,
|
||||
CurrentInfo,
|
||||
selectFile: noop,
|
||||
unselectFile: noop,
|
||||
unselectFiles: noop,
|
||||
setCurrentFile: noop,
|
||||
toggleSelectedFile: noop,
|
||||
};
|
||||
vim('/', {
|
||||
preventDefault
|
||||
});
|
||||
|
||||
const show = () => {};
|
||||
t.ok(preventDefault.calledWith(), 'should call preventDefault');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: n', (t) => {
|
||||
const findNext = sinon.stub();
|
||||
|
||||
global.CloudCmd = {
|
||||
Operation: {
|
||||
show
|
||||
}
|
||||
};
|
||||
clean(dir + 'vim');
|
||||
stub(dir + 'vim/find', {
|
||||
findNext
|
||||
});
|
||||
|
||||
const vim = require(dir + 'vim');
|
||||
const event = {};
|
||||
|
||||
vim('n', event);
|
||||
|
||||
t.ok(findNext.calledWith(), 'should call findNext');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: N', (t) => {
|
||||
const findPrevious = sinon.stub();
|
||||
|
||||
clean(dir + 'vim');
|
||||
stub(dir + 'vim/find', {
|
||||
findPrevious,
|
||||
});
|
||||
|
||||
const vim = require(dir + 'vim');
|
||||
const event = {};
|
||||
|
||||
vim('N', event);
|
||||
|
||||
t.ok(findPrevious.calledWith(), 'should call findPrevious');
|
||||
t.end();
|
||||
});
|
||||
|
||||
function clean(path) {
|
||||
delete require.cache[require.resolve(path)];
|
||||
}
|
||||
|
||||
function stub(name, fn) {
|
||||
require.cache[require.resolve(name)].exports = fn;
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue