From 235d86cd8f70a97bff56b796b4ef4f65c13969df Mon Sep 17 00:00:00 2001 From: Arne Claassen Date: Mon, 21 Jan 2013 10:16:17 -0800 Subject: [PATCH] Squashed commit of the following: commit ffa42c733df89f044a669f690ce54a24492e7050 Author: Arne Claassen Date: Mon Jan 21 09:25:50 2013 -0800 refactored cmd handling (removed redundant state variable) commit 711e948d6d2c3c3d0ed1b4f4717c0d32aa370d89 Merge: 6a8bd8f 172ae4b Author: Arne Claassen Date: Mon Jan 21 00:21:29 2013 -0800 Merge branch 'fix_backspace' into issue_7 commit 172ae4b1fbc11005864c1699e1195c7569faab64 Author: Arne Claassen Date: Mon Jan 21 00:19:47 2013 -0800 fixing backspace behavior broken by 0.2.5 commit 6a8bd8fc3d7ba626ecb9a22e65ca67d1831b6cc4 Author: Arne Claassen Date: Sun Jan 20 15:17:57 2013 -0800 removed activation/deactivation keyhandling and made an external concern --- README.md | 18 +++- index.html | 6 +- js/example.js | 35 ++++--- js/readline.js | 246 +++++++++++++++++++------------------------------ js/shell.js | 11 ++- 5 files changed, 145 insertions(+), 171 deletions(-) diff --git a/README.md b/README.md index f4baa52..1b88120 100644 --- a/README.md +++ b/README.md @@ -94,10 +94,12 @@ In the below `C-x` refers to the `Ctrl-x` keystroke, while `M-x` refers to the `
refresh line (clear screen in shell)
Tab
Invoke completion handler for text under cursor
-
C-c or Esc
-
Deactivate Readline (closes the shell)
-
~
-
Activate Readline (opens the shell)
+
Esc in reverse search
+
Cancel search
+
C-c
+
call onCancel handler
+
C-d on empty line
+
call onCancel handler
### shell.js @@ -123,8 +125,14 @@ By implementing the functions `getNode` and `getChildNodes`, this library adds p ## Changelog +**0.2.6** -- +* Removed Activation/Deactivation keybindings from Readline, making it an outside concern (see: [Issue 2](https://github.com/sdether/josh.js/issues/2 ) +* Fixed Backspace regression introduced by 0.2.5 +* Fixed `M-d` not deleting last character of line +* Example shell can now be resized (via jquery-ui.resizable) + **0.2.5** -- 2013/01/14 -* Implemented missing Readline behavior (see: [Issue 1](https://github.com/sdether/josh.js/issues/1) +* Implemented missing Readline behavior (see: [Issue 1](https://github.com/sdether/josh.js/issues/1 ) * Added scrollbar to sample implemenation (also adds scrollwheel support) **0.2.4** -- 2013/01/14 diff --git a/index.html b/index.html index bc9a676..1813906 100755 --- a/index.html +++ b/index.html @@ -1,3 +1,4 @@ + @@ -5,7 +6,9 @@ Shell testbed - + + + @@ -41,5 +44,6 @@

Press ~ to activate console.

+ \ No newline at end of file diff --git a/js/example.js b/js/example.js index 884b0de..d488ecd 100644 --- a/js/example.js +++ b/js/example.js @@ -166,24 +166,37 @@ }; $(document).ready(function() { - var consolePanel = $('#shell-panel'); - + $(document).keypress(function(event) { + if(shell.isActive()) { + return; + } + _console.log("activating shell"); + if(event.keyCode == 126) { + event.preventDefault(); + shell.activate(); + showConsole(); + } + }); + var $consolePanel = $('#shell-panel'); + $consolePanel.resizable({ handles: "s"}); function showConsole() { - consolePanel.slideDown(); - consolePanel.focus(); + $consolePanel.slideDown(); + $consolePanel.focus(); } function hideConsole() { - consolePanel.slideUp(); - consolePanel.blur(); + $consolePanel.slideUp(); + $consolePanel.blur(); } - shell.onActivate(function() { - showConsole(); - }); - shell.onDeactivate(function() { + function hideAndDeactivate() { + _console.log("deactivating shell") + shell.deactivate(); hideConsole(); - }); + } + + shell.onEOT(hideAndDeactivate); + shell.onCancel(hideAndDeactivate); }); Josh.Instance = { Tree: root, diff --git a/js/readline.js b/js/readline.js index 770f13e..2534ce6 100644 --- a/js/readline.js +++ b/js/readline.js @@ -15,6 +15,7 @@ *-------------------------------------------------------------------------*/ var Josh = Josh || {}; +Josh.Version = "0.2.6"; (function(root) { var SPECIAL = { 8: 'BACKSPACE', @@ -45,7 +46,6 @@ var Josh = Josh || {}; } }); var _history = config.history || new Josh.History(); - var _activationKey = config.activationKey || { keyCode: 192, shiftKey: true }; // ~ var _deactivationKey = config.deactivationKey || { keyCode: 27 }; // Esc var _killring = config.killring || new Josh.KillRing(); var _active = false; @@ -53,7 +53,6 @@ var Josh = Josh || {}; var _onDeactivate; var _onCompletion; var _onEnter; - var _onKeydown; var _onChange; var _onCancel; var _onEOT; @@ -73,6 +72,9 @@ var Josh = Josh || {}; // public methods var self = { + isActive: function() { + return _active; + }, activate: function() { _active = true; if(_onActivate) { @@ -91,9 +93,6 @@ var Josh = Josh || {}; onDeactivate: function(completionHandler) { _onDeactivate = completionHandler; }, - onKeydown: function(keydownHandler) { - _onKeydown = keydownHandler; - }, onChange: function(changeHandler) { _onChange = changeHandler; }, @@ -155,7 +154,7 @@ var Josh = Josh || {}; _console.log('calling: ' + cmd.name + ', previous: ' + _lastCmd); if(_inSearch && cmd.name != "cmdKeyPress" && cmd.name != "cmdReverseSearch") { _inSearch = false; - if(cmd.name == 'cmdCancelSearch') { + if(cmd.name == 'cmdEsc') { _searchMatch = null; } if(_searchMatch) { @@ -192,8 +191,12 @@ var Josh = Josh || {}; resume(); } - function cmdCancelSearch() { - // do nothing.. action for this was already taken in call() + function cmdNoOp() { + // no-op, used for keys we capture and ignore + } + + function cmdEsc() { + // no-op, only has an effect on reverse search and that action was taken in call() } function cmdBackspace() { @@ -333,15 +336,15 @@ var Josh = Josh || {}; function cmdKillWordForward() { if(_text.length == 0) { - if(_onEOT) { - _onEOT(); - return; - } + return; } if(_cursor == _text.length) { return; } var end = findEndOfCurrentWord(); + if(end == _text.length - 1) { + return cmdKillToEOF(); + } _killring.append(_text.substring(_cursor, end)) _text = remove(_text, _cursor, end); refresh(); @@ -451,13 +454,6 @@ var Josh = Josh || {}; updateCursor(_text.length); } - function checkKeyMatch(a, b) { - return a.keyCode == b.keyCode - && Boolean(a.shiftKey) == Boolean(b.shiftKey) - && Boolean(a.ctrlKey) == Boolean(b.ctrlKey) - && Boolean(a.altKey) == Boolean(b.altKey); - } - function findBeginningOfPreviousWord() { var position = _cursor - 1; if(position < 0) { @@ -534,187 +530,136 @@ var Josh = Josh || {}; root.onkeydown = function(e) { e = e || window.event; - // check if the keypress is an the activation key - if(!_active && checkKeyMatch(e, _activationKey)) { - self.activate(); - return false; - } - // return as unhandled if we're not active or the key is just a modifier key if(!_active || e.keyCode == 16 || e.keyCode == 17 || e.keyCode == 18 || e.keyCode == 91) { return true; } - var handled = true; + var cmd = null; - // check for some special keys, regardless of modifiers + // check for some special first keys, regardless of modifiers switch(e.keyCode) { + case 8: // Backspace + cmd = cmdBackspace; + break; case 9: // Tab - queue(cmdComplete); + cmd = cmdComplete; break; case 13: // Enter - queue(cmdDone); + cmd = cmdDone; break; case 27: // Esc - if(_inSearch) { - queue(cmdCancelSearch); - } else { - handled = false; - } + cmd = cmdEsc; break; case 33: // Page Up - queue(cmdHistoryTop); + cmd = cmdHistoryTop; break; case 34: // Page Down - queue(cmdHistoryEnd); + cmd = cmdHistoryEnd; break; case 35: // End - queue(cmdEnd); + cmd = cmdEnd; break; case 36: // Home - queue(cmdHome); + cmd = cmdHome; break; case 37: // Left - queue(cmdLeft); + cmd = cmdLeft; break; case 38: // Up - queue(cmdHistoryPrev); + cmd = cmdHistoryPrev; break; case 39: // Right - queue(cmdRight); + cmd = cmdRight; break; case 40: // Down - queue(cmdHistoryNext); + cmd = cmdHistoryNext; break; case 46: // Delete - queue(cmdDeleteChar); + cmd = cmdDeleteChar; break; // these we catch and have no commands for case 10: // Pause case 19: // Caps Lock case 45: // Insert + cmd = cmdNoOp; break; // all others we don't handle at this level default: - handled = false; break; } - if(!handled) { - - // intercept ctrl- and meta- sequences - if(e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey) { - switch(e.keyCode) { - case 8: // Backspace - - // Backspace behaves the same with or without Ctrl, but different for meta - queue(cmdBackspace); - break; - case 65: // A - queue(cmdHome); - handled = true; - break; - case 66: // B - queue(cmdLeft); - handled = true; - break; - case 67: // C - queue(cmdCancel); - handled = true; - break; - case 68: // D - queue(cmdDeleteChar); - handled = true; - break; - case 69: // E - queue(cmdEnd); - handled = true; - break; - case 70: // F - queue(cmdRight); - handled = true; - break; - case 80: // P - queue(cmdHistoryPrev); - handled = true; - break; - case 78: // N - queue(cmdHistoryNext); - handled = true; - break; - case 75: // K - queue(cmdKillToEOF); - handled = true; - break; - case 89: // Y - queue(cmdYank); - handled = true; - break; - case 76: // L - queue(cmdClear); - handled = true; - break; - case 82: // R - queue(cmdReverseSearch); - handled = true; - break; - } - } else if((e.altKey || e.metaKey) && !e.ctrlKey && !e.shiftKey) { - switch(e.keyCode) { - case 8: // Backspace - queue(cmdKillWordBackward); - break; - case 66: // B - queue(cmdBackwardWord); - handled = true; - break; - case 68: // D - queue(cmdKillWordForward); - handled = true; - break; - case 70: // F - queue(cmdForwardWord); - handled = true; - break; - case 89: // Y - queue(cmdRotate); - handled = true; - break; - } - } else { - // check for some more special keys without Ctrl or Alt - switch(e.keyCode) { - case 8: // Backspace - queue(cmdBackspace); - break; - } - } - } - if(!handled) { - if(!checkKeyMatch(e, _deactivationKey)) { - return true; + // intercept ctrl- and meta- sequences (may override the non-modifier cmd captured above + if(e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey) { + switch(e.keyCode) { + case 65: // A + cmd = cmdHome; + break; + case 66: // B + cmd = cmdLeft; + break; + case 67: // C + cmd = cmdCancel; + break; + case 68: // D + cmd = cmdDeleteChar; + break; + case 69: // E + cmd = cmdEnd; + break; + case 70: // F + cmd = cmdRight; + break; + case 80: // P + cmd = cmdHistoryPrev; + break; + case 78: // N + cmd = cmdHistoryNext; + break; + case 75: // K + cmd = cmdKillToEOF; + break; + case 89: // Y + cmd = cmdYank; + break; + case 76: // L + cmd = cmdClear; + break; + case 82: // R + cmd = cmdReverseSearch; + break; } - self.deactivate(); - } else { - var info = getKeyInfo(e); - if(_onKeydown) { - _onKeydown({ - code: e.keyCode, - shift: e.shiftKey, - control: e.controlKey, - alt: e.altKey, - name: SPECIAL[e.keyCode], - isChar: false - }); + } else if((e.altKey || e.metaKey) && !e.ctrlKey && !e.shiftKey) { + switch(e.keyCode) { + case 8: // Backspace + cmd = cmdKillWordBackward; + break; + case 66: // B + cmd = cmdBackwardWord; + break; + case 68: // D + cmd = cmdKillWordForward; + break; + case 70: // F + cmd = cmdForwardWord; + break; + case 89: // Y + cmd = cmdRotate; + break; } } + if(!cmd) { + return true; + } + queue(cmd); e.preventDefault(); e.stopPropagation(); e.cancelBubble = true; return false; }; + root.onkeypress = function(e) { if(!_active) { return true; @@ -729,9 +674,6 @@ var Josh = Josh || {}; } else { addText(key.character); } - if(_onKeydown) { - _onKeydown(key); - } }); e.preventDefault(); e.stopPropagation(); diff --git a/js/shell.js b/js/shell.js index 233d31f..681e72c 100644 --- a/js/shell.js +++ b/js/shell.js @@ -97,6 +97,9 @@ var Josh = Josh || {}; // public methods var self = { commands: commands, + isActive: function() { + return _readline.isActive(); + }, activate: function() { if($(_shell_view_id).length == 0) { _active = false; @@ -122,6 +125,12 @@ var Josh = Josh || {}; } self.refresh(); }, + onEOT: function(completionHandler) { + _readline.onEOT(completionHandler); + }, + onCancel: function(completionHandler) { + _readline.onCancel(completionHandler); + }, onInitialize: function(completionHandler) { _initializationHandler = completionHandler; }, @@ -379,8 +388,6 @@ var Josh = Josh || {}; return callback(match.completion); }); }); - _readline.onEOT(self.deactivate); - _readline.onCancel(self.deactivate); return self; } })(this, $, _);