hspylib-clitt 0.9.118__py3-none-any.whl → 0.9.119__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 (344) hide show
  1. build/lib/build/lib/build/lib/build/lib/clitt/__classpath__.py +28 -0
  2. build/lib/build/lib/build/lib/build/lib/clitt/__init__.py +13 -0
  3. build/lib/build/lib/build/lib/build/lib/clitt/__main__.py +139 -0
  4. build/lib/build/lib/build/lib/build/lib/clitt/addons/__init__.py +12 -0
  5. build/lib/build/lib/build/lib/build/lib/clitt/addons/appman/__init__.py +13 -0
  6. build/lib/build/lib/build/lib/build/lib/clitt/addons/appman/appman.py +305 -0
  7. build/lib/build/lib/build/lib/build/lib/clitt/addons/appman/appman_enums.py +39 -0
  8. build/lib/build/lib/build/lib/build/lib/clitt/addons/appman/templates/__init__.py +11 -0
  9. build/lib/build/lib/build/lib/build/lib/clitt/addons/widman/__init__.py +14 -0
  10. build/lib/build/lib/build/lib/build/lib/clitt/addons/widman/widget.py +70 -0
  11. build/lib/build/lib/build/lib/build/lib/clitt/addons/widman/widget_entry.py +54 -0
  12. build/lib/build/lib/build/lib/build/lib/clitt/addons/widman/widgets/__init__.py +14 -0
  13. build/lib/build/lib/build/lib/build/lib/clitt/addons/widman/widgets/widget_free.py +110 -0
  14. build/lib/build/lib/build/lib/build/lib/clitt/addons/widman/widgets/widget_punch.py +246 -0
  15. build/lib/build/lib/build/lib/build/lib/clitt/addons/widman/widgets/widget_send_msg.py +272 -0
  16. build/lib/build/lib/build/lib/build/lib/clitt/addons/widman/widgets/widget_time_calc.py +146 -0
  17. build/lib/build/lib/build/lib/build/lib/clitt/addons/widman/widman.py +123 -0
  18. build/lib/build/lib/build/lib/build/lib/clitt/core/__init__.py +15 -0
  19. build/lib/build/lib/build/lib/build/lib/clitt/core/exception/__init__.py +11 -0
  20. build/lib/build/lib/build/lib/build/lib/clitt/core/exception/exceptions.py +19 -0
  21. build/lib/build/lib/build/lib/build/lib/clitt/core/icons/__init__.py +12 -0
  22. build/lib/build/lib/build/lib/build/lib/clitt/core/icons/emojis/__init__.py +12 -0
  23. build/lib/build/lib/build/lib/build/lib/clitt/core/icons/emojis/emojis.py +41 -0
  24. build/lib/build/lib/build/lib/build/lib/clitt/core/icons/emojis/face_smiling.py +40 -0
  25. build/lib/build/lib/build/lib/build/lib/clitt/core/icons/font_awesome/__init__.py +18 -0
  26. build/lib/build/lib/build/lib/build/lib/clitt/core/icons/font_awesome/app_icons.py +55 -0
  27. build/lib/build/lib/build/lib/build/lib/clitt/core/icons/font_awesome/awesome.py +76 -0
  28. build/lib/build/lib/build/lib/build/lib/clitt/core/icons/font_awesome/dashboard_icons.py +93 -0
  29. build/lib/build/lib/build/lib/build/lib/clitt/core/icons/font_awesome/form_icons.py +69 -0
  30. build/lib/build/lib/build/lib/build/lib/clitt/core/icons/font_awesome/game_icons.py +59 -0
  31. build/lib/build/lib/build/lib/build/lib/clitt/core/icons/font_awesome/nav_icons.py +42 -0
  32. build/lib/build/lib/build/lib/build/lib/clitt/core/icons/font_awesome/trickplay_icons.py +39 -0
  33. build/lib/build/lib/build/lib/build/lib/clitt/core/icons/font_awesome/widget_icons.py +37 -0
  34. build/lib/build/lib/build/lib/build/lib/clitt/core/preferences.py +87 -0
  35. build/lib/build/lib/build/lib/build/lib/clitt/core/term/__init__.py +14 -0
  36. build/lib/build/lib/build/lib/build/lib/clitt/core/term/commons.py +106 -0
  37. build/lib/build/lib/build/lib/build/lib/clitt/core/term/cursor.py +174 -0
  38. build/lib/build/lib/build/lib/build/lib/clitt/core/term/screen.py +106 -0
  39. build/lib/build/lib/build/lib/build/lib/clitt/core/term/terminal.py +202 -0
  40. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/__init__.py +20 -0
  41. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/line_input/__init__.py +12 -0
  42. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/line_input/keyboard_input.py +229 -0
  43. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/line_input/line_input.py +31 -0
  44. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/mchoose/__init__.py +12 -0
  45. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/mchoose/mchoose.py +43 -0
  46. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/mchoose/menu_choose.py +192 -0
  47. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/mdashboard/__init__.py +14 -0
  48. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/mdashboard/dashboard_builder.py +54 -0
  49. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/mdashboard/dashboard_item.py +31 -0
  50. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/mdashboard/mdashboard.py +26 -0
  51. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/mdashboard/menu_dashboard.py +148 -0
  52. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/menu/__init__.py +16 -0
  53. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/menu/tui_menu.py +111 -0
  54. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/menu/tui_menu_action.py +47 -0
  55. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/menu/tui_menu_factory.py +117 -0
  56. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/menu/tui_menu_item.py +196 -0
  57. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/menu/tui_menu_ui.py +98 -0
  58. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/menu/tui_menu_view.py +57 -0
  59. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/minput/__init__.py +19 -0
  60. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/minput/access_type.py +26 -0
  61. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/minput/field_builder.py +117 -0
  62. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/minput/form_builder.py +72 -0
  63. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/minput/form_field.py +180 -0
  64. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/minput/input_type.py +30 -0
  65. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/minput/input_validator.py +98 -0
  66. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/minput/menu_input.py +292 -0
  67. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/minput/minput.py +44 -0
  68. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/minput/minput_utils.py +156 -0
  69. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/mselect/__init__.py +12 -0
  70. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/mselect/menu_select.py +170 -0
  71. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/mselect/mselect.py +36 -0
  72. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/table/__init__.py +12 -0
  73. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/table/table_enums.py +47 -0
  74. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/table/table_renderer.py +339 -0
  75. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/tui_application.py +52 -0
  76. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/tui_component.py +154 -0
  77. build/lib/build/lib/build/lib/build/lib/clitt/core/tui/tui_preferences.py +103 -0
  78. build/lib/build/lib/build/lib/build/lib/clitt/utils/__init__.py +11 -0
  79. build/lib/build/lib/build/lib/build/lib/clitt/utils/git_utils.py +66 -0
  80. build/lib/build/lib/build/lib/clitt/__classpath__.py +28 -0
  81. build/lib/build/lib/build/lib/clitt/__init__.py +13 -0
  82. build/lib/build/lib/build/lib/clitt/__main__.py +139 -0
  83. build/lib/build/lib/build/lib/clitt/addons/__init__.py +12 -0
  84. build/lib/build/lib/build/lib/clitt/addons/appman/__init__.py +13 -0
  85. build/lib/build/lib/build/lib/clitt/addons/appman/appman.py +305 -0
  86. build/lib/build/lib/build/lib/clitt/addons/appman/appman_enums.py +39 -0
  87. build/lib/build/lib/build/lib/clitt/addons/appman/templates/__init__.py +11 -0
  88. build/lib/build/lib/build/lib/clitt/addons/widman/__init__.py +14 -0
  89. build/lib/build/lib/build/lib/clitt/addons/widman/widget.py +70 -0
  90. build/lib/build/lib/build/lib/clitt/addons/widman/widget_entry.py +54 -0
  91. build/lib/build/lib/build/lib/clitt/addons/widman/widgets/__init__.py +14 -0
  92. build/lib/build/lib/build/lib/clitt/addons/widman/widgets/widget_free.py +110 -0
  93. build/lib/build/lib/build/lib/clitt/addons/widman/widgets/widget_punch.py +246 -0
  94. build/lib/build/lib/build/lib/clitt/addons/widman/widgets/widget_send_msg.py +272 -0
  95. build/lib/build/lib/build/lib/clitt/addons/widman/widgets/widget_time_calc.py +146 -0
  96. build/lib/build/lib/build/lib/clitt/addons/widman/widman.py +123 -0
  97. build/lib/build/lib/build/lib/clitt/core/__init__.py +15 -0
  98. build/lib/build/lib/build/lib/clitt/core/exception/__init__.py +11 -0
  99. build/lib/build/lib/build/lib/clitt/core/exception/exceptions.py +19 -0
  100. build/lib/build/lib/build/lib/clitt/core/icons/__init__.py +12 -0
  101. build/lib/build/lib/build/lib/clitt/core/icons/emojis/__init__.py +12 -0
  102. build/lib/build/lib/build/lib/clitt/core/icons/emojis/emojis.py +41 -0
  103. build/lib/build/lib/build/lib/clitt/core/icons/emojis/face_smiling.py +40 -0
  104. build/lib/build/lib/build/lib/clitt/core/icons/font_awesome/__init__.py +18 -0
  105. build/lib/build/lib/build/lib/clitt/core/icons/font_awesome/app_icons.py +55 -0
  106. build/lib/build/lib/build/lib/clitt/core/icons/font_awesome/awesome.py +76 -0
  107. build/lib/build/lib/build/lib/clitt/core/icons/font_awesome/dashboard_icons.py +93 -0
  108. build/lib/build/lib/build/lib/clitt/core/icons/font_awesome/form_icons.py +69 -0
  109. build/lib/build/lib/build/lib/clitt/core/icons/font_awesome/game_icons.py +59 -0
  110. build/lib/build/lib/build/lib/clitt/core/icons/font_awesome/nav_icons.py +42 -0
  111. build/lib/build/lib/build/lib/clitt/core/icons/font_awesome/trickplay_icons.py +39 -0
  112. build/lib/build/lib/build/lib/clitt/core/icons/font_awesome/widget_icons.py +37 -0
  113. build/lib/build/lib/build/lib/clitt/core/preferences.py +87 -0
  114. build/lib/build/lib/build/lib/clitt/core/term/__init__.py +14 -0
  115. build/lib/build/lib/build/lib/clitt/core/term/commons.py +106 -0
  116. build/lib/build/lib/build/lib/clitt/core/term/cursor.py +174 -0
  117. build/lib/build/lib/build/lib/clitt/core/term/screen.py +106 -0
  118. build/lib/build/lib/build/lib/clitt/core/term/terminal.py +202 -0
  119. build/lib/build/lib/build/lib/clitt/core/tui/__init__.py +20 -0
  120. build/lib/build/lib/build/lib/clitt/core/tui/line_input/__init__.py +12 -0
  121. build/lib/build/lib/build/lib/clitt/core/tui/line_input/keyboard_input.py +229 -0
  122. build/lib/build/lib/build/lib/clitt/core/tui/line_input/line_input.py +31 -0
  123. build/lib/build/lib/build/lib/clitt/core/tui/mchoose/__init__.py +12 -0
  124. build/lib/build/lib/build/lib/clitt/core/tui/mchoose/mchoose.py +43 -0
  125. build/lib/build/lib/build/lib/clitt/core/tui/mchoose/menu_choose.py +192 -0
  126. build/lib/build/lib/build/lib/clitt/core/tui/mdashboard/__init__.py +14 -0
  127. build/lib/build/lib/build/lib/clitt/core/tui/mdashboard/dashboard_builder.py +54 -0
  128. build/lib/build/lib/build/lib/clitt/core/tui/mdashboard/dashboard_item.py +31 -0
  129. build/lib/build/lib/build/lib/clitt/core/tui/mdashboard/mdashboard.py +26 -0
  130. build/lib/build/lib/build/lib/clitt/core/tui/mdashboard/menu_dashboard.py +148 -0
  131. build/lib/build/lib/build/lib/clitt/core/tui/menu/__init__.py +16 -0
  132. build/lib/build/lib/build/lib/clitt/core/tui/menu/tui_menu.py +111 -0
  133. build/lib/build/lib/build/lib/clitt/core/tui/menu/tui_menu_action.py +47 -0
  134. build/lib/build/lib/build/lib/clitt/core/tui/menu/tui_menu_factory.py +117 -0
  135. build/lib/build/lib/build/lib/clitt/core/tui/menu/tui_menu_item.py +196 -0
  136. build/lib/build/lib/build/lib/clitt/core/tui/menu/tui_menu_ui.py +98 -0
  137. build/lib/build/lib/build/lib/clitt/core/tui/menu/tui_menu_view.py +57 -0
  138. build/lib/build/lib/build/lib/clitt/core/tui/minput/__init__.py +19 -0
  139. build/lib/build/lib/build/lib/clitt/core/tui/minput/access_type.py +26 -0
  140. build/lib/build/lib/build/lib/clitt/core/tui/minput/field_builder.py +117 -0
  141. build/lib/build/lib/build/lib/clitt/core/tui/minput/form_builder.py +72 -0
  142. build/lib/build/lib/build/lib/clitt/core/tui/minput/form_field.py +180 -0
  143. build/lib/build/lib/build/lib/clitt/core/tui/minput/input_type.py +30 -0
  144. build/lib/build/lib/build/lib/clitt/core/tui/minput/input_validator.py +98 -0
  145. build/lib/build/lib/build/lib/clitt/core/tui/minput/menu_input.py +292 -0
  146. build/lib/build/lib/build/lib/clitt/core/tui/minput/minput.py +44 -0
  147. build/lib/build/lib/build/lib/clitt/core/tui/minput/minput_utils.py +156 -0
  148. build/lib/build/lib/build/lib/clitt/core/tui/mselect/__init__.py +12 -0
  149. build/lib/build/lib/build/lib/clitt/core/tui/mselect/menu_select.py +170 -0
  150. build/lib/build/lib/build/lib/clitt/core/tui/mselect/mselect.py +36 -0
  151. build/lib/build/lib/build/lib/clitt/core/tui/table/__init__.py +12 -0
  152. build/lib/build/lib/build/lib/clitt/core/tui/table/table_enums.py +47 -0
  153. build/lib/build/lib/build/lib/clitt/core/tui/table/table_renderer.py +339 -0
  154. build/lib/build/lib/build/lib/clitt/core/tui/tui_application.py +52 -0
  155. build/lib/build/lib/build/lib/clitt/core/tui/tui_component.py +154 -0
  156. build/lib/build/lib/build/lib/clitt/core/tui/tui_preferences.py +103 -0
  157. build/lib/build/lib/build/lib/clitt/utils/__init__.py +11 -0
  158. build/lib/build/lib/build/lib/clitt/utils/git_utils.py +66 -0
  159. build/lib/build/lib/clitt/__classpath__.py +28 -0
  160. build/lib/build/lib/clitt/__init__.py +13 -0
  161. build/lib/build/lib/clitt/__main__.py +139 -0
  162. build/lib/build/lib/clitt/addons/__init__.py +12 -0
  163. build/lib/build/lib/clitt/addons/appman/__init__.py +13 -0
  164. build/lib/build/lib/clitt/addons/appman/appman.py +305 -0
  165. build/lib/build/lib/clitt/addons/appman/appman_enums.py +39 -0
  166. build/lib/build/lib/clitt/addons/appman/templates/__init__.py +11 -0
  167. build/lib/build/lib/clitt/addons/widman/__init__.py +14 -0
  168. build/lib/build/lib/clitt/addons/widman/widget.py +70 -0
  169. build/lib/build/lib/clitt/addons/widman/widget_entry.py +54 -0
  170. build/lib/build/lib/clitt/addons/widman/widgets/__init__.py +14 -0
  171. build/lib/build/lib/clitt/addons/widman/widgets/widget_free.py +110 -0
  172. build/lib/build/lib/clitt/addons/widman/widgets/widget_punch.py +246 -0
  173. build/lib/build/lib/clitt/addons/widman/widgets/widget_send_msg.py +272 -0
  174. build/lib/build/lib/clitt/addons/widman/widgets/widget_time_calc.py +146 -0
  175. build/lib/build/lib/clitt/addons/widman/widman.py +123 -0
  176. build/lib/build/lib/clitt/core/__init__.py +15 -0
  177. build/lib/build/lib/clitt/core/exception/__init__.py +11 -0
  178. build/lib/build/lib/clitt/core/exception/exceptions.py +19 -0
  179. build/lib/build/lib/clitt/core/icons/__init__.py +12 -0
  180. build/lib/build/lib/clitt/core/icons/emojis/__init__.py +12 -0
  181. build/lib/build/lib/clitt/core/icons/emojis/emojis.py +41 -0
  182. build/lib/build/lib/clitt/core/icons/emojis/face_smiling.py +40 -0
  183. build/lib/build/lib/clitt/core/icons/font_awesome/__init__.py +18 -0
  184. build/lib/build/lib/clitt/core/icons/font_awesome/app_icons.py +55 -0
  185. build/lib/build/lib/clitt/core/icons/font_awesome/awesome.py +76 -0
  186. build/lib/build/lib/clitt/core/icons/font_awesome/dashboard_icons.py +93 -0
  187. build/lib/build/lib/clitt/core/icons/font_awesome/form_icons.py +69 -0
  188. build/lib/build/lib/clitt/core/icons/font_awesome/game_icons.py +59 -0
  189. build/lib/build/lib/clitt/core/icons/font_awesome/nav_icons.py +42 -0
  190. build/lib/build/lib/clitt/core/icons/font_awesome/trickplay_icons.py +39 -0
  191. build/lib/build/lib/clitt/core/icons/font_awesome/widget_icons.py +37 -0
  192. build/lib/build/lib/clitt/core/preferences.py +87 -0
  193. build/lib/build/lib/clitt/core/term/__init__.py +14 -0
  194. build/lib/build/lib/clitt/core/term/commons.py +106 -0
  195. build/lib/build/lib/clitt/core/term/cursor.py +174 -0
  196. build/lib/build/lib/clitt/core/term/screen.py +106 -0
  197. build/lib/build/lib/clitt/core/term/terminal.py +202 -0
  198. build/lib/build/lib/clitt/core/tui/__init__.py +20 -0
  199. build/lib/build/lib/clitt/core/tui/line_input/__init__.py +12 -0
  200. build/lib/build/lib/clitt/core/tui/line_input/keyboard_input.py +229 -0
  201. build/lib/build/lib/clitt/core/tui/line_input/line_input.py +31 -0
  202. build/lib/build/lib/clitt/core/tui/mchoose/__init__.py +12 -0
  203. build/lib/build/lib/clitt/core/tui/mchoose/mchoose.py +43 -0
  204. build/lib/build/lib/clitt/core/tui/mchoose/menu_choose.py +192 -0
  205. build/lib/build/lib/clitt/core/tui/mdashboard/__init__.py +14 -0
  206. build/lib/build/lib/clitt/core/tui/mdashboard/dashboard_builder.py +54 -0
  207. build/lib/build/lib/clitt/core/tui/mdashboard/dashboard_item.py +31 -0
  208. build/lib/build/lib/clitt/core/tui/mdashboard/mdashboard.py +26 -0
  209. build/lib/build/lib/clitt/core/tui/mdashboard/menu_dashboard.py +148 -0
  210. build/lib/build/lib/clitt/core/tui/menu/__init__.py +16 -0
  211. build/lib/build/lib/clitt/core/tui/menu/tui_menu.py +111 -0
  212. build/lib/build/lib/clitt/core/tui/menu/tui_menu_action.py +47 -0
  213. build/lib/build/lib/clitt/core/tui/menu/tui_menu_factory.py +117 -0
  214. build/lib/build/lib/clitt/core/tui/menu/tui_menu_item.py +196 -0
  215. build/lib/build/lib/clitt/core/tui/menu/tui_menu_ui.py +98 -0
  216. build/lib/build/lib/clitt/core/tui/menu/tui_menu_view.py +57 -0
  217. build/lib/build/lib/clitt/core/tui/minput/__init__.py +19 -0
  218. build/lib/build/lib/clitt/core/tui/minput/access_type.py +26 -0
  219. build/lib/build/lib/clitt/core/tui/minput/field_builder.py +117 -0
  220. build/lib/build/lib/clitt/core/tui/minput/form_builder.py +72 -0
  221. build/lib/build/lib/clitt/core/tui/minput/form_field.py +180 -0
  222. build/lib/build/lib/clitt/core/tui/minput/input_type.py +30 -0
  223. build/lib/build/lib/clitt/core/tui/minput/input_validator.py +98 -0
  224. build/lib/build/lib/clitt/core/tui/minput/menu_input.py +292 -0
  225. build/lib/build/lib/clitt/core/tui/minput/minput.py +44 -0
  226. build/lib/build/lib/clitt/core/tui/minput/minput_utils.py +156 -0
  227. build/lib/build/lib/clitt/core/tui/mselect/__init__.py +12 -0
  228. build/lib/build/lib/clitt/core/tui/mselect/menu_select.py +170 -0
  229. build/lib/build/lib/clitt/core/tui/mselect/mselect.py +36 -0
  230. build/lib/build/lib/clitt/core/tui/table/__init__.py +12 -0
  231. build/lib/build/lib/clitt/core/tui/table/table_enums.py +47 -0
  232. build/lib/build/lib/clitt/core/tui/table/table_renderer.py +339 -0
  233. build/lib/build/lib/clitt/core/tui/tui_application.py +52 -0
  234. build/lib/build/lib/clitt/core/tui/tui_component.py +154 -0
  235. build/lib/build/lib/clitt/core/tui/tui_preferences.py +103 -0
  236. build/lib/build/lib/clitt/utils/__init__.py +11 -0
  237. build/lib/build/lib/clitt/utils/git_utils.py +66 -0
  238. build/lib/clitt/__classpath__.py +28 -0
  239. build/lib/clitt/__init__.py +13 -0
  240. build/lib/clitt/__main__.py +139 -0
  241. build/lib/clitt/addons/__init__.py +12 -0
  242. build/lib/clitt/addons/appman/__init__.py +13 -0
  243. build/lib/clitt/addons/appman/appman.py +305 -0
  244. build/lib/clitt/addons/appman/appman_enums.py +39 -0
  245. build/lib/clitt/addons/appman/templates/__init__.py +11 -0
  246. build/lib/clitt/addons/widman/__init__.py +14 -0
  247. build/lib/clitt/addons/widman/widget.py +70 -0
  248. build/lib/clitt/addons/widman/widget_entry.py +54 -0
  249. build/lib/clitt/addons/widman/widgets/__init__.py +14 -0
  250. build/lib/clitt/addons/widman/widgets/widget_free.py +110 -0
  251. build/lib/clitt/addons/widman/widgets/widget_punch.py +246 -0
  252. build/lib/clitt/addons/widman/widgets/widget_send_msg.py +272 -0
  253. build/lib/clitt/addons/widman/widgets/widget_time_calc.py +146 -0
  254. build/lib/clitt/addons/widman/widman.py +123 -0
  255. build/lib/clitt/core/__init__.py +15 -0
  256. build/lib/clitt/core/exception/__init__.py +11 -0
  257. build/lib/clitt/core/exception/exceptions.py +19 -0
  258. build/lib/clitt/core/icons/__init__.py +12 -0
  259. build/lib/clitt/core/icons/emojis/__init__.py +12 -0
  260. build/lib/clitt/core/icons/emojis/emojis.py +41 -0
  261. build/lib/clitt/core/icons/emojis/face_smiling.py +40 -0
  262. build/lib/clitt/core/icons/font_awesome/__init__.py +18 -0
  263. build/lib/clitt/core/icons/font_awesome/app_icons.py +55 -0
  264. build/lib/clitt/core/icons/font_awesome/awesome.py +76 -0
  265. build/lib/clitt/core/icons/font_awesome/dashboard_icons.py +93 -0
  266. build/lib/clitt/core/icons/font_awesome/form_icons.py +69 -0
  267. build/lib/clitt/core/icons/font_awesome/game_icons.py +59 -0
  268. build/lib/clitt/core/icons/font_awesome/nav_icons.py +42 -0
  269. build/lib/clitt/core/icons/font_awesome/trickplay_icons.py +39 -0
  270. build/lib/clitt/core/icons/font_awesome/widget_icons.py +37 -0
  271. build/lib/clitt/core/preferences.py +87 -0
  272. build/lib/clitt/core/term/__init__.py +14 -0
  273. build/lib/clitt/core/term/commons.py +106 -0
  274. build/lib/clitt/core/term/cursor.py +174 -0
  275. build/lib/clitt/core/term/screen.py +106 -0
  276. build/lib/clitt/core/term/terminal.py +202 -0
  277. build/lib/clitt/core/tui/__init__.py +20 -0
  278. build/lib/clitt/core/tui/line_input/__init__.py +12 -0
  279. build/lib/clitt/core/tui/line_input/keyboard_input.py +229 -0
  280. build/lib/clitt/core/tui/line_input/line_input.py +31 -0
  281. build/lib/clitt/core/tui/mchoose/__init__.py +12 -0
  282. build/lib/clitt/core/tui/mchoose/mchoose.py +43 -0
  283. build/lib/clitt/core/tui/mchoose/menu_choose.py +192 -0
  284. build/lib/clitt/core/tui/mdashboard/__init__.py +14 -0
  285. build/lib/clitt/core/tui/mdashboard/dashboard_builder.py +54 -0
  286. build/lib/clitt/core/tui/mdashboard/dashboard_item.py +31 -0
  287. build/lib/clitt/core/tui/mdashboard/mdashboard.py +26 -0
  288. build/lib/clitt/core/tui/mdashboard/menu_dashboard.py +148 -0
  289. build/lib/clitt/core/tui/menu/__init__.py +16 -0
  290. build/lib/clitt/core/tui/menu/tui_menu.py +111 -0
  291. build/lib/clitt/core/tui/menu/tui_menu_action.py +47 -0
  292. build/lib/clitt/core/tui/menu/tui_menu_factory.py +117 -0
  293. build/lib/clitt/core/tui/menu/tui_menu_item.py +196 -0
  294. build/lib/clitt/core/tui/menu/tui_menu_ui.py +98 -0
  295. build/lib/clitt/core/tui/menu/tui_menu_view.py +57 -0
  296. build/lib/clitt/core/tui/minput/__init__.py +19 -0
  297. build/lib/clitt/core/tui/minput/access_type.py +26 -0
  298. build/lib/clitt/core/tui/minput/field_builder.py +117 -0
  299. build/lib/clitt/core/tui/minput/form_builder.py +72 -0
  300. build/lib/clitt/core/tui/minput/form_field.py +180 -0
  301. build/lib/clitt/core/tui/minput/input_type.py +30 -0
  302. build/lib/clitt/core/tui/minput/input_validator.py +98 -0
  303. build/lib/clitt/core/tui/minput/menu_input.py +292 -0
  304. build/lib/clitt/core/tui/minput/minput.py +44 -0
  305. build/lib/clitt/core/tui/minput/minput_utils.py +156 -0
  306. build/lib/clitt/core/tui/mselect/__init__.py +12 -0
  307. build/lib/clitt/core/tui/mselect/menu_select.py +170 -0
  308. build/lib/clitt/core/tui/mselect/mselect.py +36 -0
  309. build/lib/clitt/core/tui/table/__init__.py +12 -0
  310. build/lib/clitt/core/tui/table/table_enums.py +47 -0
  311. build/lib/clitt/core/tui/table/table_renderer.py +339 -0
  312. build/lib/clitt/core/tui/tui_application.py +52 -0
  313. build/lib/clitt/core/tui/tui_component.py +154 -0
  314. build/lib/clitt/core/tui/tui_preferences.py +103 -0
  315. build/lib/clitt/utils/__init__.py +11 -0
  316. build/lib/clitt/utils/git_utils.py +66 -0
  317. clitt/.version +1 -1
  318. clitt/__init__.py +3 -3
  319. clitt/addons/__init__.py +3 -3
  320. clitt/addons/appman/__init__.py +3 -3
  321. clitt/addons/appman/templates/__init__.py +3 -3
  322. clitt/addons/widman/__init__.py +3 -3
  323. clitt/addons/widman/widgets/__init__.py +3 -3
  324. clitt/core/__init__.py +3 -3
  325. clitt/core/exception/__init__.py +3 -3
  326. clitt/core/icons/__init__.py +3 -3
  327. clitt/core/icons/emojis/__init__.py +3 -3
  328. clitt/core/icons/font_awesome/__init__.py +3 -3
  329. clitt/core/term/__init__.py +3 -3
  330. clitt/core/term/commons.py +11 -12
  331. clitt/core/tui/__init__.py +3 -3
  332. clitt/core/tui/line_input/__init__.py +3 -3
  333. clitt/core/tui/mchoose/__init__.py +3 -3
  334. clitt/core/tui/mdashboard/__init__.py +3 -3
  335. clitt/core/tui/menu/__init__.py +3 -3
  336. clitt/core/tui/minput/__init__.py +3 -3
  337. clitt/core/tui/mselect/__init__.py +3 -3
  338. clitt/core/tui/table/__init__.py +3 -3
  339. clitt/utils/__init__.py +3 -3
  340. {hspylib_clitt-0.9.118.dist-info → hspylib_clitt-0.9.119.dist-info}/METADATA +2 -2
  341. hspylib_clitt-0.9.119.dist-info/RECORD +413 -0
  342. {hspylib_clitt-0.9.118.dist-info → hspylib_clitt-0.9.119.dist-info}/top_level.txt +1 -0
  343. hspylib_clitt-0.9.118.dist-info/RECORD +0 -97
  344. {hspylib_clitt-0.9.118.dist-info → hspylib_clitt-0.9.119.dist-info}/WHEEL +0 -0
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ @project: HsPyLib
6
+ @package: clitt.core.tui.minput
7
+ @file: input_validator.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
+
16
+ from hspylib.core.enums.enumeration import Enumeration
17
+ from hspylib.core.tools.validator import Validator
18
+
19
+ import re
20
+
21
+
22
+ class InputValidator(Validator):
23
+ """MenuInput 'input' validator."""
24
+
25
+ class PatternType(Enumeration):
26
+ # fmt: off
27
+ CUSTOM = r'' # It will be set later
28
+ ANYTHING = r'.'
29
+ LETTERS = r'[a-zA-Z]'
30
+ WORDS = r'[a-zA-Z0-9 _]'
31
+ NUMBERS = r'[0-9\.\,]'
32
+ MASKED = r'[a-zA-Z0-9]'
33
+ # fmt: on
34
+
35
+ @classmethod
36
+ def custom(cls, pattern: str) -> "InputValidator":
37
+ """Return a custom validator that allows customize the input rules.
38
+ :param pattern: the custom validator pattern.
39
+ """
40
+ pattern_type = cls.PatternType.CUSTOM
41
+ validator = InputValidator(pattern_type=pattern_type)
42
+ validator.pattern = pattern
43
+ return validator
44
+
45
+ @classmethod
46
+ def letters(cls) -> "InputValidator":
47
+ """Return a validator that allows only letters."""
48
+ return InputValidator(cls.PatternType.LETTERS)
49
+
50
+ @classmethod
51
+ def numbers(cls) -> "InputValidator":
52
+ """Return a validator that allows only numbers."""
53
+ return InputValidator(cls.PatternType.NUMBERS)
54
+
55
+ @classmethod
56
+ def words(cls) -> "InputValidator":
57
+ """Return a validator that allows only words (space, numbers or letters)."""
58
+ return InputValidator(cls.PatternType.WORDS)
59
+
60
+ @classmethod
61
+ def anything(cls) -> "InputValidator":
62
+ """Return a validator that allows any input value."""
63
+ return InputValidator(cls.PatternType.ANYTHING)
64
+
65
+ @classmethod
66
+ def masked(cls) -> "InputValidator":
67
+ """Return a validator that allows masked inputs."""
68
+ return InputValidator(cls.PatternType.MASKED)
69
+
70
+ def __init__(self, pattern_type: PatternType = PatternType.ANYTHING):
71
+ self._pattern_type = pattern_type
72
+ self._pattern = pattern_type.value
73
+
74
+ def __str__(self) -> str:
75
+ return f'r"{self.pattern}"' if self.pattern_type == self.PatternType.CUSTOM else self.pattern_type.name
76
+
77
+ def __repr__(self):
78
+ return str(self)
79
+
80
+ def __call__(self, *args, **kwargs) -> bool:
81
+ return all(self.validate(value) for value in args)
82
+
83
+ def validate(self, value: str) -> bool:
84
+ """Validate the value against the validator pattern."""
85
+ unmasked_value = re.split("[|,;]", value)[0] if value else ""
86
+ return bool(re.match(self.pattern, unmasked_value))
87
+
88
+ @property
89
+ def pattern(self) -> str:
90
+ return str(self._pattern)
91
+
92
+ @pattern.setter
93
+ def pattern(self, pattern: str) -> None:
94
+ self._pattern = rf"{pattern}"
95
+
96
+ @property
97
+ def pattern_type(self) -> PatternType:
98
+ return self._pattern_type
@@ -0,0 +1,292 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ @project: HsPyLib
6
+ @package: clitt.core.tui.minput
7
+ @file: menu_input.py
8
+ @created: Wed, 17 May 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 clitt.core.icons.font_awesome.form_icons import FormIcons
16
+ from clitt.core.icons.font_awesome.nav_icons import NavIcons
17
+ from clitt.core.term.commons import Direction, get_cursor_position
18
+ from clitt.core.term.terminal import Terminal
19
+ from clitt.core.tui.minput import minput_utils as mu
20
+ from clitt.core.tui.minput.form_builder import FormBuilder
21
+ from clitt.core.tui.minput.form_field import FormField
22
+ from clitt.core.tui.minput.input_type import InputType
23
+ from clitt.core.tui.minput.minput_utils import MASK_SYMBOLS, VALUE_SEPARATORS
24
+ from clitt.core.tui.tui_component import TUIComponent
25
+ from functools import reduce
26
+ from hspylib.core.exception.exceptions import InvalidInputError, InvalidStateError
27
+ from hspylib.core.namespace import Namespace
28
+ from hspylib.core.tools.text_tools import xstr
29
+ from hspylib.modules.cli.keyboard import Keyboard
30
+ from operator import add
31
+ from time import sleep
32
+ from typing import List, Optional
33
+
34
+ import pyperclip
35
+ import re
36
+
37
+
38
+ class MenuInput(TUIComponent):
39
+ """Provide a form input for terminal UIs."""
40
+
41
+ NAV_ICONS = NavIcons.compose(NavIcons.UP, NavIcons.DOWN)
42
+
43
+ @classmethod
44
+ def builder(cls) -> FormBuilder:
45
+ return FormBuilder()
46
+
47
+ def __init__(self, title: str, fields: List[FormField]):
48
+ super().__init__(title)
49
+ self.fields = fields
50
+ self.positions = [(0, 0) for _ in fields]
51
+ self.cur_field = self._done = None
52
+ self.cur_row = self.cur_col = self.tab_index = 0
53
+ self.max_label_length = max(len(field.label) for field in fields)
54
+ self.max_value_length = max(field.max_length for field in fields)
55
+ self.max_detail_length = max(mu.detail_len(field) for field in fields)
56
+
57
+ def execute(self) -> Optional[Namespace]:
58
+ if len(self.fields) == 0:
59
+ return None
60
+
61
+ self._prepare_render()
62
+ keypress = self._loop()
63
+
64
+ if keypress == Keyboard.VK_ENTER:
65
+ form_fields = Namespace("FormFields")
66
+ for field in self.fields:
67
+ form_fields.setattr(field.dest, field.value)
68
+ return form_fields
69
+
70
+ return None
71
+
72
+ def render(self) -> None:
73
+
74
+ Terminal.set_show_cursor(False)
75
+ self.cursor.restore()
76
+ self.writeln(f"{self.prefs.title_color.placeholder}{self.title}%EOL%%NC%")
77
+
78
+ for idx, field in enumerate(self.fields):
79
+ field_length = field.length
80
+ if self.tab_index == idx:
81
+ mu.mi_print(
82
+ self.screen, f" {field.label}", self.prefs.sel_bg_color.placeholder, self.max_label_length + 2
83
+ )
84
+ self.cur_field = field
85
+ else:
86
+ mu.mi_print(self.screen, f" {field.label}", field_len=self.max_label_length + 2)
87
+ self._buffer_positions(idx, field_length)
88
+ self._render_field(field)
89
+ self._render_details(field, field_length)
90
+
91
+ self.cursor.erase(Direction.DOWN)
92
+ self.draw_navbar(self.navbar())
93
+ self._set_cursor_pos()
94
+ self._re_render = False
95
+ Terminal.set_show_cursor()
96
+
97
+ def navbar(self, **kwargs) -> str:
98
+
99
+ return (
100
+ f"%EOL%{NavIcons.POINTER} %GREEN%{self.cur_field.tooltip or f'the {self.cur_field.label.lower()}'}%NC%"
101
+ f"%EOL%{self.prefs.navbar_color.placeholder}%EOL%"
102
+ f"[Enter] Submit [{self.NAV_ICONS}] "
103
+ f"Navigate [{NavIcons.TAB}] Next [Space] Toggle [^P] Paste [Esc] Quit %NC%"
104
+ )
105
+
106
+ def handle_keypress(self) -> Keyboard:
107
+ length = len(self.fields)
108
+
109
+ if keypress := Keyboard.wait_keystroke():
110
+ match keypress:
111
+ case Keyboard.VK_ESC:
112
+ self._done = True
113
+ case _ as key if key in [Keyboard.VK_TAB, Keyboard.VK_DOWN]:
114
+ self.tab_index = min(length - 1, self.tab_index + 1)
115
+ case _ as key if key in [Keyboard.VK_SHIFT_TAB, Keyboard.VK_UP]:
116
+ self.tab_index = max(0, self.tab_index - 1)
117
+ case Keyboard.VK_BACKSPACE:
118
+ if not self.cur_field.can_write():
119
+ self._display_error("This field is read only !")
120
+ else:
121
+ self._handle_backspace()
122
+ case Keyboard.VK_CTRL_P:
123
+ self._handle_ctrl_p()
124
+ case Keyboard.VK_ENTER:
125
+ return self._handle_enter()
126
+ case _ as key if key.isalnum() or key.ispunct() or key == Keyboard.VK_SPACE:
127
+ if not self.cur_field.can_write():
128
+ self._display_error("This field is read only !")
129
+ else:
130
+ self._handle_input(keypress)
131
+
132
+ self._re_render = True
133
+
134
+ return keypress
135
+
136
+ def _handle_enter(self) -> Optional[Keyboard]:
137
+ """Handle 'enter' press. Validate & Save form and exit."""
138
+ invalid = next((field for field in self.fields if not field.validate_field()), None)
139
+ if invalid:
140
+ idx = self.fields.index(invalid)
141
+ pos = self.positions[idx]
142
+ self.cur_row = pos[0]
143
+ self.tab_index = idx
144
+ self._display_error("Form field is not valid: " + str(invalid))
145
+ return None
146
+
147
+ for idx, field in enumerate(self.fields):
148
+ match field.itype:
149
+ case InputType.MASKED:
150
+ field.value = re.split(VALUE_SEPARATORS, field.value)[0]
151
+ case InputType.CHECKBOX:
152
+ field.value = bool(field.value)
153
+ case InputType.SELECT:
154
+ _, field.value = mu.get_selected(field.value)
155
+ self._done = True
156
+ return Keyboard.VK_ENTER
157
+
158
+ def _handle_input(self, keypress: Keyboard) -> None:
159
+ """Handle a form input.
160
+ :param keypress: the input provided by the keypress.
161
+ """
162
+
163
+ match self.cur_field.itype:
164
+ case InputType.CHECKBOX:
165
+ if keypress == Keyboard.VK_SPACE:
166
+ self.cur_field.value = not self.cur_field.value
167
+ case InputType.SELECT:
168
+ if keypress == Keyboard.VK_SPACE:
169
+ if self.cur_field.value:
170
+ self.cur_field.value = mu.toggle_selected(xstr(self.cur_field.value))
171
+ case InputType.MASKED:
172
+ value, mask = mu.unpack_masked(xstr(self.cur_field.value))
173
+ try:
174
+ self.cur_field.value = mu.append_masked(value, mask, keypress.value)
175
+ except InvalidInputError as err:
176
+ self._display_error(str(err))
177
+ case _:
178
+ if len(xstr(self.cur_field.value)) < self.cur_field.max_length:
179
+ if self.cur_field.validate_input(keypress.value):
180
+ self.cur_field.value = (str(self.cur_field.value) if self.cur_field.value else "") + str(
181
+ keypress.value
182
+ )
183
+ else:
184
+ self._display_error(
185
+ f"Input '{keypress.value}' is invalid. "
186
+ f"This field takes only {self.cur_field.input_validator}!"
187
+ )
188
+
189
+ def _handle_backspace(self) -> None:
190
+ """Handle 'backspace' press. Delete previous input."""
191
+
192
+ if self.cur_field.itype == InputType.MASKED:
193
+ value, mask = mu.unpack_masked(str(self.cur_field.value))
194
+ value = value[:-1]
195
+ while mask[len(value) - 1] not in MASK_SYMBOLS:
196
+ value = value[:-1]
197
+ self.cur_field.value = f"{value}|{mask}"
198
+ elif self.cur_field.itype not in [InputType.CHECKBOX, InputType.SELECT]:
199
+ if self.cur_field.can_write() and len(str(self.cur_field.value)) >= 1:
200
+ self.cur_field.value = str(self.cur_field.value)[:-1]
201
+ elif not self.cur_field.can_write():
202
+ self._display_error("This field is read only !")
203
+
204
+ def _handle_ctrl_p(self) -> None:
205
+ """Handle 'ctrl + p' press. Paste content from clipboard."""
206
+ for c in pyperclip.paste():
207
+ self._handle_input(Keyboard.of_value(c))
208
+
209
+ def _set_cursor_pos(self) -> None:
210
+ """Set the cursor at the right position according to the ATB index."""
211
+ pos = self.positions[self.tab_index]
212
+ self.screen.cursor.move_to(pos[0], pos[1] + self.cur_field.length)
213
+
214
+ def _render_field(self, field: FormField) -> None:
215
+ """Render the specified form field.
216
+ :param field: the form field to render.
217
+ """
218
+ match field.itype:
219
+ case InputType.TEXT:
220
+ mu.mi_print(self.screen, xstr(field.value), field_len=self.max_value_length)
221
+ case InputType.PASSWORD:
222
+ mu.mi_print(self.screen, "*" * field.length, field_len=self.max_value_length)
223
+ case InputType.CHECKBOX:
224
+ mu.mi_print(
225
+ self.screen,
226
+ " ",
227
+ FormIcons.CHECK_SQUARE.unicode if field.value else FormIcons.UNCHECK_SQUARE.unicode,
228
+ field_len=self.max_value_length - 1,
229
+ )
230
+ case InputType.SELECT:
231
+ if field.value:
232
+ mat = re.search(rf".*({VALUE_SEPARATORS})?<(.+)>({VALUE_SEPARATORS})?.*", str(field.value))
233
+ sel_value = mat.group(2) if mat else re.split(VALUE_SEPARATORS, str(field.value))[0]
234
+ mu.mi_print(self.screen, f"{sel_value}", field_len=self.max_value_length)
235
+ case InputType.MASKED:
236
+ value, mask = mu.unpack_masked(str(field.value))
237
+ mu.mi_print(self.screen, mu.over_masked(value, mask), field_len=self.max_value_length)
238
+ case _:
239
+ raise InvalidStateError(f"Invalid form field type: {field.itype}")
240
+
241
+ def _render_details(self, field: FormField, field_details: int) -> None:
242
+ """Render details about total/remaining field characters.
243
+ :param field: the form field to render.
244
+ :param field_details: details about the form field (total / remaining) size.
245
+ """
246
+ padding = 1 - len(str(self.max_detail_length / 2))
247
+ fmt = "{:<3}{:>" + str(padding) + "}/{:<" + str(padding) + "} %NC%"
248
+ if field.itype == InputType.SELECT:
249
+ idx, _ = mu.get_selected(field.value)
250
+ count = len(re.split(VALUE_SEPARATORS, field.value))
251
+ self.writeln(fmt.format(field.icon, idx + 1 if idx >= 0 else 1, count))
252
+ elif field.itype == InputType.MASKED:
253
+ value, mask = mu.unpack_masked(xstr(field.value))
254
+ self.writeln(
255
+ fmt.format(
256
+ field.icon,
257
+ reduce(add, list(map(mask[: len(value)].count, MASK_SYMBOLS))),
258
+ reduce(add, list(map(mask.count, MASK_SYMBOLS))),
259
+ )
260
+ )
261
+ else:
262
+ self.writeln(fmt.format(field.icon, field_details, field.max_length))
263
+
264
+ def _buffer_positions(self, field_index: int, field_size: int) -> None:
265
+ """Buffer all cursor positions to avoid calling get_cursor_pos over and over because it is a very
266
+ expensive call.
267
+ :param field_index: the current form field index.
268
+ :param field_size: the form field length.
269
+ """
270
+ if f_pos := get_cursor_position() if self.positions[field_index] == (0, 0) else self.positions[field_index]:
271
+ self.positions[field_index] = f_pos
272
+ if self.tab_index == field_index:
273
+ self.cur_row, self.cur_col = f_pos[0], f_pos[1] + field_size
274
+
275
+ def _display_error(self, err_msg: str) -> None:
276
+ """Display a form filling or submitting error.
277
+ :param err_msg: the error message.
278
+ """
279
+ Terminal.set_enable_echo(False)
280
+ Terminal.set_show_cursor(False)
281
+ offset = 15 # Sum of minput used characters that are not related to the field.
282
+ err_pos = offset + self.max_label_length + self.max_value_length + self.max_detail_length
283
+ self.cursor.move_to(self.cur_row, err_pos)
284
+ mu.mi_print_err(self.screen, f"{FormIcons.ARROW_LEFT} {err_msg}")
285
+ # This calculation gives a good delay amount based on the size of the message.
286
+ sleep(max(2.0, int(len(err_msg) / 21)))
287
+ Terminal.set_enable_echo()
288
+ # Erase the message after the timeout
289
+ self.cursor.move_to(self.cur_row, err_pos)
290
+ self.cursor.erase(Direction.RIGHT)
291
+ Terminal.set_show_cursor()
292
+ self._re_render = True
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ @project: HsPyLib
6
+ @package: clitt.core.tui.minput
7
+ @file: minput.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.tui.minput.form_field import FormField
16
+ from clitt.core.tui.minput.menu_input import MenuInput
17
+ from hspylib.core.enums.charset import Charset
18
+ from hspylib.core.namespace import Namespace
19
+ from hspylib.core.preconditions import check_argument
20
+ from hspylib.core.tools.text_tools import quote, snakecase
21
+ from typing import List, Optional
22
+
23
+ import os
24
+
25
+
26
+ def minput(
27
+ form_fields: List[FormField], title: str = "Please fill all fields of the form fields below", output: str = None
28
+ ) -> Optional[Namespace]:
29
+ """
30
+ Terminal UI menu form input method.
31
+ :param form_fields: the provided form items to input from.
32
+ :param title: the title to be displayed before the form.
33
+ :param output: optional output file containing the marked items.
34
+ :return: a namespace containing all form values.
35
+ """
36
+ check_argument(len(form_fields) > 0, "Must provide at least one form field!")
37
+ result = MenuInput(title, form_fields).execute()
38
+
39
+ if result and output:
40
+ with open(output, "w", encoding=Charset.UTF_8.val) as f_out:
41
+ for name, value in zip(result.attributes, result.values):
42
+ f_out.write(f"{snakecase(name, screaming=True)}={quote(value)}" + os.linesep)
43
+
44
+ return result
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ @project: HsPyLib
6
+ @package: clitt.core.tui.minput
7
+ @file: minput_utils.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.term.screen import Screen
16
+ from hspylib.core.exception.exceptions import InvalidInputError
17
+ from typing import Any, Optional, Tuple
18
+
19
+ import re
20
+
21
+ MASK_SYMBOLS = ["#", "@", "%", "*"]
22
+
23
+ VALUE_SEPARATORS = r"[|,;]"
24
+
25
+ VALUE_SELECTORS = r"[<>]"
26
+
27
+
28
+ def detail_len(field: Any) -> int:
29
+ """Return the length of the details, according to the form field.
30
+ :param field: the form field to get details.
31
+ """
32
+ max_len = len(str(field.max_length))
33
+ return 1 + (2 * max_len)
34
+
35
+
36
+ def mi_print(screen: Screen, text: str, prefix: str = None, field_len: int = 0, end: str = "") -> None:
37
+ """Special menu input print.
38
+ :param screen: the component's screen.
39
+ :param text: the text to be printed.
40
+ :param prefix the text to print before the text.
41
+ :param field_len: the length of the field.
42
+ :param end: string appended after the last value, default an empty string.
43
+ """
44
+ fmt = ("{}" if prefix else "") + "{:<" + str(field_len) + "} : "
45
+ if prefix:
46
+ screen.cursor.write(fmt.format(prefix, text), end=end)
47
+ else:
48
+ screen.cursor.write(fmt.format(text or ""), end=end)
49
+
50
+
51
+ def mi_print_err(screen: Screen, text: str) -> None:
52
+ """Special menu input print error message.
53
+ :param screen: the component's screen.
54
+ :param text: the text to be printed.
55
+ """
56
+ screen.cursor.write(f"%RED%{text}%NC%")
57
+
58
+
59
+ def toggle_selected(tokenized_values: str) -> str:
60
+ """Toggle the 'select' component value. Selects the next value on the token sequence.
61
+ :param tokenized_values: the 'select' component tokenized values.
62
+ """
63
+ values = re.split(VALUE_SEPARATORS, tokenized_values)
64
+ cur_idx = next((idx for idx, val in enumerate(values) if val.find("<") >= 0), -1)
65
+ if cur_idx < 0:
66
+ if len(values) > 1:
67
+ values[1] = f"<{values[1]}>"
68
+ else:
69
+ values[0] = f"<{values[0]}>"
70
+ return "|".join(values)
71
+ unselected = list(map(lambda x: re.sub(VALUE_SELECTORS, "", x), values))
72
+ # fmt: off
73
+ return '|'.join([
74
+ f'<{val}>'
75
+ if idx == (cur_idx + 1) or ((cur_idx + 1) >= len(unselected) and idx == 0)
76
+ else val for idx, val in enumerate(unselected)
77
+ ])
78
+ # fmt: on
79
+
80
+
81
+ def get_selected(tokenized_values: str) -> Optional[Tuple[int, str]]:
82
+ """Get the selected value from the 'select' component tokens.
83
+ :param tokenized_values: the 'select' component tokenized values.
84
+ """
85
+ values = re.split(VALUE_SEPARATORS, tokenized_values)
86
+ # fmt: off
87
+ sel_item = next((
88
+ re.sub(VALUE_SELECTORS, '', val)
89
+ for val in values if val.startswith('<') and val.endswith('>')
90
+ ), values[0])
91
+ # fmt: on
92
+ try:
93
+ return values.index(sel_item), sel_item
94
+ except ValueError:
95
+ try:
96
+ return values.index(f"<{sel_item}>"), sel_item
97
+ except ValueError:
98
+ return -1, sel_item
99
+
100
+
101
+ def unpack_masked(value: str) -> Tuple[str, str]:
102
+ """Unpack all values of the 'masked' component.
103
+ :param value: the masked values to unpack.
104
+ """
105
+ if value:
106
+ parts = re.split(VALUE_SEPARATORS, value)
107
+ return parts[0], parts[1] if len(parts) == 2 else ""
108
+
109
+ return "", ""
110
+
111
+
112
+ def append_masked(value: str, mask: str, keypress_value: chr) -> str:
113
+ """Append a value to the masked field.
114
+ :param value: the masked field current value.
115
+ :param mask: the masked field's mask.
116
+ :param keypress_value: the value to append (it can be a part of the mask itself).
117
+ """
118
+ idx = len(value)
119
+ masked_value = value
120
+ if idx < len(mask):
121
+ if keypress_value == mask[idx]:
122
+ return f"{value}{keypress_value}|{mask}"
123
+ while idx < len(mask) and mask[idx] not in MASK_SYMBOLS:
124
+ masked_value += mask[idx]
125
+ idx += 1
126
+ if mask and idx < len(mask):
127
+ mask_re = mask_regex(mask, idx)
128
+ if re.search(mask_re, keypress_value):
129
+ masked_value += keypress_value
130
+ else:
131
+ raise InvalidInputError(f"Value '{keypress_value}' is invalid. Expecting: {mask_re}")
132
+
133
+ return f"{masked_value}|{mask}"
134
+
135
+
136
+ def over_masked(value: str, mask: str) -> str:
137
+ """
138
+ Return the value to be printed by a 'masked' input field. A placeholder value will be used for unfilled values.
139
+ :param value: the masked field current value.
140
+ :param mask: the masked field's mask.
141
+ """
142
+ if value:
143
+ over_masked_val = ""
144
+ for idx, element in enumerate(mask):
145
+ if element in MASK_SYMBOLS:
146
+ over_masked_val += value[idx] if idx < len(value) else mask[idx]
147
+ else:
148
+ over_masked_val += element
149
+ return over_masked_val
150
+
151
+ return mask
152
+
153
+
154
+ def mask_regex(mask: str, idx: int) -> str:
155
+ """Return a regex matching the index of the mask."""
156
+ return mask[idx].replace("#", "[0-9]").replace("@", "[a-zA-Z]").replace("%", "[a-zA-Z0-9]").replace("*", ".")
@@ -0,0 +1,12 @@
1
+ # _*_ coding: utf-8 _*_
2
+ #
3
+ # hspylib-clitt v0.9.119
4
+ #
5
+ # Package: main.build.lib.build.lib.build.lib.clitt.core.tui.mselect
6
+ """Package initialization."""
7
+
8
+ __all__ = [
9
+ 'menu_select',
10
+ 'mselect'
11
+ ]
12
+ __version__ = '0.9.119'