6.2 KiB
pyTermTk Copilot Instructions
Project Overview
pyTermTk is a Text-based User Interface (TUI) library for Python inspired by Qt5, GTK, and tkinter APIs. It creates cross-platform terminal applications with rich widgets, layouts, and an event-driven architecture.
Architecture
Core Structure
libs/pyTermTk/TermTk/- Main library code organized into logical modules:TTkCore/- Core functionality (signals, colors, canvas, configuration)TTkWidgets/- All UI widgets inherit fromTTkWidgetbase classTTkLayouts/- Layout managers (GridLayout, HBoxLayout, VBoxLayout)TTkGui/- GUI components (drag & drop, application management)TTkTemplates/- Mixin classes for event handling (TKeyEvents,TMouseEvents,TDragEvents)
Widget Inheritance Pattern
All widgets follow this pattern:
class TTkMyWidget(TTkWidget): # Or TTkContainer for composite widgets
# Class-level styling
classStyle = {
'default': {'color': TTkColor.fg("#dddd88"), 'borderColor': TTkColor.RST},
'hover': {'color': TTkColor.fg("#ffffff"), 'borderColor': TTkColor.BOLD},
'focus': {'borderColor': TTkColor.fg("#ffff00")},
'disabled': {'color': TTkColor.fg('#888888')}
}
# Signal declarations
mySignal: pyTTkSignal
__slots__ = ('_private_vars',) # Always use slots for performance
def __init__(self, **kwargs):
self.mySignal = pyTTkSignal(int) # Define signals in __init__
super().__init__(**kwargs|{'size': (w, h)}) # Merge kwargs, set default size
Signal-Slot System (Qt-inspired)
Use type-safe signal-slot patterns:
# Define signals with types
signal = pyTTkSignal(int)
# Define slots with decorators
@pyTTkSlot(int)
def my_slot(value: int):
pass
# Connect them
signal.connect(my_slot)
Event Handling
Widgets handle events by overriding template methods:
keyEvent(),mousePressEvent(),paintEvent()- Core eventsfocusInEvent(),focusOutEvent()- Focus managementdropEvent(),dragEnterEvent()- Drag & drop- Always return
Trueif event is handled,Falseto propagate
Development Workflows
Testing
- Unit tests:
pytest tests/pytest/(run via Makefile:make test) - Performance tests:
tests/timeit/- Contains signal/slot benchmarks and optimization tests - Manual tests:
tests/t.*/- Interactive UI tests - CI: Tests run on Python 3.9-3.14 with flake8 linting
Build & Deploy
- Local build:
pip install -e libs/pyTermTk(usespip) - Documentation:
make doc(Sphinx-based, outputs todocs/source/_build/html/) - Apps deployment: Individual apps in
apps/have their ownpyproject.toml
Running Examples
- Demo:
python demo/demo.py -f - Designer:
pip install -e apps/ttkDesigner ; ttkDesigner - Individual tests:
python tests/t.ui/test.ui.036.datetime.01.py
Project-Specific Patterns
Widget State Management
Many widgets use internal state classes (see datetime_date_form.py):
class _TTkWidgetState:
__slots__ = ('_data', 'signal_name')
def __init__(self):
self.signal_name = pyTTkSignal()
File Organization
- One widget per file in
TTkWidgets/ - Use
__all__ = ['ClassName']exports - Import from
TermTk.TTkCore,TermTk.TTkWidgetsetc (not relative imports) - Apps in
apps/are self-contained withpyproject.toml
Color & Theming
Use TTkColor constants and theme system:
TTkColor.fg("#ffffff") + TTkColor.bg("#000044") + TTkColor.BOLD
style = self.currentStyle() # Get theme-aware colors
Cross-Platform Considerations
- Platform-specific code in
TTkCore/drivers/ - Terminal compatibility testing in
tests/ansi.images.json - HTML5 export capabilities via
tools/webExporter/
Documentation & Docstrings
Use Sphinx-compatible docstring format with Epytext-style field lists:
def setGeometry(self, x: int, y: int, width: int, height: int):
''' Resize and move the widget
:param x: the horizontal position
:type x: int
:param y: the vertical position
:type y: int
:param width: the new width
:type width: int
:param height: the new height
:type height: int
'''
# For class/module docstrings include ASCII art examples:
class TTkButton(TTkWidget):
''' TTkButton:
Border = True
::
┌────────┐
│ Text │
╘════════╛
Demo: `formwidgets.py <https://github.com/ceccopierangiolieugenio/pyTermTk/blob/main/demo/showcase/formwidgets.py>`_
'''
# For signals, document parameters:
toggled:pyTTkSignal
'''
This signal is emitted whenever the button state changes if checkeable,
i.e., whenever the user checks or unchecks it.
:param checked: True if checked otherwise False
:type checked: bool
'''
Key conventions:
- Use single quotes
'''for docstrings - Include ASCII art for visual widgets showing borders/layout
- Link to demo files with full GitHub URLs
- Use
:py:class:for cross-references to other classes - Document all parameters with
:param name:and:type name: - Include
:return:and:rtype:for non-void methods - Signal docstrings document emitted parameters, not the signal itself
Apps Ecosystem
The project includes several full applications demonstrating patterns:
- ttkDesigner - Visual UI designer (like Qt Designer)
- ttkode - Code editor with syntax highlighting
- dumbPaintTool - ASCII art editor
- tlogg - Log file viewer
Testing App Integration
Apps use the main library via path manipulation:
sys.path.append(os.path.join(sys.path[0],'../../libs/pyTermTk'))
import TermTk as ttk
Key Integration Points
Layout System
Use Qt-like layout managers:
layout = TTkGridLayout()
layout.addWidget(widget, row, col, rowspan, colspan)
container.setLayout(layout)
Focus & Input Handling
Set focus policy and handle keyboard navigation:
self.setFocusPolicy(TTkK.ClickFocus | TTkK.TabFocus)
When implementing new widgets, study existing patterns in TTkWidgets/ and ensure signal-slot integration follows the established type-safe patterns shown in tests/pytest/test_004_signals_slots.py.