From 0f52b69372a16a4cca6fb7aff1e1912ed4b1223a Mon Sep 17 00:00:00 2001 From: Jin Liu Date: Tue, 14 Nov 2023 15:30:52 +0800 Subject: [PATCH] launch watcher: add on_cmd_startstop event --- docs/launch.rst | 4 ++++ kitty/launch.py | 9 +++++++++ kitty/window.py | 19 +++++++++++++++---- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/docs/launch.rst b/docs/launch.rst index 8b8dd6219..2a392f80d 100644 --- a/docs/launch.rst +++ b/docs/launch.rst @@ -145,6 +145,10 @@ functions for the events you are interested in, for example: # when a title change was requested via escape code from the program # running in the terminal + def on_cmd_startstop(boss: Boss, window: Window, data: Dict[str, Any]) -> None: + # called when the shell starts/stops executing a command. Here + # data will contain is_start and time. + 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 that contains event dependent data. Some useful methods and attributes for the diff --git a/kitty/launch.py b/kitty/launch.py index a6a514d87..95cc15af8 100644 --- a/kitty/launch.py +++ b/kitty/launch.py @@ -398,6 +398,15 @@ def load_watch_modules(watchers: Iterable[str]) -> Optional[Watchers]: w = m.get('on_focus_change') if callable(w): ans.on_focus_change.append(w) + w = m.get('on_set_user_var') + if callable(w): + ans.on_set_user_var.append(w) + w = m.get('on_title_change') + if callable(w): + ans.on_title_change.append(w) + w = m.get('on_cmd_startstop') + if callable(w): + ans.on_cmd_startstop.append(w) return ans diff --git a/kitty/window.py b/kitty/window.py index 450e079e7..68460e9c0 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -261,6 +261,7 @@ class Watchers: on_focus_change: List[Watcher] on_set_user_var: List[Watcher] on_title_change: List[Watcher] + on_cmd_startstop: List[Watcher] def __init__(self) -> None: self.on_resize = [] @@ -268,6 +269,7 @@ class Watchers: self.on_focus_change = [] self.on_set_user_var = [] self.on_title_change = [] + self.on_cmd_startstop = [] def add(self, others: 'Watchers') -> None: def merge(base: List[Watcher], other: List[Watcher]) -> None: @@ -279,10 +281,11 @@ class Watchers: 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) + merge(self.on_cmd_startstop, others.on_cmd_startstop) 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[:] + del self.on_set_user_var[:], self.on_title_change[:], self.on_cmd_startstop[:] def copy(self) -> 'Watchers': ans = Watchers() @@ -291,11 +294,13 @@ class Watchers: 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[:] + ans.on_cmd_startstop = self.on_cmd_startstop[:] return ans @property def has_watchers(self) -> bool: - return bool(self.on_close or self.on_resize or self.on_focus_change) + return bool(self.on_close or self.on_resize or self.on_focus_change + or self.on_set_user_var or self.on_title_change or self.on_cmd_startstop) def call_watchers(windowref: Callable[[], Optional['Window']], which: str, data: Dict[str, Any]) -> None: @@ -1321,12 +1326,18 @@ class Window: def cmd_output_marking(self, is_start: int) -> None: if is_start: - self.last_cmd_output_start_time = monotonic() + start_time = monotonic() + self.last_cmd_output_start_time = start_time + + self.call_watchers(self.watchers.on_cmd_startstop, {"is_start": True, "time": start_time}) else: if self.last_cmd_output_start_time > 0: - last_cmd_output_duration = monotonic() - self.last_cmd_output_start_time + end_time = monotonic() + last_cmd_output_duration = end_time - self.last_cmd_output_start_time self.last_cmd_output_start_time = 0 + self.call_watchers(self.watchers.on_cmd_startstop, {"is_start": False, "time": end_time}) + opts = get_options() mode = opts.notify_on_cmd_finish if mode == 'never':