TUI Word Processor in Python
This is a complete terminal word processor in plain Python.
Quick Run (from repo root)
1cd Site/static/code/examples/python
2python tui_word_processor.pyIt supports:
- append, insert, edit, and delete by line number
- save/open files
- live word and line counts
- unsaved-change warning on quit
Code (Pythonic + Short)
1from dataclasses import dataclass, field
2from pathlib import Path
3
4
5@dataclass
6class Document:
7 file_path: Path
8 lines: list[str] = field(default_factory=list)
9 dirty: bool = False
10
11 def load(self) -> None:
12 if not self.file_path.exists():
13 print(f"New file: {self.file_path}")
14 return
15 self.lines = self.file_path.read_text().splitlines()
16 print(f"Loaded {len(self.lines)} line(s).")
17
18 def show(self) -> None:
19 if not self.lines:
20 print("(empty)")
21 return
22 for i, line in enumerate(self.lines, start=1):
23 print(f"{i:>3} | {line}")
24
25 def append(self, text: str) -> None:
26 self.lines.append(text)
27 self.dirty = True
28 print(f"Appended line {len(self.lines)}.")
29
30 def insert(self, line_no: int, text: str) -> None:
31 index = line_no - 1
32 if not 0 <= index <= len(self.lines):
33 print("Line out of range.")
34 return
35 self.lines.insert(index, text)
36 self.dirty = True
37 print("Inserted.")
38
39 def edit(self, line_no: int, text: str) -> None:
40 index = line_no - 1
41 if not 0 <= index < len(self.lines):
42 print("Line out of range.")
43 return
44 self.lines[index] = text
45 self.dirty = True
46 print("Updated.")
47
48 def delete(self, line_no: int) -> None:
49 index = line_no - 1
50 if not 0 <= index < len(self.lines):
51 print("Line out of range.")
52 return
53 self.lines.pop(index)
54 self.dirty = True
55 print("Deleted.")
56
57 def stats(self) -> None:
58 word_count = sum(len(line.split()) for line in self.lines)
59 print(f"Lines: {len(self.lines)}, Words: {word_count}")
60
61 def save(self) -> None:
62 self.file_path.write_text("\n".join(self.lines) + ("\n" if self.lines else ""))
63 self.dirty = False
64 print(f"Saved to {self.file_path}.")
65
66
67def read_line_no(prompt: str) -> int:
68 raw = input(prompt).strip()
69 return int(raw) if raw.isdigit() else -1
70
71
72def main() -> None:
73 file_name = input("File name (default draft.txt): ").strip() or "draft.txt"
74 doc = Document(Path(file_name))
75 doc.load()
76
77 print("Commands: show, append, insert, edit, delete, stats, save, quit")
78
79 while True:
80 command = input("> ").strip().lower()
81
82 if command == "show":
83 doc.show()
84 elif command == "append":
85 doc.append(input("Text: "))
86 elif command == "insert":
87 line_no = read_line_no("Line number: ")
88 if line_no > 0:
89 doc.insert(line_no, input("Text: "))
90 else:
91 print("Please enter a number.")
92 elif command == "edit":
93 line_no = read_line_no("Line number: ")
94 if line_no > 0:
95 doc.edit(line_no, input("New text: "))
96 else:
97 print("Please enter a number.")
98 elif command == "delete":
99 line_no = read_line_no("Line number: ")
100 if line_no > 0:
101 doc.delete(line_no)
102 else:
103 print("Please enter a number.")
104 elif command == "stats":
105 doc.stats()
106 elif command == "save":
107 doc.save()
108 elif command == "quit":
109 if doc.dirty:
110 confirm = input("Unsaved changes. Type quit! to force: ").strip()
111 if confirm != "quit!":
112 continue
113 break
114 else:
115 print("Use: show, append, insert, edit, delete, stats, save, quit")
116
117
118if __name__ == "__main__":
119 main()Run It
1python tui_word_processor.pyWhy this is pythonic
dataclassis a clean document model.- Methods do one thing each.
sum(len(line.split())...)gives clear stats logic.