fix: unifies cursor positioning through input manager
removed: block level preserve history removed until accurate reporting of render heights is available fix: fixes block multiline rendering
This commit is contained in:
parent
04d5044c43
commit
7eb7197a1c
@ -72,6 +72,14 @@ export class CLIKeypressEvent extends CustomEvent<EventDetailMap["keypress"]> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type bounds = {
|
||||||
|
top?: number;
|
||||||
|
left?: number;
|
||||||
|
right?: number;
|
||||||
|
bottom?: number;
|
||||||
|
boundMode?: "relative" | "absolute";
|
||||||
|
};
|
||||||
|
|
||||||
export class InputManager extends ManagerEventTarget {
|
export class InputManager extends ManagerEventTarget {
|
||||||
private static instance = new InputManager();
|
private static instance = new InputManager();
|
||||||
private active = false;
|
private active = false;
|
||||||
@ -144,6 +152,7 @@ export class InputManager extends ManagerEventTarget {
|
|||||||
if (byte === 127 || byte === 8) {
|
if (byte === 127 || byte === 8) {
|
||||||
this.dispatchEvent(new Event("backspace"));
|
this.dispatchEvent(new Event("backspace"));
|
||||||
i++;
|
i++;
|
||||||
|
this.moveCursor(-1, 0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,18 +166,23 @@ export class InputManager extends ManagerEventTarget {
|
|||||||
if (byte === 27 && i + 1 < n && buf[i + 1] === 91) {
|
if (byte === 27 && i + 1 < n && buf[i + 1] === 91) {
|
||||||
const code = buf[i + 2];
|
const code = buf[i + 2];
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 65:
|
case 65: // Up
|
||||||
|
this.moveCursor(0, -1);
|
||||||
this.dispatchEvent(new Event("arrow-up"));
|
this.dispatchEvent(new Event("arrow-up"));
|
||||||
break;
|
break;
|
||||||
case 66:
|
case 66: // Down
|
||||||
|
this.moveCursor(0, 1);
|
||||||
this.dispatchEvent(new Event("arrow-down"));
|
this.dispatchEvent(new Event("arrow-down"));
|
||||||
break;
|
break;
|
||||||
case 67:
|
case 67: // Right
|
||||||
|
this.moveCursor(1, 0);
|
||||||
this.dispatchEvent(new Event("arrow-right"));
|
this.dispatchEvent(new Event("arrow-right"));
|
||||||
break;
|
break;
|
||||||
case 68:
|
case 68: // Left
|
||||||
|
this.moveCursor(-1, 0);
|
||||||
this.dispatchEvent(new Event("arrow-left"));
|
this.dispatchEvent(new Event("arrow-left"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 51:
|
case 51:
|
||||||
if (i + 3 < n && buf[i + 3] === 126) {
|
if (i + 3 < n && buf[i + 3] === 126) {
|
||||||
this.dispatchEvent(new Event("delete"));
|
this.dispatchEvent(new Event("delete"));
|
||||||
@ -186,6 +200,7 @@ export class InputManager extends ManagerEventTarget {
|
|||||||
this.dispatchEvent(
|
this.dispatchEvent(
|
||||||
new CLICharEvent({ key: byte, char: String.fromCharCode(byte) }),
|
new CLICharEvent({ key: byte, char: String.fromCharCode(byte) }),
|
||||||
);
|
);
|
||||||
|
this.moveCursor(1, 0);
|
||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -219,4 +234,90 @@ export class InputManager extends ManagerEventTarget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cursor management
|
||||||
|
private cursor = { row: 0, col: 0 };
|
||||||
|
private bounds: bounds = {};
|
||||||
|
|
||||||
|
getCursor() {
|
||||||
|
return { ...this.cursor };
|
||||||
|
}
|
||||||
|
|
||||||
|
getRelativeCursor() {
|
||||||
|
const boundStart = (this.bounds.top ?? 0) * Deno.consoleSize().columns +
|
||||||
|
(this.bounds.left ?? 0);
|
||||||
|
const cursorPos = (this.cursor.row * Deno.consoleSize().columns) +
|
||||||
|
this.cursor.col;
|
||||||
|
return cursorPos - boundStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
setCursor(row: number, col: number) {
|
||||||
|
const { columns, rows } = Deno.consoleSize();
|
||||||
|
const { top, bottom, left, right, boundMode } = {
|
||||||
|
top: 0,
|
||||||
|
bottom: rows - 1,
|
||||||
|
left: 0,
|
||||||
|
right: columns,
|
||||||
|
boundMode: "relative",
|
||||||
|
...this.bounds,
|
||||||
|
} as bounds;
|
||||||
|
|
||||||
|
switch (boundMode) {
|
||||||
|
case "absolute":
|
||||||
|
this.cursor.row = Math.max(
|
||||||
|
top ?? -Infinity,
|
||||||
|
Math.min(bottom ?? Infinity, row),
|
||||||
|
);
|
||||||
|
this.cursor.col = Math.max(
|
||||||
|
left ?? -Infinity,
|
||||||
|
Math.min(right ?? Infinity, col),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "relative": {
|
||||||
|
const boundStart = (top! * columns) + left!;
|
||||||
|
const boundEnd = (bottom! * columns) + right!;
|
||||||
|
let proposedPosition = (row * columns) + col;
|
||||||
|
if (proposedPosition < boundStart) proposedPosition = boundStart;
|
||||||
|
if (proposedPosition > boundEnd) proposedPosition = boundEnd;
|
||||||
|
col = proposedPosition % columns;
|
||||||
|
row = (proposedPosition - col) / columns;
|
||||||
|
this.cursor.row = row;
|
||||||
|
this.cursor.col = col;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.applyCursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
moveCursor(dx: number, dy: number) {
|
||||||
|
this.setCursor(this.cursor.row + dy, this.cursor.col + dx);
|
||||||
|
}
|
||||||
|
|
||||||
|
setBounds(
|
||||||
|
bounds: { top?: number; left?: number; right?: number; bottom?: number },
|
||||||
|
) {
|
||||||
|
this.bounds = bounds;
|
||||||
|
this.setCursor(this.cursor.row, this.cursor.col); // enforce bounds immediately
|
||||||
|
}
|
||||||
|
getBounds() {
|
||||||
|
return { ...this.bounds };
|
||||||
|
}
|
||||||
|
updateBounds(
|
||||||
|
bounds: { top?: number; left?: number; right?: number; bottom?: number },
|
||||||
|
) {
|
||||||
|
this.bounds = { ...this.bounds, ...bounds };
|
||||||
|
this.setCursor(this.cursor.row, this.cursor.col);
|
||||||
|
}
|
||||||
|
resetBounds() {
|
||||||
|
this.bounds = {};
|
||||||
|
this.setCursor(this.cursor.row, this.cursor.col);
|
||||||
|
}
|
||||||
|
|
||||||
|
private applyCursor() {
|
||||||
|
Deno.stdout.writeSync(
|
||||||
|
new TextEncoder().encode(
|
||||||
|
`\x1b[${this.cursor.row + 1};${this.cursor.col + 1}H`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { Cursor } from "./cursor.ts";
|
import { Cursor } from "./cursor.ts";
|
||||||
|
import { InputManager } from "./InputManager.ts";
|
||||||
|
|
||||||
export class TerminalLayout {
|
export class TerminalLayout {
|
||||||
private static ALT_BUFFER_ENABLE = "\x1b[?1049h";
|
private static ALT_BUFFER_ENABLE = "\x1b[?1049h";
|
||||||
@ -132,12 +133,8 @@ export class TerminalBlock {
|
|||||||
this.layout = layout;
|
this.layout = layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
setLines(lines: string[], range?: [number, number]) {
|
setLines(lines: string[]) {
|
||||||
if (range && this.preserveHistory) {
|
this.lines = lines;
|
||||||
this.lines.splice(range[0], range[1], ...lines);
|
|
||||||
} else {
|
|
||||||
this.lines = this.preserveHistory ? this.lines.concat(lines) : lines;
|
|
||||||
}
|
|
||||||
if (this.scrollOffset > lines.length - 1) {
|
if (this.scrollOffset > lines.length - 1) {
|
||||||
this.scrollOffset = Math.max(0, lines.length - 1);
|
this.scrollOffset = Math.max(0, lines.length - 1);
|
||||||
}
|
}
|
||||||
@ -149,11 +146,47 @@ export class TerminalBlock {
|
|||||||
);
|
);
|
||||||
this.renderInternal();
|
this.renderInternal();
|
||||||
}
|
}
|
||||||
range = [
|
}
|
||||||
range?.[0] ?? this.lines.length - lines.length,
|
|
||||||
range ? range[0] + lines.length : this.lines.length,
|
wrapLines(maxWidth: number): string[] {
|
||||||
];
|
const wrapped: string[] = [];
|
||||||
return range;
|
const inputManager = InputManager.getInstance();
|
||||||
|
const cursor = inputManager.getCursor();
|
||||||
|
const bounds = inputManager.getBounds();
|
||||||
|
|
||||||
|
const blockStart = this.lastRenderRow;
|
||||||
|
let visualRow = blockStart;
|
||||||
|
|
||||||
|
let maxCursorRow = cursor.row;
|
||||||
|
|
||||||
|
for (const line of this.lines) {
|
||||||
|
const chunks: string[] = [];
|
||||||
|
|
||||||
|
for (let start = 0; start < line.length; start += maxWidth) {
|
||||||
|
const chunk = line.slice(start, start + maxWidth);
|
||||||
|
chunks.push(chunk);
|
||||||
|
wrapped.push(this.prepend + chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
const visualLines = chunks.length;
|
||||||
|
const visualEnd = visualRow + visualLines - 1;
|
||||||
|
|
||||||
|
// Check if the cursor is within this wrapped line’s visual range
|
||||||
|
if (cursor.row >= visualRow && cursor.row <= visualEnd) {
|
||||||
|
maxCursorRow = visualEnd; // this becomes the new bottom bound
|
||||||
|
}
|
||||||
|
|
||||||
|
visualRow = visualEnd + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxCursorRow !== cursor.row) {
|
||||||
|
inputManager.setBounds({
|
||||||
|
...bounds,
|
||||||
|
bottom: maxCursorRow - blockStart,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return wrapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
append(lines: string[]) {
|
append(lines: string[]) {
|
||||||
@ -186,7 +219,16 @@ export class TerminalBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getRenderedLines(maxHeight: number): string[] {
|
getRenderedLines(maxHeight: number): string[] {
|
||||||
return this.lines.slice(this.scrollOffset, this.scrollOffset + maxHeight);
|
const width = Deno.consoleSize().columns - this.prepend.length;
|
||||||
|
const wrapped = this.wrapLines(width);
|
||||||
|
return wrapped.slice(this.scrollOffset, this.scrollOffset + maxHeight);
|
||||||
|
}
|
||||||
|
getStartRow(): number {
|
||||||
|
return this.lastRenderRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
getEndRow(): number {
|
||||||
|
return this.lastRenderRow + this.renderedLineCount - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
setRenderLines(lines: string[]) {
|
setRenderLines(lines: string[]) {
|
||||||
@ -262,12 +304,21 @@ export class TerminalBlock {
|
|||||||
getFixedHeight(): number {
|
getFixedHeight(): number {
|
||||||
return this.fixedHeight ?? 0;
|
return this.fixedHeight ?? 0;
|
||||||
}
|
}
|
||||||
|
requestCursorAt(
|
||||||
|
lineOffsetFromStart = 0,
|
||||||
|
col = 0,
|
||||||
|
): [row: number, col: number] {
|
||||||
|
return [this.lastRenderRow + lineOffsetFromStart, col];
|
||||||
|
}
|
||||||
|
|
||||||
private _postRenderAction?: () => void;
|
private _postRenderAction?: () => void;
|
||||||
setPostRenderAction(action: (this: TerminalBlock) => void) {
|
setPostRenderAction(action: (this: TerminalBlock) => void) {
|
||||||
this._postRenderAction = action;
|
this._postRenderAction = action;
|
||||||
}
|
}
|
||||||
runPostRenderAction() {
|
runPostRenderAction() {
|
||||||
|
const im = InputManager.getInstance();
|
||||||
|
im.moveCursor(0, 0);
|
||||||
|
|
||||||
if (this._postRenderAction) {
|
if (this._postRenderAction) {
|
||||||
this._postRenderAction.call(this);
|
this._postRenderAction.call(this);
|
||||||
this._postRenderAction = undefined;
|
this._postRenderAction = undefined;
|
||||||
|
129
cli/prompts.ts
129
cli/prompts.ts
@ -4,115 +4,6 @@ import { colorize } from "./style.ts";
|
|||||||
import { TerminalBlock, TerminalLayout } from "./TerminalLayout.ts";
|
import { TerminalBlock, TerminalLayout } from "./TerminalLayout.ts";
|
||||||
import { type CLICharEvent, InputManager } from "./InputManager.ts";
|
import { type CLICharEvent, InputManager } from "./InputManager.ts";
|
||||||
|
|
||||||
// export async function cliPrompt(
|
|
||||||
// message: string,
|
|
||||||
// block?: TerminalBlock,
|
|
||||||
// ): Promise<string> {
|
|
||||||
// const encoder = new TextEncoder();
|
|
||||||
// const input: string[] = [];
|
|
||||||
// let cursorPos = 0;
|
|
||||||
|
|
||||||
// await Deno.stdin.setRaw(true);
|
|
||||||
|
|
||||||
// const cursorVisible = Cursor["visible"];
|
|
||||||
// Cursor.show();
|
|
||||||
|
|
||||||
// let range: [number, number] = [0, 1];
|
|
||||||
// if (block) {
|
|
||||||
// range = block.setLines([message + " "]);
|
|
||||||
// } else {
|
|
||||||
// Deno.stdout.writeSync(encoder.encode(message + " "));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const render = () => {
|
|
||||||
// const line = message + " " + input.join("");
|
|
||||||
// const moveTo = `\x1b[${message.length + 2 + cursorPos}G`;
|
|
||||||
|
|
||||||
// if (block) {
|
|
||||||
// block.setPostRenderAction(function () {
|
|
||||||
// Deno.stdout.writeSync(
|
|
||||||
// encoder.encode(`\x1b[${this["lastRenderRow"]};1H`),
|
|
||||||
// );
|
|
||||||
// Deno.stdout.writeSync(encoder.encode(moveTo));
|
|
||||||
// });
|
|
||||||
// range = block.setLines([line], range);
|
|
||||||
// } else {
|
|
||||||
// Deno.stdout.writeSync(encoder.encode("\x1b[K" + line + moveTo));
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// render();
|
|
||||||
|
|
||||||
// const buf = new Uint8Array(64); // large enough for most pastes
|
|
||||||
// inputLoop:
|
|
||||||
// while (true) {
|
|
||||||
// const n = await Deno.stdin.read(buf);
|
|
||||||
// if (n === null) break;
|
|
||||||
|
|
||||||
// for (let i = 0; i < n; i++) {
|
|
||||||
// const byte = buf[i];
|
|
||||||
|
|
||||||
// // Ctrl+C
|
|
||||||
// if (byte === 3) {
|
|
||||||
// block?.clear();
|
|
||||||
// block?.["layout"]?.clearAll();
|
|
||||||
// await Deno.stdin.setRaw(false);
|
|
||||||
// Deno.exit(130);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (byte === 13) { // Enter
|
|
||||||
// break inputLoop;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Escape sequence?
|
|
||||||
// if (byte === 27 && i + 1 < n && buf[i + 1] === 91) {
|
|
||||||
// const third = buf[i + 2];
|
|
||||||
// if (third === 68 && cursorPos > 0) cursorPos--; // Left
|
|
||||||
// else if (third === 67 && cursorPos < input.length) cursorPos++; // Right
|
|
||||||
// else if (third === 51 && i + 3 < n && buf[i + 3] === 126) { // Delete
|
|
||||||
// if (cursorPos < input.length) input.splice(cursorPos, 1);
|
|
||||||
// i += 1; // consume tilde
|
|
||||||
// }
|
|
||||||
// i += 2; // consume ESC [ X
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Backspace
|
|
||||||
// if (byte === 127 || byte === 8) {
|
|
||||||
// if (cursorPos > 0) {
|
|
||||||
// input.splice(cursorPos - 1, 1);
|
|
||||||
// cursorPos--;
|
|
||||||
// }
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Delete (ASCII 46)
|
|
||||||
// if (byte === 46 && cursorPos < input.length) {
|
|
||||||
// input.splice(cursorPos, 1);
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Printable
|
|
||||||
// if (byte >= 32 && byte <= 126) {
|
|
||||||
// input.splice(cursorPos, 0, String.fromCharCode(byte));
|
|
||||||
// cursorPos++;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Other cases: ignore
|
|
||||||
// }
|
|
||||||
|
|
||||||
// render();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// await Deno.stdin.setRaw(false);
|
|
||||||
// if (!cursorVisible) {
|
|
||||||
// Cursor.hide();
|
|
||||||
// }
|
|
||||||
// Deno.stdout.writeSync(encoder.encode("\n"));
|
|
||||||
|
|
||||||
// return input.join("");
|
|
||||||
// }
|
|
||||||
|
|
||||||
export async function cliPrompt(
|
export async function cliPrompt(
|
||||||
message: string,
|
message: string,
|
||||||
block?: TerminalBlock,
|
block?: TerminalBlock,
|
||||||
@ -120,7 +11,6 @@ export async function cliPrompt(
|
|||||||
const encoder = new TextEncoder();
|
const encoder = new TextEncoder();
|
||||||
const input: string[] = [];
|
const input: string[] = [];
|
||||||
let cursorPos = 0;
|
let cursorPos = 0;
|
||||||
let range: [number, number] | undefined;
|
|
||||||
|
|
||||||
Cursor.show();
|
Cursor.show();
|
||||||
|
|
||||||
@ -132,15 +22,21 @@ export async function cliPrompt(
|
|||||||
const moveTo = `\x1b[${message.length + 2 + cursorPos}G`;
|
const moveTo = `\x1b[${message.length + 2 + cursorPos}G`;
|
||||||
|
|
||||||
if (block) {
|
if (block) {
|
||||||
block.setPostRenderAction(() => {
|
block.setLines([line]);
|
||||||
Deno.stdout.writeSync(encoder.encode(moveTo));
|
|
||||||
});
|
|
||||||
range = block.setLines([line], range);
|
|
||||||
} else {
|
} else {
|
||||||
Deno.stdout.writeSync(encoder.encode("\r\x1b[K" + line + moveTo));
|
Deno.stdout.writeSync(encoder.encode("\r\x1b[K" + line + moveTo));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
render();
|
||||||
|
const cPos = block?.requestCursorAt(0, message.length + 1);
|
||||||
|
if (cPos) {
|
||||||
|
const [row, column] = cPos;
|
||||||
|
|
||||||
|
im.setCursor(row, column);
|
||||||
|
im.setBounds({ top: row, left: column, right: column, bottom: row });
|
||||||
|
}
|
||||||
|
|
||||||
const exit = () => {
|
const exit = () => {
|
||||||
im.removeEventListener("enter", onEnter);
|
im.removeEventListener("enter", onEnter);
|
||||||
im.removeEventListener("backspace", onBackspace);
|
im.removeEventListener("backspace", onBackspace);
|
||||||
@ -189,13 +85,12 @@ export async function cliPrompt(
|
|||||||
|
|
||||||
const onKey = (e: Event) => {
|
const onKey = (e: Event) => {
|
||||||
const ke = (e as CLICharEvent).detail;
|
const ke = (e as CLICharEvent).detail;
|
||||||
|
cursorPos = im.getRelativeCursor();
|
||||||
input.splice(cursorPos, 0, ke.char);
|
input.splice(cursorPos, 0, ke.char);
|
||||||
cursorPos++;
|
im.updateBounds({ right: input.length + message.length + 1 });
|
||||||
render();
|
render();
|
||||||
};
|
};
|
||||||
|
|
||||||
render();
|
|
||||||
|
|
||||||
return await new Promise<string>((res) => {
|
return await new Promise<string>((res) => {
|
||||||
resolve = res;
|
resolve = res;
|
||||||
im.addEventListener("enter", onEnter);
|
im.addEventListener("enter", onEnter);
|
||||||
|
@ -30,7 +30,6 @@ export async function selectMenuInteractive(
|
|||||||
terminalBlock.setRenderHeight(Deno.consoleSize().rows);
|
terminalBlock.setRenderHeight(Deno.consoleSize().rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
let range: [number, number] = [terminalBlock.lineCount, 1];
|
|
||||||
function renderMenu() {
|
function renderMenu() {
|
||||||
const { rows } = Deno.consoleSize();
|
const { rows } = Deno.consoleSize();
|
||||||
const terminalHeight = terminalBlock.getRenderHeight() || rows;
|
const terminalHeight = terminalBlock.getRenderHeight() || rows;
|
||||||
@ -52,7 +51,7 @@ export async function selectMenuInteractive(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
range = terminalBlock.setLines(lines, range);
|
terminalBlock.setLines(lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
function numberAndPadding(i: number, prefix?: string) {
|
function numberAndPadding(i: number, prefix?: string) {
|
||||||
@ -132,7 +131,7 @@ export async function selectMenuInteractive(
|
|||||||
im.addEventListener("escape", onEscape);
|
im.addEventListener("escape", onEscape);
|
||||||
});
|
});
|
||||||
|
|
||||||
terminalBlock.setLines(["Selected: " + final], range);
|
// terminalBlock.setLines(["Selected: " + final], range);
|
||||||
|
|
||||||
return final;
|
return final;
|
||||||
}
|
}
|
||||||
@ -173,7 +172,6 @@ export async function multiSelectMenuInteractive(
|
|||||||
if (!allPresent) selectedOptions = selectedOptions.filter((e) => e != 0);
|
if (!allPresent) selectedOptions = selectedOptions.filter((e) => e != 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
let range: [number, number] = [terminalBlock.lineCount, 1];
|
|
||||||
function renderMenu() {
|
function renderMenu() {
|
||||||
const { rows } = Deno.consoleSize();
|
const { rows } = Deno.consoleSize();
|
||||||
const terminalHeight = terminalBlock.getRenderHeight() || rows;
|
const terminalHeight = terminalBlock.getRenderHeight() || rows;
|
||||||
@ -198,7 +196,7 @@ export async function multiSelectMenuInteractive(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
range = terminalBlock.setLines(lines, range);
|
terminalBlock.setLines(lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
const im = InputManager.getInstance();
|
const im = InputManager.getInstance();
|
||||||
@ -269,7 +267,7 @@ export async function multiSelectMenuInteractive(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const final = selectedOptions.map((i) => rawValues[i]);
|
const final = selectedOptions.map((i) => rawValues[i]);
|
||||||
terminalBlock.setLines(["Selected: " + final.join(", ")], range);
|
terminalBlock.setLines(["Selected: " + final.join(", ")]);
|
||||||
return final;
|
return final;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@bearmetal/pdf-tools",
|
"name": "@bearmetal/pdf-tools",
|
||||||
"version": "1.0.8-n",
|
"version": "1.0.8-p",
|
||||||
"license": "GPL 3.0",
|
"license": "GPL 3.0",
|
||||||
"tasks": {
|
"tasks": {
|
||||||
"dev": "deno run -A main.ts",
|
"dev": "deno run -A main.ts",
|
||||||
|
@ -92,6 +92,7 @@ export class FieldVisibility implements ITool {
|
|||||||
);
|
);
|
||||||
return visibility;
|
return visibility;
|
||||||
}),
|
}),
|
||||||
|
{ terminalBlock: this.block },
|
||||||
);
|
);
|
||||||
if (!fieldAndVisibility) break;
|
if (!fieldAndVisibility) break;
|
||||||
const visibility = await selectMenuInteractive(
|
const visibility = await selectMenuInteractive(
|
||||||
@ -102,6 +103,7 @@ export class FieldVisibility implements ITool {
|
|||||||
"HiddenButPrintable",
|
"HiddenButPrintable",
|
||||||
"VisibleButDoesNotPrint",
|
"VisibleButDoesNotPrint",
|
||||||
] as AcrobatVisibility[],
|
] as AcrobatVisibility[],
|
||||||
|
{ terminalBlock: this.block },
|
||||||
) as AcrobatVisibility | null;
|
) as AcrobatVisibility | null;
|
||||||
if (!visibility) continue;
|
if (!visibility) continue;
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ export class ListFormFields implements ITool {
|
|||||||
|
|
||||||
const buildRLines = () => {
|
const buildRLines = () => {
|
||||||
rLines = fieldNames.slice(offset, this.block!.getRenderHeight());
|
rLines = fieldNames.slice(offset, this.block!.getRenderHeight());
|
||||||
this.block!.setLines(lines.concat(rLines), [0, 1]);
|
this.block!.setLines(lines.concat(rLines));
|
||||||
};
|
};
|
||||||
buildRLines();
|
buildRLines();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user