diff --git a/kittens/choose/subseq_matcher.pyi b/kittens/choose/subseq_matcher.pyi new file mode 100644 index 000000000..281ea7b30 --- /dev/null +++ b/kittens/choose/subseq_matcher.pyi @@ -0,0 +1,9 @@ +from typing import List, Tuple + + +def match( + lines: List[str], levels: Tuple[str, str, str], needle: str, + output_positions: bool, limit: int, num_threads: int, mark_before: str, + mark_after: str, delimiter: str +): + pass diff --git a/kittens/clipboard/main.py b/kittens/clipboard/main.py index 9ae135e49..0e2d53ca7 100644 --- a/kittens/clipboard/main.py +++ b/kittens/clipboard/main.py @@ -100,6 +100,7 @@ def main(args): if __name__ == '__main__': main(sys.argv) elif __name__ == '__doc__': - sys.cli_docs['usage'] = usage - sys.cli_docs['options'] = OPTIONS - sys.cli_docs['help_text'] = help_text + cd = sys.cli_docs # type: ignore + cd['usage'] = usage + cd['options'] = OPTIONS + cd['help_text'] = help_text diff --git a/kittens/diff/main.py b/kittens/diff/main.py index 0132a8664..abfa3c166 100644 --- a/kittens/diff/main.py +++ b/kittens/diff/main.py @@ -17,13 +17,8 @@ from gettext import gettext as _ from kitty.cli import CONFIG_HELP, parse_args from kitty.constants import appname from kitty.fast_data_types import wcswidth -from kitty.key_encoding import key_defs as K, RELEASE, enter_key +from kitty.key_encoding import RELEASE, enter_key, key_defs as K -from ..tui.handler import Handler -from ..tui.images import ImageManager -from ..tui.line_edit import LineEdit -from ..tui.loop import Loop -from ..tui.operations import styled from .collect import ( create_collection, data_for_path, lines_for_path, sanitize, set_highlight_data @@ -32,11 +27,17 @@ from .config import init_config from .patch import Differ, set_diff_command, worker_processes from .render import ImageSupportWarning, LineRef, render_diff from .search import BadRegex, Search +from ..tui.handler import Handler +from ..tui.images import ImageManager +from ..tui.line_edit import LineEdit +from ..tui.loop import Loop +from ..tui.operations import styled try: from .highlight import initialize_highlighter, highlight_collection + has_highlighter = True except ImportError: - initialize_highlighter = highlight_collection = None + has_highlighter = False INITIALIZING, COLLECTED, DIFFED, COMMAND, MESSAGE = range(5) @@ -140,7 +141,7 @@ class DiffHandler(Handler): self.current_position = self.restore_position self.restore_position = None self.draw_screen() - if initialize_highlighter is not None and not self.highlighting_done: + if has_highlighter and not self.highlighting_done: from .highlight import StyleNotFound self.highlighting_done = True try: @@ -504,12 +505,17 @@ Syntax: :italic:`name=value`. For example: :italic:`-o background=gray` '''.format, config_help=CONFIG_HELP.format(conf_name='diff', appname=appname)) -def showwarning(message, category, filename, lineno, file=None, line=None): - if category is ImageSupportWarning: - showwarning.warnings.append(message) +class ShowWarning: + + def __init__(self): + self.warnings = [] + + def __call__(self, message, category, filename, lineno, file=None, line=None): + if category is ImageSupportWarning: + showwarning.warnings.append(message) -showwarning.warnings = [] +showwarning = ShowWarning() help_text = 'Show a side-by-side diff of the specified files/directories. You can also use ssh:hostname:remote-file-path to diff remote files.' usage = 'file_or_directory_left file_or_directory_right' @@ -570,9 +576,10 @@ def main(args): if __name__ == '__main__': main(sys.argv) elif __name__ == '__doc__': - sys.cli_docs['usage'] = usage - sys.cli_docs['options'] = OPTIONS - sys.cli_docs['help_text'] = help_text + cd = sys.cli_docs # type: ignore + cd['usage'] = usage + cd['options'] = OPTIONS + cd['help_text'] = help_text elif __name__ == '__conf__': from .config import all_options - sys.all_options = all_options + sys.all_options = all_options # type: ignore diff --git a/kittens/hints/main.py b/kittens/hints/main.py index f162f65ff..bb63683de 100644 --- a/kittens/hints/main.py +++ b/kittens/hints/main.py @@ -15,7 +15,7 @@ from kitty.fast_data_types import set_clipboard_string from kitty.key_encoding import key_defs as K, backspace_key, enter_key from kitty.utils import screen_size_function -from ..tui.handler import Handler +from ..tui.handler import Handler, result_handler from ..tui.loop import Loop from ..tui.operations import faint, styled @@ -562,6 +562,7 @@ def linenum_handle_result(args, data, target_window_id, boss, extra_cli_args, *a }[action])(*cmd) +@result_handler(type_of_input='screen') def handle_result(args, data, target_window_id, boss): if data['customize_processing']: m = load_custom_processor(data['customize_processing']) @@ -617,16 +618,14 @@ def handle_result(args, data, target_window_id, boss): boss.open_url(m, program, cwd=cwd) -handle_result.type_of_input = 'screen' - - if __name__ == '__main__': # Run with kitty +kitten hints ans = main(sys.argv) if ans: print(ans) elif __name__ == '__doc__': - sys.cli_docs['usage'] = usage - sys.cli_docs['options'] = OPTIONS - sys.cli_docs['help_text'] = help_text + cd = sys.cli_docs # type: ignore + cd['usage'] = usage + cd['options'] = OPTIONS + cd['help_text'] = help_text # }}} diff --git a/kittens/tui/handler.py b/kittens/tui/handler.py index 78fa93598..79092488c 100644 --- a/kittens/tui/handler.py +++ b/kittens/tui/handler.py @@ -3,12 +3,14 @@ # License: GPL v3 Copyright: 2018, Kovid Goyal +from typing import Callable, Optional, Type + from .operations import commander class Handler: - image_manager_class = None + image_manager_class = None # type: Type[ImageManagerBase] def _initialize(self, screen_size, term_manager, schedule_write, tui_loop, debug, image_manager=None): self.screen_size = screen_size @@ -42,11 +44,11 @@ class Handler: self.debug.fobj = self self.initialize() - def __exit__(self, *a): + def __exit__(self, etype, value, tb): del self.debug.fobj self.finalize() if self.image_manager is not None: - self.image_manager.__exit__(*a) + self.image_manager.__exit__(etype, value, tb) def initialize(self): pass @@ -98,3 +100,37 @@ class Handler: def suspend(self): return self._term_manager.suspend() + + +class ImageManagerBase: + + def __init__(self, handler: Handler): + pass + + def __enter__(self): + pass + + def __exit__(self, etype, value, tb): + pass + + +class HandleResult: + + type_of_input: Optional[str] = None + no_ui: bool = False + + def __init__(self, impl, type_of_input: Optional[str], no_ui: bool): + self.impl = impl + self.no_ui = no_ui + self.type_of_input = type_of_input + + def __call__(self, args, data, target_window_id, boss): + return self.impl(args, data, target_window_id, boss) + + +def result_handler(type_of_input: Optional[str] = None, no_ui=False) -> Callable[[Callable], HandleResult]: + + def wrapper(impl): + return HandleResult(impl, type_of_input, no_ui) + + return wrapper diff --git a/kittens/tui/images.py b/kittens/tui/images.py index 194b69a2d..e805d655e 100644 --- a/kittens/tui/images.py +++ b/kittens/tui/images.py @@ -13,6 +13,7 @@ from contextlib import suppress from kitty.utils import fit_image from .operations import cursor +from .handler import ImageManagerBase try: fsenc = sys.getfilesystemencoding() or 'utf-8' @@ -109,7 +110,7 @@ def can_display_images(): return ans -class ImageManager: +class ImageManager(ImageManagerBase): def __init__(self, handler): self.image_id_counter = count() diff --git a/kittens/unicode_input/main.py b/kittens/unicode_input/main.py index f8e103294..6b2254a5b 100644 --- a/kittens/unicode_input/main.py +++ b/kittens/unicode_input/main.py @@ -14,10 +14,10 @@ from kitty.cli import parse_args from kitty.config import cached_values_for from kitty.constants import config_dir from kitty.fast_data_types import is_emoji_presentation_base, wcswidth -from kitty.key_encoding import CTRL, RELEASE, SHIFT, key_defs as K, enter_key +from kitty.key_encoding import CTRL, RELEASE, SHIFT, enter_key, key_defs as K from kitty.utils import get_editor -from ..tui.handler import Handler +from ..tui.handler import Handler, result_handler from ..tui.line_edit import LineEdit from ..tui.loop import Loop from ..tui.operations import ( @@ -556,6 +556,7 @@ def main(args): raise SystemExit(loop.return_code) +@result_handler() def handle_result(args, current_char, target_window_id, boss): w = boss.window_id_map.get(target_window_id) if w is not None: @@ -567,6 +568,7 @@ if __name__ == '__main__': if ans: print(ans) elif __name__ == '__doc__': - sys.cli_docs['usage'] = usage - sys.cli_docs['options'] = OPTIONS - sys.cli_docs['help_text'] = help_text + cd = sys.cli_docs # type: ignore + cd['usage'] = usage + cd['options'] = OPTIONS + cd['help_text'] = help_text diff --git a/kittens/unicode_input/unicode_names.pyi b/kittens/unicode_input/unicode_names.pyi new file mode 100644 index 000000000..d85a343d3 --- /dev/null +++ b/kittens/unicode_input/unicode_names.pyi @@ -0,0 +1,13 @@ +from typing import Tuple, FrozenSet, Optional + + +def all_words() -> Tuple[str, ...]: + pass + + +def codepoints_for_word(word: str) -> FrozenSet[int]: + pass + + +def name_for_codepoint(cp: int) -> Optional[str]: + pass diff --git a/kitty/cmds.py b/kitty/cmds.py index 010ad60fe..120109f7a 100644 --- a/kitty/cmds.py +++ b/kitty/cmds.py @@ -6,6 +6,7 @@ import json import os import sys from contextlib import suppress +from typing import Optional, BinaryIO from .cli import ( Namespace, get_defaults_from_seq, parse_args, parse_option_spec @@ -1322,39 +1323,44 @@ def cmd_set_background_image(global_opts, opts, args): return file_pipe(path) -def set_background_image(boss, window, payload): - from base64 import standard_b64decode - import tempfile - pg = cmd_set_background_image.payload_get - data = pg(payload, 'data') - if data != '-': - img_id = pg(payload, 'img_id') - if img_id != set_background_image.current_img_id: - set_background_image.current_img_id = img_id - set_background_image.current_file_obj = tempfile.NamedTemporaryFile() - if data: - set_background_image.current_file_obj.write(standard_b64decode(data)) - return no_response +class SetBackgroundImage: - windows = windows_for_payload(boss, window, payload) - os_windows = tuple({w.os_window_id for w in windows}) - layout = pg(payload, 'layout') - if data == '-': - path = None - else: - f = set_background_image.current_file_obj - path = f.name - set_background_image.current_file_obj = None - f.flush() + current_img_id: Optional[str] = None + current_file_obj: Optional[BinaryIO] = None - try: - boss.set_background_image(path, os_windows, pg(payload, 'configured'), layout) - except ValueError as err: - err.hide_traceback = True - raise + def __call__(self, boss, window, payload): + from base64 import standard_b64decode + import tempfile + pg = cmd_set_background_image.payload_get + data = pg(payload, 'data') + if data != '-': + img_id = pg(payload, 'img_id') + if img_id != set_background_image.current_img_id: + set_background_image.current_img_id = img_id + set_background_image.current_file_obj = tempfile.NamedTemporaryFile() + if data: + set_background_image.current_file_obj.write(standard_b64decode(data)) + return no_response + + windows = windows_for_payload(boss, window, payload) + os_windows = tuple({w.os_window_id for w in windows}) + layout = pg(payload, 'layout') + if data == '-': + path = None + else: + f = set_background_image.current_file_obj + path = f.name + set_background_image.current_file_obj = None + f.flush() + + try: + boss.set_background_image(path, os_windows, pg(payload, 'configured'), layout) + except ValueError as err: + err.hide_traceback = True + raise -set_background_image.current_img_id = set_background_image.current_file_obj = None +set_background_image = SetBackgroundImage() # }}} diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index e605a8bed..d1e3c0580 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -1,4 +1,5 @@ -from typing import Callable, Optional, Tuple +from typing import Callable, Mapping, Optional, Tuple + from kitty.cli import Namespace GLFW_IBEAM_CURSOR: int @@ -56,3 +57,97 @@ def toggle_maximized() -> bool: def toggle_fullscreen() -> bool: pass + + +def thread_write(fd: int, data: bytes) -> None: + pass + + +def set_in_sequence_mode(yes: bool) -> None: + pass + + +def set_clipboard_string(data: bytes) -> None: + pass + + +def set_background_image( + path: Optional[str], os_window_ids: Tuple[int, ...], + configured: bool = True, layout_name: Optional[str] = None +) -> None: + pass + + +def safe_pipe(nonblock: bool = True) -> Tuple[int, int]: + pass + + +def patch_global_colors(spec: Mapping[str, int], configured: bool) -> None: + pass + + +def os_window_font_size(os_window_id: int, new_sz: float = -1., force: bool = False) -> float: + pass + + +def mark_os_window_for_close(os_window_id: int, yes: bool = True) -> bool: + pass + + +def global_font_size(val: float = -1.) -> float: + pass + + +def get_clipboard_string() -> str: + pass + + +def focus_os_window(os_window_id: int, also_raise: bool = True) -> bool: + pass + + +def destroy_global_data() -> None: + pass + + +def current_os_window() -> Optional[int]: + pass + + +def cocoa_set_menubar_title(title: str) -> None: + pass + + +def change_os_window_state(state: str) -> None: + pass + + +def change_background_opacity(os_window_id: int, opacity: float) -> bool: + pass + + +def background_opacity_of(os_window_id: int) -> Optional[float]: + pass + + +def read_command_response(fd: int, timeout: float, list) -> None: + pass + + +def wcswidth(string: str) -> int: + pass + + +def is_emoji_presentation_base(code: int) -> bool: + pass + + +class ChildMonitor: + + def __init__( + self, + death_notify: Callable[[int], None], + dump_callback: Optional[callable], + talk_fd: int = -1, listen_fd: int = -1 + ): + pass