hspylib-clitt 0.9.41__py3-none-any.whl → 0.9.51__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 (60) hide show
  1. clitt/.version +1 -1
  2. clitt/__classpath__.py +1 -1
  3. clitt/__init__.py +4 -3
  4. clitt/__main__.py +8 -41
  5. clitt/addons/__init__.py +2 -3
  6. clitt/addons/appman/__init__.py +2 -2
  7. clitt/addons/appman/appman.py +1 -1
  8. clitt/addons/appman/templates/__init__.py +2 -2
  9. clitt/addons/widman/__init__.py +2 -2
  10. clitt/addons/widman/widgets/__init__.py +2 -2
  11. clitt/addons/widman/widgets/widget_free.py +2 -1
  12. clitt/addons/widman/widgets/widget_punch.py +3 -2
  13. clitt/core/__init__.py +3 -3
  14. clitt/core/icons/__init__.py +2 -2
  15. clitt/core/icons/emojis/__init__.py +2 -2
  16. clitt/core/icons/font_awesome/__init__.py +2 -2
  17. clitt/core/term/__init__.py +14 -0
  18. clitt/core/term/commons.py +63 -0
  19. clitt/core/term/cursor.py +124 -0
  20. clitt/core/term/screen.py +96 -0
  21. clitt/core/term/terminal.py +173 -0
  22. clitt/core/tui/__init__.py +3 -4
  23. clitt/core/tui/mchoose/__init__.py +2 -2
  24. clitt/core/tui/mchoose/menu_choose.py +6 -5
  25. clitt/core/tui/mdashboard/__init__.py +2 -2
  26. clitt/core/tui/mdashboard/menu_dashboard.py +9 -9
  27. clitt/core/tui/menu/__init__.py +2 -2
  28. clitt/core/tui/menu/tui_menu_action.py +1 -3
  29. clitt/core/tui/menu/tui_menu_item.py +6 -5
  30. clitt/core/tui/menu/tui_menu_ui.py +5 -7
  31. clitt/core/tui/menu/tui_menu_view.py +2 -3
  32. clitt/core/tui/minput/__init__.py +2 -2
  33. clitt/core/tui/minput/menu_input.py +22 -18
  34. clitt/core/tui/minput/minput_utils.py +4 -3
  35. clitt/core/tui/mselect/__init__.py +2 -2
  36. clitt/core/tui/mselect/menu_select.py +6 -5
  37. clitt/core/tui/table/__init__.py +2 -2
  38. clitt/core/tui/table/table_renderer.py +13 -15
  39. clitt/core/tui/tui_application.py +27 -13
  40. clitt/core/tui/tui_component.py +28 -21
  41. clitt/core/tui/tui_preferences.py +3 -0
  42. clitt/utils/__init__.py +11 -0
  43. clitt/utils/git_utils.py +67 -0
  44. clitt/welcome.txt +6 -6
  45. {hspylib_clitt-0.9.41.dist-info → hspylib_clitt-0.9.51.dist-info}/METADATA +4 -4
  46. hspylib_clitt-0.9.51.dist-info/RECORD +90 -0
  47. clitt/addons/setman/__init__.py +0 -13
  48. clitt/addons/setman/setman.py +0 -148
  49. clitt/addons/setman/setman_config.py +0 -26
  50. clitt/addons/setman/setman_enums.py +0 -54
  51. clitt/core/settings/__init__.py +0 -15
  52. clitt/core/settings/settings.py +0 -182
  53. clitt/core/settings/settings_config.py +0 -47
  54. clitt/core/settings/settings_entry.py +0 -108
  55. clitt/core/settings/settings_repository.py +0 -103
  56. clitt/core/settings/settings_service.py +0 -50
  57. clitt/core/tui/tui_screen.py +0 -222
  58. hspylib_clitt-0.9.41.dist-info/RECORD +0 -94
  59. {hspylib_clitt-0.9.41.dist-info → hspylib_clitt-0.9.51.dist-info}/WHEEL +0 -0
  60. {hspylib_clitt-0.9.41.dist-info → hspylib_clitt-0.9.51.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ @project: HsPyLib
6
+ @package: hspylib.modules.cli.vt100
7
+ @file: terminal.py
8
+ @created: Tue, 11 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 2023, HsPyLib team
14
+ """
15
+ import atexit
16
+ import logging as log
17
+ import os
18
+ import platform
19
+ import select
20
+ import shlex
21
+ import signal
22
+ import subprocess
23
+ import sys
24
+ from typing import Optional, Tuple, Any
25
+
26
+ from hspylib.core.enums.charset import Charset
27
+ from hspylib.core.exception.exceptions import NotATerminalError
28
+ from hspylib.core.metaclass.singleton import Singleton
29
+ from hspylib.core.tools.commons import sysout
30
+ from hspylib.modules.application.exit_status import ExitStatus
31
+ from hspylib.modules.cli.keyboard import Keyboard
32
+ from hspylib.modules.cli.vt100.vt_100 import Vt100
33
+
34
+ from clitt.core.term.screen import Screen
35
+
36
+
37
+ class Terminal(metaclass=Singleton):
38
+ """Utility class to provide terminal features."""
39
+
40
+ INSTANCE = None
41
+
42
+ @staticmethod
43
+ def is_a_tty() -> bool:
44
+ return sys.stdout.isatty()
45
+
46
+ @staticmethod
47
+ def shell_exec(cmd_line: str, **kwargs) -> Tuple[Optional[str], ExitStatus]:
48
+ """Execute command with arguments and return it's run status."""
49
+ try:
50
+ if "stdout" in kwargs:
51
+ del kwargs["stdout"] # Deleted since we use our own stream
52
+ if "stderr" in kwargs:
53
+ del kwargs["stderr"] # Deleted since we use our own stream
54
+ log.info("Executing shell command: %s", cmd_line)
55
+ cmd_args = list(filter(None, shlex.split(cmd_line)))
56
+ output = subprocess.check_output(cmd_args, **kwargs).decode(Charset.UTF_8.val)
57
+ log.info("Execution result: %s", ExitStatus.SUCCESS)
58
+ return output.strip() if output else None, ExitStatus.SUCCESS
59
+ except subprocess.CalledProcessError as err:
60
+ log.error("Command failed: %s => %s", cmd_line, err)
61
+ return None, ExitStatus.FAILED
62
+
63
+ @staticmethod
64
+ def shell_poll(cmd_line: str, **kwargs) -> None:
65
+ """Execute command with arguments and continuously poll it's output."""
66
+ if "stdout" in kwargs:
67
+ del kwargs["stdout"] # Deleted since we use our own stream
68
+ if "stderr" in kwargs:
69
+ del kwargs["stderr"] # Deleted since we use our own stream
70
+ try:
71
+ log.info("Polling shell command: %s", cmd_line)
72
+ cmd_args = list(filter(None, shlex.split(cmd_line)))
73
+ with subprocess.Popen(
74
+ cmd_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setsid, **kwargs) as proc:
75
+ process = select.poll()
76
+ process.register(proc.stdout)
77
+ process.register(proc.stderr)
78
+ while not Keyboard.kbhit():
79
+ if poll_obj := process.poll(0.5):
80
+ line = proc.stdout.readline()
81
+ sysout(line.decode(Charset.UTF_8.val) if isinstance(line, bytes) else line.strip(), end='')
82
+ log.debug("Polling returned: %s", str(poll_obj))
83
+ os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
84
+ except (InterruptedError, KeyboardInterrupt):
85
+ log.warning("Polling process has been interrupted command='%s'", cmd_line)
86
+ except subprocess.CalledProcessError as err:
87
+ log.error("Command failed: %s => %s", cmd_line, err)
88
+
89
+ @staticmethod
90
+ def open(filename: str) -> None:
91
+ """Open the specified file using the default editor."""
92
+ my_os = os.environ.get("HHS_MY_OS", platform.system())
93
+ if "Darwin" == my_os:
94
+ Terminal.shell_exec(f"open {filename}")
95
+ elif "Linux" == my_os:
96
+ Terminal.shell_exec(f"xdg-open {filename}")
97
+ else:
98
+ raise NotImplementedError(f"OS '{my_os}' is not supported")
99
+
100
+ @classmethod
101
+ def restore(cls) -> None:
102
+ """Clear the terminal and restore default attributes [wrap,cursor,echo]."""
103
+ sysout("%MOD(0)%")
104
+ cls.set_attributes(show_cursor=True, auto_wrap=True, enable_echo=True)
105
+
106
+ @classmethod
107
+ def set_enable_echo(cls, enabled: bool = True) -> None:
108
+ """Enable echo in the terminal.
109
+ :param enabled: whether is enabled or not.
110
+ """
111
+ if not cls.is_a_tty():
112
+ log.error(NotATerminalError("set_enable_echo:: Requires a terminal (TTY)"))
113
+ return
114
+
115
+ os.popen(f"stty {'echo -raw' if enabled else 'raw -echo min 0'}").read()
116
+
117
+ @classmethod
118
+ def set_auto_wrap(cls, auto_wrap: bool = True) -> None:
119
+ """Set auto-wrap mode in the terminal.
120
+ :param auto_wrap: whether auto_wrap is set or not.
121
+ """
122
+ if not cls.is_a_tty():
123
+ log.warning(NotATerminalError("set_enable_echo:: Requires a terminal (TTY)"))
124
+ return
125
+
126
+ sysout(Vt100.set_auto_wrap(auto_wrap), end="")
127
+
128
+ @classmethod
129
+ def set_show_cursor(cls, show_cursor: bool = True) -> None:
130
+ """Show or hide cursor in the terminal.
131
+ :param show_cursor: whether to show or hide he cursor.
132
+ """
133
+ if not cls.is_a_tty():
134
+ log.warning(NotATerminalError("set_enable_echo:: Requires a terminal (TTY)"))
135
+ return
136
+
137
+ sysout(Vt100.set_show_cursor(show_cursor), end="")
138
+
139
+ @classmethod
140
+ def set_attributes(cls, **attrs) -> None:
141
+ """Wrapper to set all terminal attributes at once."""
142
+ # fmt: off
143
+ enable_echo = attrs['enable_echo']
144
+ auto_wrap = attrs['auto_wrap']
145
+ show_cursor = attrs['show_cursor']
146
+ # fmt: on
147
+ if enable_echo is not None:
148
+ cls.set_enable_echo(enable_echo)
149
+ if auto_wrap is not None:
150
+ cls.set_auto_wrap(auto_wrap)
151
+ if show_cursor is not None:
152
+ cls.set_show_cursor(show_cursor)
153
+
154
+ @classmethod
155
+ def clear(cls) -> None:
156
+ """Clear terminal and move the cursor to HOME position (0, 0)."""
157
+ cls.INSTANCE.screen.clear()
158
+
159
+ @classmethod
160
+ def echo(cls, obj: Any, end=os.linesep) -> None:
161
+ """Write the string representation of the object to the screen."""
162
+ cls.INSTANCE.screen.cursor.write(obj, end=end)
163
+
164
+ def __init__(self):
165
+ self._screen = Screen.INSTANCE or Screen()
166
+ atexit.register(self.restore)
167
+
168
+ @property
169
+ def screen(self) -> Screen:
170
+ return self._screen
171
+
172
+
173
+ assert Terminal().INSTANCE is not None, "Failed to create Terminal instance"
@@ -1,6 +1,6 @@
1
1
  # _*_ coding: utf-8 _*_
2
2
  #
3
- # hspylib-clitt v0.9.41
3
+ # hspylib-clitt v0.9.51
4
4
  #
5
5
  # Package: main.clitt.core.tui
6
6
  """Package initialization."""
@@ -14,7 +14,6 @@ __all__ = [
14
14
  'table',
15
15
  'tui_application',
16
16
  'tui_component',
17
- 'tui_preferences',
18
- 'tui_screen'
17
+ 'tui_preferences'
19
18
  ]
20
- __version__ = '0.9.41'
19
+ __version__ = '0.9.51'
@@ -1,6 +1,6 @@
1
1
  # _*_ coding: utf-8 _*_
2
2
  #
3
- # hspylib-clitt v0.9.41
3
+ # hspylib-clitt v0.9.51
4
4
  #
5
5
  # Package: main.clitt.core.tui.mchoose
6
6
  """Package initialization."""
@@ -9,4 +9,4 @@ __all__ = [
9
9
  'mchoose',
10
10
  'menu_choose'
11
11
  ]
12
- __version__ = '0.9.41'
12
+ __version__ = '0.9.51'
@@ -13,8 +13,9 @@
13
13
  Copyright 2023, HsPyLib team
14
14
  """
15
15
  from clitt.core.icons.font_awesome.nav_icons import NavIcons
16
+ from clitt.core.term.cursor import Cursor
17
+ from clitt.core.term.screen import Screen
16
18
  from clitt.core.tui.tui_component import TUIComponent
17
- from clitt.core.tui.tui_screen import TUIScreen
18
19
  from functools import cached_property
19
20
  from hspylib.modules.cli.keyboard import Keyboard
20
21
  from typing import List, Optional, TypeVar
@@ -66,7 +67,7 @@ class MenuChoose(TUIComponent):
66
67
  break # When the index is greater than the number of items, stop rendering
67
68
 
68
69
  option_line = str(self.items[idx])
69
- self.cursor.erase(TUIScreen.ScreenPortion.LINE)
70
+ self.cursor.erase(Screen.Portion.LINE)
70
71
  # Print the selector if the index is currently selected
71
72
  selector = self.draw_selector(idx == self.sel_index)
72
73
  mark = self.prefs.marked if self.sel_options[idx] == 1 else self.prefs.unmarked
@@ -127,8 +128,8 @@ class MenuChoose(TUIComponent):
127
128
  self.write(f"{keystroke.value if keystroke else ''}")
128
129
  index_len += 1
129
130
  # Erase the index typed by the user
130
- self.cursor.move(index_len, TUIScreen.CursorDirection.LEFT)
131
- self.cursor.erase(TUIScreen.CursorDirection.RIGHT)
131
+ self.cursor.move(index_len, Cursor.Direction.LEFT)
132
+ self.cursor.erase(Cursor.Direction.RIGHT)
132
133
  if typed_index and 1 <= int(typed_index) <= length:
133
134
  self.show_to = max(int(typed_index), self.diff_index)
134
135
  self.show_from = self.show_to - self.diff_index
@@ -185,5 +186,5 @@ class MenuChoose(TUIComponent):
185
186
  self._re_render = True
186
187
 
187
188
  def _max_rows(self) -> int:
188
- max_rows = self.screen.rows - self.ROW_OFFSET
189
+ max_rows = self.screen.lines - self.ROW_OFFSET
189
190
  return max_rows if self.prefs.max_rows > max_rows else self.prefs.max_rows
@@ -1,6 +1,6 @@
1
1
  # _*_ coding: utf-8 _*_
2
2
  #
3
- # hspylib-clitt v0.9.41
3
+ # hspylib-clitt v0.9.51
4
4
  #
5
5
  # Package: main.clitt.core.tui.mdashboard
6
6
  """Package initialization."""
@@ -11,4 +11,4 @@ __all__ = [
11
11
  'mdashboard',
12
12
  'menu_dashboard'
13
13
  ]
14
- __version__ = '0.9.41'
14
+ __version__ = '0.9.51'
@@ -13,10 +13,11 @@
13
13
  Copyright 2023, HsPyLib team
14
14
  """
15
15
  from clitt.core.icons.font_awesome.nav_icons import NavIcons
16
+ from clitt.core.term.cursor import Cursor
17
+ from clitt.core.term.screen import Screen
16
18
  from clitt.core.tui.mdashboard.dashboard_builder import DashboardBuilder
17
19
  from clitt.core.tui.mdashboard.dashboard_item import DashboardItem
18
20
  from clitt.core.tui.tui_component import TUIComponent
19
- from clitt.core.tui.tui_screen import TUIScreen
20
21
  from hspylib.core.preconditions import check_state
21
22
  from hspylib.modules.cli.keyboard import Keyboard
22
23
  from typing import List, Optional, TypeVar
@@ -82,7 +83,7 @@ class MenuDashBoard(TUIComponent):
82
83
  idx, item, MenuDashBoard.CELL_TPL if self._tab_index != idx else MenuDashBoard.SEL_CELL_TPL
83
84
  )
