201 lines
5.6 KiB
JavaScript
201 lines
5.6 KiB
JavaScript
class Terminal {
|
|
constructor() {
|
|
this.terminalElem = document.getElementById("term")
|
|
this.terminalContainerElem = document.getElementById("term-container")
|
|
this.promptContainerElem = document.getElementById("prompt-container")
|
|
this.promptsAndResponses = []
|
|
this.commands = []
|
|
this.commandPosition = this.commands.length
|
|
this.currentPrompt = null
|
|
this.active = false;
|
|
this.initialized = false;
|
|
}
|
|
|
|
show() {
|
|
if (!this.initialized) {
|
|
this.initialized = true;
|
|
this.initialize()
|
|
} else {
|
|
this.terminalElem.style.display = "block"
|
|
this.terminalContainerElem.style.display = "block"
|
|
if (this.currentPrompt) {
|
|
this.currentPrompt.focus()
|
|
}
|
|
}
|
|
terminalMode = true;
|
|
}
|
|
|
|
hide () {
|
|
this.terminalElem.style.display = "none"
|
|
this.terminalContainerElem.style.display = "none"
|
|
terminalMode = false;
|
|
this.handleDialog)
|
|
}
|
|
|
|
handleDialog() {
|
|
indicator.hide('computer')
|
|
}
|
|
|
|
createPrompt() {
|
|
this.commandPosition = this.commands.length
|
|
|
|
var promptContainerElem = document.createElement("div")
|
|
promptContainerElem.classList.add("prompt-container")
|
|
|
|
var label = document.createElement("label")
|
|
label.innerHTML = '>>>'
|
|
|
|
var prompt = document.createElement("input")
|
|
prompt.setAttribute("autofocus", true)
|
|
|
|
var self = this
|
|
prompt.addEventListener("keypress", function(event) {
|
|
|
|
if (event.key === "Enter") {
|
|
if (terminalMode && this.value !== ''){
|
|
event.preventDefault();
|
|
this.disabled = true;
|
|
self.handlePrompt(this.value);
|
|
}
|
|
}
|
|
})
|
|
|
|
var clearFixDiv = document.createElement("div")
|
|
clearFixDiv.classList.add("clearfix")
|
|
|
|
promptContainerElem.appendChild(label);
|
|
promptContainerElem.appendChild(prompt);
|
|
this.terminalElem.appendChild(promptContainerElem);
|
|
|
|
prompt.focus()
|
|
this.currentPrompt = prompt
|
|
this.promptsAndResponses.push(promptContainerElem)
|
|
}
|
|
|
|
initialize() {
|
|
this.resize()
|
|
this.show();
|
|
this.createPrompt();
|
|
}
|
|
|
|
resize() {
|
|
this.terminalElem.style.width = canvas.getBoundingClientRect().width - 40 + 'px';
|
|
this.terminalElem.style.height = canvas.getBoundingClientRect().height - 80 + 'px';
|
|
this.terminalElem.style.minHeight = canvas.getBoundingClientRect().width - 80 + 'px';
|
|
}
|
|
|
|
handlePrompt(promptText) {
|
|
this.commands.push(promptText);
|
|
this.determineResult(promptText);
|
|
this.createPrompt();
|
|
}
|
|
|
|
determineResult(promptText) {
|
|
var returnText
|
|
if (promptText === 'help') {
|
|
returnText = `Documented Commands:<br>
|
|
========================================<br>
|
|
help     Shows the help screen<br>
|
|
about    Provides background of the terminal<br>
|
|
clear    Clears the terminal<br>
|
|
echo     Display a line of text<br>
|
|
exit     Exits the terminal<br>
|
|
history  Prints command history<br>
|
|
<br>
|
|
Terminal Functionality:<br>
|
|
========================================<br>
|
|
Up Arrow - cycle through commands<br>
|
|
Down Arrow - cycle through commands<br>
|
|
Ctrl+c - discard current prompt<br>
|
|
Ctrl+d - exit<br>
|
|
`
|
|
|
|
} else if (promptText.split(" ")[0] == 'echo') {
|
|
promptText = promptText.replaceAll('"', '')
|
|
promptText = promptText.split(' ').slice(1)
|
|
returnText = promptText.join(' ')
|
|
} else if (promptText === 'history') {
|
|
|
|
returnText = this.commands.join('<br>')
|
|
|
|
} else if (promptText == 'exit') {
|
|
this.hide()
|
|
|
|
} else if (promptText == 'about') {
|
|
returnText = 'I built this terminal emulator in JavaScript. While the functionality is quite simple, I wanted to showcase my love for linux and working in the terminal. All actions that can be done in the main world like: looking at my portfolio, downloading my resume, or playing one of the games I made can be done through this terminal. <br><br> I also added some quality of life commands like clear, exit, echo and more for the fun of it. That\'s right! This is what I do for fun :)'
|
|
|
|
} else if (promptText == 'clear') {
|
|
this.clear()
|
|
|
|
} else if (['vim', 'nvim', 'nano', 'ed'].includes(promptText)) {
|
|
returnText = 'Did you really think I coded a text editor in here!?'
|
|
|
|
} else {
|
|
returnText = 'Unkown command, please type "help" for options'
|
|
}
|
|
|
|
if (returnText) {
|
|
var responseElem = document.createElement('span')
|
|
responseElem.innerHTML = returnText
|
|
this.terminalElem.appendChild(responseElem)
|
|
this.promptsAndResponses.push(responseElem)
|
|
}
|
|
}
|
|
|
|
clear() {
|
|
for (let i = 0; i < this.promptsAndResponses.length; i++) {
|
|
this.promptsAndResponses[i].style.display = "none";
|
|
}
|
|
}
|
|
|
|
getKeystroke() {
|
|
var self = this
|
|
_listener = function (event) {
|
|
console.log(event.code)
|
|
if (
|
|
["ArrowUp", "ArrowDown", "ControlLeft"].indexOf(event.code,) > -1
|
|
) {
|
|
event.preventDefault();
|
|
}
|
|
|
|
if (event.ctrlKey && event.key === 'd') {
|
|
event.preventDefault();
|
|
}
|
|
|
|
if (event.key === "ArrowUp") {
|
|
if (self.commands.length > 0) {
|
|
var nextCommandPosition = self.commandPosition - 1
|
|
|
|
if (nextCommandPosition < 0) {
|
|
nextCommandPosition = self.commands.length - 1
|
|
}
|
|
|
|
self.currentPrompt.value = self.commands[nextCommandPosition]
|
|
self.commandPosition = nextCommandPosition;
|
|
}
|
|
}
|
|
|
|
if (event.key === "ArrowDown") {
|
|
if (self.commands.length > 0) {
|
|
var nextCommandPosition = self.commandPosition + 1
|
|
|
|
if (nextCommandPosition > self.commands.length - 1) {
|
|
nextCommandPosition = 0
|
|
}
|
|
|
|
self.currentPrompt.value = self.commands[nextCommandPosition]
|
|
self.commandPosition = nextCommandPosition;
|
|
}
|
|
}
|
|
|
|
if (event.ctrlKey && event.key === 'c') {
|
|
self.createPrompt()
|
|
}
|
|
|
|
if (event.ctrlKey && event.key === 'd') {
|
|
self.hide()
|
|
}
|
|
}
|
|
document.addEventListener("keydown", _listener);
|
|
}
|
|
}
|