1
Fork 0
texttools/texttools.py

86 lines
2.8 KiB
Python
Executable file

#!/usr/bin/env -S uv run python3
import tkinter as tk
from tkinter import N, S, E, W, ttk
import textwrap
# Complex transforms go here,
# Simple transforms are just lambdas
def _wordcount(s: str):
"Returns a tuple of linecount, wordcount, charcount"
return (len(s.splitlines()), len(s.split()), len(s))
def _markdown_quote(s: str):
"Returns every line prefixed with >"
return "\n".join(["> " + line for line in s.splitlines()])
transforms = [
# Transforms go here, for example
{"name": "One line", "transform": lambda x: " ".join(x.splitlines())}
,{"name": "Line/Word/Char", "transform": _wordcount}
,{"name": "Dedent", "transform": textwrap.dedent}
,{"name": "Markdown Quote", "transform": _markdown_quote}
]
class GUI():
def __init__(self) -> None:
self.root = tk.Tk()
self.active_transform = lambda x: x # start with no transform
self.layout_gui()
def layout_gui(self) -> None:
self.mainframe = ttk.Frame(self.root, padding="3 3 12 12")
self.root.title("Text Tools")
self.mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
self.root.columnconfigure(0, weight=1)
self.root.rowconfigure(0, weight=1)
self.content_box = tk.Text(self.mainframe, undo=True)
self.content_box.grid(column=2, row=2)
self.output_box = tk.Text(self.mainframe, undo=True)
self.output_box.grid(column=2, row=3)
self.transform_box = tk.Listbox(self.mainframe)
self.transform_box.grid(column=1, row=2, rowspan=2)
for t in transforms:
self.transform_box.insert(tk.END, t["name"])
# Keyboard bindings
self.root.bind("<Escape>", lambda _: self.root.quit())
self.content_box.bind("<Tab>", lambda _: self.transform_box.focus())
# vvv makes clicking or pressing enter change the transform
self.transform_box.bind("<Button-1>", self.select_transform)
self.transform_box.bind("<Return>", self.select_transform)
# vvv makes anything typed in update the output
self.content_box.bind("<Key>",
lambda _: self.root.after(1, self.update))
self.content_box.focus()
def update(self):
content = self.content_box.get('1.0', tk.END)
content = self.active_transform(content)
self.output_box.delete('1.0', tk.END)
self.output_box.insert('1.0', content)
def select_transform(self, _):
try:
selection = self.transform_box.curselection()[0]
self.active_transform = transforms[selection]["transform"]
self.update()
except (ValueError, IndexError):
pass
def main(): # Entry point for pyproject.toml
gui = GUI()
gui.root.mainloop()
if __name__ == "__main__":
main()