1#!/usr/local/bin/python3.8
2# vim:fileencoding=utf-8
3# License: GPLv3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net>
4
5from functools import update_wrapper
6from typing import TYPE_CHECKING, Callable, Generic, NamedTuple, TypeVar, Union
7
8_T = TypeVar('_T')
9
10
11class ParsedShortcut(NamedTuple):
12    mods: int
13    key_name: str
14
15
16class Edges(NamedTuple):
17    left: int = 0
18    top: int = 0
19    right: int = 0
20    bottom: int = 0
21
22
23class FloatEdges(NamedTuple):
24    left: float = 0
25    top: float = 0
26    right: float = 0
27    bottom: float = 0
28
29
30class ScreenGeometry(NamedTuple):
31    xstart: float
32    ystart: float
33    xnum: int
34    ynum: int
35    dx: float
36    dy: float
37
38
39class WindowGeometry(NamedTuple):
40    left: int
41    top: int
42    right: int
43    bottom: int
44    xnum: int
45    ynum: int
46    spaces: Edges = Edges()
47
48
49class SingleKey(NamedTuple):
50    mods: int = 0
51    is_native: bool = False
52    key: int = -1
53
54
55class MouseEvent(NamedTuple):
56    button: int = 0
57    mods: int = 0
58    repeat_count: int = 1
59    grabbed: bool = False
60
61
62ConvertibleToNumbers = Union[str, bytes, int, float]
63
64
65if TYPE_CHECKING:
66    class RunOnce(Generic[_T]):
67
68        def __init__(self, func: Callable[[], _T]): ...
69        def __call__(self) -> _T: ...
70        def set_override(self, val: _T) -> None: ...
71        def clear_override(self) -> None: ...
72else:
73    class RunOnce:
74
75        def __init__(self, f):
76            self._override = RunOnce
77            self._cached_result = RunOnce
78            update_wrapper(self, f)
79
80        def __call__(self):
81            if self._override is not RunOnce:
82                return self._override
83            if self._cached_result is RunOnce:
84                self._cached_result = self.__wrapped__()
85            return self._cached_result
86
87        def set_override(self, val):
88            self._override = val
89
90        def clear_override(self):
91            self._override = RunOnce
92
93
94def run_once(f: Callable[[], _T]) -> RunOnce:
95    return RunOnce(f)
96
97
98if TYPE_CHECKING:
99    from typing import Literal
100    ActionGroup = Literal['cp', 'sc', 'win', 'tab', 'mouse', 'mk', 'lay', 'misc']
101else:
102    ActionGroup = str
103
104
105class ActionSpec(NamedTuple):
106    group: str
107    doc: str
108
109
110def ac(group: ActionGroup, doc: str) -> Callable[[_T], _T]:
111    def w(f: _T) -> _T:
112        setattr(f, 'action_spec', ActionSpec(group, doc))
113        return f
114    return w
115