feat: esc to cancel select menus
feat: fieldVisibility tool
This commit is contained in:
@@ -6,12 +6,13 @@ interface EventMap {
|
||||
exit: Event;
|
||||
enter: Event;
|
||||
backspace: Event;
|
||||
escape: Event;
|
||||
delete: Event;
|
||||
"arrow-left": Event;
|
||||
"arrow-right": Event;
|
||||
"arrow-up": Event;
|
||||
"arrow-down": Event;
|
||||
[key: string]: Event;
|
||||
// [key: string]: Event;
|
||||
}
|
||||
|
||||
interface EventDetailMap {
|
||||
@@ -146,6 +147,12 @@ export class InputManager extends ManagerEventTarget {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (byte === 27 && i + 1 >= n) {
|
||||
this.dispatchEvent(new Event("escape"));
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Escape sequences
|
||||
if (byte === 27 && i + 1 < n && buf[i + 1] === 91) {
|
||||
const code = buf[i + 2];
|
||||
@@ -193,4 +200,23 @@ export class InputManager extends ManagerEventTarget {
|
||||
|
||||
if (raw) await Deno.stdin.setRaw(false);
|
||||
}
|
||||
|
||||
dispatchKey(key: string) {
|
||||
switch (key) {
|
||||
case "enter":
|
||||
case "backspace":
|
||||
case "arrow-up":
|
||||
case "arrow-down":
|
||||
case "arrow-right":
|
||||
case "arrow-left":
|
||||
case "delete":
|
||||
case "escape":
|
||||
this.dispatchEvent(new Event(key));
|
||||
break;
|
||||
default:
|
||||
this.dispatchEvent(
|
||||
new CLICharEvent({ key: key.charCodeAt(0), char: key }),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@ const toolRegistry: [string, Promise<{ default: ITool }>][] = [
|
||||
["fieldRename", import("../tools/fieldRename.ts")],
|
||||
["listFormFields", import("../tools/listFormFields.ts")],
|
||||
["deleteFields", import("../tools/deleteFields.ts")],
|
||||
["fieldVisibility", import("../tools/fieldVisibility.ts")],
|
||||
];
|
||||
|
||||
export class PdfToolsCli {
|
||||
|
@@ -1,5 +1,4 @@
|
||||
import type { callback } from "../types.ts";
|
||||
import { log } from "util/logfile.ts";
|
||||
import { type CLICharEvent, InputManager } from "./InputManager.ts";
|
||||
import { cliLog } from "./prompts.ts";
|
||||
import { colorize } from "./style.ts";
|
||||
@@ -92,7 +91,17 @@ export async function selectMenuInteractive(
|
||||
inputBuffer = inputBuffer.slice(0, -1);
|
||||
};
|
||||
|
||||
let resolve: null | ((value: string) => void) = null;
|
||||
let resolve: null | ((value: string | null) => void) = null;
|
||||
|
||||
const onEscape = () => {
|
||||
im.removeEventListener("arrow-up", onUp);
|
||||
im.removeEventListener("arrow-down", onDown);
|
||||
im.removeEventListener("char", onKey);
|
||||
im.removeEventListener("backspace", onBackspace);
|
||||
im.removeEventListener("enter", onEnter);
|
||||
im.removeEventListener("escape", onEscape);
|
||||
resolve?.(null);
|
||||
};
|
||||
|
||||
const onEnter = (e: Event) => {
|
||||
e.stopImmediatePropagation();
|
||||
@@ -108,22 +117,24 @@ export async function selectMenuInteractive(
|
||||
im.removeEventListener("char", onKey);
|
||||
im.removeEventListener("backspace", onBackspace);
|
||||
im.removeEventListener("enter", onEnter);
|
||||
im.removeEventListener("escape", onEscape);
|
||||
resolve?.(options[selected]);
|
||||
};
|
||||
|
||||
renderMenu();
|
||||
await new Promise<string>((res) => {
|
||||
const final = await new Promise<string | null>((res) => {
|
||||
resolve = res;
|
||||
im.addEventListener("char", onKey);
|
||||
im.addEventListener("backspace", onBackspace);
|
||||
im.addEventListener("enter", onEnter);
|
||||
im.addEventListener("arrow-up", onUp);
|
||||
im.addEventListener("arrow-down", onDown);
|
||||
im.addEventListener("escape", onEscape);
|
||||
});
|
||||
|
||||
terminalBlock.setLines(["Selected: " + options[selected]], range);
|
||||
terminalBlock.setLines(["Selected: " + final], range);
|
||||
|
||||
return options[selected];
|
||||
return final;
|
||||
}
|
||||
|
||||
export async function multiSelectMenuInteractive(
|
||||
@@ -151,10 +162,8 @@ export async function multiSelectMenuInteractive(
|
||||
|
||||
const checkSelectAll = () => {
|
||||
if (selectedOptions.includes(0)) {
|
||||
log("yeet");
|
||||
selectedOptions = [];
|
||||
} else {
|
||||
log("neat");
|
||||
selectedOptions = Array.from(options).map((_, i) => i);
|
||||
}
|
||||
};
|
||||
@@ -195,7 +204,7 @@ export async function multiSelectMenuInteractive(
|
||||
const im = InputManager.getInstance();
|
||||
im.activate();
|
||||
|
||||
let resolve = null as null | ((value: number[]) => void);
|
||||
let resolve = null as null | ((value: number[] | null) => void);
|
||||
|
||||
const onUp = (e: Event) => {
|
||||
e.stopImmediatePropagation();
|
||||
@@ -223,24 +232,36 @@ export async function multiSelectMenuInteractive(
|
||||
renderMenu();
|
||||
};
|
||||
|
||||
const onEnter = (e: Event) => {
|
||||
e.stopImmediatePropagation();
|
||||
resolve?.(selectedOptions);
|
||||
const onEscape = () => {
|
||||
im.removeEventListener("arrow-up", onUp);
|
||||
im.removeEventListener("arrow-down", onDown);
|
||||
im.removeEventListener("char", onSpace);
|
||||
im.removeEventListener("enter", onEnter);
|
||||
im.removeEventListener("escape", onEscape);
|
||||
resolve?.(null);
|
||||
};
|
||||
|
||||
const onEnter = (e: Event) => {
|
||||
e.stopImmediatePropagation();
|
||||
im.removeEventListener("arrow-up", onUp);
|
||||
im.removeEventListener("arrow-down", onDown);
|
||||
im.removeEventListener("char", onSpace);
|
||||
im.removeEventListener("enter", onEnter);
|
||||
im.removeEventListener("escape", onEscape);
|
||||
resolve?.(selectedOptions);
|
||||
};
|
||||
|
||||
renderMenu();
|
||||
|
||||
const selections = await new Promise<number[]>((res) => {
|
||||
const selections = await new Promise<number[] | null>((res) => {
|
||||
resolve = res;
|
||||
im.addEventListener("arrow-up", onUp);
|
||||
im.addEventListener("arrow-down", onDown);
|
||||
im.addEventListener("char", onSpace);
|
||||
im.addEventListener("enter", onEnter);
|
||||
im.addEventListener("escape", onEscape);
|
||||
});
|
||||
if (!selections) return null;
|
||||
for (const optionI of selections) {
|
||||
const option = options[optionI];
|
||||
if (Array.isArray(option)) {
|
||||
@@ -322,7 +343,7 @@ if (import.meta.main) {
|
||||
"yuzu",
|
||||
"zucchini",
|
||||
], { terminalBlock: block, allOption: true });
|
||||
cliLog(val || "No value");
|
||||
cliLog(val || "No value", block);
|
||||
|
||||
// Deno.stdout.writeSync(new TextEncoder().encode("\x07"));
|
||||
}
|
||||
|
Reference in New Issue
Block a user