84
85
 
85
- self.cursor.erase(TUIScreen.ScreenPortion.LINE)
86
+ self.cursor.erase(Screen.Portion.LINE)
86
87
  self.cursor.move_to(column=1)
87
88
  self.draw_navbar(self.navbar())
88
89
  self._re_render = False
@@ -119,7 +120,6 @@ class MenuDashBoard(TUIComponent):
119
120
  :param item: the dashboard item.
120
121
  :param cell_template: the template of the dashboard cell (selected or unselected).
121
122
  """
122
-
123
123
  num_cols, num_rows = len(cell_template[0]), len(cell_template)
124
124
  for row in range(0, num_rows):
125
125
  for col in range(0, num_cols):
@@ -127,13 +127,13 @@ class MenuDashBoard(TUIComponent):
127
127
  # Print current cell
128
128
  self.write(f"{item.icon if cur_cell == self.ICN else cur_cell}")
129
129
  # Move to the next the next row
130
- self.cursor.move(1, TUIScreen.CursorDirection.DOWN)
131
- self.cursor.move(num_cols, TUIScreen.CursorDirection.LEFT)
130
+ self.cursor.move(1, Cursor.Direction.DOWN)
131
+ self.cursor.move(num_cols, Cursor.Direction.LEFT)
132
132
  if item_idx > 0 and (item_idx + 1) % self.prefs.items_per_line == 0:
133
133
  # Break the line
134
- self.cursor.move(1, TUIScreen.CursorDirection.DOWN)
135
- self.cursor.move(num_cols * self.prefs.items_per_line, TUIScreen.CursorDirection.LEFT)
134
+ self.cursor.move(1, Cursor.Direction.DOWN)
135
+ self.cursor.move(num_cols * self.prefs.items_per_line, Cursor.Direction.LEFT)
136
136
  elif item_idx + 1 < len(self._items):
137
137
  # Continue on the same line
138
- self.cursor.move(num_rows, TUIScreen.CursorDirection.UP)
139
- self.cursor.move(num_cols, TUIScreen.CursorDirection.RIGHT)
138
+ self.cursor.move(num_rows, Cursor.Direction.UP)
139
+ self.cursor.move(num_cols, Cursor.Direction.RIGHT)
@@ -1,6 +1,6 @@
1
1
  # _*_ coding: utf-8 _*_
2
2
  #
3
- # hspylib-clitt v0.9.41
3
+ # hspylib-clitt v0.9.51
4
4
  #
5
5
  # Package: main.clitt.core.tui.menu
6
6
  """Package initialization."""
@@ -13,4 +13,4 @@ __all__ = [
13
13
  'tui_menu_ui',
14
14
  'tui_menu_view'
15
15
  ]
16
- __version__ = '0.9.41'
16
+ __version__ = '0.9.51'
@@ -12,10 +12,8 @@
12
12
 
13
13
  Copyright 2023, HsPyLib team
14
14
  """
