diff --git a/src/dialog.ts b/src/dialog.ts index a702208..a9fba72 100644 --- a/src/dialog.ts +++ b/src/dialog.ts @@ -9,17 +9,24 @@ export type DialogOptions = Record< true | string | undefined | string[] >; // array value means use this flag this many times +type Geometry = { x: number; y: number; width: number; height: number }; + let last_position: { x: number; y: number } | null = null; -async function get_geometry() { +async function get_geometry(): Promise { const result = (await simpleSpawn("bash", [ "-c", 'wmctrl -l -x node-zenity -G | grep node-zenity | awk \'{print $3 " " $4 " " $5 " " $6}\'', ])) as string; + console.log(result); const [x, y, width, height] = result .split("\n")[0] .split(" ") .map((s) => parseInt(s)); + console.log("getgeometry", result, { x, y, width, height }); + if (!height) { + return null; + } return { x, y, width, height }; } @@ -40,7 +47,7 @@ async function set_geometry({ if (height === undefined) { height = -1; } - await simpleSpawn("wmctrl", [ + const args = [ "-x", "-a", "node-zenity", @@ -48,15 +55,28 @@ async function set_geometry({ `0,${Math.round(x)},${Math.round(y)},${Math.round(width)},${Math.round( height )}`, - ]); + ]; + console.log(args); + await simpleSpawn("wmctrl", args); } -type DialogResponse = { +export type DialogResponse = { code: number; output: string; error: string; }; +setInterval(async () => { + const geometry = await get_geometry(); + if (!geometry) { + return; + } + last_position = { + x: Math.round(geometry.x + geometry.width / 2), + y: Math.round(geometry.y + geometry.height / 2), + }; +}, 2000); + export default class Dialog extends EventEmitter { shown = false; process: ChildProcessWithoutNullStreams; @@ -83,7 +103,6 @@ export default class Dialog extends EventEmitter { } else if (value === undefined) { //void } else { - console.log("unknown value:", value); throw new Error("uknown arg value type"); } } @@ -98,17 +117,6 @@ export default class Dialog extends EventEmitter { ]; console.log("spawning process!", args.join(" ")); this.process = spawn("zenity", args); - let position_listener_interval = setInterval(async () => { - const { x, y, width, height } = await get_geometry(); - console.log( - { x, y, width, height }, - { x: Math.round(x + width / 2), y: Math.round(y + height / 2) } - ); - last_position = { - x: Math.round(x + width / 2), - y: Math.round(y + height / 2), - }; - }, 2000); let spawned = false; return new Promise((resolve, reject) => { @@ -135,13 +143,13 @@ export default class Dialog extends EventEmitter { ]); // to activate it if (last_position) { const { width, height } = await get_geometry(); + console.log(last_position, width, height); await set_geometry({ x: last_position.x - width / 2 - 11, y: last_position.y - height / 2 - 82, }); // to put it where it last was } succeded = true; - console.log("WMCTRL SUCCEEDED!"); } catch (e) { console.error(e); continue; @@ -155,7 +163,6 @@ export default class Dialog extends EventEmitter { this.error += chunk; }); this.process.on("close", (code) => { - clearInterval(position_listener_interval); console.log("process closed. output:", this.output); if (code !== 0) { if (!spawned) { diff --git a/src/entry.ts b/src/entry.ts index 2086008..7eca356 100644 --- a/src/entry.ts +++ b/src/entry.ts @@ -17,6 +17,7 @@ export default class Entry { height: ((options?.height as unknown) as string)?.toString(), }); await dialog.show(); - return dialog.output.split("\n")[0]; + const answer = await dialog.getAnswer(); + return answer.output.split("\n")[0]; } } diff --git a/src/index.ts b/src/index.ts index 227fea0..f8bfc1e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,3 +6,4 @@ export { ItemsSelectedResponse, } from "./list"; export { default as Entry } from "./entry"; +export { default as TextInfo } from "./text-info"; diff --git a/src/info.ts b/src/info.ts index 6212fc0..d91d00b 100644 --- a/src/info.ts +++ b/src/info.ts @@ -1,4 +1,4 @@ -import Dialog from "./dialog"; +import Dialog, { DialogResponse } from "./dialog"; export default class Info { static async show( @@ -10,9 +10,9 @@ export default class Info { ellipsize: true; title: string; }> - ): Promise { + ): Promise { const dialog = new Dialog("info", { ...options, text }); await dialog.show(); - await dialog.getAnswer(); + return dialog.getAnswer(); } } diff --git a/src/list.ts b/src/list.ts index e12a22c..605d03f 100644 --- a/src/list.ts +++ b/src/list.ts @@ -8,7 +8,7 @@ export type ListOptions = { title: string; text: string; rows: string[][]; - multiple: true; + multiple: boolean; separator: string; editable: true; "print-column": number; @@ -77,7 +77,9 @@ export default class List { if (options.columns) { ret.column = options.columns; } - ret.multiple = options.multiple; + ret.multiple = (options.multiple ? true : undefined) as + | true + | undefined; ret.separator = options.separator; ret.editable = options.editable; ret["print-column"] = options["print-column"]?.toString(); diff --git a/src/text-info.ts b/src/text-info.ts new file mode 100644 index 0000000..f457ab6 --- /dev/null +++ b/src/text-info.ts @@ -0,0 +1,29 @@ +import Dialog from "./dialog"; + +export default class TextInfo { + static async show( + options: Partial<{ + text: string; + editable: true; + title: string; + width: number; + height: number; + }> + ): Promise { + const dialog = new Dialog("text-info", { + ...options, + editable: options.editable ? true : undefined, + text: undefined, + width: ((options?.width as unknown) as string)?.toString(), + height: ((options?.height as unknown) as string)?.toString(), + }); + await dialog.show(); + dialog.process.stdin.write(options.text || ""); + const answer = await dialog.getAnswer(); + if (answer.code === 0) { + return answer.output; + } else { + return null; + } + } +}