a bash-like fake shell
Created
January 16, 2020 20:04
-
-
Save janstuemmel/3cddf265c65341cd953e83a1c8b24e12 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Terminal } from 'xterm' | |
const defaultOptions = { | |
ps1: '$ ' | |
} | |
const KEY_UP = 38, | |
KEY_DOWN = 40, | |
KEY_LEFT = 37, | |
KEY_RIGHT = 39, | |
KEY_TAB = 9, | |
KEY_BACK = 8, | |
KEY_RETURN = 13 | |
export default class extends Terminal { | |
constructor(commands = [], options = {}) { | |
super(options) | |
this.options = Object.assign({}, defaultOptions, options) | |
this.ps1 = this.options.ps1 | |
this.commands = commands | |
this.history = [] | |
this.historyIndex = 0 | |
this.onKey(this._keyPress.bind(this)) | |
} | |
open(elem) { | |
super.open(elem) | |
this.promt() | |
} | |
promt() { | |
this.write(`\r\n${this.ps1}`) | |
} | |
_keyPress(e) { | |
// ctrl^C | |
if (e.domEvent.keyCode === 67 && e.domEvent.ctrlKey) { | |
this.promt() | |
// this._resetHistory() | |
} | |
else if (e.domEvent.keyCode === KEY_RETURN) { | |
// this._updateHistory(this.currentLine) | |
this.promt() | |
} | |
else if (e.domEvent.keyCode === KEY_UP || e.domEvent.keyCode === KEY_DOWN) { | |
this.write(`\x1b[2K\r${this.ps1}${this._browseHistory(e.domEvent.keyCode)}`) | |
} | |
else if (e.domEvent.keyCode === KEY_RIGHT) { | |
if (this.cursor.x < this.currentLine.length) { | |
this.write(e.key) | |
} | |
} | |
else if (e.domEvent.keyCode === KEY_LEFT) { | |
if (this.cursor.x > 0) { | |
this.insert(e.key) | |
} | |
} | |
else if (e.domEvent.keyCode === KEY_BACK) { | |
if (this.cursor.x > 0) { | |
this.insert('\b \b') | |
} | |
} | |
else if (isKeyPrintable(e)) { | |
this.write(e.key) | |
} | |
} | |
insert(key) { | |
const right = this.currentLine.slice(this.cursor.x) | |
if (right.length > 0) { | |
// delete right, insert key, insert right | |
this.write(`\x1b[0K${key}${right}`) | |
// curser go back | |
this.write(`\x1b[${right.length}D`) | |
} else { | |
this.write(key) | |
} | |
} | |
_resetHistory() { | |
this.historyIndex = this.history.length - 1 | |
} | |
_updateHistory(cmd) { | |
console.log(this.history.length > 0 && cmd === this.history[this.history.length-1]) | |
// don't neighbors to history | |
if (this.history.length > 0 && cmd === this.history[this.history.length-1]) return; | |
// dont add if cmd is empty | |
if (cmd == '') return | |
this.history.push(cmd) | |
this._resetHistory() | |
} | |
_browseHistory(dir) { | |
if (dir === KEY_UP) { | |
if (this.historyIndex < 1) return this.history[0] | |
return this.history[this.historyIndex--] | |
} else if (dir === KEY_DOWN) { | |
if (this.historyIndex >= this.history.length - 1) return '' | |
return this.history[++this.historyIndex] | |
} | |
} | |
clearLine() { | |
this.write(`\x1b[2K\r${this.ps1}`) | |
} | |
get cursor() { | |
const { x, y } = this._core.buffer | |
return { x: x - this.ps1.length, y } | |
} | |
get currentBufferLine() { | |
return this.buffer.getLine(this.cursor.y)._line | |
} | |
get currentLine() { | |
return this.currentBufferLine.translateToString(true, this.ps1.length).trim() | |
} | |
} | |
// helper | |
function isKeyPrintable(e) { | |
return !e.domEvent.altKey && !e.domEvent.altGraphKey && !e.domEvent.ctrlKey && !e.domEvent.metaKey; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment