135 lines
4.0 KiB
TypeScript
135 lines
4.0 KiB
TypeScript
import { profile } from '#lib/content';
|
|
import { themes } from '#lib/theme/themes';
|
|
import { allSitePages, findSitePage, sitePages } from '#lib/site/pages';
|
|
import { blankLine, errorLine, line, span } from '../output';
|
|
import type { Command } from './types';
|
|
|
|
function cowsay(message: string): string[] {
|
|
const text = message || 'Moo?';
|
|
const border = '-'.repeat(text.length + 2);
|
|
return [
|
|
` ${border}`,
|
|
`< ${text} >`,
|
|
` ${border}`,
|
|
' \\ ^__^',
|
|
' \\ (oo)\\_______',
|
|
' (__)\\ )\\/\\',
|
|
' ||----w |',
|
|
' || ||'
|
|
];
|
|
}
|
|
|
|
function easternDate(): string {
|
|
return new Date().toLocaleString('en-US', {
|
|
timeZone: 'America/New_York',
|
|
weekday: 'long',
|
|
year: 'numeric',
|
|
month: 'long',
|
|
day: 'numeric',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
second: '2-digit',
|
|
timeZoneName: 'short'
|
|
});
|
|
}
|
|
|
|
export const systemCommands: Command[] = [
|
|
{
|
|
name: 'clear',
|
|
aliases: ['cls'],
|
|
description: 'Clear the terminal',
|
|
run: (_args, context) => context.clear()
|
|
},
|
|
{
|
|
name: 'ls',
|
|
aliases: ['dir', 'tree'],
|
|
description: 'List the pages you can open',
|
|
run: (_args, context) => {
|
|
context.print(line(span('~', 'blue', { bold: true })));
|
|
sitePages.forEach((page, pageIndex) => {
|
|
const isLastPage = pageIndex === sitePages.length - 1;
|
|
context.print(line(span(isLastPage ? '└── ' : '├── ', 'muted'), span(`${page.name}/`, 'blue', { bold: true })));
|
|
page.children?.forEach((child, childIndex) => {
|
|
const isLastChild = childIndex === page.children!.length - 1;
|
|
const indent = isLastPage ? ' ' : '│ ';
|
|
context.print(line(span(`${indent}${isLastChild ? '└── ' : '├── '}`, 'muted'), span(`${child.name}/`, 'cyan')));
|
|
});
|
|
});
|
|
context.print(blankLine);
|
|
}
|
|
},
|
|
{
|
|
name: 'cd',
|
|
aliases: ['open', 'goto'],
|
|
description: 'Open a page in a window',
|
|
usage: 'cd <page>, for example cd projects/hackathons',
|
|
argumentOptions: () => ['~', ...allSitePages.map((page) => page.path.slice(1))],
|
|
run: (args, context) => {
|
|
const target = args[0] ?? '~';
|
|
if (target === '~' || target === '/' || target === 'home') {
|
|
context.openPage('/');
|
|
return;
|
|
}
|
|
const page = findSitePage(target);
|
|
if (!page) {
|
|
context.print(errorLine(`no such page: ${target}. Try ls`));
|
|
return;
|
|
}
|
|
context.print(line(span('opening ', 'muted'), span(page.path, 'accent')));
|
|
context.openPage(page.path);
|
|
}
|
|
},
|
|
{
|
|
name: 'theme',
|
|
description: 'List or set the color theme',
|
|
usage: 'theme [name]',
|
|
argumentOptions: () => themes.map((theme) => theme.id),
|
|
run: (args, context) => {
|
|
if (!args[0]) {
|
|
themes.forEach((theme) => {
|
|
const isCurrent = theme.id === context.currentThemeId();
|
|
context.print(line(span(isCurrent ? '* ' : ' ', 'accent'), span(theme.id, isCurrent ? 'accent' : 'foreground'), span(` ${theme.mode}`, 'muted')));
|
|
});
|
|
return;
|
|
}
|
|
if (context.setTheme(args[0].toLowerCase())) context.print(line(span('theme set to ', 'muted'), span(args[0], 'accent')));
|
|
else context.print(errorLine(`unknown theme ${args[0]}. Run theme to list them`));
|
|
}
|
|
},
|
|
{
|
|
name: 'echo',
|
|
description: 'Print text back',
|
|
usage: 'echo <text>',
|
|
run: (args, context) => context.print(line(args.join(' ')))
|
|
},
|
|
{
|
|
name: 'cowsay',
|
|
description: 'Make a cow say something',
|
|
usage: 'cowsay <text>',
|
|
run: (args, context) => context.print(...cowsay(args.join(' ')).map((text) => line(span(text, 'accent'))))
|
|
},
|
|
{
|
|
name: 'date',
|
|
description: 'Show the current date and time (Eastern)',
|
|
run: (_args, context) => context.print(line(easternDate()))
|
|
},
|
|
{
|
|
name: 'exit',
|
|
description: 'Close this terminal',
|
|
run: (_args, context) => context.exit()
|
|
},
|
|
{
|
|
name: 'sudo',
|
|
hidden: true,
|
|
description: 'Elevated privileges',
|
|
run: (_args, context) =>
|
|
context.print(errorLine(`${profile.username} is not in the sudoers file. This incident will be reported.`))
|
|
},
|
|
{
|
|
name: 'pwd',
|
|
hidden: true,
|
|
description: 'Print working directory',
|
|
run: (_args, context) => context.print(line(`/home/${profile.username}`))
|
|
}
|
|
];
|