forked from tools/josh
1
0
Fork 0
josh/js/terminal.js

227 lines
5.4 KiB
JavaScript
Raw Normal View History

2018-11-28 21:29:28 +01:00
class Terminal {
constructor(terminal, input, output, prefixDiv) {
this._terminal = terminal;
this._input = input;
this._output = output;
this._prefixDiv = prefixDiv;
2018-11-29 16:10:02 +01:00
this._user = "felix";
this._loggedIn = true;
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));
2018-11-29 01:08:58 +01:00
this._terminal.addEventListener("keydown", this._onkeydown.bind(this));
2018-11-28 21:29:28 +01:00
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
2018-11-28 22:41:59 +01:00
.replaceAll(/<br>/, "");
2018-11-28 21:29:28 +01:00
}
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 21:29:28 +01:00
static generateHeader() {
return "" +
2018-11-30 17:38:33 +01:00
`${asciiHeaderHtml}
2018-11-28 19:51:48 +01:00
2018-11-29 01:08:58 +01:00
Student MSc Computer Science <span class="smallScreenOnly">
</span>@ <a href="https://www.tudelft.nl/en/">TU Delft</a>, the Netherlands
<span class="wideScreenOnly">${(new Date()).toISOString()}
</span>
Type "help" for help.
2018-11-28 19:51:48 +01:00
2018-11-29 01:08:58 +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() {
2018-11-29 16:10:02 +01:00
if (!this._loggedIn) {
if (this._user === undefined) {
return "login as: ";
} else {
return `Password for ${this._user}@fwdekker.com: `;
}
}
2018-11-28 19:51:48 +01:00
2018-11-29 16:10:02 +01:00
return `${this._user}@fwdekker.com <span style="color: green;">${this._fs.pwd}</span>&gt; `;
}
2018-11-28 19:51:48 +01:00
2018-11-29 16:10:02 +01:00
clear() {
this.outputText = "";
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-29 16:10:02 +01:00
continueLogin(input) {
if (this._user === undefined) {
2018-11-29 16:19:50 +01:00
this.outputText += `${this.prefixText}${input}\n`;
2018-11-29 16:10:02 +01:00
this._user = input.trim();
2018-11-29 16:19:50 +01:00
this._input.classList.add("terminalCurrentFocusInputHidden");
2018-11-29 16:10:02 +01:00
} else {
2018-11-29 16:19:50 +01:00
this.outputText += `${this.prefixText}\n`;
2018-11-29 18:31:39 +01:00
if ((this._user === "felix" && input === "hotel123")
|| (this._user === "root" && input === "password")) {
2018-11-29 16:10:02 +01:00
this._loggedIn = true;
2018-11-29 18:28:37 +01:00
this.outputText += Terminal.generateHeader();
2018-11-29 16:10:02 +01:00
} else {
this._user = undefined;
2018-11-29 18:28:37 +01:00
this.outputText += "Access denied\n";
2018-11-29 16:10:02 +01:00
}
2018-11-29 16:19:50 +01:00
this._input.classList.remove("terminalCurrentFocusInputHidden");
2018-11-29 16:10:02 +01:00
}
}
logOut() {
this._user = undefined;
this._loggedIn = false;
this._inputHistory.clear();
}
processInput(input) {
this.inputText = "";
if (!this._loggedIn) {
this.continueLogin(input);
} else {
2018-11-29 16:19:50 +01:00
this.outputText += `${this.prefixText}${input}\n`;
2018-11-29 16:10:02 +01:00
this._inputHistory.addEntry(input);
const output = this._commands.parse(input.trim());
if (output !== "") {
this.outputText += output + `\n`;
}
}
this.prefixText = this.generatePrefix();
}
2018-11-28 21:29:28 +01:00
_onclick() {
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()) {
2018-11-28 22:41:59 +01:00
case "enter":
this.processInput(this.inputText.replaceAll(/&nbsp;/, " "));
2019-02-09 14:32:19 +01:00
e.preventDefault();
2018-11-28 21:29:28 +01:00
break;
}
2018-11-28 19:51:48 +01:00
}
2018-11-28 21:29:28 +01:00
_onkeydown(e) {
switch (e.key.toLowerCase()) {
2018-11-28 22:41:59 +01:00
case "arrowup":
2018-11-28 21:29:28 +01:00
this.inputText = this._inputHistory.previousEntry();
window.setTimeout(() => moveCaretToEndOf(this._input), 0);
2018-11-28 21:29:28 +01:00
break;
2018-11-28 22:41:59 +01:00
case "arrowdown":
2018-11-28 21:29:28 +01:00
this.inputText = this._inputHistory.nextEntry();
window.setTimeout(() => moveCaretToEndOf(this._input), 0);
2018-11-29 00:31:43 +01:00
break;
case "l":
if (e.ctrlKey) {
this.clear();
e.preventDefault();
}
break;
2018-11-28 21:29:28 +01:00
}
2018-11-28 19:51:48 +01:00
}
2018-11-28 21:29:28 +01:00
}
2018-11-29 16:10:02 +01:00
class InputHistory {
constructor() {
this._history = [];
this._index = -1;
}
addEntry(entry) {
if (entry.trim() !== "") {
this._history.unshift(entry);
}
this._index = -1;
}
clear() {
this._history = [];
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);
}
}
2018-11-28 21:29:28 +01:00
let terminal;
addOnLoad(() => {
terminal = new Terminal(
2018-11-28 22:41:59 +01:00
q("#terminal"),
q("#terminalCurrentFocusInput"),
q("#terminalOutput"),
q("#terminalCurrentPrefix")
2018-11-28 21:29:28 +01:00
);
2018-11-28 22:41:59 +01:00
terminal.processInput("ls");
2018-11-28 19:51:48 +01:00
});