diff --git a/index.html b/index.html index a64277a..3f2c661 100644 --- a/index.html +++ b/index.html @@ -2,7 +2,7 @@ - + Christopher Bloodsworth diff --git a/public/pear.svg b/public/pear.svg new file mode 100644 index 0000000..19ec331 --- /dev/null +++ b/public/pear.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/vite.svg b/public/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/pear.svg b/src/assets/pear.svg new file mode 100644 index 0000000..19ec331 --- /dev/null +++ b/src/assets/pear.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/ubuntu.svg b/src/assets/ubuntu.svg deleted file mode 100644 index f217bc8..0000000 --- a/src/assets/ubuntu.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/components/cursor.tsx b/src/components/cursor.tsx index 8154083..3c23974 100644 --- a/src/components/cursor.tsx +++ b/src/components/cursor.tsx @@ -14,7 +14,7 @@ const BlinkingCursor = () => { }, [speed]); return ( - | + | ); }; diff --git a/src/components/terminal.tsx b/src/components/terminal.tsx index 891ca9b..41964e4 100644 --- a/src/components/terminal.tsx +++ b/src/components/terminal.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState, useRef } from 'react'; +import React, { useEffect, useState, useRef, KeyboardEventHandler } from 'react'; // React components import Prompt from './prompt' @@ -130,6 +130,126 @@ const Terminal: React.FC = ({ user, pwd, setPwd, viewContent, set modifyDisplayHistory([...displayHistory, ...addition].slice(cutoff)); } + const handleKeyDown = (event) => { + switch (event.key) { + case "Enter": { + historyIndex.current = -1; + + // Parse! + const command = new Validator(new Tokenizer(input).tokenize()).parse(); + + // If input is empty, result is empty string. + // Otherwise, evaluate the command! + const result = (input.length === 0) + ? "" + : evaluateCommand( + command, pwd, setPwd, + currentEnvironment, modifyEnvironment, + viewContent, setViewContent, + termColors, setTermColors); + + + const commandHistoryEntry: CommandHistoryEntry = + { command: command, rawInput: input, environment: {...currentEnvironment} }; + + const outputHistoryEntry: OutputHistoryEntry = + { content: result, type: input.length === 0 ? 'no-output' : 'command-output' }; + + // If we're redirecting, write the result to a file + // and do some modification to the outputHistory object + if (command.redirectTo) { + const redirectResult = pwd.writeTo(command.redirectTo, result); + if (redirectResult.err) { + outputHistoryEntry.content = redirectResult.err; + outputHistoryEntry.type = 'error'; + } + else { + // If redirecting, don't output result to terminal: just write it to file + outputHistoryEntry.content = ""; + outputHistoryEntry.type = 'no-output'; + } + } + + const terminalHistoryEntry = { inputCommand: commandHistoryEntry, outputResult: outputHistoryEntry }; + + // Add the newest command to the history + modifyHistory([ + ...history, + terminalHistoryEntry + ]); + + addToDisplayHistory(terminalHistoryEntry); + + // If the result contains the RESET_TERM escape sequence, clear the terminal. + if (result.includes(CONSTANTS.ESCAPE_CODES.RESET_TERM)) { clearTerminal(); } + + setInput(""); + break; + } + + // Most terminals support Ctrl+L for clearing + case "l": { + if (event.ctrlKey) { + event.preventDefault(); + clearTerminal(); + } + break; + } + + // We eventually want tab completion. God help me + case "Tab": { + event.preventDefault(); + // uhhh do something eventually + break; + } + + case "ArrowLeft": + case "ArrowRight": { + event.preventDefault(); + break; + } + + // Set input to previous command entered + case "ArrowUp": { + event.preventDefault(); + if (historyIndex.current < history.length - 1) { + historyIndex.current++; + setInput(history[history.length - 1 - historyIndex.current].inputCommand.rawInput); + } + break; + } + + // Set input to next command entered + case "ArrowDown": { + event.preventDefault(); + if (historyIndex.current > 0) { + historyIndex.current--; + setInput(history[history.length - 1 - historyIndex.current].inputCommand.rawInput || ""); + } + + // No more commands in history + else if (historyIndex.current === 0) { + setInput(""); + } + break; + } + default: { + break; // I don't exactly know what to do here + } + } + } + + const handleClick = () => { + const selection = window.getSelection(); + if (!selection?.toString()) { + inputBoxRef.current.focus(); + } + } + + const handleChange = (event: React.ChangeEvent) => { + setInput(event.target.value); + } + return (
= ({ user, pwd, setPwd, viewContent, set color: termColors.default.htmlCode, border: `1px solid ${termColors.success.htmlCode}` }} - onClick={() => { inputBoxRef.current.focus(); }}> + onClick={handleClick} + > {displayHistory.map((displayLine) => ( <> {displayLine.environment ? : <> } @@ -148,126 +269,18 @@ const Terminal: React.FC = ({ user, pwd, setPwd, viewContent, set {/* Current user prompt. */} - {input} -
- + { setInput(event.target.value); } - } - onKeyDown={event => { - switch (event.key) { - case "Enter": { - historyIndex.current = -1; - - // Parse! - const command = new Validator(new Tokenizer(input).tokenize()).parse(); - - // If input is empty, result is empty string. - // Otherwise, evaluate the command! - const result = (input.length === 0) - ? "" - : evaluateCommand( - command, pwd, setPwd, - currentEnvironment, modifyEnvironment, - viewContent, setViewContent, - termColors, setTermColors); - - - const commandHistoryEntry: CommandHistoryEntry = - { command: command, rawInput: input, environment: {...currentEnvironment} }; - - const outputHistoryEntry: OutputHistoryEntry = - { content: result, type: input.length === 0 ? 'no-output' : 'command-output' }; - - // If we're redirecting, write the result to a file - // and do some modification to the outputHistory object - if (command.redirectTo) { - const redirectResult = pwd.writeTo(command.redirectTo, result); - if (redirectResult.err) { - outputHistoryEntry.content = redirectResult.err; - outputHistoryEntry.type = 'error'; - } - else { - // If redirecting, don't output result to terminal: just write it to file - outputHistoryEntry.content = ""; - outputHistoryEntry.type = 'no-output'; - } - } - - const terminalHistoryEntry = { inputCommand: commandHistoryEntry, outputResult: outputHistoryEntry }; - - // Add the newest command to the history - modifyHistory([ - ...history, - terminalHistoryEntry - ]); - - addToDisplayHistory(terminalHistoryEntry); - - // If the result contains the RESET_TERM escape sequence, clear the terminal. - if (result.includes(CONSTANTS.ESCAPE_CODES.RESET_TERM)) { clearTerminal(); } - - setInput(""); - break; - } - - // Most terminals support Ctrl+L for clearing - case "l": { - if (event.ctrlKey) { - event.preventDefault(); - clearTerminal(); - } - break; - } - - // We eventually want tab completion. God help me - case "Tab": { - event.preventDefault(); - // uhhh do something eventually - break; - } - - case "ArrowLeft": - case "ArrowRight": { - event.preventDefault(); - break; - } - - // Set input to previous command entered - case "ArrowUp": { - event.preventDefault(); - if (historyIndex.current < history.length - 1) { - historyIndex.current++; - setInput(history[history.length - 1 - historyIndex.current].inputCommand.rawInput); - } - break; - } - - // Set input to next command entered - case "ArrowDown": { - event.preventDefault(); - if (historyIndex.current > 0) { - historyIndex.current--; - setInput(history[history.length - 1 - historyIndex.current].inputCommand.rawInput || ""); - } - - // No more commands in history - else if (historyIndex.current === 0) { - setInput(""); - } - break; - } - default: { - break; // I don't exactly know what to do here - } - } - }} /> +
); }; diff --git a/src/styles/view.css b/src/styles/view.css index 21343e8..63adf0f 100644 --- a/src/styles/view.css +++ b/src/styles/view.css @@ -44,12 +44,16 @@ } .terminalInput { + position: absolute; + bottom:-0.5vw; + right:-0.5vw; + font-size: 0.25px; border: none; outline: none; margin: 0px; padding: 0px; + color: red; + user-select: none; background-color: transparent; - caret-color: white; - font-size: 0rem; font-family: 'JetBrainsMono'; } diff --git a/src/system/formatContentParser.tsx b/src/system/formatContentParser.tsx index 4f7753a..66242cc 100644 --- a/src/system/formatContentParser.tsx +++ b/src/system/formatContentParser.tsx @@ -230,7 +230,8 @@ export const parseANSICodeStyles = (content: string): JSX.Element[] => { rawElements.push({content: content, color: color, style: style, font: font}); return rawElements.map((rawElement) => { - return