diff --git a/HELP.md b/HELP.md index 6cb77a7e..da2abd1e 100644 --- a/HELP.md +++ b/HELP.md @@ -127,6 +127,7 @@ Hot keys | `F3` | view | `Shift + F3` | view as `markdown` | `F4` | edit +| `Shift + F4` | edit in `vim` mode | `F5` | copy | `F6` | rename/move | `F7` | new directory @@ -191,6 +192,7 @@ Edit |Key |Operation |:----------------------|:-------------------------------------------- | `F4` | open +| `Shift + F4` | open in `vim` mode | `Esc` | close For more details see [Edward hot keys][EDWARD_KEYS]. diff --git a/client/key.js b/client/key.js index 0924779b..abfa8a0a 100644 --- a/client/key.js +++ b/client/key.js @@ -300,7 +300,11 @@ function KeyProto() { break; case Key.F4: - CloudCmd.EditFile.show(); + if (shift) + CloudCmd.EditFileVim.show(); + else + CloudCmd.EditFile.show(); + event.preventDefault(); break; diff --git a/client/modules/edit-file-vim.js b/client/modules/edit-file-vim.js new file mode 100644 index 00000000..6b598d57 --- /dev/null +++ b/client/modules/edit-file-vim.js @@ -0,0 +1,210 @@ +'use strict'; + +/* global CloudCmd, DOM, MenuIO */ + +const Format = require('format-io'); +const currify = require('currify/legacy'); +const squad = require('squad'); +const store = require('../../common/store'); +const Key = CloudCmd.Key; + +const Events = require('../dom/events'); + +const call = currify((fn, callback) => { + fn(); + callback(); +}); + +CloudCmd.EditFileVim = function EditFileVimProto(callback) { + const Info = DOM.CurrentInfo; + const Dialog = DOM.Dialog; + const EditFileVim = this; + const config = CloudCmd.config; + + let Menu; + + const exec = require('execon'); + const TITLE = 'Edit'; + const Images = DOM.Images; + + let MSG_CHANGED; + const ConfigView = { + bindKeys: false, + beforeClose: () => { + Events.rmKey(listener); + exec.ifExist(Menu, 'hide'); + isChanged(); + } + }; + + function init(callback) { + const editor = store(); + + const getMainEditor = () => CloudCmd.Edit.getEditor(); + const getEditor = squad(editor, getMainEditor); + const auth = squad(authCheck, editor); + const listeners = squad(setListeners, editor); + + exec.series([ + CloudCmd.Edit, + call(getEditor), + call(auth), + call(listeners), + EditFileVim.show, + ], callback); + } + + function getName() { + const {name, isDir} = Info; + + if (isDir) + return `${name}.json`; + + return name; + } + + this.show = () => { + Images.show.load(); + + Info.getData((error, data) => { + const path = Info.path; + const name = getName(); + + if (error) + return Images.hide(); + + setMsgChanged(name); + + Events.addKey(listener); + + CloudCmd.Edit + .show(ConfigView) + .getEditor() + .setValueFirst(path, data) + .setModeForPath(name) + .enableKey() + .setOptions({ + keyMap: 'vim' + }); + }); + }; + + this.hide = () => { + CloudCmd.Edit.hide(); + }; + + function setListeners(editor) { + const element = CloudCmd.Edit.getElement(); + + Events.addOnce('contextmenu', element, setMenu); + + editor.on('save', (value) => { + DOM.setCurrentSize(Format.size(value)); + }); + } + + function authCheck(spawn) { + if (!config('auth')) + return; + + spawn.emit('auth', config('username'), config('password')); + spawn.on('reject', () => { + Dialog.alert(TITLE, 'Wrong credentials!'); + }); + } + + function setMenu(event) { + const position = { + x: event.clientX, + y: event.clientY + }; + + event.preventDefault(); + + !Menu && DOM.loadRemote('menu', (error) => { + let noFocus; + const editor = CloudCmd.Edit.getEditor(); + const options = { + beforeShow: (params) => { + params.x -= 18; + params.y -= 27; + }, + + afterClick: () => { + !noFocus && editor.focus(); + } + }; + + const menuData = { + 'Save Ctrl+S' : () => { + editor.save(); + }, + 'Go To Line Ctrl+G' : () => { + noFocus = true; + editor.goToLine(); + }, + 'Cut Ctrl+X' : () => { + editor.cutToClipboard(); + }, + 'Copy Ctrl+C' : () => { + editor.copyToClipboard(); + }, + 'Paste Ctrl+V' : () => { + editor.pasteFromClipboard(); + }, + 'Delete Del' : () => { + editor.remove('right'); + }, + 'Select All Ctrl+A' : () => { + editor.selectAll(); + }, + 'Beautify Ctrl+B' : () => { + editor.beautify(); + }, + 'Minify Ctrl+M' : () => { + editor.minify(); + }, + 'Close Esc' : () => { + EditFileVim.hide(); + } + }; + + if (error) + return Dialog.alert(TITLE, error); + + if (Menu || !MenuIO) + return; + + const element = CloudCmd.Edit.getElement(); + + Menu = new MenuIO(element, options, menuData); + Menu.show(position.x, position.y); + }); + } + + function setMsgChanged(name) { + MSG_CHANGED = 'Do you want to save changes to ' + name + '?'; + } + + function isChanged() { + const editor = CloudCmd.Edit.getEditor(); + const is = editor.isChanged(); + + if (!is) + return; + + const cancel = false; + Dialog.confirm(TITLE, MSG_CHANGED, {cancel}) + .then(() => { + editor.save(); + }); + } + + function listener({keyCode, shiftKey}) { + if (shiftKey && keyCode === Key.ESC) + EditFileVim.hide(); + } + + init(callback); +}; + diff --git a/client/modules/edit-file.js b/client/modules/edit-file.js index 453135ce..97b68f25 100644 --- a/client/modules/edit-file.js +++ b/client/modules/edit-file.js @@ -71,13 +71,11 @@ CloudCmd.EditFile = function EditFileProto(callback) { setMsgChanged(name); CloudCmd.Edit + .show(ConfigView) .getEditor() .setValueFirst(path, data) .setModeForPath(name) - .setOption('fontSize', 16) .enableKey(); - - CloudCmd.Edit.show(ConfigView); }); }; diff --git a/client/modules/edit-names.js b/client/modules/edit-names.js index d94136c7..d1d09664 100644 --- a/client/modules/edit-names.js +++ b/client/modules/edit-names.js @@ -58,7 +58,6 @@ CloudCmd.EditNames = function EditNamesProto(callback) { .getEditor() .setValueFirst('edit-names', names) .setMode() - .setOption('fontSize', 16) .disableKey(); DOM.Events.addKey(keyListener); diff --git a/client/modules/edit.js b/client/modules/edit.js index e3c42cbf..d78252d9 100644 --- a/client/modules/edit.js +++ b/client/modules/edit.js @@ -84,6 +84,14 @@ function EditProto(callback) { return; CloudCmd.View.show(Element, initConfig(options)); + + Edit.getEditor() + .setOptions({ + keyMap: 'default', + fontSize: 16, + }); + + return Edit; }; Edit.getEditor = () => { @@ -96,6 +104,7 @@ function EditProto(callback) { Edit.hide = () => { CloudCmd.View.hide(); + return Edit; }; function _loadFiles(element, callback) { diff --git a/client/modules/view.js b/client/modules/view.js index 2fd315f7..c9a6145f 100644 --- a/client/modules/view.js +++ b/client/modules/view.js @@ -38,6 +38,7 @@ const Config = { exec(callback); }, beforeClose: (callback) => { + Events.rmKey(listener); Key.setBind(); exec(callback); hideOverlay(); @@ -91,8 +92,6 @@ function ViewProto(callback) { Events.add(name, Overlay, onOverLayClick); }); - Events.addKey(listener); - return module.exports; } @@ -102,6 +101,9 @@ function show(data, options) { if (Loading) return; + if (options && options.bindKeys !== false) + Events.addKey(listener); + El = $('
'); if (data) { diff --git a/json/modules.json b/json/modules.json index 618209bc..5252ceb7 100644 --- a/json/modules.json +++ b/json/modules.json @@ -2,6 +2,7 @@ "local": [ "edit", "edit-file", + "edit-file-vim", "edit-names", "menu", "view", diff --git a/webpack.config.js b/webpack.config.js index 860de1c6..c86cc703 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -43,6 +43,7 @@ module.exports = { cloudcmd: `${dir}/cloudcmd.js`, [modules + '/edit']: `${dirModules}/edit.js`, [modules + '/edit-file']: `${dirModules}/edit-file.js`, + [modules + '/edit-file-vim']: `${dirModules}/edit-file-vim.js`, [modules + '/edit-names']: `${dirModules}/edit-names.js`, [modules + '/menu']: `${dirModules}/menu.js`, [modules + '/view']: `${dirModules}/view.js`,