126 lines
3.0 KiB
TypeScript
126 lines
3.0 KiB
TypeScript
#!/usr/bin/env runts -- --allow-env --allow-run
|
|
|
|
import { spawn } from "node:child_process";
|
|
import {
|
|
existsPath,
|
|
log,
|
|
readFileToString,
|
|
resolveFilename,
|
|
} from "https://global.hatter.ink/script/get/@12/deno-commons-mod.ts";
|
|
|
|
const CMD_CONFIG_FILE = "~/.config/cmd-ts.json";
|
|
|
|
interface CmdConfig {
|
|
cmds?: Map<string, Cmd>;
|
|
groups?: Map<string, CmdGroup>;
|
|
}
|
|
|
|
interface CmdGroup {
|
|
cmds?: Map<string, Cmd>;
|
|
}
|
|
|
|
interface Cmd {
|
|
command: string[];
|
|
comment?: string;
|
|
alias?: string[];
|
|
}
|
|
|
|
async function loadConfig(): Promise<CmdConfig> {
|
|
const resolvedFilename = resolveFilename(CMD_CONFIG_FILE);
|
|
if (!await existsPath(resolvedFilename)) {
|
|
throw `Cmd config file not found: ${resolvedFilename}`;
|
|
}
|
|
const config = await readFileToString(resolvedFilename);
|
|
return JSON.parse(config) as CmdConfig;
|
|
}
|
|
|
|
async function showHelp(args: string[]) {
|
|
const cmdConfig = await loadConfig();
|
|
log.info(cmdConfig); // TODO ...
|
|
}
|
|
|
|
async function findCmd(
|
|
cmdConfig: CmdConfig,
|
|
c1: string,
|
|
c2: string | null,
|
|
): Cmd {
|
|
if (c2 === null) {
|
|
const cmds = [];
|
|
if (cmdConfig.cmds && cmdConfig.cmds[c1]) {
|
|
cmds.push(cmdConfig.cmds[c1]);
|
|
}
|
|
if (cmdConfig.groups && cmdConfig.groups[c1]) {
|
|
if (cmds.length === 0) {
|
|
await showHelp([c1]);
|
|
return null;
|
|
} else {
|
|
throw `Multiple cmd or group found: ${c1}`;
|
|
}
|
|
}
|
|
if (cmds.length === 0) {
|
|
throw `No cmd found: ${c1}`;
|
|
}
|
|
return cmds[0];
|
|
} else {
|
|
const cmds = cmdConfig.groups[c1];
|
|
if (!cmds) {
|
|
throw `No group found: ${c1}`;
|
|
}
|
|
const cmd = cmds.cmds[c2];
|
|
if (!cmd) {
|
|
throw `No group and cmd found: ${c1}:${c2}`;
|
|
}
|
|
return cmd;
|
|
}
|
|
}
|
|
|
|
function splitCmd(cmd: string): {
|
|
c1: string;
|
|
c2: string;
|
|
} {
|
|
const cmdCIndex = cmd.indexOf(":");
|
|
if (cmdCIndex >= 0) {
|
|
return {
|
|
c1: cmd.substring(0, cmdCIndex),
|
|
c2: cmd.substring(cmdCIndex + 1),
|
|
};
|
|
} else {
|
|
return {
|
|
c1: cmd,
|
|
c2: null,
|
|
};
|
|
}
|
|
}
|
|
|
|
async function main() {
|
|
if (Deno.args.length === 0) {
|
|
await showHelp([]);
|
|
return;
|
|
}
|
|
log.info("Arguments", Deno.args);
|
|
const cmdConfig = await loadConfig();
|
|
const { c1, c2 } = splitCmd(Deno.args[0]);
|
|
const cmd = await findCmd(cmdConfig, c1, c2);
|
|
if (cmd === null) {
|
|
return;
|
|
}
|
|
const command = cmd.command[0];
|
|
const args = [];
|
|
if (cmd.command.length > 1) {
|
|
for (let i = 1; i < cmd.command.length; i++) {
|
|
args.push(cmd.command[i]);
|
|
}
|
|
}
|
|
if (Deno.args.length > 1) {
|
|
for (let i = 1; i < Deno.args.length; i++) {
|
|
args.push(Deno.args[i]);
|
|
}
|
|
}
|
|
log.info("Execute command", command, args);
|
|
spawn(command, args, {
|
|
shell: true,
|
|
stdio: ["inherit", "inherit", "inherit"],
|
|
});
|
|
}
|
|
await main();
|