summaryrefslogtreecommitdiff
path: root/js/codeq/console.js
diff options
context:
space:
mode:
authorAleš Smodiš <aless@guru.si>2015-09-15 18:47:26 +0200
committerAleš Smodiš <aless@guru.si>2015-09-15 18:47:26 +0200
commit6bb35042ef6fb19d9af5ee874de9da2816cbc5d7 (patch)
treef476a8db9f3275d571e39f81de8dce4ec95e7d00 /js/codeq/console.js
parent39fa66c8602bad9278d6683b35e0be6cc1ab92cc (diff)
Augmenting the console:
- implemented the support of the leftmostCol, the column from which the editing is allowed, - the onInput() handler can return a Promise, which is then waited on to be resolved before further input is allowed, - pasted multi-line content is split into lines, and processed line-by-line as if a single line was pasted multiple times.
Diffstat (limited to 'js/codeq/console.js')
-rw-r--r--js/codeq/console.js120
1 files changed, 73 insertions, 47 deletions
diff --git a/js/codeq/console.js b/js/codeq/console.js
index ddf4ce6..41aae40 100644
--- a/js/codeq/console.js
+++ b/js/codeq/console.js
@@ -263,11 +263,12 @@
handler = {
'setLineBuffered': function () { lineBuffered = true; },
'setNotBuffered': function () { lineBuffered = false; },
- 'onInput': false, // the caller should assign a function here, that takes input as parameter
+ 'onInput': false, // the caller should assign a function here, that takes input as parameter, and optionally returns a promise which is then waited to be resolved before further input is accepted
'onKeypress': false, // same, but it takes a keycode, and returns a keycode
'inputEnable': function () { inputDisabled = false; },
'inputDisable': function () { inputDisabled = true; },
'keyMaps': {}, // will be filled in later
+ 'leftmostCol': 0, // the column from where editing is possible; it is not possible to delete or change a character to the left of this column
'reflow': function () {
var startRow, endRow, i, lineDescriptor;
@@ -463,7 +464,8 @@
},
'moveLeft': function () {
- if (currentCol > 0) {
+ var leftmost = typeof this.leftmostCol === 'number' && this.leftmostCol || 0;
+ if (currentCol > leftmost) {
currentCol--;
renderLine(lines[currentRow]);
}
@@ -479,8 +481,9 @@
'deleteCharacterLeft': function () {
var lineDescriptor = lines[currentRow],
- content = lineDescriptor.content;
- if ((currentCol > 0) && (currentCol <= content.length)) {
+ content = lineDescriptor.content,
+ leftmost = typeof this.leftmostCol === 'number' && this.leftmostCol || 0;
+ if ((currentCol > leftmost) && (currentCol <= content.length)) {
currentCol--;
lineDescriptor.content = content.substring(0, currentCol) + content.substring(currentCol + 1);
renderLine(lineDescriptor);
@@ -547,65 +550,88 @@
}
},
+ internallyDisabled = false,
+
handleInput = function (chars) {
- var cookedChars = chars, // default
- startingRow = currentRow,
- dh, i;
+ var isPastedFromClipboard = clipboardPasteInProgress || !aKeyIsDown,
+ newLines = chars.split('\n'),
+ N = newLines.length,
+ lastLineIndex = N - 1,
+ i, promise;
- if (inputDisabled) {
+ if (inputDisabled || internallyDisabled) {
// flatly ignore
clipboardPasteInProgress = false;
return;
}
- // first cook the input
- if (typeof handler.onKeypress === 'function') {
- try {
- cookedChars = handler.onKeypress(chars, clipboardPasteInProgress || !aKeyIsDown);
- }
- catch (e) {
- // TODO: log error
- }
- }
+ internallyDisabled = true;
+ promise = Q();
- if (!cookedChars) {
- // nothing to append
- clipboardPasteInProgress = false;
- return;
- }
+ for (i = 0; i < N; i++) {
+ promise = promise
+ .then((function (newLine, lineIndex) {return function () {
+ var cookedChars = lineIndex < lastLineIndex ? newLine + '\n' : newLine, // default
+ thisRow = currentRow,
+ leftmost = typeof this.leftmostCol === 'number' && this.leftmostCol || 0,
+ dh;
- // now serve the cooking
- handler.insertAtCursor(cookedChars, 'input'); // append what we have to the display
- if (typeof handler.onInput === 'function') { // now tell the owner what we've done
- if (lineBuffered) {
- if (currentRow !== startingRow) {
- // in line-buffered mode emit each line separately, except for the last (current) line
- for (i = startingRow; i < lines.length; i++) {
+ // first cook the input
+ if (typeof handler.onKeypress === 'function') {
+ // only invoke the handler if the newLine is not an empty string, otherwise cookedChars = ''
try {
- handler.onInput(lines[i].content);
+ cookedChars = cookedChars && handler.onKeypress(cookedChars, isPastedFromClipboard);
}
catch (e) {
- // TODO: log error
+ codeq.log.error('Error during invocation of terminal onKeypress: ' + e, e);
}
}
- }
- }
- else {
- try {
- handler.onInput(cookedChars);
- }
- catch (e) {
- // TODO: log error
- }
- }
+
+ if (!cookedChars) {
+ // nothing to append
+ return;
+ }
+
+ // now serve the cooking
+ handler.insertAtCursor(cookedChars, 'input'); // append what we have to the display
+ // scroll to bottom on input
+ dh = jqContent.height() - jqElt.height();
+ if (dh > 0)
+ jqElt.scrollTop(dh);
+
+ if (typeof handler.onInput === 'function') { // now tell the owner what we've done
+ if (lineBuffered) {
+ if (thisRow < currentRow) {
+ // in line-buffered mode emit each line separately, except for the last (current) line
+ try {
+ return handler.onInput(lines[thisRow].content.substring(leftmost));
+ }
+ catch (e) {
+ codeq.log.error('Error while invoking terminal onInput: ' + e, e);
+ }
+ }
+ }
+ else if (cookedChars) {
+ try {
+ return handler.onInput(cookedChars);
+ }
+ catch (e) {
+ codeq.log.error('Error while invoking terminal onInput: ' + e, e);
+ }
+ }
+ }
+
+ };})(newLines[i], i))
+ .fail(function (e) {
+ codeq.log.error('Error in handleInput loop: ' + e, e);
+ });
}
- clipboardPasteInProgress = false;
+ promise.fin(function () {
+ internallyDisabled = false;
+ }).done();
- // scroll to bottom on input
- dh = jqContent.height() - jqElt.height();
- if (dh > 0)
- jqElt.scrollTop(dh);
+ clipboardPasteInProgress = false;
},
clipboardPasteInProgress = false, // whether the previous keydown was a CTRL+V or shift+insert
@@ -646,7 +672,7 @@
jqInput.on('keydown', function (evt) {
var modifiers = ['' + (0 + evt.shiftKey), '' + (0 + (evt.ctrlKey || evt.metaKey)), '' + (0 + evt.altKey)].join(''),
handlersForModifiers = handler.keyMaps[modifiers],
- acceptKeydown = !inputDisabled, // the default value
+ acceptKeydown = !(inputDisabled || internallyDisabled), // the default value
eventInfo = processKeyboardEvent(evt),
handlerForKeydown = handlersForModifiers && handlersForModifiers[eventInfo.code];