15
-
16
15
  from clitt.core.tui.menu.tui_menu import ON_TRIGGER_CB, TUIMenu
17
16
  from clitt.core.tui.menu.tui_menu_ui import TUIMenuUi
18
- from hspylib.modules.cli.vt100.vt_utils import restore_cursor
19
17
  from typing import Optional
20
18
 
21
19
 
@@ -30,7 +28,7 @@ class TUIMenuAction(TUIMenu):
30
28
  return ret_menu if ret_menu else self._default_trigger_cb(self)
31
29
 
32
30
  def render(self) -> None:
33
- restore_cursor()
31
+ self.screen.cursor.restore()
34
32
  TUIMenuUi.render_app_title()
35
33
 
36
34
  def __init__(
@@ -14,9 +14,10 @@
14
14
  """
15
15
 
16
16
  from clitt.core.icons.font_awesome.nav_icons import NavIcons
17
+ from clitt.core.term.cursor import Cursor
18
+ from clitt.core.term.screen import Screen
17
19
  from clitt.core.tui.menu.tui_menu import TUIMenu
18
20
  from clitt.core.tui.menu.tui_menu_ui import TUIMenuUi
19
- from clitt.core.tui.tui_screen import TUIScreen
20
21
  from functools import cached_property
21
22
  from hspylib.core.tools.dict_tools import get_or_default
22
23
  from hspylib.modules.cli.keyboard import Keyboard
@@ -41,7 +42,7 @@ class TUIMenuItem(TUIMenu):
41
42
  ):
42
43
  super().__init__(parent, title, tooltip or f"Access the '{title}' menu")
43
44
  self._show_from: int = 0
44
- self._show_to: int = self.screen.rows - self.ROW_OFFSET
45
+ self._show_to: int = self.screen.lines - self.ROW_OFFSET
45
46
  self._diff_index: int = self._show_to - self._show_from
46
47
  self._sel_index: int = 0
47
48
  self._items: List[TUIMenu] = items or []
@@ -81,7 +82,7 @@ class TUIMenuItem(TUIMenu):
81
82
  if idx >= length:
82
83
  break # When the number of items is lower than the max_rows, skip the other lines
83
84
  option_line = str(self._items[idx])
84
- self.cursor.erase(TUIScreen.ScreenPortion.LINE)
85
+ self.cursor.erase(Screen.Portion.LINE)
85
86
  # Print the selector if the index is currently selected
86
87
  selector = self.draw_selector(is_selected=(idx == self._sel_index), has_bg_color=False)
87
88
  # fmt: off
@@ -180,8 +181,8 @@ class TUIMenuItem(TUIMenu):
180
181
  self.write(f"{keystroke.value if keystroke else ''}")
181
182
  index_len += 1
182
183
  # Erase the index typed by the user
183
- self.cursor.move(index_len, TUIScreen.CursorDirection.LEFT)
184
- self.cursor.erase(TUIScreen.CursorDirection.RIGHT)
184
+ self.cursor.move(index_len, Cursor.Direction.LEFT)
185
+ self.cursor.erase(Cursor.Direction.RIGHT)
185
186
  if typed_index and 1 <= int(typed_index) <= length:
186
187
  self._show_to = max(int(typed_index), self._diff_index)
187
188
  self._show_from = self._show_to - self._diff_index
@@ -12,13 +12,11 @@
12
12
 
13
13
  Copyright 2023, HsPyLib team
14
14
  """
15
-
15
+ from clitt.core.term.terminal import Terminal
16
16
  from clitt.core.tui.menu.tui_menu import TUIMenu
17
17
  from clitt.core.tui.tui_preferences import TUIPreferences
18
- from clitt.core.tui.tui_screen import TUIScreen
19
18
  from hspylib.core.metaclass.singleton import Singleton
20
19
  from hspylib.core.preconditions import check_not_none
21
- from hspylib.modules.cli.vt100.vt_utils import set_auto_wrap, set_show_cursor
22
20
 
23
21
 
24
22
  class TUIMenuUi(metaclass=Singleton):
@@ -29,9 +27,9 @@ class TUIMenuUi(metaclass=Singleton):
29
27
  APP_TITLE = "Main Menu"
30
28
 
31
29
  # fmt: off
32
- PREFS = TUIPreferences.INSTANCE or TUIPreferences()
30
+ PREFS = TUIPreferences.INSTANCE
33
31
 
34
- SCREEN = TUIScreen.INSTANCE or TUIScreen()
32
+ SCREEN = Terminal.INSTANCE.screen
35
33
 
36
34
  MENU_LINE = f"{'--' * PREFS.title_line_length}"
37
35
 
@@ -89,8 +87,8 @@ class TUIMenuUi(metaclass=Singleton):
89
87
 
90
88
  def _prepare_render(self, auto_wrap: bool = True, show_cursor: bool = False, clear_screen: bool = True) -> None:
91
89
  """Prepare the screen for renderization."""
92
- set_auto_wrap(auto_wrap)
93
- set_show_cursor(show_cursor)
90
+ Terminal.set_auto_wrap(auto_wrap)
91
+ Terminal.set_show_cursor(show_cursor)
94
92
  if clear_screen:
95
93
  self.SCREEN.clear()
96
94
  self.SCREEN.cursor.save()
@@ -12,10 +12,9 @@
12
12
 
13
13
  Copyright 2023, HsPyLib team
14
14
  """
15
-
15
+ from clitt.core.term.cursor import Cursor
16
16
  from clitt.core.tui.menu.tui_menu import ON_TRIGGER_CB, TUIMenu
17
17
  from clitt.core.tui.menu.tui_menu_ui import TUIMenuUi
18
- from clitt.core.tui.tui_screen import TUIScreen
19
18
  from typing import Callable, Optional
20
19
 
21
20
 
@@ -53,6 +52,6 @@ class TUIMenuView(TUIMenu):
53
52
  self.draw_navbar(self.navbar())
54
53
 
55
54
  def _display_content(self) -> None:
56
- self.cursor.erase(TUIScreen.CursorDirection.DOWN)
55
+ self.cursor.erase(Cursor.Direction.DOWN)
57
56
  self.writeln(self._content)
58
57
  self.wait_keystroke()
@@ -1,6 +1,6 @@
1
1
  # _*_ coding: utf-8 _*_
2
2
  #
3
- # hspylib-clitt v0.9.41
3
+ # hspylib-clitt v0.9.51
4
4
  #
5
5
  # Package: main.clitt.core.tui.minput
6
6
  """Package initialization."""
@@ -16,4 +16,4 @@ __all__ = [
16
16
  'minput',
17
17
  'minput_utils'
18
18
  ]
19
- __version__ = '0.9.41'
19
+ __version__ = '0.9.51'
@@ -12,23 +12,25 @@
12
12
 
13
13
  Copyright 2023, HsPyLib team
14
14
  """
15
+ from functools import reduce
16
+ from time import sleep
17
+ from typing import List
18
+
19
+ import pyperclip
20
+ from hspylib.core.exception.exceptions import InvalidStateError
21
+ from hspylib.core.namespace import Namespace
22
+ from hspylib.modules.cli.keyboard import Keyboard
23
+
15
24
  from clitt.core.icons.font_awesome.form_icons import FormIcons
16
25
  from clitt.core.icons.font_awesome.nav_icons import NavIcons
26
+ from clitt.core.term.commons import get_cursor_position
27
+ from clitt.core.term.cursor import Cursor
28
+ from clitt.core.term.terminal import Terminal
17
29
  from clitt.core.tui.minput.form_builder import FormBuilder
18
30
  from clitt.core.tui.minput.form_field import FormField
19
31
  from clitt.core.tui.minput.input_type import InputType
20
32
  from clitt.core.tui.minput.minput_utils import *
21
33
  from clitt.core.tui.tui_component import TUIComponent
22
- from clitt.core.tui.tui_screen import TUIScreen
23
- from functools import reduce
24
- from hspylib.core.exception.exceptions import InvalidStateError
25
- from hspylib.core.namespace import Namespace
26
- from hspylib.modules.cli.keyboard import Keyboard
27
- from hspylib.modules.cli.vt100.vt_utils import get_cursor_position, set_enable_echo, set_show_cursor
28
- from time import sleep
29
- from typing import List
30
-
31
- import pyperclip
32
34
 
33
35
 
34
36
  class MenuInput(TUIComponent):
@@ -73,7 +75,7 @@ class MenuInput(TUIComponent):
73
75
  return None
74
76
 
75
77
  def render(self) -> None:
76
- set_show_cursor(False)
78
+ Terminal.set_show_cursor(False)
77
79
  self.cursor.restore()
78
80
  self.writeln(f"{self.prefs.title_color.placeholder}{self.title}%EOL%%NC%")
79
81
 
@@ -93,7 +95,7 @@ class MenuInput(TUIComponent):
93
95
  self.draw_navbar(self.navbar())
94
96
  self._re_render = False
95
97
  self._set_cursor_pos()
96
- set_show_cursor()
98
+ Terminal.set_show_cursor()
97
99
 
98
100
  def navbar(self, **kwargs) -> str:
99
101
  return (
@@ -266,7 +268,9 @@ class MenuInput(TUIComponent):
266
268
  :param field_index: the current form field index.
267
269
  :param field_size: the form field length.
268
270
  """
269
- if f_pos := get_cursor_position() if self.positions[field_index] == (0, 0) else self.positions[field_index]:
271
+ if f_pos := get_cursor_position() \
272
+ if self.positions[field_index] == (0, 0) \
273
+ else self.positions[field_index]:
270
274
  self.positions[field_index] = f_pos
271
275
  if self.tab_index == field_index:
272
276
  self.cur_row, self.cur_col = f_pos[0], f_pos[1] + field_size
@@ -275,17 +279,17 @@ class MenuInput(TUIComponent):
275
279
  """Display a form filling or submitting error.
276
280
  :param err_msg: the error message.
277
281
  """
278
- set_enable_echo(False)
279
- set_show_cursor(False)
282
+ Terminal.set_enable_echo(False)
283
+ Terminal.set_show_cursor(False)
280
284
  offset = 15 # Sum of minput used characters that are not related to the field.
281
285
  err_pos = offset + self.max_label_length + self.max_value_length + self.max_detail_length
282
286
  self.cursor.move_to(self.cur_row, err_pos)
283
287
  mi_print_err(self.screen, f"{FormIcons.ARROW_LEFT} {err_msg}")
284
288
  # This calculation gives a good delay amount based on the size of the message.
285
289
  sleep(max(2.0, int(len(err_msg) / 21)))
286
- set_enable_echo()
290
+ Terminal.set_enable_echo()
287
291
  # Erase the message after the timeout
288
292
  self.cursor.move_to(self.cur_row, err_pos)
289
- self.cursor.erase(TUIScreen.CursorDirection.RIGHT)
290
- set_show_cursor()
293
+ self.cursor.erase(Cursor.Direction.RIGHT)
294
+ Terminal.set_show_cursor()
291
295
  self._re_render = True
@@ -12,12 +12,13 @@
12
12
 
13
13
  Copyright 2023, HsPyLib team
14
14
  """
15
- from clitt.core.tui.tui_screen import TUIScreen
16
15
  from hspylib.core.exception.exceptions import InvalidInputError
17
16
  from typing import Any, Optional, Tuple
18
17
 
19
18
  import re
20
19
 
20
+ from clitt.core.term.screen import Screen
21
+
21
22
  MASK_SYMBOLS = ["#", "@", "%", "*"]
22
23
 
23
24
  VALUE_SEPARATORS = r"[|,;]"
@@ -33,7 +34,7 @@ def detail_len(field: Any) -> int:
33
34
  return 1 + (2 * max_len)
34
35
 
35
36
 
36
- def mi_print(screen: TUIScreen, text: str, prefix: str = None, field_len: int = 0, end: str = "") -> None:
37
+ def mi_print(screen: Screen, text: str, prefix: str = None, field_len: int = 0, end: str = "") -> None:
37
38
  """Special menu input print.
38
39
  :param screen: the component's screen.
39
40
  :param text: the text to be printed.
@@ -48,7 +49,7 @@ def mi_print(screen: TUIScreen, text: str, prefix: str = None, field_len: int =
48
49
  screen.cursor.write(fmt.format(text or ""), end=end)
49
50
 
50
51
 
51
- def mi_print_err(screen: TUIScreen, text: str) -> None:
52
+ def mi_print_err(screen: Screen, text: str) -> None:
52
53
  """Special menu input print error message.
53
54
  :param screen: the component's screen.
54
55
  :param text: the text to be printed.
@@ -1,6 +1,6 @@
1
1
  # _*_ coding: utf-8 _*_
2
2
  #
3
- # hspylib-clitt v0.9.41
3
+ # hspylib-clitt v0.9.51
4
4
  #
5
5
  # Package: main.clitt.core.tui.mselect
6
6
  """Package initialization."""
@@ -9,4 +9,4 @@ __all__ = [
9
9
  'menu_select',
10
10
  'mselect'
11
11
  ]
12
- __version__ = '0.9.41'
12
+ __version__ = '0.9.51'
@@ -13,8 +13,9 @@
13
13
  Copyright 2023, HsPyLib team
14
14
  """
15
15
  from clitt.core.icons.font_awesome.nav_icons import NavIcons
16
+ from clitt.core.term.cursor import Cursor
17
+ from clitt.core.term.screen import Screen
16
18
  from clitt.core.tui.tui_component import TUIComponent
17
- from clitt.core.tui.tui_screen import TUIScreen
18
19
  from functools import cached_property
19
20
  from hspylib.modules.cli.keyboard import Keyboard
20
21
  from typing import List, Optional, TypeVar
@@ -33,7 +34,7 @@ class MenuSelect(TUIComponent):
33
34
  super().__init__(title)
34
35
  self._items = items
35
36
  self._show_from = 0
36
- self._show_to = self.screen.rows - self.ROW_OFFSET
37
+ self._show_to = self.screen.lines - self.ROW_OFFSET
37
38
  self._diff_index = self._show_to - self._show_from
38
39
  self._sel_index = 0
39
40
  self._max_line_length = max(len(str(item)) for item in items)
@@ -67,7 +68,7 @@ class MenuSelect(TUIComponent):
67
68
  break # When the index is greater than the number of items, stop rendering
68
69
 
69
70
  option_line = str(self._items[idx])
70
- self.cursor.erase(TUIScreen.ScreenPortion.LINE)
71
+ self.cursor.erase(Screen.Portion.LINE)
71
72
  # Print the selector if the index is currently selected
72
73
  selector = self.draw_selector(idx == self._sel_index)
73
74
  # fmt: off
@@ -122,8 +123,8 @@ class MenuSelect(TUIComponent):
122
123
  self.cursor.write(f"{keystroke.value if keystroke else ''}")
123
124
  index_len += 1
124
125
  # Erase the index typed by the user
125
- self.cursor.move(index_len, TUIScreen.CursorDirection.LEFT)
126
- self.cursor.erase(TUIScreen.CursorDirection.RIGHT)
126
+ self.cursor.move(index_len, Cursor.Direction.LEFT)
127
+ self.cursor.erase(Cursor.Direction.RIGHT)
127
128
  if typed_index and 1 <= int(typed_index) <= length:
128
129
  self._show_to = max(int(typed_index), self._diff_index)
129
130
  self._show_from = self._show_to - self._diff_index
@@ -1,6 +1,6 @@
1
1
  # _*_ coding: utf-8 _*_
2
2
  #
3
- # hspylib-clitt v0.9.41
3
+ # hspylib-clitt v0.9.51
4
4
  #
5
5
  # Package: main.clitt.core.tui.table
6
6
  """Package initialization."""
@@ -9,4 +9,4 @@ __all__ = [
9
9
  'table_enums',
10
10
  'table_renderer'
11
11
  ]
12
- __version__ = '0.9.41'
12
+ __version__ = '0.9.51'