argenta 0.4.10__tar.gz → 0.5.0b0__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.
- {argenta-0.4.10 → argenta-0.5.0b0}/PKG-INFO +35 -13
- {argenta-0.4.10 → argenta-0.5.0b0}/README.md +34 -12
- argenta-0.5.0b0/argenta/app/autocompleter/__init__.py +4 -0
- argenta-0.5.0b0/argenta/app/autocompleter/entity.py +47 -0
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/app/defaults.py +1 -0
- argenta-0.5.0b0/argenta/app/exceptions.py +15 -0
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/app/models.py +37 -27
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/command/models.py +7 -2
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/router/command_handler/entity.py +6 -6
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/router/entity.py +44 -21
- {argenta-0.4.10 → argenta-0.5.0b0}/pyproject.toml +1 -1
- argenta-0.4.10/argenta/app/exceptions.py +0 -25
- {argenta-0.4.10 → argenta-0.5.0b0}/LICENSE +0 -0
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/__init__.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/app/__init__.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/app/dividing_line/__init__.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/app/dividing_line/models.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/app/registered_routers/__init__.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/app/registered_routers/entity.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/command/__init__.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/command/exceptions.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/command/flag/__init__.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/command/flag/defaults.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/command/flag/models.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/router/__init__.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/router/command_handler/__init__.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/router/command_handlers/__init__.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/router/command_handlers/entity.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/router/defaults.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0b0}/argenta/router/exceptions.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: argenta
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.5.0b0
|
4
4
|
Summary: Python library for creating TUI
|
5
5
|
License: MIT
|
6
6
|
Author: kolo
|
@@ -15,6 +15,8 @@ Requires-Dist: art (>=6.4,<7.0)
|
|
15
15
|
Requires-Dist: rich (>=14.0.0,<15.0.0)
|
16
16
|
Description-Content-Type: text/markdown
|
17
17
|
|
18
|
+
from argenta.app.autocompleter import AutoCompleter
|
19
|
+
|
18
20
|
# Argenta
|
19
21
|
|
20
22
|
---
|
@@ -22,7 +24,7 @@ Description-Content-Type: text/markdown
|
|
22
24
|
## Описание
|
23
25
|
**Argenta** — Python library for creating TUI
|
24
26
|
|
25
|
-

