argenta 0.4.10__tar.gz → 0.5.0__tar.gz

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.
Files changed (30) hide show
  1. {argenta-0.4.10 → argenta-0.5.0}/PKG-INFO +33 -13
  2. {argenta-0.4.10 → argenta-0.5.0}/README.md +32 -12
  3. argenta-0.5.0/argenta/app/autocompleter/__init__.py +4 -0
  4. argenta-0.5.0/argenta/app/autocompleter/entity.py +47 -0
  5. {argenta-0.4.10 → argenta-0.5.0}/argenta/app/defaults.py +1 -0
  6. argenta-0.5.0/argenta/app/exceptions.py +10 -0
  7. {argenta-0.4.10 → argenta-0.5.0}/argenta/app/models.py +54 -49
  8. {argenta-0.4.10 → argenta-0.5.0}/argenta/command/models.py +7 -2
  9. {argenta-0.4.10 → argenta-0.5.0}/argenta/router/command_handler/entity.py +6 -6
  10. {argenta-0.4.10 → argenta-0.5.0}/argenta/router/entity.py +44 -21
  11. {argenta-0.4.10 → argenta-0.5.0}/pyproject.toml +1 -1
  12. argenta-0.4.10/argenta/app/exceptions.py +0 -25
  13. {argenta-0.4.10 → argenta-0.5.0}/LICENSE +0 -0
  14. {argenta-0.4.10 → argenta-0.5.0}/argenta/__init__.py +0 -0
  15. {argenta-0.4.10 → argenta-0.5.0}/argenta/app/__init__.py +0 -0
  16. {argenta-0.4.10 → argenta-0.5.0}/argenta/app/dividing_line/__init__.py +0 -0
  17. {argenta-0.4.10 → argenta-0.5.0}/argenta/app/dividing_line/models.py +0 -0
  18. {argenta-0.4.10 → argenta-0.5.0}/argenta/app/registered_routers/__init__.py +0 -0
  19. {argenta-0.4.10 → argenta-0.5.0}/argenta/app/registered_routers/entity.py +0 -0
  20. {argenta-0.4.10 → argenta-0.5.0}/argenta/command/__init__.py +0 -0
  21. {argenta-0.4.10 → argenta-0.5.0}/argenta/command/exceptions.py +0 -0
  22. {argenta-0.4.10 → argenta-0.5.0}/argenta/command/flag/__init__.py +0 -0
  23. {argenta-0.4.10 → argenta-0.5.0}/argenta/command/flag/defaults.py +0 -0
  24. {argenta-0.4.10 → argenta-0.5.0}/argenta/command/flag/models.py +0 -0
  25. {argenta-0.4.10 → argenta-0.5.0}/argenta/router/__init__.py +0 -0
  26. {argenta-0.4.10 → argenta-0.5.0}/argenta/router/command_handler/__init__.py +0 -0
  27. {argenta-0.4.10 → argenta-0.5.0}/argenta/router/command_handlers/__init__.py +0 -0
  28. {argenta-0.4.10 → argenta-0.5.0}/argenta/router/command_handlers/entity.py +0 -0
  29. {argenta-0.4.10 → argenta-0.5.0}/argenta/router/defaults.py +0 -0
  30. {argenta-0.4.10 → argenta-0.5.0}/argenta/router/exceptions.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: argenta
3
- Version: 0.4.10
3
+ Version: 0.5.0
4
4
  Summary: Python library for creating TUI
5
5
  License: MIT
6
6
  Author: kolo
@@ -22,7 +22,7 @@ Description-Content-Type: text/markdown
22
22
  ## Описание
23
23
  **Argenta** — Python library for creating TUI
24
24
 
