diff --git a/lib/web_console/templates/console.js.erb b/lib/web_console/templates/console.js.erb index 6b8021bc..13afaeeb 100644 --- a/lib/web_console/templates/console.js.erb +++ b/lib/web_console/templates/console.js.erb @@ -706,6 +706,13 @@ REPLConsole.prototype.onKeyDown = function(ev) { } break; + case 67: // Ctrl-Shift-C + if (ev.ctrlKey && ev.shiftKey) { + this.deleteLine(); + ev.preventDefault(); + } + break; + case 69: // Ctrl-E if (ev.ctrlKey) { this.onTabKey(); @@ -724,36 +731,79 @@ REPLConsole.prototype.onKeyDown = function(ev) { ev.preventDefault(); break; - case 13: // Enter key + case 13: // Enter key this.onEnterKey(); + this.scrollToBottom(); ev.preventDefault(); break; case 38: // Up arrow this.onNavigateHistory(-1); + this.scrollToBottom(); ev.preventDefault(); break; case 40: // Down arrow this.onNavigateHistory(1); + this.scrollToBottom(); ev.preventDefault(); break; case 37: // Left arrow - var caretPos = this._caretPos > 0 ? this._caretPos - 1 : this._caretPos; - this.setInput(this._input, caretPos); + if (ev.ctrlKey) { + this.moveCaretToPreviousWord(); + }else{ + var caretPos = this._caretPos > 0 ? this._caretPos - 1 : this._caretPos; + this.setInput(this._input, caretPos); + } + this.scrollToBottom(); ev.preventDefault(); break; case 39: // Right arrow - var length = this._input.length; - var caretPos = this._caretPos < length ? this._caretPos + 1 : this._caretPos; - this.setInput(this._input, caretPos); + if (ev.ctrlKey) { + this.moveCaretToNextWord(); + } else { + var length = this._input.length; + var caretPos = this._caretPos < length ? this._caretPos + 1 : this._caretPos; + this.setInput(this._input, caretPos); + } + this.scrollToBottom(); + ev.preventDefault(); + break; + + case 76: // Ctrl-L + if (ev.ctrlKey) { + this.clear(); + ev.preventDefault(); + } + break; + + case 36: // Home + this.setInput(this._input, 0); ev.preventDefault(); break; - case 8: // Delete - this.deleteAtCurrent(); + case 35: // End + this.setInput(this._input, this._input.length); + ev.preventDefault(); + break; + + case 46: // Delete + if (ev.ctrlKey) { + this.deleteWordForward(); + }else { + this.deleteNext(); + } + ev.preventDefault(); + break; + + case 8: // Backspace + if (ev.ctrlKey) { + this.deleteWord(); + } else{ + this.deleteAtCurrent(); + } ev.preventDefault(); break; @@ -809,6 +859,32 @@ REPLConsole.prototype.deleteAtCurrent = function() { } }; +/** +* Delete the next character. +*/ +REPLConsole.prototype.deleteNext = function() { + if (this._caretPos < this._input.length) { + var caretPos = this._caretPos; + var before = this._input.substring(0, caretPos); + var after = this._input.substring(this._caretPos + 1, this._input.length); + this.setInput(before + after, caretPos); + + if (!this._input) { + this.autocomplete && this.autocomplete.cancel(); + this.autocomplete = false; + } + } +} + +REPLConsole.prototype.clear = function() { + this.autocomplete && this.autocomplete.cancel(); + this.autocomplete = false; + + var promptDisplayParentElement = this.promptDisplay.parentElement; + this.inner.textContent = ''; + this.inner.appendChild(promptDisplayParentElement); +} + /** * Deletes the current line. */ @@ -828,17 +904,13 @@ REPLConsole.prototype.deleteLine = function() { */ REPLConsole.prototype.deleteWord = function() { if (this._caretPos > 0) { - var i = 1, current = this._caretPos; - while (this._input[current - i++] == " "); - - var deleteIndex = 0; - for (; current - i > 0; i++) { - if (this._input[current - i] == " ") { - deleteIndex = current - i; - break; - } + var input = this._input, current = this._caretPos, deleteIndex = current; + while (deleteIndex > 0 && /\s/.test(input[deleteIndex - 1])) deleteIndex--; + if (/\w/.test(input[deleteIndex - 1])) { + while (deleteIndex > 0 && /\w/.test(input[deleteIndex - 1])) deleteIndex--; + } else { + while (deleteIndex > 0 && /[^\w\s]/.test(input[deleteIndex - 1])) deleteIndex--; } - var before = this._input.substring(0, deleteIndex); var after = this._input.substring(current, this._input.length); this.setInput(before + after, deleteIndex); @@ -850,6 +922,55 @@ REPLConsole.prototype.deleteWord = function() { } }; +REPLConsole.prototype.deleteWordForward = function() { + if (this._caretPos < this._input.length) { + var i = 0, current = this._caretPos; + while (current + i < this._input.length && this._input[current + i] === " ") i++; + var deleteIndex; + if (current + i < this._input.length && /\w/.test(this._input[current + i])) { + while (current + i < this._input.length && /\w/.test(this._input[current + i])) i++; + deleteIndex = current + i; + } else { + while (current + i < this._input.length && /[^\w\s]/.test(this._input[current + i])) i++; + deleteIndex = current + i; + } + var before = this._input.substring(0, current); + var after = this._input.substring(deleteIndex, this._input.length); + this.setInput(before + after, current); + if (!this._input) { + this.autocomplete && this.autocomplete.cancel(); + this.autocomplete = false; + } + } +}; + +REPLConsole.prototype.moveCaretToNextWord = function() { + if (this._caretPos < this._input.length) { + let current = this._caretPos; + while (current < this._input.length && this._input[current] === " ") { + current++; + } + if (current < this._input.length) { + const isWordCharacter = /\w/.test(this._input[current]); + while (current < this._input.length && /\w/.test(this._input[current]) === isWordCharacter) current++; + } + this.setInput(this._input, current); + } +}; + +REPLConsole.prototype.moveCaretToPreviousWord = function() { + if (this._caretPos > 0) { + let current = this._caretPos; + while (current > 0 && this._input[current - 1] === " ") current--; + if (current > 0) { + const isWordCharacter = /\w/.test(this._input[current - 1]); + while (current > 0 && /\w/.test(this._input[current - 1]) === isWordCharacter) current--; + } + this.setInput(this._input, current); + } +}; + + /** * Insert a character at the current position. */ diff --git a/lib/web_console/templates/style.css.erb b/lib/web_console/templates/style.css.erb index 4e80780f..4cc4460e 100644 --- a/lib/web_console/templates/style.css.erb +++ b/lib/web_console/templates/style.css.erb @@ -28,11 +28,12 @@ } .console { + --console-font-size: .8rem; position: fixed; left: 0; bottom: 0; width: 100%; - height: 148px; + height: 12rem; padding: 0; margin: 0; background: none repeat scroll 0% 0% #333; @@ -46,7 +47,7 @@ .console .console-inner { font-family: monospace; - font-size: 11px; + font-size: var(--console-font-size); width: 100%; height: 100%; overflow: unset; @@ -99,10 +100,19 @@ color: #096; } +.console .console-prompt-box:last-child .console-cursor{ + border: 1px solid #fefefe; +} + +.console .console-focus .console-prompt-box:last-child .console-cursor { + animation: blink 1s step-end infinite; +} + .console .console-focus .console-cursor { background: #fefefe; color: #333; font-weight: bold; + border: none; } .console .resizer { @@ -124,10 +134,10 @@ cursor: pointer; border-radius: 1px; font-family: monospace; - font-size: 13px; - width: 14px; - height: 14px; - line-height: 14px; + font-size: 1.3rem; + width: 1.2rem; + height: 1.2rem; + line-height: 1.2rem; text-align: center; color: #ccc; } @@ -180,3 +190,14 @@ .console.full-screen .close-button { display: none; } + +@keyframes blink { + from, to { + background-color: #fefefe; + color: #333; + } + 50% { + background-color: transparent; + color: #fefefe; + } +} \ No newline at end of file diff --git a/lib/web_console/version.rb b/lib/web_console/version.rb index 66e31769..29ff7135 100644 --- a/lib/web_console/version.rb +++ b/lib/web_console/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module WebConsole - VERSION = "4.2.1" + VERSION = "4.2.2" end