Two new event types for watchers

on_title_change and on_set_user_var
This commit is contained in:
Kovid Goyal 2023-10-19 07:54:33 +05:30
parent 4a463f7712
commit 6cfb451ec8
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
3 changed files with 28 additions and 2 deletions

View file

@ -68,6 +68,8 @@ Detailed list of changes
- Fix a regression that broke ``kitten update-self`` (:iss:`6729`)
- Two new event types for :ref:`watchers <watchers>`, :code:`on_title_change` and :code:`on_set_user_var`
0.30.1 [2023-10-05]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View file

@ -133,8 +133,17 @@ functions for the events you are interested in, for example:
def on_close(boss: Boss, window: Window, data: Dict[str, Any])-> None:
# called when window is closed, typically when the program running in
# it exits.
# it exits
def on_set_user_var(boss: Boss, window: Window, data: Dict[str, Any]) -> None:
# called when a "user variable" is set or deleted on a window. Here
# data will contain key and value
def on_title_change(boss: Boss, window: Window, data: Dict[str, Any]) -> None:
# called when the window title is changed on a window. Here
# data will contain title and from_child. from_child will be True
# when a title change was requested via escape code from the program
# running in the terminal
Every callback is passed a reference to the global ``Boss`` object as well as
the ``Window`` object the action is occurring on. The ``data`` object is a dict

View file

@ -257,11 +257,15 @@ class Watchers:
on_resize: List[Watcher]
on_close: List[Watcher]
on_focus_change: List[Watcher]
on_set_user_var: List[Watcher]
on_title_change: List[Watcher]
def __init__(self) -> None:
self.on_resize = []
self.on_close = []
self.on_focus_change = []
self.on_set_user_var = []
self.on_title_change = []
def add(self, others: 'Watchers') -> None:
def merge(base: List[Watcher], other: List[Watcher]) -> None:
@ -271,15 +275,20 @@ def merge(base: List[Watcher], other: List[Watcher]) -> None:
merge(self.on_resize, others.on_resize)
merge(self.on_close, others.on_close)
merge(self.on_focus_change, others.on_focus_change)
merge(self.on_set_user_var, others.on_set_user_var)
merge(self.on_title_change, others.on_title_change)
def clear(self) -> None:
del self.on_close[:], self.on_resize[:], self.on_focus_change[:]
del self.on_set_user_var[:], self.on_title_change[:]
def copy(self) -> 'Watchers':
ans = Watchers()
ans.on_close = self.on_close[:]
ans.on_resize = self.on_resize[:]
ans.on_focus_change = self.on_focus_change[:]
ans.on_set_user_var = self.on_set_user_var[:]
ans.on_title_change = self.on_title_change[:]
return ans
@property
@ -856,6 +865,7 @@ def set_title(self, title: Optional[str]) -> None:
if title:
title = sanitize_title(title)
self.override_title = title or None
self.call_watchers(self.watchers.on_title_change, {'title': self.child_title, 'from_child': False})
self.title_updated()
def set_user_var(self, key: str, val: Optional[Union[str, bytes]]) -> None:
@ -867,7 +877,10 @@ def set_user_var(self, key: str, val: Optional[Union[str, bytes]]) -> None:
if val is not None:
if isinstance(val, bytes):
val = val.decode('utf-8', 'replace')
self.user_vars[key] = sanitize_control_codes(val).replace('\n', ' ')
self.user_vars[key] = val = sanitize_control_codes(val).replace('\n', ' ')
self.call_watchers(self.watchers.on_set_user_var, {'key': key, 'value': val})
else:
self.call_watchers(self.watchers.on_set_user_var, {'key': key, 'value': None})
# screen callbacks {{{
@ -996,6 +1009,7 @@ def focus_changed(self, focused: bool) -> None:
def title_changed(self, new_title: Optional[str], is_base64: bool = False) -> None:
self.child_title = process_title_from_child(new_title or self.default_title, is_base64)
self.call_watchers(self.watchers.on_title_change, {'title': self.child_title, 'from_child': True})
if self.override_title is None:
self.title_updated()
@ -1241,6 +1255,7 @@ def manipulate_title_stack(self, pop: bool, title: str, icon: Any) -> None:
if pop:
if self.title_stack:
self.child_title = self.title_stack.pop()
self.call_watchers(self.watchers.on_title_change, {'title': self.child_title, 'from_child': True})
self.title_updated()
else:
if self.child_title: