mirror of
https://github.com/coderaiser/cloudcmd.git
synced 2026-01-23 10:45:47 +00:00
feature(cloudcmd) add ability to toggle vim hotkes using Esc
This commit is contained in:
parent
595805eeaf
commit
cd7bf0fe01
6 changed files with 541 additions and 467 deletions
2
HELP.md
2
HELP.md
|
|
@ -201,7 +201,7 @@ Then, start the server again with `cloudcmd` and reload the page.
|
|||
| `Insert` | select current file (and move to next)
|
||||
| `F9` | context menu
|
||||
| `~` | console
|
||||
| `Ctrl + Click` | open file on new tab
|
||||
| `Esc` | toggle vim hot keys
|
||||
|
||||
### Vim
|
||||
|
||||
|
|
|
|||
|
|
@ -8,15 +8,15 @@ const rendy = require('rendy');
|
|||
const load = require('load.js');
|
||||
const tryToCatch = require('try-to-catch');
|
||||
const {addSlashToEnd} = require('format-io');
|
||||
|
||||
const pascalCase = require('just-pascal-case');
|
||||
const currify = require('currify');
|
||||
|
||||
const isDev = process.env.NODE_ENV === 'development';
|
||||
|
||||
const Images = require('./dom/images');
|
||||
const {unregisterSW} = require('./sw/register');
|
||||
const getJsonFromFileTable = require('./get-json-from-file-table');
|
||||
|
||||
const currify = require('currify');
|
||||
const Key = require('./key');
|
||||
|
||||
const noJS = (a) => a.replace(/.js$/, '');
|
||||
|
||||
|
|
@ -206,7 +206,7 @@ function CloudCmdProto(DOM) {
|
|||
};
|
||||
|
||||
const initModules = async () => {
|
||||
CloudCmd.Key = new CloudCmd.Key();
|
||||
CloudCmd.Key = Key;
|
||||
CloudCmd.Key.bind();
|
||||
|
||||
const [, modules] = await tryToCatch(Files.get, 'modules');
|
||||
|
|
|
|||
18
client/key/binder.js
Normal file
18
client/key/binder.js
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
'use strict';
|
||||
|
||||
module.exports.createBinder = () => {
|
||||
let binded = false;
|
||||
|
||||
return {
|
||||
isBind() {
|
||||
return binded;
|
||||
},
|
||||
setBind() {
|
||||
binded = true;
|
||||
},
|
||||
unsetBind() {
|
||||
binded = false;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -7,495 +7,485 @@ const Info = DOM.CurrentInfo;
|
|||
const exec = require('execon');
|
||||
const clipboard = require('@cloudcmd/clipboard');
|
||||
|
||||
const Events = require('../dom/events');
|
||||
const Buffer = require('../dom/buffer');
|
||||
const Events = require('../dom/events');
|
||||
|
||||
const KEY = require('./key');
|
||||
const vim = require('./vim');
|
||||
const setCurrentByChar = require('./set-current-by-char');
|
||||
const {createBinder} = require('./binder');
|
||||
|
||||
const fullstore = require('fullstore');
|
||||
const Chars = fullstore();
|
||||
const isVimEnabled = fullstore(false);
|
||||
|
||||
const toggleVim = (keyCode) => keyCode === KEY.ESC && isVimEnabled(!isVimEnabled());
|
||||
|
||||
Chars([]);
|
||||
|
||||
KeyProto.prototype = KEY;
|
||||
CloudCmd.Key = KeyProto;
|
||||
const {loadDir} = CloudCmd;
|
||||
const {assign} = Object;
|
||||
|
||||
function KeyProto() {
|
||||
let Binded;
|
||||
const binder = createBinder();
|
||||
module.exports = assign(binder, KEY);
|
||||
module.exports.bind = () => {
|
||||
Events.addKey(listener, true);
|
||||
binder.setBind();
|
||||
};
|
||||
|
||||
module.exports._listener = listener;
|
||||
|
||||
function getChar(event) {
|
||||
/*
|
||||
* event.keyIdentifier deprecated in chrome v51
|
||||
* but event.key is absent in chrome <= v51
|
||||
*/
|
||||
|
||||
const Key = this;
|
||||
const {
|
||||
key,
|
||||
shift,
|
||||
keyCode,
|
||||
keyIdentifier,
|
||||
} = event;
|
||||
const char = key || fromCharCode(keyIdentifier);
|
||||
const symbol = getSymbol(shift, keyCode);
|
||||
|
||||
this.isBind = () => {
|
||||
return Binded;
|
||||
};
|
||||
return [symbol, char];
|
||||
}
|
||||
|
||||
async function listener(event) {
|
||||
const {keyCode} = event;
|
||||
|
||||
this.setBind = () => {
|
||||
Binded = true;
|
||||
};
|
||||
// strange chrome bug calles listener twice
|
||||
// in second time event misses a lot fields
|
||||
if (typeof event.altKey === 'undefined')
|
||||
return;
|
||||
|
||||
this.unsetBind = () => {
|
||||
Binded = false;
|
||||
};
|
||||
const alt = event.altKey;
|
||||
const ctrl = event.ctrlKey;
|
||||
const meta = event.metaKey;
|
||||
const isBetween = keyCode >= KEY.ZERO && keyCode <= KEY.Z;
|
||||
const isNumpad = /Numpad/.test(event.code);
|
||||
|
||||
this.bind = () => {
|
||||
Events.addKey(listener, true);
|
||||
Binded = true;
|
||||
};
|
||||
const [symbol, char] = getChar(event);
|
||||
|
||||
function getChar(event) {
|
||||
/*
|
||||
* event.keyIdentifier deprecated in chrome v51
|
||||
* but event.key is absent in chrome <= v51
|
||||
*/
|
||||
|
||||
if (event.key)
|
||||
return event.key;
|
||||
|
||||
return fromCharCode(event.keyIdentifier);
|
||||
if (!binder.isBind())
|
||||
return;
|
||||
|
||||
toggleVim(keyCode);
|
||||
const isVim = isVimEnabled() || CloudCmd.config('vim');
|
||||
|
||||
if (!isVim && !isNumpad && !alt && !ctrl && !meta && (isBetween || symbol))
|
||||
return setCurrentByChar(char, Chars);
|
||||
|
||||
Chars([]);
|
||||
await switchKey(event);
|
||||
|
||||
if (keyCode >= KEY.F1 && keyCode <= KEY.F10)
|
||||
return;
|
||||
|
||||
if (isVim)
|
||||
vim(char, event);
|
||||
}
|
||||
|
||||
function getSymbol(shift, keyCode) {
|
||||
switch(keyCode) {
|
||||
case KEY.DOT:
|
||||
return '.';
|
||||
|
||||
case KEY.HYPHEN:
|
||||
return shift ? '_' : '-';
|
||||
|
||||
case KEY.EQUAL:
|
||||
return shift ? '+' : '=';
|
||||
}
|
||||
|
||||
async function listener(event) {
|
||||
const {keyCode} = event;
|
||||
|
||||
// strange chrome bug calles listener twice
|
||||
// in second time event misses a lot fields
|
||||
if (typeof event.altKey === 'undefined')
|
||||
return;
|
||||
|
||||
const alt = event.altKey;
|
||||
const ctrl = event.ctrlKey;
|
||||
const shift = event.shiftKey;
|
||||
const meta = event.metaKey;
|
||||
const isBetween = keyCode >= KEY.ZERO && keyCode <= KEY.Z;
|
||||
const isNumpad = /Numpad/.test(event.code);
|
||||
|
||||
let char = getChar(event);
|
||||
let isSymbol = ['.', '_', '-', '+', '='].includes(char);
|
||||
|
||||
if (!isSymbol) {
|
||||
isSymbol = getSymbol(shift, keyCode);
|
||||
|
||||
if (isSymbol)
|
||||
char = isSymbol;
|
||||
}
|
||||
|
||||
if (!Key.isBind())
|
||||
return;
|
||||
|
||||
const isVim = CloudCmd.config('vim');
|
||||
|
||||
if (!isVim && !isNumpad && !alt && !ctrl && !meta && (isBetween || isSymbol))
|
||||
return setCurrentByChar(char, Chars);
|
||||
|
||||
Chars([]);
|
||||
await switchKey(event);
|
||||
|
||||
if (keyCode >= KEY.F1 && keyCode <= KEY.F10)
|
||||
return;
|
||||
|
||||
if (isVim)
|
||||
vim(char, event);
|
||||
return '';
|
||||
}
|
||||
|
||||
function fromCharCode(keyIdentifier) {
|
||||
const code = keyIdentifier.substring(2);
|
||||
const hex = parseInt(code, 16);
|
||||
const char = String.fromCharCode(hex);
|
||||
|
||||
return char;
|
||||
}
|
||||
|
||||
async function switchKey(event) {
|
||||
let i;
|
||||
let isSelected;
|
||||
let prev;
|
||||
let next;
|
||||
let current = Info.element;
|
||||
let dataName;
|
||||
|
||||
const {
|
||||
name,
|
||||
panel,
|
||||
path,
|
||||
isDir,
|
||||
} = Info;
|
||||
|
||||
const {Operation, loadDir} = CloudCmd;
|
||||
const {keyCode} = event;
|
||||
|
||||
const alt = event.altKey;
|
||||
const shift = event.shiftKey;
|
||||
const ctrl = event.ctrlKey;
|
||||
const meta = event.metaKey;
|
||||
const ctrlMeta = ctrl || meta;
|
||||
|
||||
if (current) {
|
||||
prev = current.previousSibling;
|
||||
next = current.nextSibling;
|
||||
}
|
||||
|
||||
function getSymbol(shift, keyCode) {
|
||||
switch(keyCode) {
|
||||
case KEY.DOT:
|
||||
return '.';
|
||||
|
||||
case KEY.HYPHEN:
|
||||
return shift ? '_' : '-';
|
||||
|
||||
case KEY.EQUAL:
|
||||
return shift ? '+' : '=';
|
||||
}
|
||||
}
|
||||
switch(keyCode) {
|
||||
case KEY.TAB:
|
||||
DOM.changePanel();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
function fromCharCode(keyIdentifier) {
|
||||
const code = keyIdentifier.substring(2);
|
||||
const hex = parseInt(code, 16);
|
||||
const char = String.fromCharCode(hex);
|
||||
|
||||
return char;
|
||||
}
|
||||
case KEY.INSERT:
|
||||
DOM .toggleSelectedFile(current)
|
||||
.setCurrentFile(next);
|
||||
break;
|
||||
|
||||
async function switchKey(event) {
|
||||
let i;
|
||||
let isSelected;
|
||||
let prev;
|
||||
let next;
|
||||
let current = Info.element;
|
||||
let dataName;
|
||||
|
||||
const {
|
||||
name,
|
||||
panel,
|
||||
path,
|
||||
isDir,
|
||||
} = Info;
|
||||
|
||||
const {Operation} = CloudCmd;
|
||||
const {keyCode} = event;
|
||||
|
||||
const alt = event.altKey;
|
||||
const shift = event.shiftKey;
|
||||
const ctrl = event.ctrlKey;
|
||||
const meta = event.metaKey;
|
||||
const ctrlMeta = ctrl || meta;
|
||||
|
||||
if (current) {
|
||||
prev = current.previousSibling;
|
||||
next = current.nextSibling;
|
||||
}
|
||||
|
||||
switch(keyCode) {
|
||||
case Key.TAB:
|
||||
DOM.changePanel();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case Key.INSERT:
|
||||
DOM .toggleSelectedFile(current)
|
||||
.setCurrentFile(next);
|
||||
break;
|
||||
|
||||
case Key.INSERT_MAC:
|
||||
DOM .toggleSelectedFile(current)
|
||||
.setCurrentFile(next);
|
||||
break;
|
||||
|
||||
case Key.DELETE:
|
||||
if (shift)
|
||||
Operation.show('delete:silent');
|
||||
else
|
||||
Operation.show('delete');
|
||||
break;
|
||||
|
||||
case Key.ASTERISK:
|
||||
DOM.toggleAllSelectedFiles(current);
|
||||
break;
|
||||
|
||||
case Key.PLUS:
|
||||
DOM.expandSelection();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case Key.MINUS:
|
||||
DOM.shrinkSelection();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case Key.F1:
|
||||
CloudCmd.Help.show();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case Key.F2:
|
||||
CloudCmd.UserMenu.show();
|
||||
break;
|
||||
|
||||
case Key.F3:
|
||||
event.preventDefault();
|
||||
|
||||
if (Info.isDir)
|
||||
await loadDir({
|
||||
path,
|
||||
});
|
||||
else if (shift)
|
||||
CloudCmd.Markdown.show(path);
|
||||
else if (ctrlMeta)
|
||||
CloudCmd.sortPanel('name');
|
||||
else
|
||||
CloudCmd.View.show();
|
||||
|
||||
break;
|
||||
|
||||
case Key.F4:
|
||||
if (shift)
|
||||
CloudCmd.EditFileVim.show();
|
||||
else
|
||||
CloudCmd.EditFile.show();
|
||||
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case Key.F5:
|
||||
if (ctrlMeta)
|
||||
CloudCmd.sortPanel('date');
|
||||
else if (alt)
|
||||
Operation.show('pack');
|
||||
else
|
||||
Operation.show('copy');
|
||||
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case Key.F6:
|
||||
if (ctrlMeta)
|
||||
CloudCmd.sortPanel('size');
|
||||
else if (shift)
|
||||
DOM.renameCurrent(current);
|
||||
else
|
||||
Operation.show('move');
|
||||
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case Key.F7:
|
||||
if (shift)
|
||||
DOM.promptNewFile();
|
||||
else
|
||||
DOM.promptNewDir();
|
||||
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case Key.F8:
|
||||
case KEY.INSERT_MAC:
|
||||
DOM .toggleSelectedFile(current)
|
||||
.setCurrentFile(next);
|
||||
break;
|
||||
|
||||
case KEY.DELETE:
|
||||
if (shift)
|
||||
Operation.show('delete:silent');
|
||||
else
|
||||
Operation.show('delete');
|
||||
event.preventDefault();
|
||||
break;
|
||||
break;
|
||||
|
||||
case KEY.ASTERISK:
|
||||
DOM.toggleAllSelectedFiles(current);
|
||||
break;
|
||||
|
||||
case KEY.PLUS:
|
||||
DOM.expandSelection();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.MINUS:
|
||||
DOM.shrinkSelection();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.F1:
|
||||
CloudCmd.Help.show();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.F2:
|
||||
CloudCmd.UserMenu.show();
|
||||
break;
|
||||
|
||||
case KEY.F3:
|
||||
event.preventDefault();
|
||||
|
||||
case Key.F9:
|
||||
if (alt)
|
||||
Operation.show('extract');
|
||||
else
|
||||
CloudCmd.Menu.show();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case Key.F10:
|
||||
CloudCmd.Config.show();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case Key.TRA:
|
||||
event.preventDefault();
|
||||
|
||||
if (shift)
|
||||
return CloudCmd.Terminal.show();
|
||||
|
||||
CloudCmd.Konsole.show();
|
||||
break;
|
||||
|
||||
case KEY.BRACKET_CLOSE:
|
||||
CloudCmd.Konsole.show();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case Key.SPACE:
|
||||
if (!isDir || name === '..')
|
||||
isSelected = true;
|
||||
else
|
||||
isSelected = DOM.isSelected(current);
|
||||
|
||||
exec.if(isSelected, () => {
|
||||
DOM.toggleSelectedFile(current);
|
||||
}, (callback) => {
|
||||
DOM.loadCurrentSize(current, callback);
|
||||
if (Info.isDir)
|
||||
await loadDir({
|
||||
path,
|
||||
});
|
||||
|
||||
else if (shift)
|
||||
CloudCmd.Markdown.show(path);
|
||||
else if (ctrlMeta)
|
||||
CloudCmd.sortPanel('name');
|
||||
else
|
||||
CloudCmd.View.show();
|
||||
|
||||
break;
|
||||
|
||||
case KEY.F4:
|
||||
if (shift)
|
||||
CloudCmd.EditFileVim.show();
|
||||
else
|
||||
CloudCmd.EditFile.show();
|
||||
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.F5:
|
||||
if (ctrlMeta)
|
||||
CloudCmd.sortPanel('date');
|
||||
else if (alt)
|
||||
Operation.show('pack');
|
||||
else
|
||||
Operation.show('copy');
|
||||
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.F6:
|
||||
if (ctrlMeta)
|
||||
CloudCmd.sortPanel('size');
|
||||
else if (shift)
|
||||
DOM.renameCurrent(current);
|
||||
else
|
||||
Operation.show('move');
|
||||
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.F7:
|
||||
if (shift)
|
||||
DOM.promptNewFile();
|
||||
else
|
||||
DOM.promptNewDir();
|
||||
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.F8:
|
||||
Operation.show('delete');
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.F9:
|
||||
if (alt)
|
||||
Operation.show('extract');
|
||||
else
|
||||
CloudCmd.Menu.show();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.F10:
|
||||
CloudCmd.Config.show();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.TRA:
|
||||
event.preventDefault();
|
||||
|
||||
if (shift)
|
||||
return CloudCmd.Terminal.show();
|
||||
|
||||
CloudCmd.Konsole.show();
|
||||
break;
|
||||
|
||||
case KEY.BRACKET_CLOSE:
|
||||
CloudCmd.Konsole.show();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.SPACE:
|
||||
if (!isDir || name === '..')
|
||||
isSelected = true;
|
||||
else
|
||||
isSelected = DOM.isSelected(current);
|
||||
|
||||
exec.if(isSelected, () => {
|
||||
DOM.toggleSelectedFile(current);
|
||||
}, (callback) => {
|
||||
DOM.loadCurrentSize(current, callback);
|
||||
});
|
||||
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.U:
|
||||
if (ctrlMeta) {
|
||||
DOM.swapPanels();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case Key.U:
|
||||
if (ctrlMeta) {
|
||||
DOM.swapPanels();
|
||||
event.preventDefault();
|
||||
}
|
||||
break;
|
||||
|
||||
/* navigation on file table: *
|
||||
* in case of pressing button 'up', *
|
||||
* select previous row */
|
||||
case Key.UP:
|
||||
if (shift)
|
||||
DOM.toggleSelectedFile(current);
|
||||
|
||||
DOM.setCurrentFile(prev);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
/* in case of pressing button 'down', *
|
||||
* select next row */
|
||||
case Key.DOWN:
|
||||
if (shift)
|
||||
DOM.toggleSelectedFile(current);
|
||||
|
||||
DOM.setCurrentFile(next);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case Key.LEFT:
|
||||
if (!alt)
|
||||
return;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
dataName = Info.panel.getAttribute('data-name');
|
||||
|
||||
if (dataName === 'js-right')
|
||||
DOM.duplicatePanel();
|
||||
|
||||
break;
|
||||
|
||||
case Key.RIGHT:
|
||||
if (!alt)
|
||||
return;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
dataName = Info.panel.getAttribute('data-name');
|
||||
|
||||
if (dataName === 'js-left')
|
||||
DOM.duplicatePanel();
|
||||
|
||||
break;
|
||||
|
||||
/* in case of pressing button 'Home', *
|
||||
* go to top element */
|
||||
case Key.HOME:
|
||||
DOM.setCurrentFile(Info.first);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
/* in case of pressing button 'End', select last element */
|
||||
case Key.END:
|
||||
DOM.setCurrentFile(Info.last);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
/* если нажали клавишу page down проматываем экран */
|
||||
case Key.PAGE_DOWN:
|
||||
DOM.scrollByPages(panel, 1);
|
||||
|
||||
for (i = 0; i < 30; i++) {
|
||||
if (!current.nextSibling)
|
||||
break;
|
||||
|
||||
current = current.nextSibling;
|
||||
}
|
||||
|
||||
DOM.setCurrentFile(current);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
/* если нажали клавишу page up проматываем экран */
|
||||
case Key.PAGE_UP:
|
||||
DOM.scrollByPages(panel, -1);
|
||||
|
||||
for (i = 0; i < 30; i++) {
|
||||
if (!current.previousSibling)
|
||||
break;
|
||||
|
||||
current = current.previousSibling;
|
||||
}
|
||||
|
||||
DOM.setCurrentFile(current);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case Key.ENTER:
|
||||
if (Info.isDir)
|
||||
await loadDir({path});
|
||||
else
|
||||
CloudCmd.View.show();
|
||||
break;
|
||||
|
||||
case Key.BACKSPACE:
|
||||
CloudCmd.goToParentDir();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case Key.BACKSLASH:
|
||||
if (ctrlMeta)
|
||||
await loadDir({
|
||||
path: '/',
|
||||
});
|
||||
break;
|
||||
|
||||
case Key.A:
|
||||
if (ctrlMeta) {
|
||||
DOM.selectAllFiles();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Key.G:
|
||||
if (alt) {
|
||||
DOM.goToDirectory();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Key.M:
|
||||
if (ctrlMeta) {
|
||||
if (shift)
|
||||
CloudCmd.EditNamesVim.show();
|
||||
else
|
||||
CloudCmd.EditNames.show();
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Key.P:
|
||||
if (!ctrlMeta)
|
||||
return;
|
||||
|
||||
event.preventDefault();
|
||||
clipboard
|
||||
.writeText(Info.dirPath)
|
||||
.catch(CloudCmd.log);
|
||||
|
||||
break;
|
||||
/**
|
||||
* обновляем страницу,
|
||||
* загружаем содержимое каталога
|
||||
* при этом данные берём всегда с
|
||||
* сервера, а не из кэша
|
||||
* (обновляем кэш)
|
||||
*/
|
||||
case Key.R:
|
||||
if (ctrlMeta) {
|
||||
CloudCmd.log('reloading page...\n');
|
||||
CloudCmd.refresh();
|
||||
event.preventDefault();
|
||||
}
|
||||
break;
|
||||
|
||||
case Key.C:
|
||||
if (ctrlMeta)
|
||||
Buffer.copy();
|
||||
break;
|
||||
|
||||
case Key.X:
|
||||
if (ctrlMeta)
|
||||
Buffer.cut();
|
||||
break;
|
||||
|
||||
case Key.V:
|
||||
if (ctrlMeta)
|
||||
Buffer.paste();
|
||||
break;
|
||||
|
||||
case Key.Z:
|
||||
if (ctrlMeta)
|
||||
Buffer.clear();
|
||||
break;
|
||||
|
||||
/* чистим хранилище */
|
||||
case Key.D:
|
||||
if (ctrlMeta) {
|
||||
CloudCmd.log('clearing storage...');
|
||||
await DOM.Storage.clear();
|
||||
CloudCmd.log('storage cleared');
|
||||
event.preventDefault();
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* navigation on file table: *
|
||||
* in case of pressing button 'up', *
|
||||
* select previous row */
|
||||
case KEY.UP:
|
||||
if (shift)
|
||||
DOM.toggleSelectedFile(current);
|
||||
|
||||
DOM.setCurrentFile(prev);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
/* in case of pressing button 'down', *
|
||||
* select next row */
|
||||
case KEY.DOWN:
|
||||
if (shift)
|
||||
DOM.toggleSelectedFile(current);
|
||||
|
||||
DOM.setCurrentFile(next);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.LEFT:
|
||||
if (!alt)
|
||||
return;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
dataName = Info.panel.getAttribute('data-name');
|
||||
|
||||
if (dataName === 'js-right')
|
||||
DOM.duplicatePanel();
|
||||
|
||||
break;
|
||||
|
||||
case KEY.RIGHT:
|
||||
if (!alt)
|
||||
return;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
dataName = Info.panel.getAttribute('data-name');
|
||||
|
||||
if (dataName === 'js-left')
|
||||
DOM.duplicatePanel();
|
||||
|
||||
break;
|
||||
|
||||
/* in case of pressing button 'Home', *
|
||||
* go to top element */
|
||||
case KEY.HOME:
|
||||
DOM.setCurrentFile(Info.first);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
/* in case of pressing button 'End', select last element */
|
||||
case KEY.END:
|
||||
DOM.setCurrentFile(Info.last);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
/* если нажали клавишу page down проматываем экран */
|
||||
case KEY.PAGE_DOWN:
|
||||
DOM.scrollByPages(panel, 1);
|
||||
|
||||
for (i = 0; i < 30; i++) {
|
||||
if (!current.nextSibling)
|
||||
break;
|
||||
|
||||
current = current.nextSibling;
|
||||
}
|
||||
|
||||
DOM.setCurrentFile(current);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
/* если нажали клавишу page up проматываем экран */
|
||||
case KEY.PAGE_UP:
|
||||
DOM.scrollByPages(panel, -1);
|
||||
|
||||
for (i = 0; i < 30; i++) {
|
||||
if (!current.previousSibling)
|
||||
break;
|
||||
|
||||
current = current.previousSibling;
|
||||
}
|
||||
|
||||
DOM.setCurrentFile(current);
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.ENTER:
|
||||
if (Info.isDir)
|
||||
await loadDir({path});
|
||||
else
|
||||
CloudCmd.View.show();
|
||||
break;
|
||||
|
||||
case KEY.BACKSPACE:
|
||||
CloudCmd.goToParentDir();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case KEY.BACKSLASH:
|
||||
if (ctrlMeta)
|
||||
await loadDir({
|
||||
path: '/',
|
||||
});
|
||||
break;
|
||||
|
||||
case KEY.A:
|
||||
if (ctrlMeta) {
|
||||
DOM.selectAllFiles();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case KEY.G:
|
||||
if (alt) {
|
||||
DOM.goToDirectory();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case KEY.M:
|
||||
if (ctrlMeta) {
|
||||
if (shift)
|
||||
CloudCmd.EditNamesVim.show();
|
||||
else
|
||||
CloudCmd.EditNames.show();
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case KEY.P:
|
||||
if (!ctrlMeta)
|
||||
return;
|
||||
|
||||
event.preventDefault();
|
||||
clipboard
|
||||
.writeText(Info.dirPath)
|
||||
.catch(CloudCmd.log);
|
||||
|
||||
break;
|
||||
/**
|
||||
* обновляем страницу,
|
||||
* загружаем содержимое каталога
|
||||
* при этом данные берём всегда с
|
||||
* сервера, а не из кэша
|
||||
* (обновляем кэш)
|
||||
*/
|
||||
case KEY.R:
|
||||
if (ctrlMeta) {
|
||||
CloudCmd.log('reloading page...\n');
|
||||
CloudCmd.refresh();
|
||||
event.preventDefault();
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY.C:
|
||||
if (ctrlMeta)
|
||||
Buffer.copy();
|
||||
break;
|
||||
|
||||
case KEY.X:
|
||||
if (ctrlMeta)
|
||||
Buffer.cut();
|
||||
break;
|
||||
|
||||
case KEY.V:
|
||||
if (ctrlMeta)
|
||||
Buffer.paste();
|
||||
break;
|
||||
|
||||
case KEY.Z:
|
||||
if (ctrlMeta)
|
||||
Buffer.clear();
|
||||
break;
|
||||
|
||||
/* чистим хранилище */
|
||||
case KEY.D:
|
||||
if (ctrlMeta) {
|
||||
CloudCmd.log('clearing storage...');
|
||||
await DOM.Storage.clear();
|
||||
CloudCmd.log('storage cleared');
|
||||
event.preventDefault();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
65
client/key/index.spec.js
Normal file
65
client/key/index.spec.js
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
'use strict';
|
||||
|
||||
const autoGlobals = require('auto-globals');
|
||||
const test = autoGlobals(require('supertape'));
|
||||
const stub = require('@cloudcmd/stub');
|
||||
const mockRequire = require('mock-require');
|
||||
const {reRequire, stopAll} = mockRequire;
|
||||
|
||||
const {ESC} = require('./key');
|
||||
|
||||
const {
|
||||
getDOM,
|
||||
getCloudCmd,
|
||||
} = require('./vim/globals.fixture');
|
||||
|
||||
global.DOM = getDOM();
|
||||
global.CloudCmd = getCloudCmd();
|
||||
|
||||
test('cloudcmd: client: key: enable vim', async (t) => {
|
||||
const vim = stub();
|
||||
|
||||
mockRequire('./vim', vim);
|
||||
const {_listener, setBind} = reRequire('.');
|
||||
|
||||
const event = {
|
||||
keyCode: ESC,
|
||||
key: 'Escape',
|
||||
altKey: false,
|
||||
};
|
||||
|
||||
setBind();
|
||||
await _listener(event);
|
||||
|
||||
stopAll();
|
||||
|
||||
t.calledWith(vim, ['Escape', event]);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: client: key: disable vim', async (t) => {
|
||||
const vim = stub();
|
||||
const _config = stub();
|
||||
|
||||
const {_listener, setBind} = reRequire('.');
|
||||
|
||||
const event = {
|
||||
keyCode: ESC,
|
||||
key: 'Escape',
|
||||
altKey: false,
|
||||
};
|
||||
|
||||
const {CloudCmd} = global;
|
||||
const {config} = CloudCmd;
|
||||
CloudCmd.config = _config;
|
||||
|
||||
setBind();
|
||||
await _listener(event);
|
||||
await _listener(event);
|
||||
|
||||
CloudCmd.config = config;
|
||||
|
||||
t.calledWith(_config, ['vim']);
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
|
@ -4,6 +4,7 @@ module.exports = {
|
|||
BACKSPACE : 8,
|
||||
TAB : 9,
|
||||
ENTER : 13,
|
||||
CAPSLOCK : 20,
|
||||
ESC : 27,
|
||||
|
||||
SPACE : 32,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue