Refactoring Kodos For Multi-Document Editing With Tabs
Kodos began as a focused Python regular expression debugger: enter a pattern, provide sample text, and inspect the matches without building a complete test script. That simplicity made the tool approachable, but it also exposed a limitation familiar to anyone working through a large pattern library. Each new experiment replaced the previous one, making comparison and recovery unnecessarily difficult.
Adding tabs changes the interaction model from a single working surface into a small document editor. A user can keep several regular expressions open, compare matching behavior, revise a pattern, and return to an earlier test case without copying text into another application. The visible feature is straightforward; the refactoring behind it requires careful separation of document state, user interface controls, and application-level commands.
The work is best understood as a modernization of Kodos rather than a cosmetic interface update. Multi-document editing affects how files are opened, saved, closed, modified, restored, and represented internally. A sound design keeps those concerns manageable while preserving the quick feedback that makes a regex debugger useful.
From One Workspace To Multiple Documents
The original single-document design likely allows controls to access pattern text, sample data, and match results directly. That arrangement is convenient while only one document exists, but it creates hidden assumptions throughout the code. Event handlers may read global widgets, file operations may update fixed controls, and validation logic may assume that the current state is always the only state.
Tabbed editing calls for an explicit document model. Each document should own its regular expression, test string, flags, filename, modified status, and any display preferences needed to reproduce its session. The tab becomes a view of that model, not the model itself. This distinction prevents file commands and matching operations from becoming tightly bound to whichever widgets happen to be visible.
A central editor controller can track the active document and coordinate updates between the model and the selected tab. When a user switches tabs, the controller changes context rather than copying values through a collection of unrelated global variables. That approach also makes future features, such as split views or session restoration, easier to add.
Choosing A Tab Architecture
The tab widget should manage pages, selection, and close actions, while Kodos-specific code handles documents and commands. Each page can contain the existing pattern editor, test-data editor, result panel, and status indicators. Keeping the current debugging controls inside a reusable document page limits the amount of change required in the matching logic.
The active tab must be treated as a first-class application state. Menu items, toolbar buttons, keyboard shortcuts, and status messages should all operate on the selected document. If no documents are open, commands such as save, close, or run should be disabled or provide a clear empty-state response rather than failing through a missing widget reference.
A small document manager can provide operations such as create, open, select, save, save as, and close. It can also generate unique display names for untitled documents and maintain the relationship between a tab label and its path. This layer is valuable because it keeps window-management details out of the regular expression engine.
Preserving State During Editing
A tabbed interface is useful only when switching documents feels lossless. Kodos should preserve the pattern, sample text, selected flags, cursor position where practical, and current match output for every open document. Match results can either be recalculated on selection or retained as cached state, depending on the cost of the operation and the behavior users expect.
Modified-state tracking is especially important. Editing either the expression or its test data should mark the document as dirty. The tab label can display a marker, while close and application-exit commands should route dirty documents through a save, discard, or cancel decision. This protects experiments that may have taken time to construct even when they are not stored in files.
The file format should remain compatible with existing Kodos usage wherever possible. If a project previously saved only a pattern or a simple configuration, the refactor should avoid silently changing its meaning. A versioned document format can support additional fields later, but migration should be explicit and tolerant of missing values.
| Concern | Single-document behavior | Multi-document design |
|---|---|---|
| Active content | Fixed editor controls | State owned by the selected document |
| File operations | Operate on global fields | Routed through a document manager |
| Unsaved changes | One application-wide flag | Dirty status per tab |
| Matching | Reads the only visible workspace | Runs against the active document |
| Closing | Exits or clears the workspace | Prompts for each affected document |
| Keyboard commands | Bound to one editor | Context-aware and selection-aware |
Keeping Matching Logic Independent
The regular expression engine should not know that tabs exist. It should receive a pattern, test data, flags, and any requested options, then return matches, errors, and diagnostic information. This boundary makes the refactor safer because the core debugging behavior can be tested without launching the graphical interface.
Results should be represented in a form the user interface can render consistently. A structured match result might include matched text, group values, spans, and error details rather than a preformatted block of display text. The document page can then present that information in the existing result panel while remaining free to change its layout later.
Error handling also benefits from this separation. A malformed expression should update the active document’s result area without damaging another open tab or interrupting the whole application. Exceptions should be converted into useful diagnostics at the application boundary, with enough context to identify the affected pattern and location when possible.
Managing Files, Tabs, And Commands
Opening a file should create a new document unless that path is already open. Preventing duplicate tabs avoids confusion about which copy contains the latest edit. The document manager can normalize paths, compare them safely across platforms, and focus the existing tab when a duplicate open request occurs.
Closing requires more than removing a page from the tab widget. Kodos should first check the document’s dirty flag, present the appropriate decision, and remove the document from the manager only after saving or discarding succeeds. A failed save must leave the tab open and active so that the user can correct the problem.
Keyboard shortcuts are part of the editing experience, not an afterthought. New, open, save, save as, close, next-tab, and previous-tab actions should work consistently on Linux desktop environments and across the supported Python GUI toolkit. Tab labels should expose enough filename information to distinguish related expressions, while tooltips can show full paths.
Testing The Refactor Safely
The most valuable tests cover transitions between states rather than isolated button clicks. Create two documents, edit both, switch repeatedly, save one, close the other, and verify that each document retains its own content. Additional cases should include opening the same file twice, canceling a close prompt, and recovering from a failed save.
The matching engine deserves its own regression suite. Existing examples should continue to produce the same groups, spans, and error messages unless a deliberate compatibility change has been documented. GUI tests can then concentrate on whether the correct document receives those results.
Manual testing remains useful for visual details such as tab ordering, dirty markers, disabled commands, and long filenames. Running the application against multiple Python and desktop configurations can expose assumptions about event handling, text widgets, or filesystem paths that unit tests may miss.
Practical Priorities For The Implementation
A staged refactor reduces risk and keeps each change reviewable. The first pass can introduce a document object around the existing fields, followed by a document page, tab management, file routing, and finally persistence enhancements. This sequence preserves a working debugger throughout the migration.
Useful priorities include:
- Move pattern, sample text, flags, and dirty status into an explicit document model.
- Keep regular expression execution independent from tab and window classes.
- Route every menu, toolbar, and shortcut action through the active document.
- Add regression tests for switching, saving, closing, and malformed expressions.
- Preserve existing file behavior and document any format changes clearly.
The result should feel familiar to existing Kodos users. Tabs provide room for comparison and experimentation, but they should not obscure the fast edit-run-inspect cycle that defines the application. A restrained interface, predictable shortcuts, and reliable state management matter more than adding decorative controls.
A well-structured multi-document Kodos gives its Python regex debugger a longer useful life. Developers can inspect several patterns side by side, retain test cases between sessions, and work through complex expressions without losing context. Explore the Kodos codebase, evaluate the document boundaries, and contribute improvements that make open-source debugging tools more capable without making them harder to use.
