diff --git a/HELP.md b/HELP.md index ee2aaf24..f042ac8e 100644 --- a/HELP.md +++ b/HELP.md @@ -55,26 +55,26 @@ cloudcmd Cloud Commander supports command line parameters: -|Parameter |Operation -|:--------------------------|:-------------------------------------------- -| `-h, --help` | display help and exit -| `-v, --version` | display version and exit -| `-s, --save` | save configuration -| `-o, --online` | load scripts from remote servers -| `-a, --auth` | enable authorization -| `-u, --username` | set username -| `-p, --password` | set password -| `-c, --config` | configuration file path -| `--editor` | set editor: "dword" or "edward" -| `--root` | set root directory -| `--port` | set port number -| `--no-auth` | disable authorization -| `--no-server` | do not start server -| `--no-online` | load scripts from local server -| `--minify` | enable minification -| `--no-minify` | disable minification -| `--progress-of-copying` | show progress of copying -| `--no-progress-of-copying`| do not show progress of copying +|Parameter |Operation +|:------------------------------|:------------------------------ +| `-h, --help` | display help and exit +| `-v, --version` | display version and exit +| `-s, --save` | save configuration +| `-o, --online` | load scripts from remote servers +| `-a, --auth` | enable authorization +| `-u, --username` | set username +| `-p, --password` | set password +| `-c, --config` | configuration file path +| `--editor` | set editor: "dword" or "edward" +| `--root` | set root directory +| `--port` | set port number +| `--no-auth` | disable authorization +| `--no-server` | do not start server +| `--no-online` | load scripts from local server +| `--minify` | enable minification +| `--no-minify` | disable minification +| `--progress` | show progress of file operations +| `--no-progress` | do not show progress of file operations If no parameters given Cloud Commander reads information from `~/.cloudcmd.json` and use port from it (`8000` default). if port variables `PORT` or `VCAP_APP_PORT` isn't exist. @@ -215,7 +215,7 @@ Here is description of options: "port" : 8000, /* http port */ "ip" : null, /* ip or null(default) */ "root" : "/" /* root directory */ - "progressOfCopying" : false /* show progress of copying */ + "progress" : false /* show progress of file operations */ } ``` diff --git a/img/screen/config.png b/img/screen/config.png index 0d57756f..1da52b59 100644 Binary files a/img/screen/config.png and b/img/screen/config.png differ diff --git a/json/bin.json b/json/bin.json index 6eed0e1d..081cfbef 100644 --- a/json/bin.json +++ b/json/bin.json @@ -15,6 +15,6 @@ "--no-online ": "load scripts from local server", "--minify ": "enable minification", "--no-minify ": "disable minification", - "--progress-of-copying ": "show progress of copying", - "--no-progress-of-copying ": "not show progress of copying" + "--progress ": "show progress of file operations", + "--no-progress ": "not show progress of file operations" } diff --git a/json/config.json b/json/config.json index 9f15125d..25219e84 100644 --- a/json/config.json +++ b/json/config.json @@ -17,5 +17,5 @@ "port": 8000, "ip": null, "root": "/", - "progressOfCopying": false + "progress": false } diff --git a/lib/client/dom.js b/lib/client/dom.js index 45fe1e41..54dd5834 100644 --- a/lib/client/dom.js +++ b/lib/client/dom.js @@ -512,96 +512,6 @@ var CloudCmd, Util, DOM, CloudFunc, Dialog; }); }; - /** - * prompt and delete current file or selected files - * - * @currentFile - */ - this.promptDelete = function(currentFile) { - var ret, type, isDir, msg, current, - name = '', - msgAsk = 'Do you really want to delete the ', - msgSel = 'selected ', - files = Cmd.getSelectedFiles(), - names = Cmd.getSelectedNames(files), - i, n = names && names.length; - - if (!Cmd.isCurrentFile(currentFile)) - current = DOM.getCurrentFile(); - - if (n) { - for (i = 0; i < 5 && i < n; i++) - name += '\n' + names[i]; - - if (n >= 5) - name += '\n...'; - - msg = msgAsk + msgSel + n + ' files/directoris?\n' + name ; - } else { - isDir = Cmd.isCurrentIsDir(current); - - if (isDir) - type = 'directory'; - else - type = 'file'; - - type += ' '; - - name = Cmd.getCurrentName(current); - msg = msgAsk + msgSel + type + name + '?'; - } - - if (name !== '..') - ret = Dialog.confirm(msg); - else - Dialog.alert('No files selected!'); - - if (ret) - DOM.sendDelete(files); - - return ret; - }; - - /** - * delete current or selected files - * - * @files - */ - this.sendDelete = function(files) { - var n, names, path, - query = '', - RESTful = DOM.RESTful, - current = CurrentInfo.element; - - Images.show(); - - if (!files) - files = Cmd.getSelectedFiles(); - - names = DOM.getSelectedNames(files), - n = names && names.length; - - if (n) { - path = Cmd.getCurrentDirPath(); - query = '?files'; - } else { - path = Cmd.getCurrentPath(current); - } - - RESTful.delete(path + query, names, function() { - var Storage = DOM.Storage, - dirPath = CurrentInfo.dirPath, - dir = CloudFunc.rmLastSlash(dirPath); - - if (n > 1) - DOM.deleteSelected(files); - else - DOM.deleteCurrent(current); - - Storage.removeMatch(dir); - }); - }; - /** * get current direcotory name */ diff --git a/lib/client/key.js b/lib/client/key.js index e31f0f0b..25839dc2 100644 --- a/lib/client/key.js +++ b/lib/client/key.js @@ -217,6 +217,7 @@ var CloudCmd, Util, DOM; function switchKey(event) { var i, name, isSelected, isDir, prev, next, + Operation = CloudCmd.Operation, current = Info.element, panel = Info.panel, path = Info.path, @@ -250,9 +251,9 @@ var CloudCmd, Util, DOM; case Key.DELETE: if (shift) - DOM.sendDelete(); + Operation.show('delete:silent'); else - DOM.promptDelete(current); + Operation.show('delete'); break; case Key.ASTERISK: @@ -291,12 +292,12 @@ var CloudCmd, Util, DOM; break; case Key.F5: - CloudCmd.Operation.show('copy'); + Operation.show('copy'); event.preventDefault(); break; case Key.F6: - CloudCmd.Operation.show('move'); + Operation.show('move'); event.preventDefault(); break; @@ -310,7 +311,7 @@ var CloudCmd, Util, DOM; break; case Key.F8: - DOM.promptDelete(current); + Operation.show('delete'); break; case Key.F9: diff --git a/lib/client/listeners.js b/lib/client/listeners.js index 4e1ee409..5bc76e8f 100644 --- a/lib/client/listeners.js +++ b/lib/client/listeners.js @@ -31,22 +31,27 @@ var Util, DOM, CloudFunc, CloudCmd; if (keysElement) Events.addClick(keysElement, function(event) { var element = event.target, - id = element.id, + id = element.id, + operation = function() { + var Operation = CloudCmd.Operation, + fn = Operation.show.bind(null, name); + + return fn; + }, clickFuncs = { 'f1' : CloudCmd.Help.show, + 'f2' : DOM.renameCurrent, 'f3' : CloudCmd.View.show, 'f4' : CloudCmd.Edit.show, - 'f5' : CloudCmd.Operation.show.bind(null, 'copy'), - 'f6' : CloudCmd.Operation.show.bind(null, 'move'), + 'f5' : operation('copy'), + 'f6' : operation('move'), + 'f7' : DOM.promptNewDir, + 'f8' : operation('delete'), 'f9' : CloudCmd.Menu.show, 'f10' : CloudCmd.Config.show, '~' : CloudCmd.Konsole.show, 'contact' : CloudCmd.Contact.show, - - 'f2' : DOM.renameCurrent, - 'f7' : DOM.promptNewDir, - 'f8' : DOM.promptDelete }, func = clickFuncs[id]; diff --git a/lib/client/menu.js b/lib/client/menu.js index 6bd70c84..26c60bdc 100644 --- a/lib/client/menu.js +++ b/lib/client/menu.js @@ -157,6 +157,9 @@ var CloudCmd, Util, DOM, CloudFunc, MenuIO; var show = function(name) { CloudCmd[name].show(); }, + + Operation = CloudCmd.Operation, + menuData = getMenuData(is), menu = { 'View' : Util.exec.with(show, 'View'), @@ -164,7 +167,7 @@ var CloudCmd, Util, DOM, CloudFunc, MenuIO; 'Rename' : function() { setTimeout(DOM.renameCurrent, 100); }, - 'Delete' : DOM.promptDelete, + 'Delete' : Operation.show.bind(null, 'delete'), 'Pack' : getActiveFunc(DOM.pack), 'Unpack' : getActiveFunc(DOM.unpack), 'Upload' : function() { diff --git a/lib/client/operation.js b/lib/client/operation.js index 189e144e..4d338317 100644 --- a/lib/client/operation.js +++ b/lib/client/operation.js @@ -1,11 +1,11 @@ /* global CloudCmd */ /* global Util */ /* global DOM */ -/* global CloudFunc */ /* global rendy */ /* global spero */ +/* global remedy */ -(function(CloudCmd, Util, DOM, CloudFunc, rendy) { +(function(CloudCmd, Util, DOM, rendy) { 'use strict'; CloudCmd.Operation = OperationProto; @@ -13,24 +13,33 @@ function OperationProto(operation, data) { var Name = 'Operation', Loaded, - copyFn = DOM.RESTful.cp, - moveFn = DOM.RESTful.mv, + RESTful = DOM.RESTful, + + copyFn = RESTful.cp, + moveFn = RESTful.mv, + deleteFn = RESTful.delete, + Images = DOM.Images, Dialog = DOM.Dialog, Operation = this; + + function rmLastSlash(str) { + return str.replace(/\/$/, ''); + } function init() { Images.show.load(); Util.exec.series([ + DOM.loadSocket, function(callback) { var Files = DOM.Files; Files.get('config', function(error, config) { if (error) alert(error); - else if (config.progressOfCopying) + else if (config.progress) load(function() { create(callback); }); @@ -48,51 +57,63 @@ function create(callback) { spero(function() { - var parse = function(fn) { - return function(data, callback) { - var listeners = { - progress: function(value) { - Images.setProgress(value); - }, - - end: function() { - callback(); - events.forEach(function(name) { - spero.removeListener(name, listeners[name]); - }); - }, - - error: function(data) { - var msg = data + '\n Continue?', - is = confirm(msg); - - if (is) - spero.continue(); - else - spero.abort(); - } - }, - events = Object.keys(listeners); - - Images.show('top'); - - fn(data.from, data.to, data.names); - - events.forEach(function(name) { - spero.on(name, listeners[name]); - }); + spero.on('connect', function() { + copyFn = function(data, callback) { + setListeners(spero, callback); + spero.copy(data.from, data.to, data.names); }; - }; - - spero.on('connect', function() { - copyFn = parse(spero.copy); }); spero.on('disconnect', function() { - copyFn = DOM.RESTful.cp; + copyFn = DOM.RESTful.cp; + }); + }); + + remedy(function() { + remedy.on('connect', function() { + deleteFn = function(from, files, callback) { + from = from.replace(/\?.*/, ''); + + setListeners(remedy, callback); + remedy.remove(from, files); + }; }); - Util.exec(callback); + remedy.on('disconnect', function() { + deleteFn = DOM.RESTful.remove; + }); + }); + + Util.exec(callback); + } + + function setListeners(emitter, callback) { + var listeners = { + progress: function(value) { + Images.setProgress(value); + }, + + end: function() { + callback(); + events.forEach(function(name) { + emitter.removeListener(name, listeners[name]); + }); + }, + + error: function(data) { + var msg = data + '\n Continue?', + is = confirm(msg); + + if (is) + spero.continue(); + else + spero.abort(); + } + }, + events = Object.keys(listeners); + + events.forEach(function(name) { + emitter.on(name, listeners[name]); }); } @@ -110,17 +131,117 @@ case 'move': Operation.move(data); break; + + case 'delete': + Operation.delete(); + break; + + case 'delete:silent': + Operation.deleteShift(); } }; - this.copy = function(data) { + this.copy = function(data) { processFiles(data, copyFn, message('Copy')); }; - this.move = function(data) { + this.move = function(data) { processFiles(data, moveFn, message('Rename/Move')); }; + this.delete = function() { + promptDelete(); + }; + + this.deleteSilent = function() { + deleteSilent(); + }; + + /** + * prompt and delete current file or selected files + * + * @currentFile + */ + function promptDelete() { + var ret, type, isDir, msg, + name = '', + msgAsk = 'Do you really want to delete the ', + msgSel = 'selected ', + files = DOM.getSelectedFiles(), + names = DOM.getSelectedNames(files), + i, n = names && names.length, + current = DOM.getCurrentFile(); + + if (n) { + for (i = 0; i < 5 && i < n; i++) + name += '\n' + names[i]; + + if (n >= 5) + name += '\n...'; + + msg = msgAsk + msgSel + n + ' files/directoris?\n' + name ; + } else { + isDir = DOM.isCurrentIsDir(current); + + if (isDir) + type = 'directory'; + else + type = 'file'; + + type += ' '; + + name = DOM.getCurrentName(current); + msg = msgAsk + msgSel + type + name + '?'; + } + + if (name !== '..') + ret = Dialog.confirm(msg); + else + Dialog.alert('No files selected!'); + + if (ret) + deleteSilent(files); + + return ret; + } + + /** + * delete current or selected files + * + * @files + */ + function deleteSilent(files) { + var n, names, + query = '?files', + Info = DOM.CurrentInfo, + path = Info.dirPath, + current = Info.element; + + Images.show(); + + if (!files) + files = DOM.getSelectedFiles(); + + names = DOM.getSelectedNames(files), + n = names && names.length; + + if (!n) + names = [Info.name]; + + deleteFn(path + query, names, function() { + var Storage = DOM.Storage, + dirPath = Info.dirPath, + dir = rmLastSlash(dirPath); + + if (n > 1) + DOM.deleteSelected(files); + else + DOM.deleteCurrent(current); + + Storage.removeMatch(dir); + }); + } + /* * process files (copy or move) * @param data @@ -128,7 +249,7 @@ */ function processFiles(data, operation, message) { var name, files, - CurrentInfo = DOM.CurrentInfo, + Info = DOM.CurrentInfo, panel, shouldAsk, sameName, @@ -144,14 +265,14 @@ from = data.from; to = data.to; names = data.names; - panel = CurrentInfo.panel; + panel = Info.panel; } else { - from = CurrentInfo.dirPath; + from = Info.dirPath; to = DOM.getNotCurrentDirPath(); names = DOM.getSelectedNames(); data = {}; shouldAsk = true; - panel = CurrentInfo.panelPassive; + panel = Info.panelPassive; } if (!names.length) @@ -184,11 +305,11 @@ }; operation(files, function() { - var path = CloudFunc.rmLastSlash(from); + var path = rmLastSlash(from); DOM.Storage.remove(path, function() { - var panel = CurrentInfo.panel, - panelPassive = CurrentInfo.panelPassive, + var panel = Info.panel, + panelPassive = Info.panelPassive, setCurrent = function() { var current; @@ -199,7 +320,7 @@ DOM.setCurrentFile(current); }; - if (!CurrentInfo.isOnePanel) + if (!Info.isOnePanel) CloudCmd.refresh(panelPassive, {noCurrent: true}, function() {}); CloudCmd.refresh(panel, setCurrent); @@ -231,7 +352,12 @@ } function load(callback) { - DOM.load.js('/spero/spero.js', function(error) { + var files = [ + '/spero/spero.js', + '/remedy/remedy.js' + ]; + + DOM.load.parallel(files, function(error) { if (error) { Dialog.alert(error.message); } else { @@ -247,4 +373,4 @@ init(); } -})(CloudCmd, Util, DOM, CloudFunc, rendy); +})(CloudCmd, Util, DOM, rendy); diff --git a/lib/cloudcmd.js b/lib/cloudcmd.js index 952a44e8..330cd6e6 100644 --- a/lib/cloudcmd.js +++ b/lib/cloudcmd.js @@ -23,6 +23,7 @@ edward = require('edward'), dword = require('dword'), spero = require('spero'), + remedy = require('remedy'), root = function() { return config('root'); @@ -99,6 +100,10 @@ spero.listen(socket, { root: root }); + + remedy.listen(socket, { + root: root + }); } function cloudcmd(prefix, socket) { @@ -161,6 +166,11 @@ online: isOnline }), + remedy({ + minify: isMinify, + online: isOnline + }), + mollify({ dir : DIR_ROOT, is : isMinify diff --git a/man/cloudcmd.1 b/man/cloudcmd.1 index 7626c8be..a800cdbc 100644 --- a/man/cloudcmd.1 +++ b/man/cloudcmd.1 @@ -22,24 +22,24 @@ programs in browser from any computer, mobile or tablet device. .SH OPTIONS - -h, --help display help and exit - -v, --version display version and exit - -s, --save save configuration - -o, --online load scripts from remote servers - -a, --auth enable authorization - -u, --username set username - -p, --password set password - -c, --config configuration file path - --editor set editor: "dword" or "edward" - --root set root directory - --port set port number - --no-auth disable authorization - --no-server do not start server - --no-online load scripts from local server - --minify enable minification - --no-minify disable minification - --progress-of-copying show progress of copying - --no-progress-of-copying do not show progress of copying + -h, --help display help and exit + -v, --version display version and exit + -s, --save save configuration + -o, --online load scripts from remote servers + -a, --auth enable authorization + -u, --username set username + -p, --password set password + -c, --config configuration file path + --editor set editor: "dword" or "edward" + --root set root directory + --port set port number + --no-auth disable authorization + --no-server do not start server + --no-online load scripts from local server + --minify enable minification + --no-minify disable minification + --progress show progress of file operations + --no-progress do not show progress of file operations .SH RESOURCES AND DOCUMENTATION diff --git a/package.json b/package.json index 745498cf..a87cebc4 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "pipe-io": "~1.1.1", "ponse": "~1.4.0", "readjson": "~1.1.0", + "remedy": "~1.0.5", "rendy": "~1.1.0", "restafary": "~1.3.0", "socket.io": "~1.3.5", diff --git a/tmpl/config.hbs b/tmpl/config.hbs index 487067b1..281279b3 100644 --- a/tmpl/config.hbs +++ b/tmpl/config.hbs @@ -123,8 +123,8 @@