Skip to content

Instantly share code, notes, and snippets.

@janstuemmel
Created January 16, 2020 20:04
Show Gist options
  • Save janstuemmel/3cddf265c65341cd953e83a1c8b24e12 to your computer and use it in GitHub Desktop.
Save janstuemmel/3cddf265c65341cd953e83a1c8b24e12 to your computer and use it in GitHub Desktop.
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