mirror of
https://github.com/coderaiser/cloudcmd.git
synced 2026-01-23 02:35:49 +00:00
feature(vim) add hot keys
This commit is contained in:
parent
dc79ab4a25
commit
324022743b
13 changed files with 649 additions and 21 deletions
28
HELP.md
28
HELP.md
|
|
@ -89,18 +89,20 @@ Cloud Commander supports command line parameters:
|
|||
| `--console` | enable console
|
||||
| `--terminal` | enable terminal
|
||||
| `--terminal-path` | set terminal path
|
||||
| `--vim` | enable vim hot keys
|
||||
| `--no-server` | do not start server
|
||||
| `--no-auth` | disable authorization
|
||||
| `--no-online` | load scripts from local server
|
||||
| `--no-open` | do not open web browser when server started
|
||||
| `--no-name` | set empty tab name in web browser
|
||||
| `--no-one-panel-mode` | unset one panel mode
|
||||
| `--no-progress` | do not show progress of file operations
|
||||
| `--no-html-dialogs` | do not use html dialogs
|
||||
| `--no-one-panel-mode` | unset one panel mode
|
||||
| `--no-contact` | disable contact
|
||||
| `--no-config-dialog` | disable config dialog
|
||||
| `--no-console` | disable console
|
||||
| `--no-terminal` | disable terminal
|
||||
| `--no-name` | set empty tab name in web browser
|
||||
| `--no-vim` | disable vim hot keys
|
||||
|
||||
|
||||
If no parameters given Cloud Commander reads information from `~/.cloudcmd.json` and use
|
||||
|
|
@ -174,6 +176,27 @@ Hot keys
|
|||
| `~` | console
|
||||
| `Ctrl + Click` | open file on new tab
|
||||
|
||||
### Vim
|
||||
|
||||
When `--vim` option provided, or configuration parameter `vim` set, next hot keys become available:
|
||||
|
||||
|Key |Operation
|
||||
|:----------------------|:--------------------------------------------
|
||||
| `j` | navigate to next file
|
||||
| `k` | navigate to previous file
|
||||
| `dd` | remove current file
|
||||
| `G` | navigate to bottom file
|
||||
| `gg` | navigate to top file
|
||||
| `v` | visual mode
|
||||
| `y` | copy (selected in visual mode files)
|
||||
| `p` | paste files
|
||||
| `Esc` | unselect all
|
||||
|
||||
Commands can be joined, for example:
|
||||
- `5j` will navigate `5` files below current;
|
||||
- `d5j` will remove next `5` files;
|
||||
- `dG` will remove all files from current to bottom;
|
||||
|
||||
View
|
||||
---------------
|
||||

|
||||
|
|
@ -333,6 +356,7 @@ Here is description of options:
|
|||
"console" : true, /* enable console */
|
||||
"terminal" : false, /* disable terminal */
|
||||
"terminalPath" : '', /* path of a terminal */
|
||||
"vim" : false, /* disable vim hot keys */
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -533,6 +533,14 @@ function CmdProto() {
|
|||
return Cmd;
|
||||
};
|
||||
|
||||
this.unselectFile = (currentFile) => {
|
||||
const current = currentFile || DOM.getCurrentFile();
|
||||
|
||||
current.classList.remove(SELECTED_FILE);
|
||||
|
||||
return Cmd;
|
||||
};
|
||||
|
||||
this.toggleSelectedFile = (currentFile) => {
|
||||
const current = currentFile || DOM.getCurrentFile();
|
||||
const name = DOM.getCurrentName(current);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ const exec = require('execon');
|
|||
const Events = require('../dom/events');
|
||||
const Buffer = require('../dom/buffer');
|
||||
const KEY = require('./key');
|
||||
const vim = require('./vim');
|
||||
const setCurrentByChar = require('./set-current-by-char');
|
||||
const fullstore = require('fullstore/legacy');
|
||||
const Chars = fullstore();
|
||||
|
|
@ -71,15 +72,19 @@ function KeyProto() {
|
|||
char = isSymbol;
|
||||
}
|
||||
|
||||
/* in case buttons can be processed */
|
||||
if (!Key.isBind())
|
||||
return;
|
||||
|
||||
if (!isNumpad && !alt && !ctrl && !meta && (isBetween || isSymbol))
|
||||
const isVim = CloudCmd.config('vim');
|
||||
|
||||
if (!isVim && !isNumpad && !alt && !ctrl && !meta && (isBetween || isSymbol))
|
||||
return setCurrentByChar(char, Chars);
|
||||
|
||||
Chars([]);
|
||||
switchKey(event);
|
||||
|
||||
if (isVim)
|
||||
vim(char, event);
|
||||
}
|
||||
|
||||
function getSymbol(shift, keyCode) {
|
||||
|
|
@ -106,6 +111,8 @@ function KeyProto() {
|
|||
function switchKey(event) {
|
||||
let i, isSelected, prev, next;
|
||||
let current = Info.element;
|
||||
let dataName;
|
||||
|
||||
const name = Info.name;
|
||||
|
||||
const {Operation} = CloudCmd;
|
||||
|
|
@ -301,9 +308,9 @@ function KeyProto() {
|
|||
|
||||
event.preventDefault();
|
||||
|
||||
const attr = Info.panel.getAttribute('data-name');
|
||||
dataName = Info.panel.getAttribute('data-name');
|
||||
|
||||
if (attr === 'js-right')
|
||||
if (dataName === 'js-right')
|
||||
DOM.duplicatePanel();
|
||||
|
||||
break;
|
||||
|
|
@ -314,9 +321,9 @@ function KeyProto() {
|
|||
|
||||
event.preventDefault();
|
||||
|
||||
name = Info.panel.getAttribute('data-name');
|
||||
dataName = Info.panel.getAttribute('data-name');
|
||||
|
||||
if (name === 'js-left')
|
||||
if (dataName === 'js-left')
|
||||
DOM.duplicatePanel();
|
||||
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
BACKSPACE : 8,
|
||||
TAB : 9,
|
||||
|
|
@ -20,6 +22,10 @@ module.exports = {
|
|||
|
||||
ZERO : 48,
|
||||
|
||||
SEMICOLON : 52,
|
||||
|
||||
COLON : 54,
|
||||
|
||||
A : 65,
|
||||
|
||||
C : 67,
|
||||
|
|
@ -27,6 +33,9 @@ module.exports = {
|
|||
|
||||
G : 71,
|
||||
|
||||
J : 74,
|
||||
K : 75,
|
||||
|
||||
M : 77,
|
||||
|
||||
O : 79,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
'use strict';
|
||||
|
||||
const Info = DOM.CurrentInfo;
|
||||
|
||||
const {escapeRegExp} = require('../../common/util');
|
||||
|
||||
module.exports = function setCurrentByChar(char, charStore) {
|
||||
|
|
@ -56,5 +55,5 @@ module.exports = function setCurrentByChar(char, charStore) {
|
|||
DOM.setCurrentFile(firstByName);
|
||||
charStore([char]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
172
client/key/vim.js
Normal file
172
client/key/vim.js
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
'use strict';
|
||||
/* global CloudCmd, DOM */
|
||||
|
||||
const Info = DOM.CurrentInfo;
|
||||
const KEY = require('./key');
|
||||
|
||||
const fullstore = require('fullstore/legacy');
|
||||
const store = fullstore('');
|
||||
const visual = fullstore(false);
|
||||
|
||||
const stopVisual = () => {
|
||||
visual(false);
|
||||
};
|
||||
|
||||
const end = () => {
|
||||
store('');
|
||||
};
|
||||
|
||||
const rmFirst = (a) => {
|
||||
return a
|
||||
.split('')
|
||||
.slice(1)
|
||||
.join('');
|
||||
};
|
||||
|
||||
module.exports = (key, event) => {
|
||||
const current = Info.element;
|
||||
const keyCode = event.keyCode;
|
||||
const prevStore = store();
|
||||
|
||||
const value = store(prevStore.concat(key));
|
||||
|
||||
if (keyCode === KEY.ENTER)
|
||||
return end();
|
||||
|
||||
if (keyCode === KEY.ESC) {
|
||||
DOM.unselectFiles();
|
||||
visual(false);
|
||||
return end();
|
||||
}
|
||||
|
||||
if (key === 'j') {
|
||||
move('next', {
|
||||
prevStore,
|
||||
current,
|
||||
});
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
if (key === 'k') {
|
||||
move('previous', {
|
||||
prevStore,
|
||||
current,
|
||||
});
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
if (/gg/.test(value)) {
|
||||
move('previous', {
|
||||
current,
|
||||
prevStore,
|
||||
max: Infinity,
|
||||
});
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
if (key === 'd' && (visual() || prevStore === 'd')) {
|
||||
CloudCmd.Operation.show('delete');
|
||||
stopVisual();
|
||||
return end();
|
||||
}
|
||||
|
||||
if (key === 'G') {
|
||||
move('next', {
|
||||
current,
|
||||
prevStore,
|
||||
max: Infinity,
|
||||
});
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
if (key === 'y') {
|
||||
if (!visual())
|
||||
return end();
|
||||
|
||||
DOM.Buffer.copy();
|
||||
stopVisual();
|
||||
DOM.unselectFiles();
|
||||
return end();
|
||||
}
|
||||
|
||||
if (/^p$/i.test(key)) {
|
||||
DOM.Buffer.paste();
|
||||
return end();
|
||||
}
|
||||
|
||||
if (/^v$/i.test(key)) {
|
||||
DOM.toggleSelectedFile(current);
|
||||
visual(!visual());
|
||||
|
||||
return end();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.selectFile = selectFile;
|
||||
|
||||
function move(sibling, {max, current, prevStore}) {
|
||||
const isDelete = prevStore[0] === 'd';
|
||||
|
||||
if (isDelete) {
|
||||
visual(true);
|
||||
prevStore = rmFirst(prevStore);
|
||||
}
|
||||
|
||||
const n = max || getNumber(prevStore);
|
||||
|
||||
if (isNaN(n))
|
||||
return;
|
||||
|
||||
setCurrent({
|
||||
n,
|
||||
current,
|
||||
sibling,
|
||||
visual: visual(),
|
||||
});
|
||||
|
||||
if (isDelete)
|
||||
CloudCmd.Operation.show('delete');
|
||||
}
|
||||
|
||||
function getNumber(value) {
|
||||
if (!value)
|
||||
return 1;
|
||||
|
||||
if (value === 'g')
|
||||
return 1;
|
||||
|
||||
return parseInt(value);
|
||||
}
|
||||
|
||||
function selectFile(current) {
|
||||
const name = DOM.getCurrentName(current);
|
||||
|
||||
if (name === '..')
|
||||
return;
|
||||
|
||||
DOM.selectFile(current);
|
||||
}
|
||||
|
||||
function setCurrent({n, current, visual, sibling}) {
|
||||
const select = visual ? selectFile : DOM.unselectFile;
|
||||
|
||||
select(current);
|
||||
|
||||
const position = `${sibling}Sibling`;
|
||||
for (let i = 0; i < n; i++) {
|
||||
const next = current[position];
|
||||
|
||||
if (!next)
|
||||
break;
|
||||
|
||||
current = next;
|
||||
select(current);
|
||||
}
|
||||
|
||||
DOM.setCurrentFile(current);
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 229 KiB After Width: | Height: | Size: 228 KiB |
|
|
@ -27,6 +27,7 @@
|
|||
"console": true,
|
||||
"terminal": false,
|
||||
"terminalPath": "",
|
||||
"showConfig": "false"
|
||||
"showConfig": "false",
|
||||
"vim": "true"
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,24 +15,26 @@
|
|||
"--port ": "set port number",
|
||||
"--progress ": "show progress of file operations",
|
||||
"--html-dialogs ": "use html dialogs",
|
||||
"--open ": "open web browser when server started",
|
||||
"--name ": "set tab name in web browser",
|
||||
"--one-panel-mode ": "set one panel mode",
|
||||
"--config-dialog ": "enable config dialog",
|
||||
"--console ": "enable console",
|
||||
"--contact ": "enable contact",
|
||||
"--terminal ": "enable terminal",
|
||||
"--terminal-path ": "set terminal path",
|
||||
"--open ": "open web browser when server started",
|
||||
"--name ": "set tab name in web browser",
|
||||
"--vim ": "enable vim hot keys",
|
||||
"--no-server ": "do not start server",
|
||||
"--no-auth ": "disable authorization",
|
||||
"--no-online ": "load scripts from local server",
|
||||
"--no-open ": "do not open web browser when server started",
|
||||
"--no-name ": "set default tab name in web browser",
|
||||
"--no-one-panel-mode ": "unset one panel mode",
|
||||
"--no-progress ": "do not show progress of file operations",
|
||||
"--no-html-dialogs ": "do not use html dialogs",
|
||||
"--no-one-panel-mode ": "unset one panel mode",
|
||||
"--no-config-dialog ": "disable config dialog",
|
||||
"--no-console ": "disable console",
|
||||
"--no-contact ": "disable contact",
|
||||
"--no-terminal ": "disable terminal",
|
||||
"--no-name ": "set default tab name in web browser"
|
||||
"--no-vim ": "disable vim hot keys"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,26 +38,28 @@ programs in browser from any computer, mobile or tablet device.
|
|||
--port set port number
|
||||
--progress show progress of file operations
|
||||
--html-dialogs use html dialogs
|
||||
--open open web browser when server started
|
||||
--name set tab name in web browser
|
||||
--one-panel-mode set one panel mode
|
||||
--contact enable contact
|
||||
--config-dialog enable config dialog
|
||||
--console enable console
|
||||
--terminal enable terminal
|
||||
--terminal-path set terminal path
|
||||
--open open web browser when server started
|
||||
--name set tab name in web browser
|
||||
--vim enable vim hot keys
|
||||
--no-auth disable authorization
|
||||
--no-server do not start server
|
||||
--no-online load scripts from local server
|
||||
--no-open do not open web browser when server started
|
||||
--no-name set default tab name in web browser
|
||||
--no-one-panel-mode unset one panel mode
|
||||
--no-progress do not show progress of file operations
|
||||
--no-html-dialogs do not use html dialogs
|
||||
--no-one-panel-mode unset one panel mode
|
||||
--no-contact disable contact
|
||||
--no-config-dialog disable config dialog
|
||||
--no-console disable console
|
||||
--no-terminal disable terminal
|
||||
--no-name set default tab name in web browser
|
||||
--no-vim disable vim hot keys
|
||||
|
||||
.SH RESOURCES AND DOCUMENTATION
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@
|
|||
"fix:js:eslint:client": "redrun eslint:client -- --fix",
|
||||
"fix:js:eslint:server": "redrun eslint:server -- --fix",
|
||||
"test": "tape 'test/**/*.js'",
|
||||
"test:client": "tape 'test/client/**/*.js'",
|
||||
"spell": "yaspeller .",
|
||||
"wisdom": "redrun build",
|
||||
"wisdom:type": "bin/release.js",
|
||||
|
|
@ -91,7 +92,8 @@
|
|||
"watch:server": "nodemon bin/cloudcmd.js",
|
||||
"watch:lint": "nodemon -w client -w server -w webpack.config.js -x 'redrun lint:js'",
|
||||
"watch:lint:client": "nodemon -w client -w webpack.config.js -x 'redrun lint:js:eslint:client'",
|
||||
"watch:test": "nodemon -w server -w test -w common -x \"npm run test\"",
|
||||
"watch:test": "nodemon -w server -w test -w common -x \"npm test\"",
|
||||
"watch:test:client": "nodemon -w client -w test/client -x \"npm run test:client\"",
|
||||
"watch:coverage": "nodemon -w server -w test -w common -x \"npm run coverage\"",
|
||||
"w:c": "redrun watch:client",
|
||||
"w:c:d": "redrun watch:client:dev",
|
||||
|
|
|
|||
394
test/client/key/vim.js
Normal file
394
test/client/key/vim.js
Normal file
|
|
@ -0,0 +1,394 @@
|
|||
'use strict';
|
||||
|
||||
const test = require('tape');
|
||||
const diff = require('sinon-called-with-diff');
|
||||
const sinon = diff(require('sinon'));
|
||||
const dir = '../../../client/key/';
|
||||
const KEY = require(dir + 'key');
|
||||
|
||||
initGlobals();
|
||||
|
||||
const DOM = global.DOM;
|
||||
const Buffer = DOM.Buffer;
|
||||
|
||||
const vim = require(dir + 'vim');
|
||||
|
||||
test('cloudcmd: client: key: set next file: no', (t) => {
|
||||
const element = {
|
||||
};
|
||||
|
||||
const setCurrentFile = sinon.stub();
|
||||
|
||||
global.DOM.CurrentInfo.element = element;
|
||||
global.DOM.setCurrentFile = setCurrentFile;
|
||||
|
||||
vim('j', {});
|
||||
|
||||
t.ok(setCurrentFile.calledWith(element), 'should set next file');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: set next file current', (t) => {
|
||||
const nextSibling = 'hello';
|
||||
const element = {
|
||||
nextSibling
|
||||
};
|
||||
|
||||
const setCurrentFile = sinon.stub();
|
||||
|
||||
global.DOM.CurrentInfo.element = element;
|
||||
global.DOM.setCurrentFile = setCurrentFile;
|
||||
|
||||
vim('j', {});
|
||||
|
||||
t.ok(setCurrentFile.calledWith(nextSibling), 'should set next file');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: set next file current', (t) => {
|
||||
const nextSibling = 'hello';
|
||||
const element = {
|
||||
nextSibling
|
||||
};
|
||||
|
||||
const setCurrentFile = sinon.stub();
|
||||
|
||||
global.DOM.CurrentInfo.element = element;
|
||||
global.DOM.setCurrentFile = setCurrentFile;
|
||||
|
||||
vim('m', {});
|
||||
vim('j', {});
|
||||
vim('j', {});
|
||||
|
||||
t.ok(setCurrentFile.calledWith(nextSibling), 'should set next file');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: set next file current: g', (t) => {
|
||||
const nextSibling = 'hello';
|
||||
const element = {
|
||||
nextSibling
|
||||
};
|
||||
|
||||
const setCurrentFile = sinon.stub();
|
||||
|
||||
global.DOM.CurrentInfo.element = element;
|
||||
global.DOM.setCurrentFile = setCurrentFile;
|
||||
|
||||
vim('g', {});
|
||||
vim('j', {});
|
||||
|
||||
t.ok(setCurrentFile.calledWith(nextSibling), 'should ignore g');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: set +2 file current', (t) => {
|
||||
const last = {};
|
||||
const nextSibling = {
|
||||
nextSibling: last
|
||||
};
|
||||
const element = {
|
||||
nextSibling
|
||||
};
|
||||
|
||||
const setCurrentFile = sinon.stub();
|
||||
|
||||
global.DOM.CurrentInfo.element = element;
|
||||
global.DOM.setCurrentFile = setCurrentFile;
|
||||
|
||||
const event = {};
|
||||
|
||||
vim('2', event);
|
||||
vim('j', event);
|
||||
|
||||
t.ok(setCurrentFile.calledWith(last), 'should set next file');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: select +2 files from current before delete', (t) => {
|
||||
const last = {};
|
||||
const nextSibling = {
|
||||
nextSibling: last
|
||||
};
|
||||
const element = {
|
||||
nextSibling
|
||||
};
|
||||
|
||||
const setCurrentFile = sinon.stub();
|
||||
|
||||
global.DOM.CurrentInfo.element = element;
|
||||
global.DOM.setCurrentFile = setCurrentFile;
|
||||
global.DOM.selectFile = sinon.stub();
|
||||
global.DOM.getCurrentName = () => false;
|
||||
global.CloudCmd.Operation.show = sinon.stub();
|
||||
|
||||
const event = {};
|
||||
|
||||
vim('d', event);
|
||||
vim('2', event);
|
||||
vim('j', event);
|
||||
|
||||
t.ok(setCurrentFile.calledWith(last), 'should set next file');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: delete +2 files from current', (t) => {
|
||||
const last = {};
|
||||
const nextSibling = {
|
||||
nextSibling: last
|
||||
};
|
||||
const element = {
|
||||
nextSibling
|
||||
};
|
||||
|
||||
const setCurrentFile = sinon.stub();
|
||||
const show = sinon.stub();
|
||||
|
||||
global.DOM.CurrentInfo.element = element;
|
||||
global.DOM.setCurrentFile = setCurrentFile;
|
||||
global.DOM.selectFile = sinon.stub();
|
||||
global.DOM.getCurrentName = () => false;
|
||||
global.CloudCmd.Operation.show = show;
|
||||
|
||||
const event = {};
|
||||
|
||||
vim('d', event);
|
||||
vim('2', event);
|
||||
vim('j', event);
|
||||
|
||||
t.ok(show.calledWith('delete'), 'should call delete');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: set previous file current', (t) => {
|
||||
const previousSibling = 'hello';
|
||||
const element = {
|
||||
previousSibling
|
||||
};
|
||||
|
||||
const setCurrentFile = sinon.stub();
|
||||
|
||||
global.DOM.CurrentInfo.element = element;
|
||||
global.DOM.setCurrentFile = setCurrentFile;
|
||||
|
||||
vim('k', {});
|
||||
|
||||
t.ok(setCurrentFile.calledWith(previousSibling), 'should set previous file');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: copy: no', (t) => {
|
||||
const copy = sinon.stub();
|
||||
|
||||
Buffer.copy = copy;
|
||||
|
||||
vim('y', {});
|
||||
|
||||
t.notOk(copy.called, 'should not copy files');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: copy', (t) => {
|
||||
const copy = sinon.stub();
|
||||
|
||||
Buffer.copy = copy;
|
||||
|
||||
vim('v', {});
|
||||
vim('y', {});
|
||||
|
||||
t.ok(copy.calledWith(), 'should copy files');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: copy: unselectFiles', (t) => {
|
||||
const unselectFiles = sinon.stub();
|
||||
|
||||
DOM.unselectFiles = unselectFiles;
|
||||
|
||||
vim('v', {});
|
||||
vim('y', {});
|
||||
|
||||
t.ok(unselectFiles.calledWith(), 'should unselect files');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: paste', (t) => {
|
||||
const paste = sinon.stub();
|
||||
|
||||
Buffer.paste = paste;
|
||||
|
||||
vim('p', {});
|
||||
|
||||
t.ok(paste.calledWith(), 'should paste files');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: selectFile: ..', (t) => {
|
||||
const selectFile = sinon.stub();
|
||||
const getCurrentName = sinon.stub();
|
||||
|
||||
DOM.selectFile = selectFile;
|
||||
DOM.getCurrentName = () => '..';
|
||||
|
||||
const current = {};
|
||||
vim.selectFile(current);
|
||||
|
||||
t.notOk(getCurrentName.called, 'should not call selectFile');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: selectFile', (t) => {
|
||||
const selectFile = sinon.stub();
|
||||
|
||||
DOM.selectFile = selectFile;
|
||||
DOM.getCurrentName = (a) => a.name;
|
||||
|
||||
const current = {};
|
||||
|
||||
vim.selectFile(current);
|
||||
|
||||
t.ok(selectFile.calledWith(current), 'should call selectFile');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: set last file current', (t) => {
|
||||
const last = 'last';
|
||||
const nextSibling = {
|
||||
nextSibling: last
|
||||
};
|
||||
const element = {
|
||||
nextSibling
|
||||
};
|
||||
|
||||
const setCurrentFile = sinon.stub();
|
||||
|
||||
global.DOM.CurrentInfo.element = element;
|
||||
global.DOM.setCurrentFile = setCurrentFile;
|
||||
|
||||
vim('G', {});
|
||||
|
||||
t.ok(setCurrentFile.calledWith(last), 'should set last file');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: set first file current', (t) => {
|
||||
const first = 'first';
|
||||
const previousSibling= {
|
||||
previousSibling: first
|
||||
};
|
||||
|
||||
const element = {
|
||||
previousSibling
|
||||
};
|
||||
|
||||
const setCurrentFile = sinon.stub();
|
||||
|
||||
global.DOM.CurrentInfo.element = element;
|
||||
global.DOM.setCurrentFile = setCurrentFile;
|
||||
|
||||
vim('g', {});
|
||||
vim('g', {});
|
||||
|
||||
t.ok(setCurrentFile.calledWith(first), 'should set first file');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: visual', (t) => {
|
||||
const element = {
|
||||
};
|
||||
|
||||
const toggleSelectedFile = sinon.stub();
|
||||
|
||||
global.DOM.CurrentInfo.element = element;
|
||||
global.DOM.toggleSelectedFile = toggleSelectedFile;
|
||||
|
||||
vim('v', {});
|
||||
|
||||
t.ok(toggleSelectedFile.calledWith(element), 'should toggle selection');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: ESC', (t) => {
|
||||
const element = {
|
||||
};
|
||||
|
||||
const unselectFiles = sinon.stub();
|
||||
|
||||
global.DOM.CurrentInfo.element = element;
|
||||
global.DOM.unselectFiles = unselectFiles ;
|
||||
|
||||
vim('', {
|
||||
keyCode: KEY.ESC
|
||||
});
|
||||
|
||||
t.ok(unselectFiles.calledWith(), 'should toggle selection');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: Enter', (t) => {
|
||||
const nextSibling = 'hello';
|
||||
const element = {
|
||||
nextSibling
|
||||
};
|
||||
|
||||
const setCurrentFile = sinon.stub();
|
||||
|
||||
global.DOM.CurrentInfo.element = element;
|
||||
global.DOM.setCurrentFile = setCurrentFile;
|
||||
|
||||
vim('', {
|
||||
keyCode: KEY.ENTER
|
||||
});
|
||||
|
||||
vim('j', {});
|
||||
|
||||
t.ok(setCurrentFile.calledWith(nextSibling), 'should set next file');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
function initGlobals() {
|
||||
const CurrentInfo = {
|
||||
element: {},
|
||||
};
|
||||
|
||||
const noop = () => {};
|
||||
const Buffer = {
|
||||
copy: noop,
|
||||
};
|
||||
|
||||
global.DOM = {
|
||||
Buffer,
|
||||
CurrentInfo,
|
||||
selectFile: noop,
|
||||
unselectFile: noop,
|
||||
unselectFiles: noop,
|
||||
setCurrentFile: noop,
|
||||
toggleSelectedFile: noop,
|
||||
};
|
||||
|
||||
const show = () => {};
|
||||
|
||||
global.CloudCmd = {
|
||||
Operation: {
|
||||
show
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -48,6 +48,15 @@
|
|||
<option {{ deepword-selected }}>deepword</option>
|
||||
</select>
|
||||
</li>
|
||||
<li>
|
||||
<label>
|
||||
<input
|
||||
data-name="js-vim"
|
||||
type="checkbox"
|
||||
{{ vim }}>
|
||||
Vim
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label>
|
||||
<input
|
||||
|
|
@ -58,7 +67,6 @@
|
|||
</label>
|
||||
</li>
|
||||
<li>
|
||||
|
||||
<label>
|
||||
<input data-name="js-buffer" type="checkbox" {{ buffer }}>
|
||||
Buffer
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue