hspylib-clitt 0.9.115__py3-none-any.whl → 0.9.117__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of hspylib-clitt might be problematic. Click here for more details.

Files changed (195) hide show
  1. clitt/.version +1 -1
  2. clitt/__classpath__.py +2 -2
  3. clitt/__init__.py +3 -3
  4. clitt/__main__.py +3 -3
  5. clitt/addons/__init__.py +3 -3
  6. clitt/addons/appman/__init__.py +3 -3
  7. clitt/addons/appman/templates/__init__.py +3 -3
  8. clitt/addons/appman/templates/main_qt_view.py.tpl +1 -1
  9. clitt/addons/widman/__init__.py +3 -3
  10. clitt/addons/widman/widgets/__init__.py +3 -3
  11. clitt/core/__init__.py +3 -3
  12. clitt/core/exception/__init__.py +3 -3
  13. clitt/core/icons/__init__.py +3 -3
  14. clitt/core/icons/emojis/__init__.py +3 -3
  15. clitt/core/icons/font_awesome/__init__.py +3 -3
  16. clitt/core/term/__init__.py +3 -3
  17. clitt/core/term/cursor.py +1 -1
  18. clitt/core/term/screen.py +1 -1
  19. clitt/core/term/terminal.py +2 -2
  20. clitt/core/tui/__init__.py +3 -3
  21. clitt/core/tui/line_input/__init__.py +3 -3
  22. clitt/core/tui/line_input/keyboard_input.py +34 -34
  23. clitt/core/tui/line_input/line_input.py +5 -13
  24. clitt/core/tui/mchoose/__init__.py +3 -3
  25. clitt/core/tui/mdashboard/__init__.py +3 -3
  26. clitt/core/tui/menu/__init__.py +3 -3
  27. clitt/core/tui/minput/__init__.py +3 -3
  28. clitt/core/tui/mselect/__init__.py +3 -3
  29. clitt/core/tui/table/__init__.py +3 -3
  30. clitt/core/tui/tui_application.py +11 -23
  31. clitt/core/tui/tui_preferences.py +1 -1
  32. clitt/utils/__init__.py +3 -3
  33. {hspylib_clitt-0.9.115.dist-info → hspylib_clitt-0.9.117.dist-info}/METADATA +2 -2
  34. hspylib_clitt-0.9.117.dist-info/RECORD +97 -0
  35. {hspylib_clitt-0.9.115.dist-info → hspylib_clitt-0.9.117.dist-info}/WHEEL +1 -1
  36. {hspylib_clitt-0.9.115.dist-info → hspylib_clitt-0.9.117.dist-info}/top_level.txt +0 -1
  37. build/lib/build/lib/clitt/__classpath__.py +0 -28
  38. build/lib/build/lib/clitt/__init__.py +0 -13
  39. build/lib/build/lib/clitt/__main__.py +0 -139
  40. build/lib/build/lib/clitt/addons/__init__.py +0 -12
  41. build/lib/build/lib/clitt/addons/appman/__init__.py +0 -13
  42. build/lib/build/lib/clitt/addons/appman/appman.py +0 -305
  43. build/lib/build/lib/clitt/addons/appman/appman_enums.py +0 -39
  44. build/lib/build/lib/clitt/addons/appman/templates/__init__.py +0 -11
  45. build/lib/build/lib/clitt/addons/widman/__init__.py +0 -14
  46. build/lib/build/lib/clitt/addons/widman/widget.py +0 -70
  47. build/lib/build/lib/clitt/addons/widman/widget_entry.py +0 -54
  48. build/lib/build/lib/clitt/addons/widman/widgets/__init__.py +0 -14
  49. build/lib/build/lib/clitt/addons/widman/widgets/widget_free.py +0 -110
  50. build/lib/build/lib/clitt/addons/widman/widgets/widget_punch.py +0 -246
  51. build/lib/build/lib/clitt/addons/widman/widgets/widget_send_msg.py +0 -272
  52. build/lib/build/lib/clitt/addons/widman/widgets/widget_time_calc.py +0 -146
  53. build/lib/build/lib/clitt/addons/widman/widman.py +0 -123
  54. build/lib/build/lib/clitt/core/__init__.py +0 -15
  55. build/lib/build/lib/clitt/core/exception/__init__.py +0 -11
  56. build/lib/build/lib/clitt/core/exception/exceptions.py +0 -18
  57. build/lib/build/lib/clitt/core/icons/__init__.py +0 -12
  58. build/lib/build/lib/clitt/core/icons/emojis/__init__.py +0 -12
  59. build/lib/build/lib/clitt/core/icons/emojis/emojis.py +0 -41
  60. build/lib/build/lib/clitt/core/icons/emojis/face_smiling.py +0 -40
  61. build/lib/build/lib/clitt/core/icons/font_awesome/__init__.py +0 -18
  62. build/lib/build/lib/clitt/core/icons/font_awesome/app_icons.py +0 -55
  63. build/lib/build/lib/clitt/core/icons/font_awesome/awesome.py +0 -76
  64. build/lib/build/lib/clitt/core/icons/font_awesome/dashboard_icons.py +0 -93
  65. build/lib/build/lib/clitt/core/icons/font_awesome/form_icons.py +0 -69
  66. build/lib/build/lib/clitt/core/icons/font_awesome/game_icons.py +0 -59
  67. build/lib/build/lib/clitt/core/icons/font_awesome/nav_icons.py +0 -42
  68. build/lib/build/lib/clitt/core/icons/font_awesome/trickplay_icons.py +0 -39
  69. build/lib/build/lib/clitt/core/icons/font_awesome/widget_icons.py +0 -37
  70. build/lib/build/lib/clitt/core/preferences.py +0 -87
  71. build/lib/build/lib/clitt/core/term/__init__.py +0 -14
  72. build/lib/build/lib/clitt/core/term/commons.py +0 -82
  73. build/lib/build/lib/clitt/core/term/cursor.py +0 -159
  74. build/lib/build/lib/clitt/core/term/screen.py +0 -91
  75. build/lib/build/lib/clitt/core/term/terminal.py +0 -203
  76. build/lib/build/lib/clitt/core/tui/__init__.py +0 -20
  77. build/lib/build/lib/clitt/core/tui/line_input/__init__.py +0 -12
  78. build/lib/build/lib/clitt/core/tui/line_input/keyboard_input.py +0 -228
  79. build/lib/build/lib/clitt/core/tui/line_input/line_input.py +0 -43
  80. build/lib/build/lib/clitt/core/tui/mchoose/__init__.py +0 -12
  81. build/lib/build/lib/clitt/core/tui/mchoose/mchoose.py +0 -44
  82. build/lib/build/lib/clitt/core/tui/mchoose/menu_choose.py +0 -200
  83. build/lib/build/lib/clitt/core/tui/mdashboard/__init__.py +0 -14
  84. build/lib/build/lib/clitt/core/tui/mdashboard/dashboard_builder.py +0 -54
  85. build/lib/build/lib/clitt/core/tui/mdashboard/dashboard_item.py +0 -31
  86. build/lib/build/lib/clitt/core/tui/mdashboard/mdashboard.py +0 -26
  87. build/lib/build/lib/clitt/core/tui/mdashboard/menu_dashboard.py +0 -154
  88. build/lib/build/lib/clitt/core/tui/menu/__init__.py +0 -16
  89. build/lib/build/lib/clitt/core/tui/menu/tui_menu.py +0 -111
  90. build/lib/build/lib/clitt/core/tui/menu/tui_menu_action.py +0 -47
  91. build/lib/build/lib/clitt/core/tui/menu/tui_menu_factory.py +0 -117
  92. build/lib/build/lib/clitt/core/tui/menu/tui_menu_item.py +0 -196
  93. build/lib/build/lib/clitt/core/tui/menu/tui_menu_ui.py +0 -98
  94. build/lib/build/lib/clitt/core/tui/menu/tui_menu_view.py +0 -57
  95. build/lib/build/lib/clitt/core/tui/minput/__init__.py +0 -19
  96. build/lib/build/lib/clitt/core/tui/minput/access_type.py +0 -26
  97. build/lib/build/lib/clitt/core/tui/minput/field_builder.py +0 -117
  98. build/lib/build/lib/clitt/core/tui/minput/form_builder.py +0 -72
  99. build/lib/build/lib/clitt/core/tui/minput/form_field.py +0 -180
  100. build/lib/build/lib/clitt/core/tui/minput/input_type.py +0 -30
  101. build/lib/build/lib/clitt/core/tui/minput/input_validator.py +0 -98
  102. build/lib/build/lib/clitt/core/tui/minput/menu_input.py +0 -292
  103. build/lib/build/lib/clitt/core/tui/minput/minput.py +0 -44
  104. build/lib/build/lib/clitt/core/tui/minput/minput_utils.py +0 -156
  105. build/lib/build/lib/clitt/core/tui/mselect/__init__.py +0 -12
  106. build/lib/build/lib/clitt/core/tui/mselect/menu_select.py +0 -171
  107. build/lib/build/lib/clitt/core/tui/mselect/mselect.py +0 -36
  108. build/lib/build/lib/clitt/core/tui/table/__init__.py +0 -12
  109. build/lib/build/lib/clitt/core/tui/table/table_enums.py +0 -47
  110. build/lib/build/lib/clitt/core/tui/table/table_renderer.py +0 -339
  111. build/lib/build/lib/clitt/core/tui/tui_application.py +0 -65
  112. build/lib/build/lib/clitt/core/tui/tui_component.py +0 -155
  113. build/lib/build/lib/clitt/core/tui/tui_preferences.py +0 -103
  114. build/lib/build/lib/clitt/utils/__init__.py +0 -11
  115. build/lib/build/lib/clitt/utils/git_utils.py +0 -66
  116. build/lib/clitt/__classpath__.py +0 -28
  117. build/lib/clitt/__init__.py +0 -13
  118. build/lib/clitt/__main__.py +0 -139
  119. build/lib/clitt/addons/__init__.py +0 -12
  120. build/lib/clitt/addons/appman/__init__.py +0 -13
  121. build/lib/clitt/addons/appman/appman.py +0 -305
  122. build/lib/clitt/addons/appman/appman_enums.py +0 -39
  123. build/lib/clitt/addons/appman/templates/__init__.py +0 -11
  124. build/lib/clitt/addons/widman/__init__.py +0 -14
  125. build/lib/clitt/addons/widman/widget.py +0 -70
  126. build/lib/clitt/addons/widman/widget_entry.py +0 -54
  127. build/lib/clitt/addons/widman/widgets/__init__.py +0 -14
  128. build/lib/clitt/addons/widman/widgets/widget_free.py +0 -110
  129. build/lib/clitt/addons/widman/widgets/widget_punch.py +0 -246
  130. build/lib/clitt/addons/widman/widgets/widget_send_msg.py +0 -272
  131. build/lib/clitt/addons/widman/widgets/widget_time_calc.py +0 -146
  132. build/lib/clitt/addons/widman/widman.py +0 -123
  133. build/lib/clitt/core/__init__.py +0 -15
  134. build/lib/clitt/core/exception/__init__.py +0 -11
  135. build/lib/clitt/core/exception/exceptions.py +0 -18
  136. build/lib/clitt/core/icons/__init__.py +0 -12
  137. build/lib/clitt/core/icons/emojis/__init__.py +0 -12
  138. build/lib/clitt/core/icons/emojis/emojis.py +0 -41
  139. build/lib/clitt/core/icons/emojis/face_smiling.py +0 -40
  140. build/lib/clitt/core/icons/font_awesome/__init__.py +0 -18
  141. build/lib/clitt/core/icons/font_awesome/app_icons.py +0 -55
  142. build/lib/clitt/core/icons/font_awesome/awesome.py +0 -76
  143. build/lib/clitt/core/icons/font_awesome/dashboard_icons.py +0 -93
  144. build/lib/clitt/core/icons/font_awesome/form_icons.py +0 -69
  145. build/lib/clitt/core/icons/font_awesome/game_icons.py +0 -59
  146. build/lib/clitt/core/icons/font_awesome/nav_icons.py +0 -42
  147. build/lib/clitt/core/icons/font_awesome/trickplay_icons.py +0 -39
  148. build/lib/clitt/core/icons/font_awesome/widget_icons.py +0 -37
  149. build/lib/clitt/core/preferences.py +0 -87
  150. build/lib/clitt/core/term/__init__.py +0 -14
  151. build/lib/clitt/core/term/commons.py +0 -82
  152. build/lib/clitt/core/term/cursor.py +0 -159
  153. build/lib/clitt/core/term/screen.py +0 -91
  154. build/lib/clitt/core/term/terminal.py +0 -203
  155. build/lib/clitt/core/tui/__init__.py +0 -20
  156. build/lib/clitt/core/tui/line_input/__init__.py +0 -12
  157. build/lib/clitt/core/tui/line_input/keyboard_input.py +0 -228
  158. build/lib/clitt/core/tui/line_input/line_input.py +0 -43
  159. build/lib/clitt/core/tui/mchoose/__init__.py +0 -12
  160. build/lib/clitt/core/tui/mchoose/mchoose.py +0 -44
  161. build/lib/clitt/core/tui/mchoose/menu_choose.py +0 -200
  162. build/lib/clitt/core/tui/mdashboard/__init__.py +0 -14
  163. build/lib/clitt/core/tui/mdashboard/dashboard_builder.py +0 -54
  164. build/lib/clitt/core/tui/mdashboard/dashboard_item.py +0 -31
  165. build/lib/clitt/core/tui/mdashboard/mdashboard.py +0 -26
  166. build/lib/clitt/core/tui/mdashboard/menu_dashboard.py +0 -154
  167. build/lib/clitt/core/tui/menu/__init__.py +0 -16
  168. build/lib/clitt/core/tui/menu/tui_menu.py +0 -111
  169. build/lib/clitt/core/tui/menu/tui_menu_action.py +0 -47
  170. build/lib/clitt/core/tui/menu/tui_menu_factory.py +0 -117
  171. build/lib/clitt/core/tui/menu/tui_menu_item.py +0 -196
  172. build/lib/clitt/core/tui/menu/tui_menu_ui.py +0 -98
  173. build/lib/clitt/core/tui/menu/tui_menu_view.py +0 -57
  174. build/lib/clitt/core/tui/minput/__init__.py +0 -19
  175. build/lib/clitt/core/tui/minput/access_type.py +0 -26
  176. build/lib/clitt/core/tui/minput/field_builder.py +0 -117
  177. build/lib/clitt/core/tui/minput/form_builder.py +0 -72
  178. build/lib/clitt/core/tui/minput/form_field.py +0 -180
  179. build/lib/clitt/core/tui/minput/input_type.py +0 -30
  180. build/lib/clitt/core/tui/minput/input_validator.py +0 -98
  181. build/lib/clitt/core/tui/minput/menu_input.py +0 -292
  182. build/lib/clitt/core/tui/minput/minput.py +0 -44
  183. build/lib/clitt/core/tui/minput/minput_utils.py +0 -156
  184. build/lib/clitt/core/tui/mselect/__init__.py +0 -12
  185. build/lib/clitt/core/tui/mselect/menu_select.py +0 -171
  186. build/lib/clitt/core/tui/mselect/mselect.py +0 -36
  187. build/lib/clitt/core/tui/table/__init__.py +0 -12
  188. build/lib/clitt/core/tui/table/table_enums.py +0 -47
  189. build/lib/clitt/core/tui/table/table_renderer.py +0 -339
  190. build/lib/clitt/core/tui/tui_application.py +0 -65
  191. build/lib/clitt/core/tui/tui_component.py +0 -155
  192. build/lib/clitt/core/tui/tui_preferences.py +0 -103
  193. build/lib/clitt/utils/__init__.py +0 -11
  194. build/lib/clitt/utils/git_utils.py +0 -66
  195. hspylib_clitt-0.9.115.dist-info/RECORD +0 -255
@@ -1,42 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
-
4
- """
5
- @project: HsPyLib-Clitt
6
- @package: clitt.core.icons.font_awesome
7
- @file: nav_icons.py
8
- @created: Tue, 4 May 2021
9
- @author: <B>H</B>ugo <B>S</B>aporetti <B>J</B>unior"
10
- @site: https://github.com/yorevs/hspylib
11
- @license: MIT - Please refer to <https://opensource.org/licenses/MIT>
12
-
13
- Copyright·(c)·2024,·HSPyLib
14
- """
15
- from clitt.core.icons.font_awesome.awesome import Awesome
16
- from enum import auto
17
-
18
-
19
- # @composable
20
- class NavIcons(Awesome):
21
- """
22
- Navigation icons.
23
- Codes can be found here:
24
- - https://fontawesome.com/cheatsheet?from=io
25
- """
26
-
27
- # fmt: off
28
- _CUSTOM = auto()
29
- UP = '\u2191' # ↑
30
- RIGHT = '\u2192' # →
31
- DOWN = '\u2193' # ↓
32
- LEFT = '\u2190' # ←
33
- UP_DOWN = '\uF9E1' # 李
34
- LEFT_RIGHT = '\uF9E0' # 易
35
- ENTER = '\u21B5' # ↵
36
- TAB = '\u21B9' # ↹
37
- BACKSPACE = '\u232B' # ⌫
38
- POINTER = '\uF432' # 
39
- SELECTED = '\uF814' # 
40
- UNSELECTED = '\uF815' # 
41
- BREADCRUMB = '\uF44A' # 
42
- # fmt: on
@@ -1,39 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
-
4
- """
5
- @project: HsPyLib-Clitt
6
- @package: clitt.core.icons.font_awesome
7
- @file: trickplay_icons.py
8
- @created: Tue, 4 May 2021
9
- @author: <B>H</B>ugo <B>S</B>aporetti <B>J</B>unior"
10
- @site: https://github.com/yorevs/hspylib
11
- @license: MIT - Please refer to <https://opensource.org/licenses/MIT>
12
-
13
- Copyright·(c)·2024,·HSPyLib
14
- """
15
- from clitt.core.icons.font_awesome.awesome import Awesome
16
- from enum import auto
17
-
18
-
19
- # @composable
20
- class TrickplayIcons(Awesome):
21
- """
22
- Navigation icons.
23
- Codes can be found here:
24
- - https://fontawesome.com/cheatsheet?from=io
25
- """
26
-
27
- # fmt: off
28
- _CUSTOM = auto()
29
- PREVIOUS = '\uF048' # 
30
- REWIND = '\uF049' # 
31
- BACKWARD = '\uF04A' # 
32
- PLAY = '\uF04B' # 
33
- PAUSE = '\uF04C' # 
34
- STOP = '\uF04D' # 
35
- NEXT = '\uF051' # 
36
- ADVANCE = '\uF050' # 
37
- FORWARD = '\uF04E' # 
38
- EJECT = '\uF052' # 
39
- # fmt: on
@@ -1,37 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
-
4
- """
5
- @project: HsPyLib-Clitt
6
- @package: clitt.core.icons.font_awesome
7
- @file: widget_icons.py
8
- @created: Thu, 20 May 2021
9
- @author: <B>H</B>ugo <B>S</B>aporetti <B>J</B>unior"
10
- @site: https://github.com/yorevs/hspylib
11
- @license: MIT - Please refer to <https://opensource.org/licenses/MIT>
12
-
13
- Copyright·(c)·2024,·HSPyLib
14
- """
15
- from clitt.core.icons.font_awesome.awesome import Awesome
16
- from enum import auto
17
-
18
-
19
- class WidgetIcons(Awesome):
20
- """
21
- Dashboard UI icons.
22
- Codes can be found here:
23
- - https://fontawesome.com/cheatsheet?from=io
24
- """
25
-
26
- # fmt: off
27
- _CUSTOM = auto()
28
- CHART_2 = '\uF200' # 
29
- CHART_1 = '\uF1FE' # 
30
- CLOCK = '\uF651' # 
31
- CHIP = '\uFB19' # ﬙
32
- MUSIC = '\uF3B5' # 
33
- NETWORK = '\uF819' # 
34
- PUNCH = '\uF255' # 
35
- SIGN = '\uF45D' # 
36
- WIDGET = '\uF198' # 
37
- # fmt: on
@@ -1,87 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
-
4
- """
5
- @project: HsPyLib-Clitt
6
- @package: clitt.core
7
- @file: preferences.py
8
- @created: Fri, 7 Jul 2023
9
- @author: <B>H</B>ugo <B>S</B>aporetti <B>J</B>unior"
10
- @site: https://github.com/yorevs/hspylib
11
- @license: MIT - Please refer to <https://opensource.org/licenses/MIT>
12
-
13
- Copyright·(c)·2024,·HSPyLib
14
- """
15
- from enum import Enum
16
- from hspylib.core.metaclass.singleton import AbstractSingleton
17
- from hspylib.core.preconditions import check_argument, check_not_none
18
- from hspylib.core.tools.dict_tools import get_or_default_by_key
19
- from hspylib.core.tools.text_tools import ensure_startswith, environ_name
20
- from typing import Any
21
-
22
- import os
23
-
24
-
25
- class Preferences(metaclass=AbstractSingleton):
26
- """General purpose bas class to provide preference management."""
27
-
28
- def __init__(self, prefix: str = ""):
29
- self._prefix = prefix
30
- self._overrides = {}
31
-
32
- def __str__(self):
33
- # fmt: off
34
- return (
35
- f"Terminal UI Preferences{os.linesep}"
36
- f"{'-=' * 20}{os.linesep}"
37
- + os.linesep.join([f"|-{p[1:]:<16}: {getattr(self, p)}" for p in vars(self)])
38
- + f"{os.linesep}{'-=' * 20}{os.linesep}"
39
- )
40
- # fmt: on
41
-
42
- def __repr__(self):
43
- return str(self)
44
-
45
- def __getitem__(self, name: str):
46
- attr_name = name.replace(self._prefix + ".", "").replace(".", "_")
47
- return getattr(self, attr_name)
48
-
49
- def __setitem__(self, name: str, value: Any):
50
- attr_name = name.replace(self._prefix + ".", "").replace(".", "_")
51
- curr_val = getattr(self, attr_name)
52
- t1, t2 = type(curr_val), type(value)
53
- check_not_none(curr_val, f"Preference '{name}' does not exist")
54
- check_argument(t1 == t2, f"Preference '{name}' value must be of type '{t1}', not '{t2}'")
55
- self._overrides[self._get_name(name)] = value
56
-
57
- def __iter__(self):
58
- return self._overrides.__iter__()
59
-
60
- def __len__(self):
61
- return len(self._overrides)
62
-
63
- def get_preference(self, name: str, default: Any = None) -> Any:
64
- """Retrieve preference for the given specified name. If not found, return the default value.
65
- :param name: the preference name.
66
- :param default: the preference default value.
67
- :return the preference value.
68
- """
69
- pref_name = self._get_name(name)
70
- value = get_or_default_by_key(self._overrides, pref_name, default)
71
- if str_value := os.environ.get(environ_name(pref_name)):
72
- type_attr = type(value)
73
- try:
74
- if isinstance(value, Enum):
75
- value = type_attr[str_value.upper()]
76
- else:
77
- value = type_attr(str_value)
78
- except (KeyError, TypeError, ValueError):
79
- pass
80
- return value
81
-
82
- def _get_name(self, name: str) -> str:
83
- """Retrieve the preference name based. It uses the specified prefix to compose the actual name.
84
- :param name: the preference name.
85
- :return the prefixed preference name.
86
- """
87
- return ensure_startswith(name, self._prefix + ".")
@@ -1,14 +0,0 @@
1
- # _*_ coding: utf-8 _*_
2
- #
3
- # hspylib-clitt v0.9.115
4
- #
5
- # Package: main.build.lib.build.lib.clitt.core.term
6
- """Package initialization."""
7
-
8
- __all__ = [
9
- 'commons',
10
- 'cursor',
11
- 'screen',
12
- 'terminal'
13
- ]
14
- __version__ = '0.9.115'
@@ -1,82 +0,0 @@
1
- from clitt.core.exception.exceptions import NotATerminalError
2
- from hspylib.core.enums.enumeration import Enumeration
3
- from hspylib.core.tools.commons import is_debugging
4
- from hspylib.modules.cli.vt100.vt_100 import Vt100
5
- from shutil import get_terminal_size
6
- from typing import Callable, Tuple, TypeAlias, Union
7
-
8
- import logging as log
9
- import re
10
- import sys
11
- import termios
12
- import tty
13
-
14
- # fmt: off
15
- Dimension : TypeAlias = Tuple[int, int]
16
- Position : TypeAlias = Tuple[int, int]
17
- Resize_Cb : TypeAlias = Callable[[], None]
18
- MoveDirection : TypeAlias = "Direction"
19
- EraseDirection : TypeAlias = Union["Direction", "Portion"]
20
- # fmt: on
21
-
22
-
23
- class Direction(Enumeration):
24
- """Provide a base class for the cursor direction."""
25
-
26
- # fmt: off
27
- UP = '%ED1%', '%CUU({n})%' # Cursor up (line)
28
- RIGHT = '%EL0%', '%CUF({n})%' # Cursor right (forward)
29
- DOWN = '%ED0%', '%CUD({n})%' # Cursor down (line)
30
- LEFT = '%EL1%', '%CUB({n})%' # Cursor left (backward)
31
- # fmt: on
32
-
33
-
34
- class Portion(Enumeration):
35
- """Provide a base class for the portions of the screen."""
36
-
37
- # fmt: off
38
- SCREEN = '%ED2%', '' # Entire screen (screen)
39
- LINE = '%EL2%', '' # Entire line (line)
40
- # fmt: on
41
-
42
-
43
- def get_dimensions(fallback: Tuple[int, int] = (24, 80)) -> Tuple[int, int]:
44
- """Retrieve the size of the terminal.
45
- :return lines, columns
46
- """
47
- if not sys.stdout.isatty():
48
- log.warning(NotATerminalError("get_dimensions:: Requires a terminal (TTY)"))
49
- return fallback
50
- dim = get_terminal_size((fallback[1], fallback[0]))
51
- return dim.lines, dim.columns
52
-
53
-
54
- def get_cursor_position(fallback: Tuple[int, int] = (0, 0)) -> Tuple[int, int]:
55
- """Get the terminal cursor position.
56
- :return line, column
57
- """
58
- pos, buf, re_query_resp = fallback, "", r"^\x1b\[(\d*);(\d*)R"
59
-
60
- if not sys.stdout.isatty():
61
- log.warning(NotATerminalError("get_cursor_position:: Requires a terminal (TTY)"))
62
- return pos
63
-
64
- if is_debugging():
65
- return pos
66
-
67
- stdin = sys.stdin.fileno() # Get the stdin file descriptor.
68
- attrs = termios.tcgetattr(stdin) # Save terminal attributes.
69
-
70
- try:
71
- tty.setcbreak(stdin, termios.TCSANOW)
72
- sys.stdout.write(Vt100.get_cursor_pos())
73
- sys.stdout.flush()
74
- while not buf or buf[-1] != "R":
75
- buf += sys.stdin.read(1)
76
- if matches := re.match(re_query_resp, buf): # If the response is 'Esc[r;cR'
77
- groups = matches.groups()
78
- pos = int(groups[0]), int(groups[1])
79
- finally:
80
- termios.tcsetattr(stdin, termios.TCSANOW, attrs) # Reset terminal attributes
81
-
82
- return pos
@@ -1,159 +0,0 @@
1
- import os
2
- from hspylib.core.metaclass.singleton import Singleton
3
- from hspylib.core.tools.commons import sysout
4
- from hspylib.core.tools.text_tools import last_index_of
5
- from hspylib.modules.cli.vt100.vt_100 import Vt100
6
- from hspylib.modules.cli.vt100.vt_code import VtCode
7
- from hspylib.modules.cli.vt100.vt_color import VtColor
8
- from typing import Any
9
-
10
- from clitt.core.term.commons import Direction, EraseDirection, get_cursor_position, MoveDirection, Position, Portion
11
-
12
-
13
- class Cursor(metaclass=Singleton):
14
- """Provide a base class for the screen cursor."""
15
-
16
- INSTANCE = None
17
-
18
- CURSOR_HOME = 1, 1
19
-
20
- def __init__(self):
21
- self._position: Position = get_cursor_position() or self.CURSOR_HOME
22
- self._bottom: Position = self.CURSOR_HOME
23
- self._saved_attrs = self._position, self._bottom
24
-
25
- def __str__(self):
26
- return f"({', '.join(list(map(str, self._position)))})"
27
-
28
- def __repr__(self):
29
- return str(self)
30
-
31
- @property
32
- def position(self) -> Position:
33
- return self._position
34
-
35
- @position.setter
36
- def position(self, new_position: Position) -> None:
37
- self._bottom = (new_position[0], new_position[1]) if new_position >= self._bottom else self._bottom
38
- self._position = new_position
39
-
40
- @property
41
- def bottom(self) -> Position:
42
- return self._bottom
43
-
44
- def home(self) -> None:
45
- """Move the cursor to home position.
46
- :return None
47
- """
48
- self.move_to(self.CURSOR_HOME[0], self.CURSOR_HOME[1])
49
-
50
- def end(self) -> None:
51
- """Move the cursor to the bottom most position on the screen.
52
- :return None
53
- """
54
- self.move_to(self.bottom[0], self.bottom[1])
55
-
56
- def move_to(self, row: int = None, column: int = None) -> Position:
57
- """Move the cursor to the specified position.
58
- :param row the specified row to move.
59
- :param column the specified column to move.
60
- :return the cursor position after moving.
61
- """
62
- row_pos = max(self.CURSOR_HOME[0], row if row is not None else self.position[0])
63
- col_pos = max(self.CURSOR_HOME[1], column if column is not None else self.position[1])
64
- sysout(f"%CUP({row_pos};{col_pos})%", end="")
65
- self.position = row_pos, col_pos
66
- return self.position
67
-
68
- def move(self, amount: int, direction: MoveDirection) -> Position:
69
- """Move the cursor towards the specified direction.
70
- :param amount the amount of columns to move.
71
- :param direction the direction to move.
72
- :return the cursor position after moving.
73
- """
74
- if amount > 0:
75
- sysout(direction.value[1].format(n=amount), end="")
76
- row_pos, col_pos = self.position
77
- match direction:
78
- case Direction.UP:
79
- row_pos -= max(0, amount)
80
- case Direction.DOWN:
81
- row_pos += max(0, amount)
82
- case Direction.LEFT:
83
- col_pos -= max(0, amount)
84
- case Direction.RIGHT:
85
- col_pos += max(0, amount)
86
- self.position = row_pos, col_pos
87
- return self.position
88
-
89
- def erase(self, direction: EraseDirection) -> Position:
90
- """Erase the screen following the specified direction.
91
- Note: It does not move the cursor along the way.
92
- :param direction the direction to erase the screen.
93
- :return the cursor position after erasing.
94
- """
95
- sysout(direction.value[0], end="")
96
- return self.position
97
-
98
- def erase_line(self) -> Position:
99
- """Erase the previous line of the screen."""
100
- row_pos, col_pos = self.position
101
- self.move(1, Direction.UP)
102
- self.erase(Portion.LINE)
103
- self.move(col_pos, Direction.LEFT)
104
- self.position = row_pos, 0
105
- return self.position
106
-
107
- def track(self) -> Position:
108
- """Track the cursor position.
109
- :return the tracked cursor position.
110
- """
111
- self.position = get_cursor_position() or self.position
112
- return self.position
113
-
114
- def write(self, obj: Any, end: str = "") -> Position:
115
- """Write the string representation of the object to the screen.
116
- :param obj the object to be written.
117
- :param end string appended after the last value, default a newline.
118
- :return the cursor position after writing.
119
- """
120
- sysout(obj, end=end)
121
- text = (str(obj) + end).replace("%EOL%", os.linesep)
122
- text = VtColor.strip_colors(VtCode.strip_codes(text))
123
- text_offset = len(text[max(0, last_index_of(text, os.linesep)):])
124
- self.position = self.position[0] + text.count(os.linesep), text_offset + (
125
- self.position[1] if text.count(os.linesep) == 0 else 0
126
- )
127
- return self.position
128
-
129
- def writeln(self, obj: Any) -> Position:
130
- """Write the string representation of the object to the screen, appending a new line.
131
- :param obj the object to be written.
132
- :return the cursor position after writing.
133
- """
134
- return self.write(obj, end=os.linesep)
135
-
136
- def save(self) -> Position:
137
- """Save the current cursor position and attributes.
138
- :return the actual cursor position.
139
- """
140
- sysout(Vt100.save_cursor(), end="")
141
- self._saved_attrs = self._position, self._bottom
142
- return self.position
143
-
144
- def restore(self) -> Position:
145
- """Restore the saved cursor position and attributes.
146
- :return the cursor position after restoration.
147
- """
148
- sysout(Vt100.restore_cursor(), end="")
149
- self._position = self._saved_attrs[0]
150
- self._bottom = self._saved_attrs[1]
151
- return self.position
152
-
153
- def reset_mode(self, end="") -> Position:
154
- """Reset cursor modifiers."""
155
- sysout(Vt100.mode(0), end=end)
156
- return self.position
157
-
158
-
159
- assert Cursor().INSTANCE is not None, "Failed to create Cursor instance"
@@ -1,91 +0,0 @@
1
- from clitt.core.term.commons import Dimension, get_dimensions, Portion, Resize_Cb
2
- from clitt.core.term.cursor import Cursor
3
- from clitt.core.tui.tui_preferences import TUIPreferences
4
- from hspylib.core.metaclass.singleton import Singleton
5
- from hspylib.core.tools.commons import sysout
6
- from threading import Timer
7
- from typing import List, Optional
8
-
9
- import threading
10
-
11
-
12
- class Screen(metaclass=Singleton):
13
- """Provide a base class for terminal UI components."""
14
-
15
- INSTANCE = None
16
-
17
- RESIZE_WATCH_INTERVAL = 0.5
18
-
19
- def __init__(self):
20
- self._preferences: TUIPreferences = TUIPreferences.INSTANCE
21
- self._dimension: Dimension = get_dimensions()
22
- self._cursor: Cursor = Cursor.INSTANCE or Cursor()
23
- self._resize_timer: Optional[Timer] = None
24
- self._cb_watchers: List[Resize_Cb] = []
25
- self._alternate: bool = False
26
- self._resize_watcher()
27
-
28
- def __str__(self):
29
- return f"Terminal.Screen(rows={self.lines}, columns={self.columns}, cursor={self.cursor})"
30
-
31
- def __repr__(self):
32
- return str(self)
33
-
34
- @property
35
- def preferences(self) -> TUIPreferences:
36
- return self._preferences
37
-
38
- @property
39
- def dimension(self) -> Dimension:
40
- return self._dimension
41
-
42
- @property
43
- def lines(self) -> int:
44
- return self._dimension[0]
45
-
46
- @property
47
- def columns(self) -> int:
48
- return self._dimension[1]
49
-
50
- @property
51
- def cursor(self) -> Cursor:
52
- return self._cursor
53
-
54
- @property
55
- def alternate(self) -> bool:
56
- return self._alternate
57
-
58
- @alternate.setter
59
- def alternate(self, enable: bool) -> None:
60
- """Switch to the alternate screen buffer.
61
- :param enable: alternate enable on/off.
62
- """
63
- if enable != self._alternate:
64
- self._alternate = enable
65
- sysout(f"%SC{'A' if enable else 'M'}%", end="")
66
- self.cursor.track()
67
-
68
- def clear(self) -> None:
69
- """Clear terminal and move the cursor to HOME position (0, 0)."""
70
- self.cursor.home()
71
- self.cursor.erase(Portion.SCREEN)
72
-
73
- def add_watcher(self, watcher: Resize_Cb) -> None:
74
- """Add a resize watcher."""
75
- self._cb_watchers.append(watcher)
76
- if not self._resize_timer:
77
- self._resize_watcher()
78
-
79
- def _resize_watcher(self) -> None:
80
- """Add a watcher for screen resizes. If a resize is detected, the callback is called with the
81
- new dimension."""
82
- if self._cb_watchers and threading.main_thread().is_alive():
83
- dimension: Dimension = get_dimensions()
84
- self._resize_timer = Timer(self.RESIZE_WATCH_INTERVAL, self._resize_watcher)
85
- if dimension != self._dimension:
86
- list(map(lambda cb_w: cb_w(), self._cb_watchers))
87
- self._dimension = dimension
88
- self._resize_timer.start()
89
-
90
-
91
- assert Screen().INSTANCE is not None, "Failed to create Screen instance"