Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c78ac23

Browse filesBrowse files
committed
- added supported key bindings for readline to README
- added hook for C-l so shell clear command can be triggered by it - fixed word forward/back logic to consider only alphanumeric as word chars, and extracted logic for this so it can be used for word deletes
1 parent e6da4f4 commit c78ac23
Copy full SHA for c78ac23

File tree

Expand file treeCollapse file tree

3 files changed

+117
-36
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+117
-36
lines changed

‎README.md

Copy file name to clipboardExpand all lines: README.md
+54-4Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,8 @@ josh.js is licensed under the Apache 2.0 License
2525
* `more`-like handling for output that exceeds the shell viewport size
2626
* resizing and close chrome
2727
* scrollwheel support
28-
* Readline Issues/Omissions
29-
* Not handling spaces in path completion
30-
* Missing support for Alt-Backspace & Alt-D in readline.js
31-
* ***Word***-commands do not have path separator awareness
28+
* Readline has not been tested with non-ascii.
29+
* [Readline Issues/Omissions](https://github.com/sdether/josh.js/issues/1)
3230

3331
## Usage
3432

@@ -43,6 +41,58 @@ Until documentation is written, refer to `index.html` and `example.js` for a sam
4341

4442
It implements key trapping to bring [GNU Readline](http://cnswww.cns.cwru.edu/php/chet/readline/readline.html) like line editing to the browser. It can be used by itself to bring readline support to custom data entry fields or in conjunction with `shell.js` to create a full console.
4543

44+
#### Line Editing
45+
In the below `C-x` refers to the `Ctrl-x` keystroke, while `M-x` refers to the `Meta-x` which is currently only mapped to `Alt` (i.e. no `` yet).
46+
47+
48+
<dl>
49+
<dt><em>Movement</em></dt>
50+
<dt><code>C-b</code> or <code>Left Arrow</code></dt>
51+
<dd>Move back one character</dd>
52+
<dt><code>M-b</code> or <code>Right Arrow</code></dt>
53+
<dd>Move back one word</dd>
54+
<dt><code>C-f</code></dt>
55+
<dd>Move forward one character</dd>
56+
<dt><code>M-f</code></dt>
57+
<dd>Move forward one word</dd>
58+
<dt><code>C-a</code> or <code>Home</code></dt>
59+
<dd>Move to the beginning of the line</dd>
60+
<dt><code>C-e</code> or <code>End</code></dt>
61+
<dd>Move to the end of the line</dd>
62+
63+
<dt><em>Edit/Kill</em></dt>
64+
<dt><code>Backspace</code></dt>
65+
<dd>Delete one character back</dd>
66+
<dt><code>C-d</code> or <code>Delete</code></dt>
67+
<dd>Delete character under cursor</dd>
68+
<dt><code>C-k</code></dt>
69+
<dd><em>Kill</em> (i.e. put in kill buffer) text to the end of the line</dd>
70+
<dt><code>C-y</code></dt>
71+
<dd><em>Yank</em> (i.e. pull from kill buffer) the most recently <em>killed</em> text</dd>
72+
73+
<dt><em>History</em></dt>
74+
<dt><code>C-r</code></dt>
75+
<dd>Reverse search through history</dd>
76+
<dt><code>C-p</code> or <code>Up Arrow</code></dt>
77+
<dd>Previous entry in history</dd>
78+
<dt><code>C-n</code> or <code>Down Arrow</code></dt>
79+
<dd>Next entry in history</dd>
80+
<dt><code>Page Up</code></dt>
81+
<dd>Top of history</dd>
82+
<dt><code>Page Down</code></dt>
83+
<dd>Bottom of history</dd>
84+
85+
<dt><em>Misc</em></dt>
86+
<dt><code>C-l</code></dt>
87+
<dd>refresh line (clear screen in shell)</dd>
88+
<dt><code>Tab</code></dt>
89+
<dd>Invoke completion handler for text under cursor</dd>
90+
<dt><code>C-c</code> or <code>Esc</code></dt>
91+
<dd>Deactivate Readline (closes the shell)</dd>
92+
<dt><code>~</code></dt>
93+
<dd>Activate Readline (opens the shell)</dd>
94+
</dl>
95+
4696
### shell.js
4797
`shell.js` has external dependencies of [jQuery](http://jquery.com/), [Underscore](http://underscorejs.org/) and internal dependencies of `readline.js` and `history.js`.
4898

‎js/readline.js

Copy file name to clipboardExpand all lines: js/readline.js
+56-31Lines changed: 56 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ var Josh = Josh || {};
5656
var _onChange;
5757
var _onCancel;
5858
var _onEOT;
59+
var _onClear;
5960
var _onSearchStart;
6061
var _onSearchEnd;
6162
var _onSearchChange;
@@ -96,6 +97,9 @@ var Josh = Josh || {};
9697
onChange: function(changeHandler) {
9798
_onChange = changeHandler;
9899
},
100+
onClear: function(completionHandler) {
101+
_onClear = completionHandler;
102+
},
99103
onEnter: function(enterHandler) {
100104
_onEnter = enterHandler;
101105
},
@@ -267,42 +271,59 @@ var Josh = Josh || {};
267271
if(_cursor == 0) {
268272
return;
269273
}
270-
var previousWhitespace = 0;
271-
var findNonWhiteSpace = _text[_cursor] == ' ' || _text[_cursor - 1] == ' ';
272-
for(var i = _cursor - 1; i > 0; i--) {
273-
if(findNonWhiteSpace) {
274-
if(_text[i] != ' ') {
275-
findNonWhiteSpace = false;
276-
}
277-
} else {
278-
if(_text[i] == ' ') {
279-
previousWhitespace = i + 1;
280-
break;
281-
}
274+
updateCursor(findBeginningOfPreviousWord());
275+
}
276+
277+
function findBeginningOfPreviousWord() {
278+
var position = _cursor - 1;
279+
if(position < 0) {
280+
return 0;
281+
}
282+
var word = false;
283+
for(var i = position; i > 0; i--) {
284+
var word2 = isWordChar(_text[i]);
285+
if(word && !word2) {
286+
return i + 1;
287+
}
288+
word = word2;
289+
}
290+
return 0;
291+
}
292+
293+
function findEndOfCurrentWord() {
294+
if(_text.length == 0) {
295+
return 0;
296+
}
297+
var position = _cursor + 1;
298+
if(position >= _text.length) {
299+
return _text.length - 1;
300+
}
301+
var word = false;
302+
for(var i = position; i < _text.length; i++) {
303+
var word2 = isWordChar(_text[i]);
304+
if(word && !word2) {
305+
return i;
282306
}
307+
word = word2;
283308
}
284-
updateCursor(previousWhitespace);
309+
return _text.length - 1;
310+
}
311+
312+
function isWordChar(c) {
313+
if(c == undefined) {
314+
return false;
315+
}
316+
var code = c.charCodeAt(0);
317+
return (code >= 48 && code <= 57)
318+
|| (code >= 65 && code <= 90)
319+
|| (code >= 97 && code <= 122);
285320
}
286321

287322
function cmdForwardWord() {
288323
if(_cursor == _text.length) {
289324
return;
290325
}
291-
var nextWhitespace = _text.length;
292-
var findNonWhitespace = _text[_cursor] == ' ';
293-
for(var i = _cursor + 1; i < _text.length; i++) {
294-
if(findNonWhitespace) {
295-
if(_text[i] != ' ') {
296-
findNonWhitespace = false;
297-
}
298-
} else {
299-
if(_text[i] == ' ') {
300-
nextWhitespace = i;
301-
break;
302-
}
303-
}
304-
}
305-
updateCursor(nextWhitespace);
326+
updateCursor(findEndOfCurrentWord());
306327
}
307328

308329
function cmdHistoryPrev() {
@@ -358,8 +379,12 @@ var Josh = Josh || {};
358379
updateCursor(_cursor + _kill_buffer.length);
359380
}
360381

361-
function cmdRefresh() {
362-
refresh();
382+
function cmdClear() {
383+
if(_onClear) {
384+
_onClear();
385+
} else {
386+
refresh();
387+
}
363388
}
364389

365390
function cmdReverseSearch() {
@@ -576,7 +601,7 @@ var Josh = Josh || {};
576601
handled = true;
577602
break;
578603
case 76: // L
579-
queue(cmdRefresh);
604+
queue(cmdClear);
580605
handled = true;
581606
break;
582607
case 82: // R

‎js/shell.js

Copy file name to clipboardExpand all lines: js/shell.js
+7-1Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ var Josh = Josh || {};
167167
_panel.animate({scrollTop: _view.height()}, 0);
168168
},
169169
bestMatch: function(partial, possible) {
170-
_console.log("bestMatch on partial '"+partial+"'");
170+
_console.log("bestMatch on partial '" + partial + "'");
171171
var result = {
172172
completion: null,
173173
suggestions: []
@@ -307,6 +307,12 @@ var Josh = Josh || {};
307307
_line = line;
308308
self.render();
309309
});
310+
_readline.onClear(function() {
311+
_cmdHandlers.clear.exec(null, null, function() {
312+
renderOutput(null, function() {
313+
});
314+
});
315+
});
310316
_readline.onSearchStart(function() {
311317
$(_input_id).replaceWith(_search_html);
312318
_console.log('started search');

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.