Add simple clickable links to ls command

Only supports `nano` as I couldn't figure out how to infer `vim`
support without an explicit `nano` or `vim` command being run.
This commit is contained in:
smolgumball 2022-01-10 20:40:01 -07:00
parent f742782e4a
commit 358f5ee8ee

@ -1,9 +1,13 @@
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import makeStyles from "@mui/styles/makeStyles";
import { toString } from "lodash";
import React from "react"; import React from "react";
import { ITerminal } from "../ITerminal";
import { IRouter } from "../../ui/Router";
import { IPlayer } from "../../PersonObjects/IPlayer"; import { IPlayer } from "../../PersonObjects/IPlayer";
import { BaseServer } from "../../Server/BaseServer"; import { BaseServer } from "../../Server/BaseServer";
import { getFirstParentDirectory, isValidDirectoryPath, evaluateDirectoryPath } from "../../Terminal/DirectoryHelpers"; import { evaluateDirectoryPath, getFirstParentDirectory, isValidDirectoryPath } from "../../Terminal/DirectoryHelpers";
import { IRouter } from "../../ui/Router";
import { ITerminal } from "../ITerminal";
export function ls( export function ls(
terminal: ITerminal, terminal: ITerminal,
@ -113,7 +117,51 @@ export function ls(
allMessages.sort(); allMessages.sort();
folders.sort(); folders.sort();
function postSegments(segments: string[], style?: any): void { interface ClickableScriptRowProps {
row: string;
prefix: string;
}
function ClickableScriptRow({ row, prefix }: ClickableScriptRowProps): React.ReactElement {
const classes = makeStyles((theme: Theme) =>
createStyles({
scriptLinksWrap: {
display: "flex",
color: theme.palette.warning.main,
},
scriptLink: {
cursor: "pointer",
textDecorationLine: "underline",
paddingRight: "1.15em",
"&:last-child": { padding: 0 },
},
}),
)();
const rowSplit = row
.split(" ")
.map((x) => x.trim())
.filter((x) => !!x);
function onScriptLinkClick(filename: string): void {
if (filename.startsWith("/")) filename = filename.slice(1);
const filepath = terminal.getFilepath(`${prefix}${filename}`);
const code = toString(terminal.getScript(player, filepath)?.code);
router.toScriptEditor({ [filepath]: code });
}
return (
<span className={classes.scriptLinksWrap}>
{rowSplit.map((rowItem) => (
<span key={rowItem} className={classes.scriptLink} onClick={() => onScriptLinkClick(rowItem)}>
{rowItem}
</span>
))}
</span>
);
}
function postSegments(segments: string[], style?: any, linked?: boolean): void {
const maxLength = Math.max(...segments.map((s) => s.length)) + 1; const maxLength = Math.max(...segments.map((s) => s.length)) + 1;
const filesPerRow = Math.floor(80 / maxLength); const filesPerRow = Math.floor(80 / maxLength);
for (let i = 0; i < segments.length; i++) { for (let i = 0; i < segments.length; i++) {
@ -127,11 +175,15 @@ export function ls(
i--; i--;
if (!style) { if (!style) {
terminal.print(row); terminal.print(row);
} else {
if (linked) {
terminal.printRaw(<ClickableScriptRow row={row} prefix={prefix} />);
} else { } else {
terminal.printRaw(<span style={style}>{row}</span>); terminal.printRaw(<span style={style}>{row}</span>);
} }
} }
} }
}
const groups = [ const groups = [
{ segments: folders, style: { color: "cyan" } }, { segments: folders, style: { color: "cyan" } },
@ -139,9 +191,9 @@ export function ls(
{ segments: allTextFiles }, { segments: allTextFiles },
{ segments: allPrograms }, { segments: allPrograms },
{ segments: allContracts }, { segments: allContracts },
{ segments: allScripts, style: { color: "yellow", fontStyle: "bold" } }, { segments: allScripts, style: { color: "yellow", fontStyle: "bold" }, linked: true },
].filter((g) => g.segments.length > 0); ].filter((g) => g.segments.length > 0);
for (let i = 0; i < groups.length; i++) { for (let i = 0; i < groups.length; i++) {
postSegments(groups[i].segments, groups[i].style); postSegments(groups[i].segments, groups[i].style, groups[i].linked);
} }
} }