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; } 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:
========================================
help     Shows the help screen
about    Provides background of the terminal
clear    Clears the terminal
echo     Display a line of text
exit     Exits the terminal
history  Prints command history

Terminal Functionality:
========================================
Up Arrow - cycle through commands
Down Arrow - cycle through commands
Ctrl+c - discard current prompt
Ctrl+d - exit
` } 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('
') } 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.

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); } }