143 lines
4.3 KiB
TypeScript
143 lines
4.3 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";
|
|
|
|
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(tools?: string) {
|
|
tools = tools?.replace(/\/$/, "").replace(/^\.?\//, "") || "tools";
|
|
for (const toolfile of Deno.readDirSync(tools)) {
|
|
if (toolfile.isFile) {
|
|
const tool = await import(
|
|
Deno.cwd() + "/" + tools + "/" + toolfile.name
|
|
);
|
|
if (tool.default) {
|
|
this.tools.set(
|
|
toCase(toolfile.name.replace(".ts", ""), "title"),
|
|
tool.default,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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 {
|
|
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.importTools();
|
|
await this.toolMenu();
|
|
} else {
|
|
await this.importTools();
|
|
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);
|
|
}
|
|
}
|