Version 2.0 of terminal-widgets introduces a major refactor to centralise state management and improve typing.
If you have created custom widgets in ~/.config/twidgets/py_widgets/, you will need to update them to work
with the new release.
~/.config/twidgets/py_widgets/. Run twidgets init if you want to add them back to your layout.z.WidgetContainer: Replaces the separate UIState, BaseConfig and ConfigLoader arguments.add_widget_content and safe_addstr are now methods of the Widget class (e.g., widget.add_widget_content(...)).draw, update, init, and input handling functions have new signatures.The imports in your custom widget files need to be cleaned up. UIState, BaseConfig, and standalone helper functions are no longer imported directly from twidgets.core.base.
Old (v1.3):
from twidgets.core.base import Widget, draw_widget, add_widget_content, Config, UIState, BaseConfig, CursesWindowType
New (v2.0):
from twidgets.core.base import Widget, WidgetContainer, Config, CursesWindowType
# Optional: Import CursesColors if you use specific styling
from twidgets.core.base import CursesColors
# Optional: Import CursesKeys if you use specific keyboard or mouse actions
from twidgets.core.base import CursesKeys
draw functionThe draw function signature has changed. Instead of passing ui_state and base_config separately, you now pass a single widget_container.
Old (v1.3):
def draw(widget: Widget, ui_state: UIState, base_config: BaseConfig) -> None:
draw_widget(widget, ui_state, base_config)
content = ['Hello', 'World']
add_widget_content(widget, content)
New (v2.0):
def draw(widget: Widget, widget_container: WidgetContainer) -> None:
# 1. Update draw_widget call
draw_widget(widget, widget_container)
content = ['Hello', 'World']
# 2. Use the widget instance method for adding content
widget.add_widget_content(content)
Note: If your
drawfunction accepts data from anupdatefunction (e.g.,info), the signature becomes:def draw(widget: Widget, widget_container: WidgetContainer, info: Any) -> None:
update function and secretsIf your widget fetches data (APIs, heavy loading), the update function signature has changed. Additionally, accessing secrets is now done through the widget_container.
Old (v1.3):
from twidgets.core.base import ConfigLoader
def update(_widget: Widget, _config_loader: ConfigLoader) -> list[str]:
api_key = _config_loader.get_secret('MY_KEY')
...
New (v2.0):
# ConfigLoader import is likely no longer needed if only used for type hinting secrets
def update(widget: Widget, widget_container: WidgetContainer) -> list[str]:
# Access config_loader via the container
api_key = widget_container.config_loader.get_secret('MY_KEY')
...
safe_addstr)If you use safe_addstr for precise text placement, the arguments have changed significantly. It is now a method of widget, and colors/attributes are passed as lists.
Old (v1.3):
from twidgets.core.base import safe_addstr, convert_color_number_to_curses_pair, CursesBold
# ... inside draw ...
safe_addstr(widget, y, x, 'Text', convert_color_number_to_curses_pair(base_config.PRIMARY_PAIR_NUMBER) | CursesBold)
New (v2.0):
from twidgets.core.base import CursesColors
# ... inside draw ...
widget.safe_addstr(y, x, 'Text',
[widget_container.base_config.PRIMARY_PAIR_NUMBER], # Pass all numbers (PRIMARY_PAIR_NUMBER, SECONDARY_PAIR_NUMBER etc.) here (as a list)
[CursesColors.BOLD] # Pass all pairs (BOLD, REVERSE, etc.) here (as a list)
)
If your widget handles mouse clicks, keyboard presses, or has an init function, update the signatures to accept widget_container.
Old (v1.3): def mouse_click_action(widget: Widget, mx: int, my: int, b_state: int, ui_state: UIState):
New (v2.0): def mouse_click_action(widget: Widget, mx: int, my: int, b_state: int, widget_container: WidgetContainer) -> None:
Old (v1.3): def keyboard_press_action(widget: Widget, key: int, ui_state: UIState, base_config: BaseConfig):
New (v2.0): def keyboard_press_action(widget: Widget, key: int, widget_container: WidgetContainer) -> None:
Old (v1.3): confirm = prompt_user_input(widget, 'Are you sure?')
New (v2.0): confirm = widget.prompt_user_input('Are you sure?')
Old (v1.3): def init(widget, ui_state, base_config):
New (v2.0): def init(widget: Widget, widget_container: WidgetContainer) -> None:
All widgets (also built-ins) are now located at ~/.config/twidgets/py_widgets/. This means you will have to run twidgets init if you still want the built-in widgets integrated in your layout.
Widgets now support z-coordinates too. Set them in each .yaml file in ~/.config/twidgets/widgets/ using the key z.
Example:
name: '...'
title: ' ... '
enabled: True
interval: 0
height: 5
width: 30
y: 4
x: 87
z: 0