feat: delete fields tool
fix: field rename fix: list fields now scrolls
This commit is contained in:
50
tools/deleteFields.ts
Normal file
50
tools/deleteFields.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { forceArgs } from "../cli/forceArgs.ts";
|
||||
import { cliPrompt } from "../cli/prompts.ts";
|
||||
import { multiSelectMenuInteractive } from "../cli/selectMenu.ts";
|
||||
import { TerminalBlock } from "../cli/TerminalLayout.ts";
|
||||
import type { callback, ITool } from "../types.ts";
|
||||
import { loadPdf, savePdf } from "util/saveLoadPdf.ts";
|
||||
import { log } from "util/logfile.ts";
|
||||
|
||||
export class DeleteFormFields implements ITool {
|
||||
name = "deleteFormFields";
|
||||
description = "delete multiple form fields from a PDF";
|
||||
block?: TerminalBlock;
|
||||
|
||||
async run(pdfPath: string = "") {
|
||||
if (!this.block) this.block = new TerminalBlock();
|
||||
[pdfPath] = await forceArgs([pdfPath], [[
|
||||
"Please provide path to PDF",
|
||||
(d) => d?.endsWith(".pdf"),
|
||||
]], this.block);
|
||||
|
||||
const pdf = await loadPdf(pdfPath);
|
||||
const form = pdf.getForm();
|
||||
const fields = form.getFields();
|
||||
let updatesMade = false;
|
||||
await multiSelectMenuInteractive(
|
||||
`${pdfPath}\nSelect fields to delete:`,
|
||||
fields.map<[string, callback]>((
|
||||
f,
|
||||
) => [f.getName(), () => {
|
||||
while (f.acroField.getWidgets().length) {
|
||||
f.acroField.removeWidget(0);
|
||||
}
|
||||
form.removeField(f);
|
||||
updatesMade = true;
|
||||
}]),
|
||||
);
|
||||
if (!updatesMade) return;
|
||||
const path = await cliPrompt(
|
||||
"Save to path (or hit enter to keep current):",
|
||||
this.block,
|
||||
) || pdfPath;
|
||||
await savePdf(pdf, path);
|
||||
}
|
||||
help?: (() => Promise<void> | void) | undefined;
|
||||
done?: (() => Promise<void> | void) | undefined;
|
||||
setBlock(block: TerminalBlock) {
|
||||
this.block = block;
|
||||
}
|
||||
}
|
||||
export default new DeleteFormFields();
|
@@ -404,7 +404,7 @@ class RenameFields implements ITool {
|
||||
if (!this.block) {
|
||||
this.block = new TerminalBlock();
|
||||
}
|
||||
this.block.setPreserveHistory(true);
|
||||
this.block.setPreserveHistory(false);
|
||||
|
||||
[pdfPath, pattern, change] = await forceArgs(
|
||||
[pdfPath, pattern, change],
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import { forceArgs } from "../cli/forceArgs.ts";
|
||||
import { cliAlert } from "../cli/prompts.ts";
|
||||
import { TerminalBlock } from "../cli/TerminalLayout.ts";
|
||||
import { loadPdfForm } from "util/saveLoadPdf.ts";
|
||||
import type { ITool } from "../types.ts";
|
||||
import { InputManager } from "../cli/InputManager.ts";
|
||||
|
||||
export class ListFormFields implements ITool {
|
||||
name = "listformfields";
|
||||
@@ -12,21 +12,48 @@ export class ListFormFields implements ITool {
|
||||
if (!this.block) {
|
||||
this.block = new TerminalBlock();
|
||||
}
|
||||
this.block.setPreserveHistory(true);
|
||||
this.block.setPreserveHistory(false);
|
||||
[pdfPath] = await forceArgs([pdfPath], [[
|
||||
"Please provide path to PDF:",
|
||||
(p) => !!p && p.endsWith(".pdf"),
|
||||
]], this.block);
|
||||
const lines = [pdfPath];
|
||||
let rLines: string[] = [];
|
||||
|
||||
const form = await loadPdfForm(pdfPath);
|
||||
const fields = form.getFields();
|
||||
const fieldNames = fields.map((f) => f.getName());
|
||||
const lines = [];
|
||||
for (const fieldName of fieldNames) {
|
||||
lines.push(fieldName);
|
||||
}
|
||||
this.block.setLines(lines, [0, 1]);
|
||||
await cliAlert("", this.block);
|
||||
|
||||
let offset = 0;
|
||||
|
||||
const buildRLines = () => {
|
||||
rLines = fieldNames.slice(offset, this.block!.getRenderHeight());
|
||||
this.block!.setLines(lines.concat(rLines), [0, 1]);
|
||||
};
|
||||
buildRLines();
|
||||
|
||||
await new Promise<void>((res) => {
|
||||
const im = InputManager.getInstance();
|
||||
const up = () => {
|
||||
if (fieldNames.length < this.block!.getRenderHeight() - 1) return;
|
||||
offset = Math.max(0, offset - 1);
|
||||
buildRLines();
|
||||
};
|
||||
const down = () => {
|
||||
if (fieldNames.length < this.block!.getRenderHeight() - 1) return;
|
||||
offset = Math.min(fieldNames.length, offset + 1);
|
||||
buildRLines();
|
||||
};
|
||||
const enter = () => {
|
||||
res();
|
||||
im.removeEventListener("arrow-up", up);
|
||||
im.removeEventListener("arrow-down", down);
|
||||
im.removeEventListener("enter", enter);
|
||||
};
|
||||
im.addEventListener("arrow-up", up);
|
||||
im.addEventListener("arrow-down", down);
|
||||
im.addEventListener("enter", enter);
|
||||
});
|
||||
}
|
||||
setBlock(terminalBlock: TerminalBlock) {
|
||||
this.block = terminalBlock;
|
||||
|
Reference in New Issue
Block a user