151 lines
4.5 KiB
TypeScript
151 lines
4.5 KiB
TypeScript
import { getAsciiArt } from "../util/asciiArt.ts";
|
|
import { toCase } from "util/caseManagement.ts";
|
|
import { ArgParser } from "./argParser.ts";
|
|
import { colorize } from "./style.ts";
|
|
import { selectMenuInteractive } from "./selectMenu.ts";
|
|
import { TerminalBlock, TerminalLayout } from "./TerminalLayout.ts";
|
|
import { cliAlert, cliLog } from "./prompts.ts";
|
|
import type { ITool } from "../types.ts";
|
|
import { join, toFileUrl } from "@std/path";
|
|
import { log } from "util/logfile.ts";
|
|
|
|
// Register tools here (filename, no extension)
|
|
const toolRegistry: [string, Promise<{ default: ITool }>][] = [
|
|
["checkCode", import("../tools/checkCode.ts")],
|
|
["fieldRename", import("../tools/fieldRename.ts")],
|
|
["listFormFields", import("../tools/listFormFields.ts")],
|
|
];
|
|
|
|
export class PdfToolsCli {
|
|
private tools: Map<string, ITool> = new Map();
|
|
private terminalLayout = new TerminalLayout();
|
|
closeMessage?: string;
|
|
|
|
private args = ArgParser.parse(Deno.args).setFlagDefs({
|
|
help: ["-h", "--help"],
|
|
});
|
|
|
|
async importTools() {
|
|
for (const [name, toolfile] of toolRegistry) {
|
|
const t = await toolfile;
|
|
try {
|
|
if (t.default) {
|
|
this.tools.set(
|
|
toCase(name, "title"),
|
|
t.default,
|
|
);
|
|
}
|
|
} catch (e) {
|
|
cliLog(e + "\n", this.terminalLayout.getBlock("body"));
|
|
}
|
|
}
|
|
}
|
|
|
|
private async banana() {
|
|
const asciiArt = await getAsciiArt("banana");
|
|
const body = this.terminalLayout.getBlock("body");
|
|
body.clearAll();
|
|
cliLog(colorize(asciiArt, "yellow"), body);
|
|
}
|
|
|
|
private async help() {
|
|
this.terminalLayout.clear();
|
|
this.ensmallenHeader("Help");
|
|
const bodyBlock = this.terminalLayout.getBlock("body");
|
|
bodyBlock.clearAll();
|
|
await cliAlert("BearMetal PDF CLI\n", bodyBlock);
|
|
await this.embiggenHeader();
|
|
}
|
|
|
|
public async run() {
|
|
try {
|
|
await this.importTools();
|
|
const titleBlock = new TerminalBlock();
|
|
this.terminalLayout.register("title", titleBlock);
|
|
const bodyBlock = new TerminalBlock();
|
|
this.terminalLayout.register("body", bodyBlock);
|
|
if (this.args.getFlag("help") && !this.args.task) {
|
|
await this.help();
|
|
return;
|
|
} else if (this.args.nonFlags.length === 0 || !this.args.task) {
|
|
this.embiggenHeader();
|
|
await this.toolMenu();
|
|
} else {
|
|
const task = this.args.task;
|
|
await this.runTool(toCase(task, "title"));
|
|
}
|
|
} finally {
|
|
this.terminalLayout.clearAll();
|
|
Deno.stdin.setRaw(false);
|
|
if (this.closeMessage) console.log(this.closeMessage);
|
|
}
|
|
}
|
|
|
|
private async toolMenu() {
|
|
const tools = this.tools.keys().toArray();
|
|
const bodyBlock = this.terminalLayout.getBlock("body");
|
|
bodyBlock.clearAll();
|
|
bodyBlock.setPreserveHistory(false);
|
|
const selected = await selectMenuInteractive(
|
|
"Choose a tool",
|
|
tools.concat(["Help", "Exit"]),
|
|
{
|
|
terminalBlock: bodyBlock,
|
|
},
|
|
);
|
|
if (!selected) return;
|
|
if (selected === "Exit") {
|
|
return;
|
|
}
|
|
await this.runTool(selected);
|
|
await this.toolMenu();
|
|
}
|
|
|
|
private async runTool(toolName: string) {
|
|
if (toolName === "Help") {
|
|
return await this.help();
|
|
}
|
|
const tool = this.tools.get(toolName);
|
|
if (tool) {
|
|
this.ensmallenHeader(tool.name + " - " + tool.description);
|
|
const bodyBlock = this.terminalLayout.getBlock("body");
|
|
bodyBlock.clearAll();
|
|
tool.setBlock?.(bodyBlock);
|
|
if (this.args.getFlag("help")) {
|
|
await tool.help?.();
|
|
} else {
|
|
await tool.run(...this.args.taskArgs);
|
|
await tool.done?.();
|
|
}
|
|
await this.embiggenHeader();
|
|
} else {
|
|
this.closeMessage = "No tool found for " + toolName;
|
|
}
|
|
}
|
|
|
|
private ensmallenHeader(subtitle: string) {
|
|
this.terminalLayout.clear();
|
|
const titleBlock = this.terminalLayout.getBlock("title");
|
|
titleBlock.clear();
|
|
titleBlock.setFixedHeight(3);
|
|
titleBlock.setLines([
|
|
colorize("BearMetal PDF Tools", "porple"),
|
|
colorize(subtitle, "gray"),
|
|
"-=".repeat(Deno.consoleSize().columns / 2),
|
|
]);
|
|
}
|
|
|
|
private async embiggenHeader() {
|
|
const titleBlock = this.terminalLayout.getBlock("title");
|
|
titleBlock.clear();
|
|
const lines: string[] = [];
|
|
for (const t of ["bearmetal:porple", "pdftools:cyan"]) {
|
|
const [name, color] = t.split(":");
|
|
const asciiArt = await getAsciiArt(name);
|
|
lines.push(...colorize(asciiArt, color).split("\n"));
|
|
}
|
|
titleBlock.setFixedHeight(lines.length);
|
|
titleBlock.setLines(lines);
|
|
}
|
|
}
|