From 9affe93ae56268e9cee81603b028904419805006 Mon Sep 17 00:00:00 2001 From: cpsdqs Date: Tue, 12 Sep 2017 23:08:59 +0200 Subject: [PATCH 01/10] Add mouse demo --- js/demo.js | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 5 deletions(-) diff --git a/js/demo.js b/js/demo.js index 48946ec..2a95e1e 100644 --- a/js/demo.js +++ b/js/demo.js @@ -82,7 +82,10 @@ class ANSIParser { // something something nothing this.currentSequence = 0 this.handler('write', character) - } else if (code === 0x07) this.handler('bell') + } else if (code < 0x03) this.handler('_null') + else if (code === 0x03) this.handler('sigint') + else if (code < 0x05) this.handler('_null') + else if (code === 0x07) this.handler('bell') else if (code === 0x08) this.handler('back') else if (code === 0x0a) this.handler('new-line') else if (code === 0x0d) this.handler('return') @@ -203,8 +206,8 @@ class ScrollingTerminal { } else if (action === 'return') { this.cursor.x = 0 } else if (action === 'set-cursor') { - this.cursor.x = args[0] - this.cursor.y = args[1] + this.cursor.x = args[1] + this.cursor.y = args[0] this.clampCursor() } else if (action === 'move-cursor-y') { this.cursor.y += args[0] @@ -370,7 +373,8 @@ let demoData = { } setTimeout(loop, 200) } - } + }, + mouseReceiver: null } let demoshIndex = { @@ -613,6 +617,69 @@ let demoshIndex = { this.destroy() } }, + mouse: class ShowMouse extends Process { + constructor (shell) { + super() + this.shell = shell + } + run () { + this.shell.terminal.trackMouse = true + demoData.mouseReceiver = this + this.randomData = [] + this.highlighted = {} + let characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' + for (let i = 0; i < 23; i++) { + let line = '' + for (let j = 0; j < 79; j++) { + line += characters[Math.floor(characters.length * Math.random())] + } + this.randomData.push(line) + } + this.scrollOffset = 0 + this.render() + } + render () { + this.emit('write', '\x1b[m\x1b[2J\x1b[1;1H') + this.emit('write', '\x1b[97m\x1b[1mMouse Demo\r\n\x1b[mMouse movement, clicking and scrolling!') + + // render random data for scrolling + for (let y = 0; y < 23; y++) { + let index = y + this.scrollOffset + // proper modulo: + index = ((index % this.randomData.length) + this.randomData.length) % this.randomData.length + let line = this.randomData[index] + let lineData = `\x1b[${3 + y};1H\x1b[38;5;239m` + for (let x in line) { + if (this.highlighted[(y + 2) * 80 + (+x)]) lineData += '\x1b[97m' + lineData += line[x] + if (this.highlighted[(y + 2) * 80 + (+x)]) lineData += '\x1b[38;5;239m' + } + this.emit('write', lineData) + } + + // move cursor to mouse + if (this.mouse) { + this.emit('write', `\x1b[${this.mouse.y + 1};${this.mouse.x + 1}H`) + } + } + mouseMove (x, y) { + this.mouse = { x, y } + this.render() + } + mouseDown (x, y, button) { + if (button === 4) this.scrollOffset-- + else if (button === 5) this.scrollOffset++ + else this.highlighted[y * 80 + x] = !this.highlighted[y * 80 + x] + this.render() + } + mouseUp (x, y, button) {} + destroy () { + this.shell.terminal.write('\x1b[2J\x1b[1;1H') + this.shell.terminal.trackMouse = false + if (demoData.mouseReceiver === this) demoData.mouseReceiver = null + super.destroy() + } + }, pwd: '/this/is/a/demo\r\n', cd: '\x1b[38;5;239mNo directories to change to\r\n', whoami: `${window.navigator.userAgent}\r\n`, @@ -748,7 +815,16 @@ window.demoInterface = { else if (action instanceof Function) action(this.terminal, this.shell) } } else if (type === 'm' || type === 'p' || type === 'r') { - console.log(JSON.stringify(data)) + let row = parse2B(content, 0) + let column = parse2B(content, 2) + let button = parse2B(content, 4) + let modifiers = parse2B(content, 6) + + if (demoData.mouseReceiver) { + if (type === 'm') demoData.mouseReceiver.mouseMove(column, row, button, modifiers) + else if (type === 'p') demoData.mouseReceiver.mouseDown(column, row, button, modifiers) + else if (type === 'r') demoData.mouseReceiver.mouseUp(column, row, button, modifiers) + } } }, init (screen) { From 67257349007f67bd8f5d6b0ffee048726531a2a4 Mon Sep 17 00:00:00 2001 From: cpsdqs Date: Wed, 13 Sep 2017 07:03:57 +0200 Subject: [PATCH 02/10] Also add 0x05 and 0x06 to ignored --- js/demo.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/demo.js b/js/demo.js index 2a95e1e..098046f 100644 --- a/js/demo.js +++ b/js/demo.js @@ -84,7 +84,7 @@ class ANSIParser { this.handler('write', character) } else if (code < 0x03) this.handler('_null') else if (code === 0x03) this.handler('sigint') - else if (code < 0x05) this.handler('_null') + else if (code <= 0x06) this.handler('_null') else if (code === 0x07) this.handler('bell') else if (code === 0x08) this.handler('back') else if (code === 0x0a) this.handler('new-line') From 6ac00ad74771ad23b1a5d4d67aba8c7ca108cd6b Mon Sep 17 00:00:00 2001 From: cpsdqs Date: Wed, 13 Sep 2017 14:00:27 +0200 Subject: [PATCH 03/10] Add command history to demo --- js/demo.js | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/js/demo.js b/js/demo.js index 098046f..0f3e78a 100644 --- a/js/demo.js +++ b/js/demo.js @@ -699,7 +699,8 @@ class DemoShell { this.terminal = terminal this.terminal.reset() this.parser = new ANSIParser((...args) => this.handleParsed(...args)) - this.input = '' + this.history = [] + this.historyIndex = 0 this.cursorPos = 0 this.child = null this.index = demoshIndex @@ -718,38 +719,54 @@ class DemoShell { this.terminal.write('\x1b[34;1mdemosh \x1b[m') if (!success) this.terminal.write('\x1b[31m') this.terminal.write('$ \x1b[m') - this.input = '' + this.history.unshift('') this.cursorPos = 0 } + copyFromHistoryIndex () { + if (!this.historyIndex) return + let current = this.history[this.historyIndex] + this.history[0] = current + this.historyIndex = 0 + } handleParsed (action, ...args) { this.terminal.write('\b\x1b[P'.repeat(this.cursorPos)) if (action === 'write') { - this.input = this.input.substr(0, this.cursorPos) + args[0] + this.input.substr(this.cursorPos) + this.copyFromHistoryIndex() + this.history[0] = this.history[0].substr(0, this.cursorPos) + args[0] + this.history[0].substr(this.cursorPos) this.cursorPos++ } else if (action === 'back') { - this.input = this.input.substr(0, this.cursorPos - 1) + this.input.substr(this.cursorPos) + this.copyFromHistoryIndex() + this.history[0] = this.history[0].substr(0, this.cursorPos - 1) + this.history[0].substr(this.cursorPos) this.cursorPos-- if (this.cursorPos < 0) this.cursorPos = 0 } else if (action === 'move-cursor-x') { - this.cursorPos = Math.max(0, Math.min(this.input.length, this.cursorPos + args[0])) + this.copyFromHistoryIndex() + this.cursorPos = Math.max(0, Math.min(this.history[0].length, this.cursorPos + args[0])) } else if (action === 'delete-line') { - this.input = '' + this.copyFromHistoryIndex() + this.history[0] = '' this.cursorPos = 0 } else if (action === 'delete-word') { - let words = this.input.substr(0, this.cursorPos).split(' ') + this.copyFromHistoryIndex() + let words = this.history[0].substr(0, this.cursorPos).split(' ') words.pop() - this.input = words.join(' ') + this.input.substr(this.cursorPos) + this.history[0] = words.join(' ') + this.history[0].substr(this.cursorPos) this.cursorPos = words.join(' ').length + } else if (action === 'move-cursor-y') { + this.historyIndex -= args[0] + if (this.historyIndex < 0) this.historyIndex = 0 + if (this.historyIndex >= this.history.length) this.historyIndex = this.history.length - 1 + this.cursorPos = this.history[this.historyIndex].length } - this.terminal.write(this.input) - this.terminal.write('\b'.repeat(this.input.length)) + this.terminal.write(this.history[this.historyIndex]) + this.terminal.write('\b'.repeat(this.history[this.historyIndex].length)) this.terminal.moveForward(this.cursorPos) this.terminal.write('') // dummy. Apply the moveFoward if (action === 'return') { this.terminal.write('\r\n') - this.parse(this.input) + this.parse(this.history[this.historyIndex]) } } parse (input) { From f6b47ee3585561edc61b31e32a1b6fa219cb13e2 Mon Sep 17 00:00:00 2001 From: cpsdqs Date: Wed, 13 Sep 2017 14:01:30 +0200 Subject: [PATCH 04/10] Don't make moving the cursor update input --- js/demo.js | 1 - 1 file changed, 1 deletion(-) diff --git a/js/demo.js b/js/demo.js index 0f3e78a..37cd24f 100644 --- a/js/demo.js +++ b/js/demo.js @@ -740,7 +740,6 @@ class DemoShell { this.cursorPos-- if (this.cursorPos < 0) this.cursorPos = 0 } else if (action === 'move-cursor-x') { - this.copyFromHistoryIndex() this.cursorPos = Math.max(0, Math.min(this.history[0].length, this.cursorPos + args[0])) } else if (action === 'delete-line') { this.copyFromHistoryIndex() From 54d314517fe0d0aa0a31b229db45d84ce1353a43 Mon Sep 17 00:00:00 2001 From: cpsdqs Date: Wed, 13 Sep 2017 18:18:34 +0200 Subject: [PATCH 05/10] ES6ify some things --- js/soft_keyboard.js | 16 ++++++---------- js/term.js | 4 +--- js/term_conn.js | 4 ++-- js/term_input.js | 42 ++++++++++++++++++++---------------------- 4 files changed, 29 insertions(+), 37 deletions(-) diff --git a/js/soft_keyboard.js b/js/soft_keyboard.js index 5829033..7921e5d 100644 --- a/js/soft_keyboard.js +++ b/js/soft_keyboard.js @@ -4,6 +4,9 @@ window.initSoftKeyboard = function (screen, input) { let keyboardOpen = false + // moves the input to where the cursor is on the canvas. + // this is because most browsers will always scroll to wherever the focused + // input is let updateInputPosition = function () { if (!keyboardOpen) return @@ -20,16 +23,9 @@ window.initSoftKeyboard = function (screen, input) { screen.on('cursor-moved', updateInputPosition) - let kbOpen = function (open) { - keyboardOpen = open - updateInputPosition() - if (open) keyInput.focus() - else keyInput.blur() - } - - qs('#term-kb-open').addEventListener('click', function () { - kbOpen(true) - return false + qs('#term-kb-open').addEventListener('click', e => { + e.preventDefault() + keyInput.focus() }) // Chrome for Android doesn't send proper keydown/keypress events with diff --git a/js/term.js b/js/term.js index ddd05af..e9c5981 100644 --- a/js/term.js +++ b/js/term.js @@ -1,7 +1,5 @@ /** Init the terminal sub-module - called from HTML */ -window.termInit = function (opts) { - let { labels, theme, allFn } = opts - +window.termInit = function ({ labels, theme, allFn }) { const screen = new TermScreen() const conn = Conn(screen) const input = Input(conn) diff --git a/js/term_conn.js b/js/term_conn.js index 955fee1..37b2800 100644 --- a/js/term_conn.js +++ b/js/term_conn.js @@ -137,8 +137,8 @@ window.Conn = function (screen) { return { ws: null, - init: init, + init, send: doSend, - canSend: canSend // check flood control + canSend // check flood control } } diff --git a/js/term_input.js b/js/term_input.js index e42ee35..e9cee03 100644 --- a/js/term_input.js +++ b/js/term_input.js @@ -32,7 +32,7 @@ window.Input = function (conn) { /** Send a button event */ function sendBtnMsg (n) { - conn.send('b' + Chr(n)) + conn.send('b' + String.fromCharCode(n)) } /** Fn alt choice for key message */ @@ -50,7 +50,7 @@ window.Input = function (conn) { return cfg.np_alt ? alt : normal } - function _bindFnKeys (allFn) { + function bindFnKeys (allFn) { const keymap = { 'tab': '\x09', 'backspace': '\x08', @@ -139,9 +139,7 @@ window.Input = function (conn) { } /** Bind/rebind key messages */ - function _initKeys (opts) { - let { allFn } = opts - + function initKeys ({ allFn }) { // This takes care of text characters typed window.addEventListener('keypress', function (evt) { if (cfg.no_keys) return @@ -188,11 +186,11 @@ window.Input = function (conn) { bind('⌥+right', '\x1bf') // ⌥→ to go forward one word (^[f) bind('⌘+left', '\x01') // ⌘← to go to the beginning of a line (^A) bind('⌘+right', '\x05') // ⌘→ to go to the end of a line (^E) - bind('⌥+backspace', '\x17') // ⌥⌫ to delete a word (^W, I think) - bind('⌘+backspace', '\x15') // ⌘⌫ to delete to the beginning of a line (possibly ^U) + bind('⌥+backspace', '\x17') // ⌥⌫ to delete a word (^W) + bind('⌘+backspace', '\x15') // ⌘⌫ to delete to the beginning of a line (^U) /* eslint-enable */ - _bindFnKeys(allFn) + bindFnKeys(allFn) } // mouse button states @@ -202,23 +200,23 @@ window.Input = function (conn) { /** Init the Input module */ function init (opts) { - _initKeys(opts) + initKeys(opts) // Button presses - $('#action-buttons button').forEach(function (s) { - s.addEventListener('click', function () { + $('#action-buttons button').forEach(s => { + s.addEventListener('click', () => { sendBtnMsg(+this.dataset['n']) }) }) // global mouse state tracking - for motion reporting - window.addEventListener('mousedown', function (evt) { + window.addEventListener('mousedown', evt => { if (evt.button === 0) mb1 = 1 if (evt.button === 1) mb2 = 1 if (evt.button === 2) mb3 = 1 }) - window.addEventListener('mouseup', function (evt) { + window.addEventListener('mouseup', evt => { if (evt.button === 0) mb1 = 0 if (evt.button === 1) mb2 = 0 if (evt.button === 2) mb3 = 0 @@ -235,7 +233,7 @@ window.Input = function (conn) { return { /** Init the Input module */ - init: init, + init, /** Send a literal string message */ sendString: sendStrMsg, @@ -249,24 +247,24 @@ window.Input = function (conn) { cfg.crlf_mode = crlf // rebind keys - codes have changed - _bindFnKeys() + bindFnKeys() } }, - setMouseMode: function (click, move) { + setMouseMode (click, move) { cfg.mt_click = click cfg.mt_move = move }, // Mouse events - onMouseMove: function (x, y) { + onMouseMove (x, y) { if (!cfg.mt_move) return const b = mb1 ? 1 : mb2 ? 2 : mb3 ? 3 : 0 const m = packModifiersForMouse() conn.send('m' + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m)) }, - onMouseDown: function (x, y, b) { + onMouseDown (x, y, b) { if (!cfg.mt_click) return if (b > 3 || b < 1) return const m = packModifiersForMouse() @@ -274,7 +272,7 @@ window.Input = function (conn) { // console.log("B ",b," M ",m); }, - onMouseUp: function (x, y, b) { + onMouseUp (x, y, b) { if (!cfg.mt_click) return if (b > 3 || b < 1) return const m = packModifiersForMouse() @@ -282,7 +280,7 @@ window.Input = function (conn) { // console.log("B ",b," M ",m); }, - onMouseWheel: function (x, y, dir) { + onMouseWheel (x, y, dir) { if (!cfg.mt_click) return // -1 ... btn 4 (away from user) // +1 ... btn 5 (towards user) @@ -292,11 +290,11 @@ window.Input = function (conn) { // console.log("B ",b," M ",m); }, - mouseTracksClicks: function () { + mouseTracksClicks () { return cfg.mt_click }, - blockKeys: function (yes) { + blockKeys (yes) { cfg.no_keys = yes } } From 83f24cbe3490fdbf3372653900d182edb03f42cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Wed, 13 Sep 2017 22:45:52 +0200 Subject: [PATCH 06/10] undo one es6 fix that wasn't really all that great + some comments cleaning and removed one forgotten console.log --- _debug_replacements.php | 2 +- base.php | 22 +++++++++++++++------- js/appcommon.js | 2 +- js/term_input.js | 14 ++++++++------ js/term_upload.js | 8 ++++---- js/wifi.js | 2 +- 6 files changed, 30 insertions(+), 20 deletions(-) diff --git a/_debug_replacements.php b/_debug_replacements.php index 3ae64da..c7d4124 100644 --- a/_debug_replacements.php +++ b/_debug_replacements.php @@ -83,7 +83,7 @@ return [ 'term_height' => '25', 'default_bg' => '0', 'default_fg' => '7', - 'show_buttons' => '0', + 'show_buttons' => '1', 'show_config_links' => '1', 'uart_baud' => 115200, diff --git a/base.php b/base.php index 2e211d0..a049c68 100644 --- a/base.php +++ b/base.php @@ -12,19 +12,27 @@ if (!empty($argv[1])) { parse_str($argv[1], $_GET); } -if (!file_exists(__DIR__ . '/_env.php')) { - die("Copy _env.php.example to _env.php and check the settings inside!"); -} - define('GIT_HASH', trim(shell_exec('git rev-parse --short HEAD'))); -require_once __DIR__ . '/_env.php'; - $prod = defined('STDIN'); define('DEBUG', !$prod); -$root = DEBUG ? json_encode(ESP_IP) : 'location.host'; + +// Resolve hostname for ajax etc +$root = 'location.host'; +if (!file_exists(__DIR__ . '/_env.php')) { + if (DEBUG) { + die("No _env.php found! Copy _env.php.example to _env.php and check the settings inside!"); + } +} else { + if (DEBUG) { + require_once __DIR__ . '/_env.php'; + $root = json_encode(ESP_IP); + } +} + define('JS_WEB_ROOT', $root); + define('ESP_DEMO', (bool)getenv('ESP_DEMO')); if (ESP_DEMO) { define('DEMO_APS', << 550) { $('.Box h2').forEach(function (x) { x.removeAttribute('tabindex') diff --git a/js/term_input.js b/js/term_input.js index e9cee03..2199f7e 100644 --- a/js/term_input.js +++ b/js/term_input.js @@ -106,7 +106,9 @@ window.Input = function (conn) { 'np_sub': na('\x1bOS', '-'), 'np_point': na('\x1bOn', '.'), 'np_div': na('\x1bOQ', '/') - // we don't implement numlock key (should change in numpad_alt mode, but it's even more useless than the rest) + // we don't implement numlock key (should change in numpad_alt mode, + // but it's even more useless than the rest and also has the side + // effect of changing the user's numlock state) } const blacklist = [ @@ -204,7 +206,7 @@ window.Input = function (conn) { // Button presses $('#action-buttons button').forEach(s => { - s.addEventListener('click', () => { + s.addEventListener('click', function (evt) { sendBtnMsg(+this.dataset['n']) }) }) @@ -290,10 +292,10 @@ window.Input = function (conn) { // console.log("B ",b," M ",m); }, - mouseTracksClicks () { - return cfg.mt_click - }, - + /** + * Prevent capturing keys. This is used for text input + * modals on the terminal screen + */ blockKeys (yes) { cfg.no_keys = yes } diff --git a/js/term_upload.js b/js/term_upload.js index e399c4b..938b420 100644 --- a/js/term_upload.js +++ b/js/term_upload.js @@ -97,7 +97,6 @@ window.TermUpl = function (conn, input, screen) { inline_pos += MAX_LINE_LEN } - console.log(chunk) if (!input.sendString(chunk)) { updateStatus('FAILED!') return @@ -134,10 +133,11 @@ window.TermUpl = function (conn, input, screen) { qs('#fu_file').addEventListener('change', function (evt) { let reader = new FileReader() let file = evt.target.files[0] - console.log('Selected file type: ' + file.type) - if (!file.type.match(/text\/.*|application\/(json|csv|.*xml.*|.*script.*)/)) { + let ftype = file.type || 'application/octet-stream' + console.log('Selected file type: ' + ftype) + if (!ftype.match(/text\/.*|application\/(json|csv|.*xml.*|.*script.*|x-php)/)) { // Deny load of blobs like img - can crash browser and will get corrupted anyway - if (!confirm('This does not look like a text file: ' + file.type + '\nReally load?')) { + if (!confirm(`This does not look like a text file: ${ftype}\nReally load?`)) { qs('#fu_file').value = '' return } diff --git a/js/wifi.js b/js/wifi.js index bd35fe4..8e90328 100644 --- a/js/wifi.js +++ b/js/wifi.js @@ -149,7 +149,7 @@ }) // Forget STA credentials - $('#forget-sta').on('click', function () { + $('#forget-sta').on('click', () => { selectSta('', '', '') return false }) From a8354f22884356eed219b43e7958b4fa4a607352 Mon Sep 17 00:00:00 2001 From: cpsdqs Date: Thu, 14 Sep 2017 09:02:52 +0200 Subject: [PATCH 07/10] Always round DPR to nice value to prevent gaps --- js/term_screen.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/js/term_screen.js b/js/term_screen.js index 9573df4..b230128 100644 --- a/js/term_screen.js +++ b/js/term_screen.js @@ -524,7 +524,8 @@ window.TermScreen = class TermScreen { * Updates the canvas size if it changed */ updateSize () { - this._window.devicePixelRatio = this._windowScale * (window.devicePixelRatio || 1) + // see below (this is just updating it) + this._window.devicePixelRatio = Math.round(this._windowScale * (window.devicePixelRatio || 1) * 2) / 2 let didChange = false for (let key in this.windowState) { @@ -573,7 +574,8 @@ window.TermScreen = class TermScreen { // store new window scale this._windowScale = realWidth / (width * cellSize.width) - let devicePixelRatio = this._window.devicePixelRatio = this._windowScale * window.devicePixelRatio + // the DPR must be rounded to a very nice value to prevent gaps between cells + let devicePixelRatio = this._window.devicePixelRatio = Math.round(this._windowScale * (window.devicePixelRatio || 1) * 2) / 2 this.canvas.width = width * devicePixelRatio * cellSize.width this.canvas.style.width = `${realWidth}px` @@ -744,8 +746,8 @@ window.TermScreen = class TermScreen { drawCellBackground ({ x, y, cellWidth, cellHeight, bg }) { const ctx = this.ctx ctx.fillStyle = this.getColor(bg) - ctx.clearRect(x * cellWidth, y * cellHeight, Math.ceil(cellWidth), Math.ceil(cellHeight)) - ctx.fillRect(x * cellWidth, y * cellHeight, Math.ceil(cellWidth), Math.ceil(cellHeight)) + ctx.clearRect(x * cellWidth, y * cellHeight, cellWidth, cellHeight) + ctx.fillRect(x * cellWidth, y * cellHeight, cellWidth, cellHeight) } /** @@ -1239,7 +1241,8 @@ window.TermScreen = class TermScreen { mcbIndex = i } } - this.canvas.style.backgroundColor = this.getColor(mcbIndex) + // this.canvas.style.backgroundColor = this.getColor(mcbIndex) + this.canvas.style.backgroundColor = '#f00' this.scheduleDraw('load', 16) this.emit('load') From a9f59488fd8ea3b8e6981de014087b965fe9470c Mon Sep 17 00:00:00 2001 From: cpsdqs Date: Thu, 14 Sep 2017 09:37:15 +0200 Subject: [PATCH 08/10] Remove debug code --- js/term_screen.js | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/js/term_screen.js b/js/term_screen.js index b230128..fb391d1 100644 --- a/js/term_screen.js +++ b/js/term_screen.js @@ -1151,8 +1151,6 @@ window.TermScreen = class TermScreen { this.screenAttrs = new Array(screenLength).fill(' ') } - let bgcount = new Array(256).fill(0) - let strArray = !undef(Array.from) ? Array.from(str) : str.split('') const MASK_LINE_ATTR = 0xC8 @@ -1174,7 +1172,6 @@ window.TermScreen = class TermScreen { else this.blinkingCellCount-- } - bgcount[bg]++ this.screen[cell] = lastChar this.screenFG[cell] = fg this.screenBG[cell] = bg @@ -1231,19 +1228,6 @@ window.TermScreen = class TermScreen { if (this.window.debug) console.log(`Blinky cells = ${this.blinkingCellCount}`) - // work-around for the grid gaps bug - // will mask the glitch if most of the screen uses the same background - let mostCommonBg = 0 - let mcbIndex = 0 - for (let i = 255; i >= 0; i--) { - if (bgcount[i] > mostCommonBg) { - mostCommonBg = bgcount[i] - mcbIndex = i - } - } - // this.canvas.style.backgroundColor = this.getColor(mcbIndex) - this.canvas.style.backgroundColor = '#f00' - this.scheduleDraw('load', 16) this.emit('load') } From d44dce766b4a942e434b927566bf3229ac6c1ff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Thu, 14 Sep 2017 22:44:46 +0200 Subject: [PATCH 09/10] added a very important demo command --- _build_js.sh | 8 ++------ js/demo.js | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/_build_js.sh b/_build_js.sh index 7122d5e..fa03512 100755 --- a/_build_js.sh +++ b/_build_js.sh @@ -5,17 +5,13 @@ mkdir -p out/js echo 'Generating lang.js...' php ./dump_js_lang.php -if [[ $ESP_DEMO ]]; then - demofile=js/demo.js -else - demofile= -fi - echo 'Processing JS...' if [[ $ESP_PROD ]]; then smarg= + demofile= else smarg=--source-maps + demofile=js/demo.js fi npm run babel -- -o "out/js/app.$FRONT_END_HASH.js" ${smarg} js/lib \ diff --git a/js/demo.js b/js/demo.js index 37cd24f..3d4ed4d 100644 --- a/js/demo.js +++ b/js/demo.js @@ -680,6 +680,43 @@ let demoshIndex = { super.destroy() } }, + sudo: class Sudo extends Process { + run (...args) { + if (args.length === 0) this.emit('write', 'usage: sudo ') + else if (args.length === 4 && args.join(' ').toLowerCase() === 'make me a sandwich') { + this.emit('write', ' _.---._\r\n' + + ' _.-~ ~-._\r\n' + + ' _.-~ ~-._\r\n' + + ' _.-~ ~---._\r\n' + + ' _.-~ ~\\\r\n' + + ' .-~ _.;\r\n' + + ' :-._ _.-~ ./\r\n' + + ' `-._~-._ _..__.-~ _.-~\r\n' + + ' / ~-._~-._ / .__..--~----._\r\n' + + ' \\_____(_;-._\\. _.-~_/ ~).. . \\\r\n' + + ' /(_____ \\`--...--~_.-~______..-+_______)\r\n' + + ' .(_________/`--...--~/ _/ /\\\r\n' + + ' /-._ \\_ (___./_..-~__.....__..-~./\r\n' + + ' `-._~-._ ~\\--------~ .-~_..__.-~ _.-~\r\n' + + ' ~-._~-._ ~---------\' / .__..--~\r\n' + + ' ~-._\\. _.-~_/\r\n' + + ' \\`--...--~_.-~\r\n' + + ' `--...--~\r\n') + } + this.destroy() + } + }, + make: class Make extends Process { + run (...args) { + if (args.length === 0) this.emit('write', '\x1b[31mmake: *** No targets specified. Stop.\x1b[0m\r\n') + else if (args.length === 3 && args.join(' ').toLowerCase() === 'me a sandwich') { + this.emit('write', '\x1b[31mmake: me a sandwich : Permission denied\x1b[0m\r\n') + } else { + this.emit('write', `\x1b[31mmake: *** No rule to make target '${args.join(' ').toLowerCase()}'. Stop.\x1b[0m\r\n`) + } + this.destroy() + } + }, pwd: '/this/is/a/demo\r\n', cd: '\x1b[38;5;239mNo directories to change to\r\n', whoami: `${window.navigator.userAgent}\r\n`, From 6e021402c24b0f589d8d21ea17782acedbfdd2fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Thu, 14 Sep 2017 23:11:57 +0200 Subject: [PATCH 10/10] colours and sudo works as expected --- js/demo.js | 58 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/js/demo.js b/js/demo.js index 3d4ed4d..3c93ab8 100644 --- a/js/demo.js +++ b/js/demo.js @@ -682,26 +682,35 @@ let demoshIndex = { }, sudo: class Sudo extends Process { run (...args) { - if (args.length === 0) this.emit('write', 'usage: sudo ') + if (args.length === 0) this.emit('write', '\x1b[31musage: sudo \x1b[0m\n') else if (args.length === 4 && args.join(' ').toLowerCase() === 'make me a sandwich') { - this.emit('write', ' _.---._\r\n' + - ' _.-~ ~-._\r\n' + - ' _.-~ ~-._\r\n' + - ' _.-~ ~---._\r\n' + - ' _.-~ ~\\\r\n' + - ' .-~ _.;\r\n' + - ' :-._ _.-~ ./\r\n' + - ' `-._~-._ _..__.-~ _.-~\r\n' + - ' / ~-._~-._ / .__..--~----._\r\n' + - ' \\_____(_;-._\\. _.-~_/ ~).. . \\\r\n' + - ' /(_____ \\`--...--~_.-~______..-+_______)\r\n' + - ' .(_________/`--...--~/ _/ /\\\r\n' + - ' /-._ \\_ (___./_..-~__.....__..-~./\r\n' + - ' `-._~-._ ~\\--------~ .-~_..__.-~ _.-~\r\n' + - ' ~-._~-._ ~---------\' / .__..--~\r\n' + - ' ~-._\\. _.-~_/\r\n' + - ' \\`--...--~_.-~\r\n' + - ' `--...--~\r\n') + const b = '\x1b[33m' + const r = '\x1b[0m' + const l = '\x1b[32m' + const c = '\x1b[38;5;229m' + const h = '\x1b[38;5;225m' + this.emit('write', + ` ${b}_.---._\r\n` + + ` _.-~ ~-._\r\n` + + ` _.-~ ~-._\r\n` + + ` _.-~ ~---._\r\n` + + ` _.-~ ~\\\r\n` + + ` .-~ _.;\r\n` + + ` :-._ _.-~ ./\r\n` + + ` \`-._~-._ _..__.-~ _.-~\r\n` + + ` ${c}/ ${b}~-._~-._ / .__..--${c}~-${l}---._\r\n` + + `${c} \\_____(_${b};-._\\. _.-~_/${c} ~)${l}.. . \\\r\n` + + `${l} /(_____ ${b}\\\`--...--~_.-~${c}______..-+${l}_______)\r\n` + + `${l} .(_________/${b}\`--...--~/${l} _/ ${h} ${b}/\\\r\n` + + `${b} /-._${h} \\_ ${l}(___./_..-~${h}__.....${b}__..-~./\r\n` + + `${b} \`-._~-._${h} ~\\--------~ .-~${b}_..__.-~ _.-~\r\n` + + `${b} ~-._~-._ ${h}~---------\` ${b}/ .__..--~\r\n` + + `${b} ~-._\\. _.-~_/\r\n` + + `${b} \\\`--...--~_.-~\r\n` + + `${b} \`--...--~${r}\r\n`) + } else { + this.emit('exec', args.join(' ')) + return } this.destroy() } @@ -728,7 +737,13 @@ let demoshIndex = { mv: '\x1b[38;5;239mNothing to move because this is a demo.\r\n', ln: '\x1b[38;5;239mNothing to link because this is a demo.\r\n', touch: '\x1b[38;5;239mNothing to touch\r\n', - exit: '\x1b[38;5;239mNowhere to go\r\n' + exit: '\x1b[38;5;239mNowhere to go\r\n', + github: class GoToGithub extends Process { + run () { + window.open('https://github.com/espterm/espterm-firmware') + this.destroy() + } + } } class DemoShell { @@ -839,9 +854,12 @@ class DemoShell { if (Process instanceof Function) { this.child = new Process(this) let write = data => this.terminal.write(data) + let exec = line => this.run(line) this.child.on('write', write) + this.child.on('exec', exec) this.child.on('exit', code => { if (this.child) this.child.off('write', write) + if (this.child) this.child.off('exec', exec) this.child = null this.prompt(!code) })