From 34d098b15cb1c5f03857aa925115737417df0ce9 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Sat, 21 Jun 2025 14:50:59 -0400 Subject: [PATCH] Improve Tkinter text editor --- README.md | 2 +- voxvera/cli.py | 53 ++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index e214ab6..09e6558 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Generate printable flyers with QR codes linking to Tor (.onion) or HTTPS sites, ## 🚀 Key Features -* **Interactive setup**: `voxvera init` prompts for metadata or extracts from a PDF form. +* **Interactive setup**: `voxvera init` prompts for metadata or extracts from a PDF form. When editing body text, a small Tkinter window opens with the current content pre-filled. If no GUI is available it falls back to `$EDITOR`. * **Template support**: `voxvera init --template ` copies built‑in templates (`blank`, `voxvera`). * **Build assets**: `voxvera build [--pdf ] [--download ]` generates HTML, obfuscated JS/CSS, QR codes, and bundles PDFs. * **Batch import**: `voxvera import` processes all JSON configs in `imports/`. diff --git a/voxvera/cli.py b/voxvera/cli.py index 598dccc..14a2fee 100644 --- a/voxvera/cli.py +++ b/voxvera/cli.py @@ -84,20 +84,61 @@ def save_config(data: dict, path: str): json.dump(data, fh, indent=2) -def open_editor(initial: str) -> str: +def _open_editor_terminal(initial: str) -> str: + """Fallback to opening the user's $EDITOR in the terminal.""" import tempfile - editor = os.environ.get('EDITOR', 'nano') - fd, path = tempfile.mkstemp(suffix='.txt') + + editor = os.environ.get("EDITOR", "nano") + fd, path = tempfile.mkstemp(suffix=".txt") try: - with os.fdopen(fd, 'w', encoding='utf-8') as fh: - fh.write(initial or '') + with os.fdopen(fd, "w", encoding="utf-8") as fh: + fh.write(initial or "") subprocess.call([editor, path]) - with open(path, 'r', encoding='utf-8') as fh: + with open(path, "r", encoding="utf-8") as fh: return fh.read() finally: os.unlink(path) +def open_editor(initial: str) -> str: + """Edit text in a small GUI window if possible. + + Existing text is pre-filled in the editor. When ``tkinter`` or a display + server is unavailable the function falls back to ``$EDITOR`` in the + terminal. + """ + + try: + import tkinter as tk + from tkinter import scrolledtext + except Exception: + return _open_editor_terminal(initial) + + try: + root = tk.Tk() + root.title("Edit text") + except tk.TclError: + return _open_editor_terminal(initial) + + result = {"text": initial or ""} + + text = scrolledtext.ScrolledText(root, width=80, height=20) + text.pack(expand=True, fill="both") + if initial: + text.insert("1.0", initial) + text.focus_set() + + def finalize(): + result["text"] = text.get("1.0", "end-1c") + root.quit() + + tk.Button(root, text="Save", command=finalize).pack() + root.protocol("WM_DELETE_WINDOW", finalize) + root.mainloop() + root.destroy() + return result["text"] + + def _len_transform(limit: int): def _t(val: str) -> str: length = len(val)