Skip to content

Commit

Permalink
Add Chrome compatibility, change favicon.
Browse files Browse the repository at this point in the history
The site had not functioned well with Chrome-based browsers, only
Firefox. It works as expected now.

Additionally, the favicon was changed to something more pear-themed.
  • Loading branch information
cbloodsworth committed Jun 4, 2024
1 parent 7ee035a commit b7367f8
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 131 deletions.
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" type="image/svg+xml" href="/pear.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Christopher Bloodsworth</title>
</head>
Expand Down
1 change: 1 addition & 0 deletions public/pear.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion public/vite.svg

This file was deleted.

1 change: 1 addition & 0 deletions src/assets/pear.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 0 additions & 8 deletions src/assets/ubuntu.svg

This file was deleted.

2 changes: 1 addition & 1 deletion src/components/cursor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const BlinkingCursor = () => {
}, [speed]);

return (
<span id="cursor" style={{ opacity: cursorVisible ? 1 : 0 }}>|</span>
<span id="cursor" style={{ fontWeight: '50', userSelect: 'none', opacity: cursorVisible ? 1 : 0 }}>|</span>
);
};

Expand Down
247 changes: 130 additions & 117 deletions src/components/terminal.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -130,14 +130,135 @@ const Terminal: React.FC<TerminalProps> = ({ 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<HTMLInputElement>) => {
setInput(event.target.value);
}

return (
<div className='window terminal'
style={{
background: termColors.background.htmlCode,
color: termColors.default.htmlCode,
border: `1px solid ${termColors.success.htmlCode}`
}}
onClick={() => { inputBoxRef.current.focus(); }}>
onClick={handleClick}
>
{displayHistory.map((displayLine) => (
<>
{displayLine.environment ? <Prompt environment={displayLine.environment} colors={termColors}/> : <></> }
Expand All @@ -148,126 +269,18 @@ const Terminal: React.FC<TerminalProps> = ({ user, pwd, setPwd, viewContent, set

{/* Current user prompt. */}
<Prompt environment={currentEnvironment} colors={termColors}/>
<span>{input}</span><BlinkingCursor/>
<div></div>

<TerminalContent content={input} formatted={false}/>
<input
ref={inputBoxRef}
type='text'
value={input}
size={1}
ref={inputBoxRef}
onChange={handleChange}
onKeyDown={handleKeyDown}
spellCheck={false}
className='terminalInput'
onChange={
event => { 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
}
}
}}
/>
<BlinkingCursor/>
</div >
);
};
Expand Down
8 changes: 6 additions & 2 deletions src/styles/view.css
Original file line number Diff line number Diff line change
Expand Up @@ -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';
}
3 changes: 2 additions & 1 deletion src/system/formatContentParser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 <span style={{
return <span
style={{
...rawElement.style,
...rawElement.color,
...rawElement.font,
Expand Down

0 comments on commit b7367f8

Please sign in to comment.