Cancel an async request on timeout so no spurious data is sent to the tty

This commit is contained in:
Kovid Goyal
2021-10-30 14:46:48 +05:30
parent 2a637e4220
commit 6241369b6c
3 changed files with 50 additions and 11 deletions

View File

@@ -108,6 +108,22 @@ class ParsingOfArgsFailed(ValueError):
pass
class AsyncResponder:
def __init__(self, payload_get: PayloadGetType, window: Optional[Window]) -> None:
self.async_id: str = payload_get('async_id', missing='')
self.peer_id: int = payload_get('peer_id', missing=0)
self.window_id: int = getattr(window, 'id', 0)
def send_data(self, data: Any) -> None:
from kitty.remote_control import send_response_to_client
send_response_to_client(data=data, peer_id=self.peer_id, window_id=self.window_id, async_id=self.async_id)
def send_error(self, error: str) -> None:
from kitty.remote_control import send_response_to_client
send_response_to_client(error=error, peer_id=self.peer_id, window_id=self.window_id, async_id=self.async_id)
class RemoteCommand:
name: str = ''
@@ -121,6 +137,7 @@ class RemoteCommand:
args_count: Optional[int] = None
args_completion: Optional[Dict[str, Tuple[str, Union[Callable[[], Iterable[str]], Tuple[str, ...]]]]] = None
defaults: Optional[Dict[str, Any]] = None
is_asynchronous: bool = False
options_class: Type[RCOptions] = RCOptions
def __init__(self) -> None:
@@ -191,6 +208,9 @@ class RemoteCommand:
windows += list(tab)
return windows
def create_async_responder(self, payload_get: PayloadGetType, window: Optional[Window]) -> AsyncResponder:
return AsyncResponder(payload_get, window)
def message_to_kitty(self, global_opts: RCOptions, opts: Any, args: ArgsType) -> PayloadType:
raise NotImplementedError()

View File

@@ -1,10 +1,8 @@
#!/usr/bin/env python
# License: GPLv3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
from typing import TYPE_CHECKING, Optional
from .base import (
MATCH_TAB_OPTION, ArgsType, Boss, PayloadGetType, PayloadType, RCOptions,
RemoteCommand, ResponseType, Window, no_response
@@ -39,21 +37,20 @@ type=bool-set
If specified the tab containing the window this command is run in is used
instead of the active tab.
'''
is_asynchronous = True
def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType:
ans = {'self': opts.self, 'match': opts.match}
return ans
def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType:
peer_id: int = payload_get('peer_id', missing=0)
window_id: int = getattr(window, 'id', 0)
responder = self.create_async_responder(payload_get, window)
def callback(tab: Optional['Tab'], window: Optional[Window]) -> None:
from kitty.remote_control import send_response_to_client
if window:
send_response_to_client(data=window.id, peer_id=peer_id, window_id=window_id)
responder.send_data(window.id)
else:
send_response_to_client(error='No window selected', peer_id=peer_id, window_id=window_id)
responder.send_error('No window selected')
for tab in self.tabs_for_match_payload(boss, window, payload_get):
if tab:
boss.visual_window_select_action(tab, callback, 'Choose window')