2018-11-28 21:29:28 +01:00
|
|
|
class InputHistory {
|
|
|
|
constructor() {
|
|
|
|
this._history = [];
|
|
|
|
this._index = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
addEntry(entry) {
|
|
|
|
if (entry.trim() !== ``) {
|
|
|
|
this._history.unshift(entry);
|
|
|
|
}
|
|
|
|
this._index = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
getEntry(index) {
|
|
|
|
if (index >= 0) {
|
|
|
|
return this._history[index];
|
|
|
|
} else {
|
|
|
|
return ``;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nextEntry() {
|
|
|
|
this._index--;
|
|
|
|
if (this._index < -1) {
|
|
|
|
this._index = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.getEntry(this._index);
|
|
|
|
}
|
|
|
|
|
|
|
|
previousEntry() {
|
|
|
|
this._index++;
|
|
|
|
if (this._index >= this._history.length) {
|
|
|
|
this._index = this._history.length - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.getEntry(this._index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class Terminal {
|
|
|
|
constructor(terminal, input, output, prefixDiv) {
|
|
|
|
this._terminal = terminal;
|
|
|
|
this._input = input;
|
|
|
|
this._output = output;
|
|
|
|
this._prefixDiv = prefixDiv;
|
|
|
|
this._inputHistory = new InputHistory();
|
|
|
|
|
2018-11-28 22:23:11 +01:00
|
|
|
this._fs = new FileSystem();
|
|
|
|
this._commands = new Commands(this, this._fs);
|
|
|
|
|
2018-11-28 21:29:28 +01:00
|
|
|
this._terminal.addEventListener("click", this._onclick.bind(this));
|
|
|
|
this._terminal.addEventListener("keypress", this._onkeypress.bind(this));
|
|
|
|
this._input.addEventListener("keydown", this._onkeydown.bind(this));
|
|
|
|
|
|
|
|
this.reset();
|
|
|
|
this._input.focus();
|
|
|
|
}
|
2018-11-28 19:51:48 +01:00
|
|
|
|
|
|
|
|
2018-11-28 21:29:28 +01:00
|
|
|
get inputText() {
|
|
|
|
return this._input.innerHTML
|
|
|
|
.replaceAll(/<br>/, ``);
|
|
|
|
}
|
2018-11-28 19:51:48 +01:00
|
|
|
|
2018-11-28 21:29:28 +01:00
|
|
|
set inputText(inputText) {
|
|
|
|
this._input.innerHTML = inputText;
|
|
|
|
}
|
2018-11-28 19:51:48 +01:00
|
|
|
|
2018-11-28 21:29:28 +01:00
|
|
|
get outputText() {
|
|
|
|
return this._output.innerHTML;
|
|
|
|
}
|
2018-11-28 19:51:48 +01:00
|
|
|
|
2018-11-28 21:29:28 +01:00
|
|
|
set outputText(outputText) {
|
|
|
|
this._output.innerHTML = outputText;
|
|
|
|
}
|
2018-11-28 19:51:48 +01:00
|
|
|
|
2018-11-28 21:29:28 +01:00
|
|
|
get prefixText() {
|
|
|
|
return this._prefixDiv.innerHTML;
|
2018-11-28 19:51:48 +01:00
|
|
|
}
|
|
|
|
|
2018-11-28 21:29:28 +01:00
|
|
|
set prefixText(prefixText) {
|
|
|
|
this._prefixDiv.innerHTML = prefixText;
|
|
|
|
}
|
2018-11-28 19:51:48 +01:00
|
|
|
|
|
|
|
|
2018-11-28 22:36:35 +01:00
|
|
|
clear() {
|
|
|
|
this.outputText = ``;
|
|
|
|
}
|
|
|
|
|
2018-11-28 21:29:28 +01:00
|
|
|
static generateHeader() {
|
2018-11-28 21:36:04 +01:00
|
|
|
return "" +
|
2018-11-28 21:29:28 +01:00
|
|
|
`${asciiHeader}
|
2018-11-28 19:51:48 +01:00
|
|
|
|
2018-11-28 21:36:04 +01:00
|
|
|
Student MSc Computer Science @ <a href="https://www.tudelft.nl/en/">TU Delft</a>, the Netherlands
|
|
|
|
${(new Date()).toISOString()}
|
2018-11-28 19:51:48 +01:00
|
|
|
|
2018-11-28 21:36:04 +01:00
|
|
|
Type "help" for help.
|
2018-11-28 19:51:48 +01:00
|
|
|
|
2018-11-28 21:36:04 +01:00
|
|
|
`.trimLines();
|
2018-11-28 21:29:28 +01:00
|
|
|
}
|
2018-11-28 19:51:48 +01:00
|
|
|
|
2018-11-28 22:23:11 +01:00
|
|
|
generatePrefix() {
|
|
|
|
return `felix@fwdekker.com <span style="color: green;">${this._fs.pwd}</span>> `;
|
2018-11-28 21:29:28 +01:00
|
|
|
}
|
2018-11-28 19:51:48 +01:00
|
|
|
|
2018-11-28 21:29:28 +01:00
|
|
|
processInput(input) {
|
|
|
|
this._inputHistory.addEntry(input);
|
|
|
|
this.inputText = ``;
|
|
|
|
this.outputText += `${this.prefixText}${input}\n`;
|
2018-11-28 19:51:48 +01:00
|
|
|
|
2018-11-28 22:23:11 +01:00
|
|
|
const output = this._commands.parse(input.trim());
|
2018-11-28 21:29:28 +01:00
|
|
|
if (output !== ``) {
|
|
|
|
this.outputText += output + `\n`;
|
|
|
|
}
|
2018-11-28 19:51:48 +01:00
|
|
|
|
2018-11-28 22:23:11 +01:00
|
|
|
this.prefixText = this.generatePrefix();
|
2018-11-28 19:51:48 +01:00
|
|
|
}
|
|
|
|
|
2018-11-28 21:29:28 +01:00
|
|
|
reset() {
|
2018-11-28 22:23:11 +01:00
|
|
|
this._fs.reset();
|
2018-11-28 19:51:48 +01:00
|
|
|
|
2018-11-28 21:29:28 +01:00
|
|
|
this.outputText = Terminal.generateHeader();
|
2018-11-28 22:23:11 +01:00
|
|
|
this.prefixText = this.generatePrefix();
|
2018-11-28 21:29:28 +01:00
|
|
|
}
|
2018-11-28 19:51:48 +01:00
|
|
|
|
|
|
|
|
2018-11-28 21:29:28 +01:00
|
|
|
_onclick() {
|
|
|
|
console.log(this);
|
|
|
|
this._input.focus();
|
|
|
|
}
|
2018-11-28 19:51:48 +01:00
|
|
|
|
2018-11-28 21:29:28 +01:00
|
|
|
_onkeypress(e) {
|
|
|
|
switch (e.key.toLowerCase()) {
|
|
|
|
case `enter`:
|
|
|
|
this.processInput(this.inputText.replaceAll(/ /, ` `));
|
|
|
|
break;
|
|
|
|
}
|
2018-11-28 19:51:48 +01:00
|
|
|
}
|
|
|
|
|
2018-11-28 21:29:28 +01:00
|
|
|
_onkeydown(e) {
|
|
|
|
switch (e.key.toLowerCase()) {
|
|
|
|
case `arrowup`:
|
|
|
|
this.inputText = this._inputHistory.previousEntry();
|
|
|
|
break;
|
|
|
|
case `arrowdown`:
|
|
|
|
this.inputText = this._inputHistory.nextEntry();
|
|
|
|
}
|
2018-11-28 19:51:48 +01:00
|
|
|
}
|
2018-11-28 21:29:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-11-28 22:23:11 +01:00
|
|
|
|
2018-11-28 21:29:28 +01:00
|
|
|
let terminal;
|
|
|
|
|
|
|
|
addOnLoad(() => {
|
|
|
|
terminal = new Terminal(
|
|
|
|
q(`#terminal`),
|
|
|
|
q(`#terminalCurrentFocusInput`),
|
|
|
|
q(`#terminalOutput`),
|
|
|
|
q(`#terminalCurrentPrefix`)
|
|
|
|
);
|
|
|
|
|
|
|
|
terminal.processInput(`ls`);
|
2018-11-28 19:51:48 +01:00
|
|
|
});
|