25
- ![prewiev](https://github.com/koloideal/Argenta/blob/kolo/imgs/mock_app_preview_last.png?raw=True)
25
+ ![preview](https://github.com/koloideal/Argenta/blob/kolo/imgs/mock_app_preview_last.png?raw=True)
26
26
  Пример внешнего вида TUI, написанного с помощью Argenta
27
27
 
28
28
  ---
@@ -112,16 +112,16 @@ def handler_with_flags(flags: InputFlags):
112
112
 
113
113
  ### Конструктор
114
114
  ```python
115
- App(prompt: str = 'What do you want to do?\n',
116
- initial_message: str = 'Argenta',
117
- farewell_message: str = 'See you',
118
- exit_command: str = 'Q',
119
- exit_command_description: str = 'Exit command',
120
- system_points_title: str = 'System points:',
115
+ App(prompt: str = '[italic dim bold]What do you want to do?\n',
116
+ initial_message: str = '\nArgenta\n',
117
+ farewell_message: str = '\nSee you\n',
118
+ exit_command: Command = Command('Q', 'Exit command'),
119
+ system_points_title: str | None = 'System points:',
121
120
  ignore_command_register: bool = True,
122
121
  dividing_line: StaticDividingLine | DynamicDividingLine = StaticDividingLine(),
123
122
  repeat_command_groups: bool = True,
124
- full_override_system_messages: bool = False
123
+ override_system_messages: bool = False,
124
+ autocompleter: AutoCompleter = AutoCompleter(),
125
125
  print_func: Callable[[str], None] = Console().print)
126
126
  ```
127
127
  **Аргументы:**
@@ -129,13 +129,13 @@ App(prompt: str = 'What do you want to do?\n',
129
129
  - `prompt` (`str`): Сообщение перед вводом команды.
130
130
  - `initial_message` (`str`): Приветственное сообщение при запуске.
131
131
  - `farewell_message` (`str`): Сообщение при выходе.
132
- - `exit_command` (`str`): Команда выхода (по умолчанию `'Q'`).
133
- - `exit_command_description` (`str`): Описание команды выхода.
132
+ - `exit_command` (`Command`): Сущность команды, которая будет отвечать за завершение работы.
134
133
  - `system_points_title` (`str`): Заголовок перед списком системных команд.
135
134
  - `ignore_command_register` (`bool`): Игнорировать регистр всех команд.
136
135
  - `dividing_line` (`StaticDividingLine | DynamicDividingLine`): Разделительная строка.
137
136
  - `repeat_command_groups` (`bool`): Повторять описание команд перед вводом.
138
- - `full_override_system_messages` (`bool`): Переопределить ли дефолтное оформление сообщений ([подробнее см.](#override_defaults))
137
+ - `override_system_messages` (`bool`): Переопределить ли дефолтное оформление сообщений ([подробнее см.](#override_defaults))
138
+ - `autocompleter` (`AutoCompleter`): Сущность автодополнителя ввода.
139
139
  - `print_func` (`Callable[[str], None]`): Функция вывода текста в терминал.
140
140
 
141
141
  ---
@@ -260,6 +260,26 @@ App(prompt: str = 'What do you want to do?\n',
260
260
 
261
261
  ---
262
262
 
263
+ ## *class* :: `AutoCompleter`
264
+ Класс, экземпляр которого представляет собой автодополнитель ввода
265
+
266
+ ### Конструктор
267
+ ```python
268
+ AutoCompleter(history_filename: str = False,
269
+ autocomplete_button: str = 'tab')
270
+ ```
271
+
272
+ **Аргументы:**
273
+ - **name : mean**
274
+ - `history_filename` (`str` | `False`): Путь к файлу, который будет являться или является
275
+ историй пользовательского ввода, в последующем эти команды будут автодополняться, файл
276
+ может не существовать при инициализации, тогда он будет создан, при значении аргумента `False`
277
+ история пользовательского ввода будет существовать только в пределах сессии и не сохраняться в файл
278
+ - `autocomplete_button` (`str`): Строковое обозначение кнопки на клавиатуре, которая будет
279
+ использоваться для автодополнения при вводе, по умолчанию `tab`
280
+
281
+ ---
282
+
263
283
  ## *class* :: `StaticDivideLine`
264
284
  Класс, экземпляр которого представляет собой строковый разделитель фиксированной длины
265
285
 
@@ -295,7 +315,7 @@ DinamicDivideLine(unit_part: str = '-')
295
315
 
296
316
  ### Конструктор
297
317
  ```python
298
- Router(title: str = 'Commands group title:',
318
+ Router(title: str | None = None,
299
319
  name: str = 'Default')
300
320
  ```
301
321
 
@@ -5,7 +5,7 @@
5
5
  ## Описание
6
6
  **Argenta** — Python library for creating TUI
7
7
 
8
- ![prewiev](https://github.com/koloideal/Argenta/blob/kolo/imgs/mock_app_preview_last.png?raw=True)
8
+ ![preview](https://github.com/koloideal/Argenta/blob/kolo/imgs/mock_app_preview_last.png?raw=True)
9
9
  Пример внешнего вида TUI, написанного с помощью Argenta
10
10
 
11
11
  ---
@@ -95,16 +95,16 @@ def handler_with_flags(flags: InputFlags):
95
95
 
96
96
  ### Конструктор
97
97
  ```python
98
- App(prompt: str = 'What do you want to do?\n',
99
- initial_message: str = 'Argenta',
100
- farewell_message: str = 'See you',
101
- exit_command: str = 'Q',
102
- exit_command_description: str = 'Exit command',
103
- system_points_title: str = 'System points:',
98
+ App(prompt: str = '[italic dim bold]What do you want to do?\n',
99
+ initial_message: str = '\nArgenta\n',
100
+ farewell_message: str = '\nSee you\n',
101
+ exit_command: Command = Command('Q', 'Exit command'),
102
+ system_points_title: str | None = 'System points:',
104
103
  ignore_command_register: bool = True,
105
104
  dividing_line: StaticDividingLine | DynamicDividingLine = StaticDividingLine(),
106
105
  repeat_command_groups: bool = True,
107
- full_override_system_messages: bool = False
106
+ override_system_messages: bool = False,
107
+ autocompleter: AutoCompleter = AutoCompleter(),
108
108
  print_func: Callable[[str], None] = Console().print)
109
109
  ```
110
110
  **Аргументы:**
@@ -112,13 +112,13 @@ App(prompt: str = 'What do you want to do?\n',
112
112
  - `prompt` (`str`): Сообщение перед вводом команды.
113
113
  - `initial_message` (`str`): Приветственное сообщение при запуске.
114
114
  - `farewell_message` (`str`): Сообщение при выходе.
115
- - `exit_command` (`str`): Команда выхода (по умолчанию `'Q'`).
116
- - `exit_command_description` (`str`): Описание команды выхода.
115
+ - `exit_command` (`Command`): Сущность команды, которая будет отвечать за завершение работы.
117
116
  - `system_points_title` (`str`): Заголовок перед списком системных команд.
118
117
  - `ignore_command_register` (`bool`): Игнорировать регистр всех команд.
119
118
  - `dividing_line` (`StaticDividingLine | DynamicDividingLine`): Разделительная строка.
120
119
  - `repeat_command_groups` (`bool`): Повторять описание команд перед вводом.
121
- - `full_override_system_messages` (`bool`): Переопределить ли дефолтное оформление сообщений ([подробнее см.](#override_defaults))
120
+ - `override_system_messages` (`bool`): Переопределить ли дефолтное оформление сообщений ([подробнее см.](#override_defaults))
121
+ - `autocompleter` (`AutoCompleter`): Сущность автодополнителя ввода.
122
122
  - `print_func` (`Callable[[str], None]`): Функция вывода текста в терминал.
123
123
 
124
124
  ---
@@ -243,6 +243,26 @@ App(prompt: str = 'What do you want to do?\n',
243
243
 
244
244
  ---
245
245
 
246
+ ## *class* :: `AutoCompleter`
247
+ Класс, экземпляр которого представляет собой автодополнитель ввода
248
+
249
+ ### Конструктор
250
+ ```python
251
+ AutoCompleter(history_filename: str = False,
252
+ autocomplete_button: str = 'tab')
253
+ ```
254
+
255
+ **Аргументы:**
256
+ - **name : mean**
257
+ - `history_filename` (`str` | `False`): Путь к файлу, который будет являться или является
258
+ историй пользовательского ввода, в последующем эти команды будут автодополняться, файл
259
+ может не существовать при инициализации, тогда он будет создан, при значении аргумента `False`
260
+ история пользовательского ввода будет существовать только в пределах сессии и не сохраняться в файл
261
+ - `autocomplete_button` (`str`): Строковое обозначение кнопки на клавиатуре, которая будет
262
+ использоваться для автодополнения при вводе, по умолчанию `tab`
263
+
264
+ ---
265
+
246
266
  ## *class* :: `StaticDivideLine`
247
267
  Класс, экземпляр которого представляет собой строковый разделитель фиксированной длины
248
268
 
@@ -278,7 +298,7 @@ DinamicDivideLine(unit_part: str = '-')
278
298
 
279
299
  ### Конструктор
280
300
  ```python
281
- Router(title: str = 'Commands group title:',
301
+ Router(title: str | None = None,
282
302
  name: str = 'Default')
283
303
  ```
284
304
 
@@ -0,0 +1,4 @@
1
+ __all__ = ["AutoCompleter"]
2
+
3
+
4
+ from argenta.app.autocompleter.entity import AutoCompleter
@@ -0,0 +1,47 @@
1
+ import os
2
+ import readline
3
+
4
+
5
+ class AutoCompleter:
6
+ def __init__(self, history_filename: str = False, autocomplete_button: str = 'tab'):
7
+ self.history_filename = history_filename
8
+ self.autocomplete_button = autocomplete_button
9
+ self.matches = []
10
+
11
+ def complete(self, text, state):
12
+ matches = sorted(cmd for cmd in self.get_history_items() if cmd.startswith(text))
13
+ if len(matches) > 1:
14
+ common_prefix = matches[0]
15
+ for match in matches[1:]:
16
+ i = 0
17
+ while i < len(common_prefix) and i < len(match) and common_prefix[i] == match[i]:
18
+ i += 1
19
+ common_prefix = common_prefix[:i]
20
+ if state == 0:
21
+ readline.insert_text(common_prefix[len(text):])
22
+ readline.redisplay()
23
+ return None
24
+ elif len(matches) == 1:
25
+ return matches[0] if state == 0 else None
26
+ else:
27
+ return None
28
+
29
+ def initial_setup(self, all_commands: list[str]):
30
+ if self.history_filename:
31
+ if os.path.exists(self.history_filename):
32
+ readline.read_history_file(self.history_filename)
33
+ else:
34
+ for line in all_commands:
35
+ readline.add_history(line)
36
+
37
+ readline.set_completer(self.complete)
38
+ readline.set_completer_delims(readline.get_completer_delims().replace(' ', ''))
39
+ readline.parse_and_bind(f'{self.autocomplete_button}: complete')
40
+
41
+ def exit_setup(self):
42
+ if self.history_filename:
43
+ readline.write_history_file(self.history_filename)
44
+
45
+ @staticmethod
46
+ def get_history_items():
47
+ return [readline.get_history_item(i) for i in range(1, readline.get_current_history_length() + 1)]
@@ -5,4 +5,5 @@ from dataclasses import dataclass
5
5
  class PredeterminedMessages:
6
6
  USAGE = '[b dim]Usage[/b dim]: [i]<command> <[green]flags[/green]>[/i]'
7
7
  HELP = '[b dim]Help[/b dim]: [i]<command>[/i] [b red]--help[/b red]'
8
+ AUTOCOMPLETE = '[b dim]Autocomplete[/b dim]: [i]<part>[/i] [bold]<tab>'
8
9
 
@@ -0,0 +1,10 @@
1
+ class NoRegisteredRoutersException(Exception):
2
+ def __str__(self):
3
+ return "No Registered Router Found"
4
+
5
+
6
+ class NoRegisteredHandlersException(Exception):
7
+ def __init__(self, router_name):
8
+ self.router_name = router_name
9
+ def __str__(self):
10
+ return f"No Registered Handlers Found For '{self.router_name}'"
@@ -1,5 +1,6 @@
1
1
  from typing import Callable
2
2
  from rich.console import Console
3
+ from rich.markup import escape
3
4
  from art import text2art
4
5
  from contextlib import redirect_stdout
5
6
  import io
@@ -8,14 +9,13 @@ import re
8
9
  from argenta.command.models import Command, InputCommand
9
10
  from argenta.router import Router
10
11
  from argenta.router.defaults import system_router
12
+ from argenta.app.autocompleter import AutoCompleter
11
13
  from argenta.app.dividing_line.models import StaticDividingLine, DynamicDividingLine
12
14
  from argenta.command.exceptions import (UnprocessedInputFlagException,
13
15
  RepeatedInputFlagsException,
14
16
  EmptyInputCommandException,
15
17
  BaseInputCommandException)
16
- from argenta.app.exceptions import (InvalidRouterInstanceException,
17
- InvalidDescriptionMessagePatternException,
18
- NoRegisteredRoutersException,
18
+ from argenta.app.exceptions import (NoRegisteredRoutersException,
19
19
  NoRegisteredHandlersException)
20
20
  from argenta.app.registered_routers.entity import RegisteredRouters
21
21
 
@@ -26,47 +26,42 @@ class AppInit:
26
26
  prompt: str = '[italic dim bold]What do you want to do?\n',
27
27
  initial_message: str = '\nArgenta\n',
28
28
  farewell_message: str = '\nSee you\n',
29
- exit_command: str = 'Q',
30
- exit_command_description: str = 'Exit command',
31
- system_points_title: str = 'System points:',
29
+ exit_command: Command = Command('Q', 'Exit command'),
30
+ system_points_title: str | None = 'System points:',
32
31
  ignore_command_register: bool = True,
33
32
  dividing_line: StaticDividingLine | DynamicDividingLine = StaticDividingLine(),
34
33
  repeat_command_groups: bool = True,
35
- full_override_system_messages: bool = False,
34
+ override_system_messages: bool = False,
35
+ autocompleter: AutoCompleter = AutoCompleter(),
36
36
  print_func: Callable[[str], None] = Console().print) -> None:
37
37
  self._prompt = prompt
38
38
  self._print_func = print_func
39
39
  self._exit_command = exit_command
40
- self._exit_command_description = exit_command_description
41
40
  self._system_points_title = system_points_title
42
41
  self._dividing_line = dividing_line
43
42
  self._ignore_command_register = ignore_command_register
44
43
  self._repeat_command_groups_description = repeat_command_groups
45
- self._full_override_system_messages = full_override_system_messages
44
+ self._override_system_messages = override_system_messages
45
+ self._autocompleter = autocompleter
46
46
 
47
47
  self._farewell_message = farewell_message
48
48
  self._initial_message = initial_message
49
49
 
50
- self._description_message_pattern: str = '[bold red][{command}][/bold red] [blue dim]*=*=*[/blue dim] [bold yellow italic]{description}'
50
+
51
+ self._description_message_gen: Callable[[str, str], str] = lambda command, description: f'[bold red]{escape('['+command+']')}[/bold red] [blue dim]*=*=*[/blue dim] [bold yellow italic]{escape(description)}'
51
52
  self._registered_routers: RegisteredRouters = RegisteredRouters()
52
53
  self._messages_on_startup = []
53
54
 
54
- self._invalid_input_flags_handler: Callable[[str], None] = lambda raw_command: print_func(f'[red bold]Incorrect flag syntax: {raw_command}')
55
- self._repeated_input_flags_handler: Callable[[str], None] = lambda raw_command: print_func(f'[red bold]Repeated input flags: {raw_command}')
55
+ self._invalid_input_flags_handler: Callable[[str], None] = lambda raw_command: print_func(f'[red bold]Incorrect flag syntax: {escape(raw_command)}')
56
+ self._repeated_input_flags_handler: Callable[[str], None] = lambda raw_command: print_func(f'[red bold]Repeated input flags: {escape(raw_command)}')
56
57
  self._empty_input_command_handler: Callable[[], None] = lambda: print_func('[red bold]Empty input command')
57
- self._unknown_command_handler: Callable[[InputCommand], None] = lambda command: print_func(f"[red bold]Unknown command: {command.get_trigger()}")
58
+ self._unknown_command_handler: Callable[[InputCommand], None] = lambda command: print_func(f"[red bold]Unknown command: {escape(command.get_trigger())}")
58
59
  self._exit_command_handler: Callable[[], None] = lambda: print_func(self._farewell_message)
59
60
 
60
61
 
61
62
  class AppSetters(AppInit):
62
- def set_description_message_pattern(self, pattern: str) -> None:
63
- first_check = re.match(r'.*{command}.*', pattern)
64
- second_check = re.match(r'.*{description}.*', pattern)
65
-
66
- if bool(first_check) and bool(second_check):
67
- self._description_message_pattern: str = pattern
68
- else:
69
- raise InvalidDescriptionMessagePatternException(pattern)
63
+ def set_description_message_pattern(self, pattern: Callable[[str, str], str]) -> None:
64
+ self._description_message_gen: Callable[[str, str], str] = pattern
70
65
 
71
66
 
72
67
  def set_invalid_input_flags_handler(self, handler: Callable[[str], None]) -> None:
@@ -92,11 +87,12 @@ class AppSetters(AppInit):
92
87
  class AppPrinters(AppInit):
93
88
  def _print_command_group_description(self):
94
89
  for registered_router in self._registered_routers:
95
- self._print_func(registered_router.get_title())
90
+ if registered_router.get_title():
91
+ self._print_func(registered_router.get_title())
96
92
  for command_handler in registered_router.get_command_handlers():
97
- self._print_func(self._description_message_pattern.format(
98
- command=command_handler.get_handled_command().get_trigger(),
99
- description=command_handler.get_handled_command().get_description()))
93
+ self._print_func(self._description_message_gen(
94
+ command_handler.get_handled_command().get_trigger(),
95
+ command_handler.get_handled_command().get_description()))
100
96
  self._print_func('')
101
97
 
102
98
 
@@ -109,13 +105,22 @@ class AppPrinters(AppInit):
109
105
  self._print_func(self._dividing_line.get_full_line(max_length_line))
110
106
 
111
107
 
108
+ def _print_framed_text(self, text: str):
109
+ if isinstance(self._dividing_line, StaticDividingLine):
110
+ self._print_func(self._dividing_line.get_full_line())
111
+ self._print_func(text)
112
+ self._print_func(self._dividing_line.get_full_line())
113
+ elif isinstance(self._dividing_line, DynamicDividingLine):
114
+ self._print_framed_text_with_dynamic_line(text)
115
+
116
+
112
117
  class AppNonStandardHandlers(AppPrinters):
113
118
  def _is_exit_command(self, command: InputCommand):
114
- if command.get_trigger().lower() == self._exit_command.lower():
119
+ if command.get_trigger().lower() == self._exit_command.get_trigger().lower():
115
120
  if self._ignore_command_register:
116
121
  system_router.input_command_handler(command)
117
122
  return True
118
- elif command.get_trigger() == self._exit_command:
123
+ elif command.get_trigger() == self._exit_command.get_trigger():
119
124
  system_router.input_command_handler(command)
120
125
  return True
121
126
  return False
@@ -125,10 +130,16 @@ class AppNonStandardHandlers(AppPrinters):
125
130
  for router_entity in self._registered_routers:
126
131
  for command_handler in router_entity.get_command_handlers():
127
132
  handled_command_trigger = command_handler.get_handled_command().get_trigger()
133
+ handled_command_aliases = command_handler.get_handled_command().get_aliases()
128
134
  if handled_command_trigger.lower() == command.get_trigger().lower() and self._ignore_command_register:
129
135
  return False
130
136
  elif handled_command_trigger == command.get_trigger():
131
137
  return False
138
+ elif handled_command_aliases:
139
+ if (command.get_trigger().lower() in [x.lower() for x in handled_command_aliases]) and self._ignore_command_register:
140
+ return False
141
+ elif command.get_trigger() in handled_command_trigger:
142
+ return False
132
143
  if isinstance(self._dividing_line, StaticDividingLine):
133
144
  self._print_func(self._dividing_line.get_full_line())
134
145
  self._unknown_command_handler(command)
@@ -167,7 +178,7 @@ class AppSetups(AppValidators, AppPrinters):
167
178
  def _setup_system_router(self):
168
179
  system_router.set_title(self._system_points_title)
169
180
 
170
- @system_router.command(Command(self._exit_command, self._exit_command_description))
181
+ @system_router.command(self._exit_command)
171
182
  def exit_command():
172
183
  self._exit_command_handler()
173
184
 
@@ -176,7 +187,7 @@ class AppSetups(AppValidators, AppPrinters):
176
187
  self._registered_routers.add_registered_router(system_router)
177
188
 
178
189
  def _setup_default_view(self):
179
- if not self._full_override_system_messages:
190
+ if not self._override_system_messages:
180
191
  self._initial_message = f'\n[bold red]{text2art(self._initial_message, font='tarty1')}\n\n'
181
192
  self._farewell_message = (
182
193
  f'[bold red]\n{text2art(f'\n{self._farewell_message}\n', font='chanky')}[/bold red]\n'
@@ -188,10 +199,17 @@ class AppSetups(AppValidators, AppPrinters):
188
199
  self._validate_number_of_routers()
189
200
  self._validate_included_routers()
190
201
 
202
+ all_triggers: list[str] = []
203
+ for router_entity in self._registered_routers:
204
+ all_triggers.extend(router_entity.get_triggers())
205
+ all_triggers.extend(router_entity.get_aliases())
206
+ self._autocompleter.initial_setup(all_triggers)
207
+
191
208
  self._print_func(self._initial_message)
192
209
 
193
210
  for message in self._messages_on_startup:
194
211
  self._print_func(message)
212
+ print('\n\n')
195
213
 
196
214
  if not self._repeat_command_groups_description:
197
215
  self._print_command_group_description()
@@ -209,43 +227,30 @@ class App(AppSetters, AppNonStandardHandlers, AppSetups):
209
227
  try:
210
228
  input_command: InputCommand = InputCommand.parse(raw_command=raw_command)
211
229
  except BaseInputCommandException as error:
212
- if isinstance(self._dividing_line, StaticDividingLine):
213
- self._print_func(self._dividing_line.get_full_line())
230
+ with redirect_stdout(io.StringIO()) as f:
214
231
  self._error_handler(error, raw_command)
215
- self._print_func(self._dividing_line.get_full_line())
216
- elif isinstance(self._dividing_line, DynamicDividingLine):
217
- with redirect_stdout(io.StringIO()) as f:
218
- self._error_handler(error, raw_command)
219
- res: str = f.getvalue()
220
- self._print_framed_text_with_dynamic_line(res)
232
+ res: str = f.getvalue()
233
+ self._print_framed_text(res)
221
234
  continue
222
235
 
223
236
  if self._is_exit_command(input_command):
237
+ self._autocompleter.exit_setup()
224
238
  return
225
239
 
226
240
  if self._is_unknown_command(input_command):
227
241
  continue
228
242
 
229
- if isinstance(self._dividing_line, StaticDividingLine):
230
- self._print_func(self._dividing_line.get_full_line())
243
+ with redirect_stdout(io.StringIO()) as f:
231
244
  for registered_router in self._registered_routers:
232
245
  registered_router.input_command_handler(input_command)
233
- self._print_func(self._dividing_line.get_full_line())
234
- elif isinstance(self._dividing_line, DynamicDividingLine):
235
- with redirect_stdout(io.StringIO()) as f:
236
- for registered_router in self._registered_routers:
237
- registered_router.input_command_handler(input_command)
238
- res: str = f.getvalue()
239
- self._print_framed_text_with_dynamic_line(res)
246
+ res: str = f.getvalue()
247
+ self._print_framed_text(res)
240
248
 
241
249
  if not self._repeat_command_groups_description:
242
250
  self._print_func(self._prompt)
243
251
 
244
252
 
245
253
  def include_router(self, router: Router) -> None:
246
- if not isinstance(router, Router):
247
- raise InvalidRouterInstanceException()
248
-
249
254
  router.set_ignore_command_register(self._ignore_command_register)
250
255
  self._registered_routers.add_registered_router(router)
251
256
 
@@ -19,14 +19,19 @@ class BaseCommand:
19
19
  class Command(BaseCommand):
20
20
  def __init__(self, trigger: str,
21
21
  description: str = None,
22
- flags: Flag | Flags = None):
22
+ flags: Flag | Flags = None,
23
+ aliases: list[str] = None):
23
24
  super().__init__(trigger)
24
25
  self._registered_flags: Flags = flags if isinstance(flags, Flags) else Flags(flags) if isinstance(flags, Flag) else Flags()
25
- self._description = f'description for "{self._trigger}" command' if not description else description
26
+ self._description = f'Description for "{self._trigger}" command' if not description else description
27
+ self._aliases = aliases
26
28
 
27
29
  def get_registered_flags(self) -> Flags:
28
30
  return self._registered_flags
29
31
 
32
+ def get_aliases(self) -> list[str] | None:
33
+ return self._aliases
34
+
30
35
  def validate_input_flag(self, flag: InputFlag):
31
36
  registered_flags: Flags | None = self.get_registered_flags()
32
37
  if registered_flags:
@@ -5,17 +5,17 @@ from argenta.command.flag.models import InputFlags
5
5
 
6
6
  class CommandHandler:
7
7
  def __init__(self, handler: Callable[[], None] | Callable[[InputFlags], None], handled_command: Command):
8
- self.handler = handler
9
- self.handled_command = handled_command
8
+ self._handler = handler
9
+ self._handled_command = handled_command
10
10
 
11
11
  def handling(self, input_flags: InputFlags = None):
12
12
  if input_flags is not None:
13
- self.handler(input_flags)
13
+ self._handler(input_flags)
14
14
  else:
15
- self.handler()
15
+ self._handler()
16
16
 
17
17
  def get_handler(self):
18
- return self.handler
18
+ return self._handler
19
19
 
20
20
  def get_handled_command(self):
21
- return self.handled_command
21
+ return self._handled_command
@@ -7,15 +7,15 @@ from argenta.router.command_handlers.entity import CommandHandlers
7
7
  from argenta.router.command_handler.entity import CommandHandler
8
8
  from argenta.command.flag.models import Flag, Flags, InputFlags
9
9
  from argenta.router.exceptions import (RepeatedFlagNameException,
10
- TooManyTransferredArgsException,
11
- RequiredArgumentNotPassedException,
12
- IncorrectNumberOfHandlerArgsException,
13
- TriggerCannotContainSpacesException)
10
+ TooManyTransferredArgsException,
11
+ RequiredArgumentNotPassedException,
12
+ IncorrectNumberOfHandlerArgsException,
13
+ TriggerCannotContainSpacesException)
14
14
 
15
15
 
16
16
  class Router:
17
17
  def __init__(self,
18
- title: str = 'Commands group title:',
18
+ title: str = None,
19
19
  name: str = 'Default'):
20
20
  self._title = title
21
21
  self._name = name
@@ -54,21 +54,29 @@ class Router:
54
54
  for command_handler in self._command_handlers:
55
55
  handle_command = command_handler.get_handled_command()
56
56
  if input_command_name.lower() == handle_command.get_trigger().lower():
57
- if handle_command.get_registered_flags().get_flags():
58
- if input_command_flags.get_flags():
59
- if self._validate_input_flags(handle_command, input_command_flags):
60
- command_handler.handling(input_command_flags)
61
- return
62
- else:
63
- command_handler.handling(input_command_flags)
64
- return
65
- else:
66
- if input_command_flags.get_flags():
67
- self._not_valid_flag_handler(input_command_flags[0])
68
- return
69
- else:
70
- command_handler.handling()
71
- return
57
+ self._validate_input_command(input_command_flags, command_handler)
58
+ elif handle_command.get_aliases():
59
+ if input_command_name.lower() in handle_command.get_aliases():
60
+ self._validate_input_command(input_command_flags, command_handler)
61
+
62
+
63
+ def _validate_input_command(self, input_command_flags: InputFlags, command_handler: CommandHandler):
64
+ handle_command = command_handler.get_handled_command()
65
+ if handle_command.get_registered_flags().get_flags():
66
+ if input_command_flags.get_flags():
67
+ if self._validate_input_flags(handle_command, input_command_flags):
68
+ command_handler.handling(input_command_flags)
69
+ return
70
+ else:
71
+ command_handler.handling(input_command_flags)
72
+ return
73
+ else:
74
+ if input_command_flags.get_flags():
75
+ self._not_valid_flag_handler(input_command_flags[0])
76
+ return
77
+ else:
78
+ command_handler.handling()
79
+ return
72
80
 
73
81
 
74
82
  def _validate_input_flags(self, handle_command: Command, input_flags: InputFlags):
@@ -110,6 +118,21 @@ class Router:
110
118
  self._ignore_command_register = ignore_command_register
111
119
 
112
120
 
121
+ def get_triggers(self):
122
+ all_triggers: list[str] = []
123
+ for command_handler in self._command_handlers:
124
+ all_triggers.append(command_handler.get_handled_command().get_trigger())
125
+ return all_triggers
126
+
127
+
128
+ def get_aliases(self):
129
+ all_aliases: list[str] = []
130
+ for command_handler in self._command_handlers:
131
+ if command_handler.get_handled_command().get_aliases():
132
+ all_aliases.extend(command_handler.get_handled_command().get_aliases())
133
+ return all_aliases
134
+
135
+
113
136
  def get_command_handlers(self) -> CommandHandlers:
114
137
  return self._command_handlers
115
138
 
@@ -118,7 +141,7 @@ class Router:
118
141
  return self._name
119
142
 
120
143
 
121
- def get_title(self) -> str:
144
+ def get_title(self) -> str | None:
122
145
  return self._title
123
146
 
124
147
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "argenta"
3
- version = "0.4.10"
3
+ version = "0.5.0"
4
4
  description = "Python library for creating TUI"
5
5
  authors = [
6
6
  {name = "kolo", email = "kolo.is.main@gmail.com"}
@@ -1,25 +0,0 @@
1
- class InvalidRouterInstanceException(Exception):
2
- def __str__(self):
3
- return "Invalid Router Instance"
4
-
5
-
6
- class InvalidDescriptionMessagePatternException(Exception):
7
- def __init__(self, pattern: str):
8
- self.pattern = pattern
9
- def __str__(self):
10
- return ("Invalid Description Message Pattern\n"
11
- "Correct pattern example: [{command}] *=*=* {description}\n"
12
- "The pattern must contain two variables: `command` and `description` - description of the command\n"
13
- f"Your pattern: {self.pattern}")
14
-
15
-
16
- class NoRegisteredRoutersException(Exception):
17
- def __str__(self):
18
- return "No Registered Router Found"
19
-
20
-
21
- class NoRegisteredHandlersException(Exception):
22
- def __init__(self, router_name):
23
- self.router_name = router_name
24
- def __str__(self):
25
- return f"No Registered Handlers Found For '{self.router_name}'"
File without changes
File without changes