Fix stuff, help command
This commit is contained in:
parent
a535c5b69a
commit
c25a0e34e2
@ -11,7 +11,7 @@ const REPLHistory: NextPage<REPLHistoryParams> = ({history, inputRef}) => {
|
||||
const focusInput = () => {if (inputRef.current) inputRef.current.focus();};
|
||||
|
||||
return <div className={styles.container} onClick={focusInput}>
|
||||
{ history.map((value, idx) => <div className={styles.line} key={idx}>{value === "" ? "\u00A0" : value}</div>) }
|
||||
{ history.map((value, idx) => <pre className={styles.line} key={idx}>{value === "" ? "\u00A0" : value}</pre>) }
|
||||
</div>;
|
||||
};
|
||||
|
||||
|
@ -15,19 +15,34 @@ const REPLInput: NextPage<REPLInputParams> = ({historyCallback, inputRef}) => {
|
||||
const [justTabbed, setJustTabbed] = React.useState<number>(0);
|
||||
|
||||
const replinOnChange = (e: React.FormEvent<HTMLInputElement>) => {
|
||||
const currentInput = (e.target as HTMLInputElement).value.toLowerCase();
|
||||
(e.target as HTMLInputElement).value = currentInput;
|
||||
const input = (e.target as HTMLInputElement);
|
||||
const currentInput = input.value.toLowerCase();
|
||||
// Force lowercase
|
||||
input.value = currentInput;
|
||||
|
||||
if (currentInput.includes(" ")) {
|
||||
// Command already typed
|
||||
input.maxLength = 524288; // Default value
|
||||
if (typed.current) typed.current.innerHTML = "";
|
||||
if (completion.current) completion.current.innerHTML = "";
|
||||
setCurrentCmd([]);
|
||||
return;
|
||||
} else {
|
||||
input.maxLength = 20;
|
||||
// Get completion hint
|
||||
const suggest = commandCompletion(currentInput);
|
||||
setCurrentCmd(suggest);
|
||||
if (suggest.length === 0) suggest.push("");
|
||||
if (typed.current) typed.current.innerHTML = currentInput;
|
||||
if (completion.current) completion.current.innerHTML = suggest[0].substring(currentInput.length);
|
||||
}
|
||||
};
|
||||
|
||||
const tabComplete = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
const input = (e.target as HTMLInputElement);
|
||||
if (e.key === "Tab" && currentCmd.length !== 0) {
|
||||
e.preventDefault();
|
||||
(e.target as HTMLInputElement).value = currentCmd[justTabbed % currentCmd.length];
|
||||
input.value = currentCmd[justTabbed % currentCmd.length];
|
||||
if(typed.current) typed.current.innerHTML = currentCmd[justTabbed % currentCmd.length];
|
||||
if(completion.current) completion.current.innerHTML = "";
|
||||
setJustTabbed(justTabbed + 1);
|
||||
@ -35,7 +50,7 @@ const REPLInput: NextPage<REPLInputParams> = ({historyCallback, inputRef}) => {
|
||||
|
||||
if (e.key === "Enter") {
|
||||
const result = executeCommand((e.target as HTMLInputElement).value);
|
||||
(e.target as HTMLInputElement).value = "";
|
||||
input.value = "";
|
||||
if(typed.current) typed.current.innerHTML = "";
|
||||
if(completion.current) completion.current.innerHTML = "";
|
||||
historyCallback(result);
|
||||
@ -47,7 +62,7 @@ const REPLInput: NextPage<REPLInputParams> = ({historyCallback, inputRef}) => {
|
||||
return <div className={styles.wrapperwrapper}>
|
||||
<span className={styles.inputstart}>$ </span>
|
||||
<div className={styles.wrapper}>
|
||||
<input ref={inputRef as MutableRefObject<HTMLInputElement>} className={styles.in} type={"text"} onChange={replinOnChange} onKeyDown={tabComplete} spellCheck={"false"} autoFocus />
|
||||
<input ref={inputRef as MutableRefObject<HTMLInputElement>} className={styles.in} type={"text"} onChange={replinOnChange} onKeyDown={tabComplete} spellCheck={"false"} autoFocus maxLength={20} />
|
||||
<span className={styles.completionWrapper}><span ref={typed} className={styles.typed}></span><span ref={completion} className={styles.completion}></span></span>
|
||||
</div>
|
||||
</div>;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { Command } from "./types";
|
||||
import type { Command, Flag } from "./types";
|
||||
|
||||
function illegalUse(raw: string, cmd: Command): string[] {
|
||||
return [
|
||||
@ -31,6 +31,10 @@ function checkSubcmd(subcmds: string[], cmd: Command): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
function checkFlagInclude(flagsProvided: string[], flag: Flag): boolean {
|
||||
return flagsProvided.includes(`-${flag.short}`) || flagsProvided.includes(`--${flag.long}`);
|
||||
}
|
||||
|
||||
export function printSyntax(cmd: Command): string[] {
|
||||
let flagsOption = "";
|
||||
let flagsDesc = [];
|
||||
@ -82,4 +86,31 @@ const about: Command = {
|
||||
}
|
||||
};
|
||||
|
||||
export const commandList = [about];
|
||||
const help: Command = {
|
||||
name: "help",
|
||||
desc: "Shows helptext.",
|
||||
flags: [{ long: "more", short: "m", desc: "Show more information." }],
|
||||
execute: (flags, _args, _raw) => {
|
||||
checkFlags(flags, help);
|
||||
if (help.flags && checkFlagInclude(flags, help.flags[0])) {
|
||||
return [
|
||||
"Hello user!",
|
||||
"What you see here should resemble an CLI. If you ever used Linux this should be pretty easy for you.",
|
||||
"Everyone else: Have no fear. It is pretty simple. You just type in commands and the output is shown here or it does something on the webite.",
|
||||
"To find out, which commands are available, you can type just 'help'.",
|
||||
"",
|
||||
"Have fun!"
|
||||
];
|
||||
} else {
|
||||
const available = ["Available commands:"];
|
||||
commandList.forEach(cmd => available.push(`\t${cmd.name}\t${cmd.desc}`));
|
||||
available.concat([
|
||||
"",
|
||||
"Need more help? Type 'help -m'!"
|
||||
]);
|
||||
return available;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const commandList = [about, help];
|
@ -1,4 +1,4 @@
|
||||
interface Flag {
|
||||
export interface Flag {
|
||||
short: string;
|
||||
long: string;
|
||||
desc: string;
|
||||
@ -15,5 +15,5 @@ export interface Command {
|
||||
desc: string;
|
||||
flags?: Flag[];
|
||||
subcommands?: SubCommand[];
|
||||
execute: (flags: string[], args: string[], raw: string) => string[];
|
||||
execute: (flags: string[], args: string[], raw: string, extra?: any) => string[];
|
||||
}
|
||||
|
2
package-lock.json
generated
2
package-lock.json
generated
@ -6,7 +6,7 @@
|
||||
"": {
|
||||
"name": "my_website",
|
||||
"dependencies": {
|
||||
"next": "^12.0.7",
|
||||
"next": "12.0.7",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2"
|
||||
},
|
||||
|
@ -1,13 +1,17 @@
|
||||
import type { NextPage } from "next";
|
||||
import Head from "next/head";
|
||||
import REPL from "../components/REPL";
|
||||
import styles from "../styles/Home.module.css";
|
||||
|
||||
const Home: NextPage = () => {
|
||||
return (
|
||||
return (<>
|
||||
<Head>
|
||||
<title>c0ntroller.de</title>
|
||||
</Head>
|
||||
<div className={styles.container}>
|
||||
<REPL />
|
||||
</div>
|
||||
);
|
||||
</>);
|
||||
};
|
||||
|
||||
export default Home;
|
||||
|
@ -9,4 +9,8 @@
|
||||
|
||||
.line {
|
||||
padding: 3px 0;
|
||||
white-space: pre-wrap;
|
||||
font-family: inherit;
|
||||
display: block;
|
||||
margin: 0;
|
||||
}
|
@ -53,13 +53,17 @@
|
||||
.completionWrapper span {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: inline-block;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.typed {
|
||||
opacity: 0;
|
||||
flex-shrink: 1;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.completion {
|
||||
color: var(--repl-color-hint);
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user