|
26
28
|
Пример внешнего вида TUI, написанного с помощью Argenta
|
27
29
|
|
28
30
|
---
|
@@ -112,16 +114,16 @@ def handler_with_flags(flags: InputFlags):
|
|
112
114
|
|
113
115
|
### Конструктор
|
114
116
|
```python
|
115
|
-
App(prompt: str = 'What do you want to do?\n',
|
116
|
-
initial_message: str = '
|
117
|
-
farewell_message: str = '
|
118
|
-
exit_command:
|
119
|
-
|
120
|
-
system_points_title: str = 'System points:',
|
117
|
+
App(prompt: str = '[italic dim bold]What do you want to do?\n',
|
118
|
+
initial_message: str = '\nArgenta\n',
|
119
|
+
farewell_message: str = '\nSee you\n',
|
120
|
+
exit_command: Command = Command('Q', 'Exit command'),
|
121
|
+
system_points_title: str | None = 'System points:',
|
121
122
|
ignore_command_register: bool = True,
|
122
123
|
dividing_line: StaticDividingLine | DynamicDividingLine = StaticDividingLine(),
|
123
124
|
repeat_command_groups: bool = True,
|
124
|
-
|
125
|
+
override_system_messages: bool = False,
|
126
|
+
autocompleter: AutoCompleter = AutoCompleter(),
|
125
127
|
print_func: Callable[[str], None] = Console().print)
|
126
128
|
```
|
127
129
|
**Аргументы:**
|
@@ -129,13 +131,13 @@ App(prompt: str = 'What do you want to do?\n',
|
|
129
131
|
- `prompt` (`str`): Сообщение перед вводом команды.
|
130
132
|
- `initial_message` (`str`): Приветственное сообщение при запуске.
|
131
133
|
- `farewell_message` (`str`): Сообщение при выходе.
|
132
|
-
- `exit_command` (`
|
133
|
-
- `exit_command_description` (`str`): Описание команды выхода.
|
134
|
+
- `exit_command` (`Command`): Сущность команды, которая будет отвечать за завершение работы.
|
134
135
|
- `system_points_title` (`str`): Заголовок перед списком системных команд.
|
135
136
|
- `ignore_command_register` (`bool`): Игнорировать регистр всех команд.
|
136
137
|
- `dividing_line` (`StaticDividingLine | DynamicDividingLine`): Разделительная строка.
|
137
138
|
- `repeat_command_groups` (`bool`): Повторять описание команд перед вводом.
|
138
|
-
- `
|
139
|
+
- `override_system_messages` (`bool`): Переопределить ли дефолтное оформление сообщений ([подробнее см.](#override_defaults))
|
140
|
+
- `autocompleter` (`AutoCompleter`): Сущность автодополнителя ввода.
|
139
141
|
- `print_func` (`Callable[[str], None]`): Функция вывода текста в терминал.
|
140
142
|
|
141
143
|
---
|
@@ -260,6 +262,26 @@ App(prompt: str = 'What do you want to do?\n',
|
|
260
262
|
|
261
263
|
---
|
262
264
|
|
265
|
+
## *class* :: `AutoCompleter`
|
266
|
+
Класс, экземпляр которого представляет собой автодополнитель ввода
|
267
|
+
|
268
|
+
### Конструктор
|
269
|
+
```python
|
270
|
+
AutoCompleter(history_filename: str = False,
|
271
|
+
autocomplete_button: str = 'tab')
|
272
|
+
```
|
273
|
+
|
274
|
+
**Аргументы:**
|
275
|
+
- **name : mean**
|
276
|
+
- `history_filename` (`str` | `False`): Путь к файлу, который будет являться или является
|
277
|
+
историй пользовательского ввода, в последующем эти команды будут автодополняться, файл
|
278
|
+
может не существовать при инициализации, тогда он будет создан, при значении аргумента `False`
|
279
|
+
история пользовательского ввода будет существовать только в пределах сессии и не сохраняться в файл
|
280
|
+
- `autocomplete_button` (`str`): Строковое обозначение кнопки на клавиатуре, которая будет
|
281
|
+
использоваться для автодополнения при вводе, по умолчанию `tab`
|
282
|
+
|
283
|
+
---
|
284
|
+
|
263
285
|
## *class* :: `StaticDivideLine`
|
264
286
|
Класс, экземпляр которого представляет собой строковый разделитель фиксированной длины
|
265
287
|
|
@@ -295,7 +317,7 @@ DinamicDivideLine(unit_part: str = '-')
|
|
295
317
|
|
296
318
|
### Конструктор
|
297
319
|
```python
|
298
|
-
Router(title: str
|
320
|
+
Router(title: str | None = None,
|
299
321
|
name: str = 'Default')
|
300
322
|
```
|
301
323
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
from argenta.app.autocompleter import AutoCompleter
|
2
|
+
|
1
3
|
# Argenta
|
2
4
|
|
3
5
|
---
|
@@ -5,7 +7,7 @@
|
|
5
7
|
## Описание
|
6
8
|
**Argenta** — Python library for creating TUI
|
7
9
|
|
8
|
-

|
9
11
|
Пример внешнего вида TUI, написанного с помощью Argenta
|
10
12
|
|
11
13
|
---
|
@@ -95,16 +97,16 @@ def handler_with_flags(flags: InputFlags):
|
|
95
97
|
|
96
98
|
### Конструктор
|
97
99
|
```python
|
98
|
-
App(prompt: str = 'What do you want to do?\n',
|
99
|
-
initial_message: str = '
|
100
|
-
farewell_message: str = '
|
101
|
-
exit_command:
|
102
|
-
|
103
|
-
system_points_title: str = 'System points:',
|
100
|
+
App(prompt: str = '[italic dim bold]What do you want to do?\n',
|
101
|
+
initial_message: str = '\nArgenta\n',
|
102
|
+
farewell_message: str = '\nSee you\n',
|
103
|
+
exit_command: Command = Command('Q', 'Exit command'),
|
104
|
+
system_points_title: str | None = 'System points:',
|
104
105
|
ignore_command_register: bool = True,
|
105
106
|
dividing_line: StaticDividingLine | DynamicDividingLine = StaticDividingLine(),
|
106
107
|
repeat_command_groups: bool = True,
|
107
|
-
|
108
|
+
override_system_messages: bool = False,
|
109
|
+
autocompleter: AutoCompleter = AutoCompleter(),
|
108
110
|
print_func: Callable[[str], None] = Console().print)
|
109
111
|
```
|
110
112
|
**Аргументы:**
|
@@ -112,13 +114,13 @@ App(prompt: str = 'What do you want to do?\n',
|
|
112
114
|
- `prompt` (`str`): Сообщение перед вводом команды.
|
113
115
|
- `initial_message` (`str`): Приветственное сообщение при запуске.
|
114
116
|
- `farewell_message` (`str`): Сообщение при выходе.
|
115
|
-
- `exit_command` (`
|
116
|
-
- `exit_command_description` (`str`): Описание команды выхода.
|
117
|
+
- `exit_command` (`Command`): Сущность команды, которая будет отвечать за завершение работы.
|
117
118
|
- `system_points_title` (`str`): Заголовок перед списком системных команд.
|
118
119
|
- `ignore_command_register` (`bool`): Игнорировать регистр всех команд.
|
119
120
|
- `dividing_line` (`StaticDividingLine | DynamicDividingLine`): Разделительная строка.
|
120
121
|
- `repeat_command_groups` (`bool`): Повторять описание команд перед вводом.
|
121
|
-
- `
|
122
|
+
- `override_system_messages` (`bool`): Переопределить ли дефолтное оформление сообщений ([подробнее см.](#override_defaults))
|
123
|
+
- `autocompleter` (`AutoCompleter`): Сущность автодополнителя ввода.
|
122
124
|
- `print_func` (`Callable[[str], None]`): Функция вывода текста в терминал.
|
123
125
|
|
124
126
|
---
|
@@ -243,6 +245,26 @@ App(prompt: str = 'What do you want to do?\n',
|
|
243
245
|
|
244
246
|
---
|
245
247
|
|
248
|
+
## *class* :: `AutoCompleter`
|
249
|
+
Класс, экземпляр которого представляет собой автодополнитель ввода
|
250
|
+
|
251
|
+
### Конструктор
|
252
|
+
```python
|
253
|
+
AutoCompleter(history_filename: str = False,
|
254
|
+
autocomplete_button: str = 'tab')
|
255
|
+
```
|
256
|
+
|
257
|
+
**Аргументы:**
|
258
|
+
- **name : mean**
|
259
|
+
- `history_filename` (`str` | `False`): Путь к файлу, который будет являться или является
|
260
|
+
историй пользовательского ввода, в последующем эти команды будут автодополняться, файл
|
261
|
+
может не существовать при инициализации, тогда он будет создан, при значении аргумента `False`
|
262
|
+
история пользовательского ввода будет существовать только в пределах сессии и не сохраняться в файл
|
263
|
+
- `autocomplete_button` (`str`): Строковое обозначение кнопки на клавиатуре, которая будет
|
264
|
+
использоваться для автодополнения при вводе, по умолчанию `tab`
|
265
|
+
|
266
|
+
---
|
267
|
+
|
246
268
|
## *class* :: `StaticDivideLine`
|
247
269
|
Класс, экземпляр которого представляет собой строковый разделитель фиксированной длины
|
248
270
|
|
@@ -278,7 +300,7 @@ DinamicDivideLine(unit_part: str = '-')
|
|
278
300
|
|
279
301
|
### Конструктор
|
280
302
|
```python
|
281
|
-
Router(title: str
|
303
|
+
Router(title: str | None = None,
|
282
304
|
name: str = 'Default')
|
283
305
|
```
|
284
306
|
|
@@ -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,15 @@
|
|
1
|
+
class InvalidRouterInstanceException(Exception):
|
2
|
+
def __str__(self):
|
3
|
+
return "Invalid Router Instance"
|
4
|
+
|
5
|
+
|
6
|
+
class NoRegisteredRoutersException(Exception):
|
7
|
+
def __str__(self):
|
8
|
+
return "No Registered Router Found"
|
9
|
+
|
10
|
+
|
11
|
+
class NoRegisteredHandlersException(Exception):
|
12
|
+
def __init__(self, router_name):
|
13
|
+
self.router_name = router_name
|
14
|
+
def __str__(self):
|
15
|
+
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,13 +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
18
|
from argenta.app.exceptions import (InvalidRouterInstanceException,
|
17
|
-
InvalidDescriptionMessagePatternException,
|
18
19
|
NoRegisteredRoutersException,
|
19
20
|
NoRegisteredHandlersException)
|
20
21
|
from argenta.app.registered_routers.entity import RegisteredRouters
|
@@ -26,47 +27,42 @@ class AppInit:
|
|
26
27
|
prompt: str = '[italic dim bold]What do you want to do?\n',
|
27
28
|
initial_message: str = '\nArgenta\n',
|
28
29
|
farewell_message: str = '\nSee you\n',
|
29
|
-
exit_command:
|
30
|
-
|
31
|
-
system_points_title: str = 'System points:',
|
30
|
+
exit_command: Command = Command('Q', 'Exit command'),
|
31
|
+
system_points_title: str | None = 'System points:',
|
32
32
|
ignore_command_register: bool = True,
|
33
33
|
dividing_line: StaticDividingLine | DynamicDividingLine = StaticDividingLine(),
|
34
34
|
repeat_command_groups: bool = True,
|
35
|
-
|
35
|
+
override_system_messages: bool = False,
|
36
|
+
autocompleter: AutoCompleter = AutoCompleter(),
|
36
37
|
print_func: Callable[[str], None] = Console().print) -> None:
|
37
38
|
self._prompt = prompt
|
38
39
|
self._print_func = print_func
|
39
40
|
self._exit_command = exit_command
|
40
|
-
self._exit_command_description = exit_command_description
|
41
41
|
self._system_points_title = system_points_title
|
42
42
|
self._dividing_line = dividing_line
|
43
43
|
self._ignore_command_register = ignore_command_register
|
44
44
|
self._repeat_command_groups_description = repeat_command_groups
|
45
|
-
self.
|
45
|
+
self._override_system_messages = override_system_messages
|
46
|
+
self._autocompleter = autocompleter
|
46
47
|
|
47
48
|
self._farewell_message = farewell_message
|
48
49
|
self._initial_message = initial_message
|
49
50
|
|
50
|
-
|
51
|
+
|
52
|
+
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
53
|
self._registered_routers: RegisteredRouters = RegisteredRouters()
|
52
54
|
self._messages_on_startup = []
|
53
55
|
|
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}')
|
56
|
+
self._invalid_input_flags_handler: Callable[[str], None] = lambda raw_command: print_func(f'[red bold]Incorrect flag syntax: {escape(raw_command)}')
|
57
|
+
self._repeated_input_flags_handler: Callable[[str], None] = lambda raw_command: print_func(f'[red bold]Repeated input flags: {escape(raw_command)}')
|
56
58
|
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()}")
|
59
|
+
self._unknown_command_handler: Callable[[InputCommand], None] = lambda command: print_func(f"[red bold]Unknown command: {escape(command.get_trigger())}")
|
58
60
|
self._exit_command_handler: Callable[[], None] = lambda: print_func(self._farewell_message)
|
59
61
|
|
60
62
|
|
61
63
|
class AppSetters(AppInit):
|
62
|
-
def set_description_message_pattern(self, pattern: str) -> None:
|
63
|
-
|
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)
|
64
|
+
def set_description_message_pattern(self, pattern: Callable[[str, str], str]) -> None:
|
65
|
+
self._description_message_gen: Callable[[str, str], str] = pattern
|
70
66
|
|
71
67
|
|
72
68
|
def set_invalid_input_flags_handler(self, handler: Callable[[str], None]) -> None:
|
@@ -92,11 +88,12 @@ class AppSetters(AppInit):
|
|
92
88
|
class AppPrinters(AppInit):
|
93
89
|
def _print_command_group_description(self):
|
94
90
|
for registered_router in self._registered_routers:
|
95
|
-
|
91
|
+
if registered_router.get_title():
|
92
|
+
self._print_func(registered_router.get_title())
|
96
93
|
for command_handler in registered_router.get_command_handlers():
|
97
|
-
self._print_func(self.
|
98
|
-
|
99
|
-
|
94
|
+
self._print_func(self._description_message_gen(
|
95
|
+
command_handler.get_handled_command().get_trigger(),
|
96
|
+
command_handler.get_handled_command().get_description()))
|
100
97
|
self._print_func('')
|
101
98
|
|
102
99
|
|
@@ -111,11 +108,11 @@ class AppPrinters(AppInit):
|
|
111
108
|
|
112
109
|
class AppNonStandardHandlers(AppPrinters):
|
113
110
|
def _is_exit_command(self, command: InputCommand):
|
114
|
-
if command.get_trigger().lower() == self._exit_command.lower():
|
111
|
+
if command.get_trigger().lower() == self._exit_command.get_trigger().lower():
|
115
112
|
if self._ignore_command_register:
|
116
113
|
system_router.input_command_handler(command)
|
117
114
|
return True
|
118
|
-
elif command.get_trigger() == self._exit_command:
|
115
|
+
elif command.get_trigger() == self._exit_command.get_trigger():
|
119
116
|
system_router.input_command_handler(command)
|
120
117
|
return True
|
121
118
|
return False
|
@@ -125,10 +122,16 @@ class AppNonStandardHandlers(AppPrinters):
|
|
125
122
|
for router_entity in self._registered_routers:
|
126
123
|
for command_handler in router_entity.get_command_handlers():
|
127
124
|
handled_command_trigger = command_handler.get_handled_command().get_trigger()
|
125
|
+
handled_command_aliases = command_handler.get_handled_command().get_aliases()
|
128
126
|
if handled_command_trigger.lower() == command.get_trigger().lower() and self._ignore_command_register:
|
129
127
|
return False
|
130
128
|
elif handled_command_trigger == command.get_trigger():
|
131
129
|
return False
|
130
|
+
elif handled_command_aliases:
|
131
|
+
if (command.get_trigger().lower() in [x.lower() for x in handled_command_aliases]) and self._ignore_command_register:
|
132
|
+
return False
|
133
|
+
elif command.get_trigger() in handled_command_trigger:
|
134
|
+
return False
|
132
135
|
if isinstance(self._dividing_line, StaticDividingLine):
|
133
136
|
self._print_func(self._dividing_line.get_full_line())
|
134
137
|
self._unknown_command_handler(command)
|
@@ -167,7 +170,7 @@ class AppSetups(AppValidators, AppPrinters):
|
|
167
170
|
def _setup_system_router(self):
|
168
171
|
system_router.set_title(self._system_points_title)
|
169
172
|
|
170
|
-
@system_router.command(
|
173
|
+
@system_router.command(self._exit_command)
|
171
174
|
def exit_command():
|
172
175
|
self._exit_command_handler()
|
173
176
|
|
@@ -176,7 +179,7 @@ class AppSetups(AppValidators, AppPrinters):
|
|
176
179
|
self._registered_routers.add_registered_router(system_router)
|
177
180
|
|
178
181
|
def _setup_default_view(self):
|
179
|
-
if not self.
|
182
|
+
if not self._override_system_messages:
|
180
183
|
self._initial_message = f'\n[bold red]{text2art(self._initial_message, font='tarty1')}\n\n'
|
181
184
|
self._farewell_message = (
|
182
185
|
f'[bold red]\n{text2art(f'\n{self._farewell_message}\n', font='chanky')}[/bold red]\n'
|
@@ -188,6 +191,12 @@ class AppSetups(AppValidators, AppPrinters):
|
|
188
191
|
self._validate_number_of_routers()
|
189
192
|
self._validate_included_routers()
|
190
193
|
|
194
|
+
all_triggers: list[str] = []
|
195
|
+
for router_entity in self._registered_routers:
|
196
|
+
all_triggers.extend(router_entity.get_triggers())
|
197
|
+
all_triggers.extend(router_entity.get_aliases())
|
198
|
+
self._autocompleter.initial_setup(all_triggers)
|
199
|
+
|
191
200
|
self._print_func(self._initial_message)
|
192
201
|
|
193
202
|
for message in self._messages_on_startup:
|
@@ -221,6 +230,7 @@ class App(AppSetters, AppNonStandardHandlers, AppSetups):
|
|
221
230
|
continue
|
222
231
|
|
223
232
|
if self._is_exit_command(input_command):
|
233
|
+
self._autocompleter.exit_setup()
|
224
234
|
return
|
225
235
|
|
226
236
|
if self._is_unknown_command(input_command):
|
@@ -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'
|
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.
|
9
|
-
self.
|
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.
|
13
|
+
self._handler(input_flags)
|
14
14
|
else:
|
15
|
-
self.
|
15
|
+
self._handler()
|
16
16
|
|
17
17
|
def get_handler(self):
|
18
|
-
return self.
|
18
|
+
return self._handler
|
19
19
|
|
20
20
|
def get_handled_command(self):
|
21
|
-
return self.
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
TooManyTransferredArgsException,
|
11
|
+
RequiredArgumentNotPassedException,
|
12
|
+
IncorrectNumberOfHandlerArgsException,
|
13
|
+
TriggerCannotContainSpacesException)
|
14
14
|
|
15
15
|
|
16
16
|
class Router:
|
17
17
|
def __init__(self,
|
18
|
-
title: str =
|
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
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
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,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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|