This commit is contained in:
2025-05-23 14:33:13 +03:00
parent f6561de9b3
commit c3d9541330
3 changed files with 65 additions and 122 deletions
+7 -5
View File
@@ -1,6 +1,7 @@
from rich.console import Console from rich.console import Console
from argenta.app import App from argenta.app import App
from argenta.app.autocompleter import AutoCompleter
from argenta.router import Router from argenta.router import Router
from argenta.command import Command from argenta.command import Command
from argenta.response import Response from argenta.response import Response
@@ -54,7 +55,7 @@ network_router = Router("Сетевые операции", disable_redirect_stdo
def ping_host(response: Response): def ping_host(response: Response):
host = input("Введите имя хоста: ") host = input("Введите имя хоста: ")
print(f"Пингую {host}...") print(f"Пингую {host}...")
subprocess.run(["ping", "-c", "4", host]) subprocess.run(["ping", host])
@network_router.command(Command("ip", "Показать IP-адреса")) @network_router.command(Command("ip", "Показать IP-адреса"))
def show_ip(response: Response): def show_ip(response: Response):
@@ -78,12 +79,13 @@ def delete_user(response: Response):
# Создаем приложение и регистрируем маршрутизаторы # Создаем приложение и регистрируем маршрутизаторы
app = App( app = App(
prompt="MyApp> ", prompt="MyApp> ",
initial_message="Сложное тестовое приложение Argenta!", initial_message="Caser",
farewell_message="До свидания!", farewell_message="Pokeda",
dividing_line=StaticDividingLine("*"), dividing_line=DynamicDividingLine("*"),
repeat_command_groups=False, repeat_command_groups=False,
ignore_command_register=True, ignore_command_register=True,
override_system_messages=True, override_system_messages=False,
autocompleter=AutoCompleter('.history')
) )
app.include_routers(file_router, system_router, network_router, user_router) app.include_routers(file_router, system_router, network_router, user_router)
+38 -95
View File
@@ -21,10 +21,9 @@ from argenta.app.registered_routers.entity import RegisteredRouters
from argenta.response import Response from argenta.response import Response
class BaseApp: class BaseApp:
def __init__( def __init__(self, prompt: str,
self,
prompt: str,
initial_message: str, initial_message: str,
farewell_message: str, farewell_message: str,
exit_command: Command, exit_command: Command,
@@ -34,8 +33,7 @@ class BaseApp:
repeat_command_groups: bool, repeat_command_groups: bool,
override_system_messages: bool, override_system_messages: bool,
autocompleter: AutoCompleter, autocompleter: AutoCompleter,
print_func: Callable[[str], None], print_func: Callable[[str], None]) -> None:
) -> None:
self._prompt = prompt self._prompt = prompt
self._print_func = print_func self._print_func = print_func
self._exit_command = exit_command self._exit_command = exit_command
@@ -49,14 +47,17 @@ class BaseApp:
self._farewell_message = farewell_message self._farewell_message = farewell_message
self._initial_message = initial_message self._initial_message = initial_message
self._description_message_gen: Callable[[str, str], str] = ( self._description_message_gen: Callable[[str, str], str] = lambda command, description: f"{command} *=*=* {description}"
lambda command, description: f"{command} *=*=* {description}"
)
self._registered_routers: RegisteredRouters = RegisteredRouters() self._registered_routers: RegisteredRouters = RegisteredRouters()
self._messages_on_startup: list[str] = [] self._messages_on_startup: list[str] = []
self._all_registered_triggers_in_lower_case: list[str] = [] self._matching_lower_triggers_with_routers: dict[str, Router] = {}
self._all_registered_triggers_in_default_case: list[str] = [] self._matching_default_triggers_with_routers: dict[str, Router] = {}
if self._ignore_command_register:
self._current_matching_triggers_with_routers: dict[str, Router] = self._matching_lower_triggers_with_routers
else:
self._current_matching_triggers_with_routers: dict[str, Router] = self._matching_default_triggers_with_routers
self._incorrect_input_syntax_handler: Callable[[str], None] = ( self._incorrect_input_syntax_handler: Callable[[str], None] = (
lambda raw_command: print_func(f"Incorrect flag syntax: {raw_command}") lambda raw_command: print_func(f"Incorrect flag syntax: {raw_command}")
@@ -208,13 +209,10 @@ class BaseApp:
""" """
input_command_trigger = command.get_trigger() input_command_trigger = command.get_trigger()
if self._ignore_command_register: if self._ignore_command_register:
if ( if input_command_trigger.lower() in list(self._current_matching_triggers_with_routers.keys()):
input_command_trigger.lower()
in self._all_registered_triggers_in_lower_case
):
return False return False
else: else:
if input_command_trigger in self._all_registered_triggers_in_default_case: if input_command_trigger in list(self._current_matching_triggers_with_routers.keys()):
return False return False
return True return True
@@ -250,11 +248,8 @@ class BaseApp:
self._registered_routers.add_registered_router(system_router) self._registered_routers.add_registered_router(system_router)
def _most_similar_command(self, unknown_command: str) -> str | None: def _most_similar_command(self, unknown_command: str) -> str | None:
all_commands = ( all_commands = list(self._current_matching_triggers_with_routers.keys())
self._all_registered_triggers_in_lower_case
if self._ignore_command_register
else self._all_registered_triggers_in_default_case
)
matches: list[str] | list = sorted( matches: list[str] | list = sorted(
cmd for cmd in all_commands if cmd.startswith(unknown_command) cmd for cmd in all_commands if cmd.startswith(unknown_command)
) )
@@ -275,9 +270,7 @@ class BaseApp:
:return: None :return: None
""" """
self._prompt = f"[italic dim bold]{self._prompt}" self._prompt = f"[italic dim bold]{self._prompt}"
self._initial_message = ( self._initial_message = ("\n" + f"[bold red]{text2art(self._initial_message, font='tarty1')}" + "\n")
"\n" + f"[bold red]{text2art(self._initial_message, font='tarty1')}" + "\n"
)
self._farewell_message = ( self._farewell_message = (
"[bold red]\n\n" "[bold red]\n\n"
+ text2art(self._farewell_message, font="chanky") + text2art(self._farewell_message, font="chanky")
@@ -289,22 +282,14 @@ class BaseApp:
f"[blue dim]*=*=*[/blue dim] " f"[blue dim]*=*=*[/blue dim] "
f"[bold yellow italic]{escape(description)}" f"[bold yellow italic]{escape(description)}"
) )
self._incorrect_input_syntax_handler = lambda raw_command: self._print_func( self._incorrect_input_syntax_handler = lambda raw_command: self._print_func(f"[red bold]Incorrect flag syntax: {escape(raw_command)}")
f"[red bold]Incorrect flag syntax: {escape(raw_command)}" self._repeated_input_flags_handler = lambda raw_command: self._print_func(f"[red bold]Repeated input flags: {escape(raw_command)}")
) self._empty_input_command_handler = lambda: self._print_func("[red bold]Empty input command")
self._repeated_input_flags_handler = lambda raw_command: self._print_func(
f"[red bold]Repeated input flags: {escape(raw_command)}"
)
self._empty_input_command_handler = lambda: self._print_func(
"[red bold]Empty input command"
)
def unknown_command_handler(command: InputCommand) -> None: def unknown_command_handler(command: InputCommand) -> None:
cmd_trg: str = command.get_trigger() cmd_trg: str = command.get_trigger()
mst_sim_cmd: str | None = self._most_similar_command(cmd_trg) mst_sim_cmd: str | None = self._most_similar_command(cmd_trg)
first_part_of_text = ( first_part_of_text = f"[red]Unknown command:[/red] [blue]{escape(cmd_trg)}[/blue]"
f"[red]Unknown command:[/red] [blue]{escape(cmd_trg)}[/blue]"
)
second_part_of_text = ( second_part_of_text = (
("[red], most similar:[/red] " + ("[blue]" + mst_sim_cmd + "[/blue]")) ("[red], most similar:[/red] " + ("[blue]" + mst_sim_cmd + "[/blue]"))
if mst_sim_cmd if mst_sim_cmd
@@ -326,30 +311,16 @@ class BaseApp:
router_aliases = router_entity.get_aliases() router_aliases = router_entity.get_aliases()
combined = router_triggers + router_aliases combined = router_triggers + router_aliases
self._all_registered_triggers_in_default_case.extend(combined) for trigger in combined:
self._matching_default_triggers_with_routers[trigger] = router_entity
self._matching_lower_triggers_with_routers[trigger.lower()] = router_entity
self._all_registered_triggers_in_lower_case.extend( self._autocompleter.initial_setup(list(self._current_matching_triggers_with_routers.keys()))
x.lower() for x in combined
)
self._autocompleter.initial_setup(self._all_registered_triggers_in_lower_case)
if self._ignore_command_register:
seen = {} seen = {}
for item in self._all_registered_triggers_in_lower_case: for item in list(self._current_matching_triggers_with_routers.keys()):
if item in seen: if item in seen:
Console().print( Console().print(f"\n[b red]WARNING:[/b red] Overlapping trigger or alias: [b blue]{item}[/b blue]")
f"\n[b red]WARNING:[/b red] Overlapping trigger or alias: [b blue]{item}[/b blue]"
)
else:
seen[item] = True
else:
seen = {}
for item in self._all_registered_triggers_in_default_case:
if item in seen:
Console().print(
f"\n[b red]WARNING:[/b red] Overlapping trigger or alias: [b blue]{item}[/b blue]"
)
else: else:
seen[item] = True seen[item] = True
@@ -424,9 +395,7 @@ class App(BaseApp):
raw_command: str = Console().input(self._prompt) raw_command: str = Console().input(self._prompt)
try: try:
input_command: InputCommand = InputCommand.parse( input_command: InputCommand = InputCommand.parse(raw_command=raw_command)
raw_command=raw_command
)
except BaseInputCommandException as error: except BaseInputCommandException as error:
with redirect_stdout(io.StringIO()) as f: with redirect_stdout(io.StringIO()) as f:
self._error_handler(error, raw_command) self._error_handler(error, raw_command)
@@ -436,14 +405,7 @@ class App(BaseApp):
if self._is_exit_command(input_command): if self._is_exit_command(input_command):
system_router.finds_appropriate_handler(input_command) system_router.finds_appropriate_handler(input_command)
if self._ignore_command_register: self._autocompleter.exit_setup(list(self._current_matching_triggers_with_routers.keys()))
self._autocompleter.exit_setup(
self._all_registered_triggers_in_lower_case
)
else:
self._autocompleter.exit_setup(
self._all_registered_triggers_in_default_case
)
return return
if self._is_unknown_command(input_command): if self._is_unknown_command(input_command):
@@ -453,41 +415,22 @@ class App(BaseApp):
self._print_framed_text(res) self._print_framed_text(res)
continue continue
for registered_router in self._registered_routers: processing_router = self._current_matching_triggers_with_routers[input_command.get_trigger()]
if registered_router.disable_redirect_stdout:
if processing_router.disable_redirect_stdout:
if isinstance(self._dividing_line, StaticDividingLine): if isinstance(self._dividing_line, StaticDividingLine):
print('k') self._print_func(self._dividing_line.get_full_static_line(self._override_system_messages))
self._print_func( processing_router.finds_appropriate_handler(input_command)
self._dividing_line.get_full_static_line( self._print_func(self._dividing_line.get_full_static_line(self._override_system_messages))
self._override_system_messages
)
)
registered_router.finds_appropriate_handler(input_command)
self._print_func(
self._dividing_line.get_full_static_line(
self._override_system_messages
)
)
else: else:
print('j') self._print_func(StaticDividingLine(self._dividing_line.get_unit_part()).get_full_static_line(self._override_system_messages))
self._print_func( processing_router.finds_appropriate_handler(input_command)
StaticDividingLine( self._print_func(StaticDividingLine(self._dividing_line.get_unit_part()).get_full_static_line(self._override_system_messages))
self._dividing_line.get_unit_part()
).get_full_static_line(self._override_system_messages)
)
registered_router.finds_appropriate_handler(input_command)
self._print_func(
StaticDividingLine(
self._dividing_line.get_unit_part()
).get_full_static_line(self._override_system_messages)
)
else: else:
print('m')
with redirect_stdout(io.StringIO()) as f: with redirect_stdout(io.StringIO()) as f:
registered_router.finds_appropriate_handler(input_command) processing_router.finds_appropriate_handler(input_command)
res: str = f.getvalue() res: str = f.getvalue()
if res: if res:
print('w')
self._print_framed_text(res) self._print_framed_text(res)
def include_router(self, router: Router) -> None: def include_router(self, router: Router) -> None:
+1 -3
View File
@@ -93,9 +93,7 @@ class Router:
response: Response = Response() response: Response = Response()
if handle_command.get_registered_flags().get_flags(): if handle_command.get_registered_flags().get_flags():
if input_command_flags.get_flags(): if input_command_flags.get_flags():
response: Response = self._structuring_input_flags( response: Response = self._structuring_input_flags( handle_command, input_command_flags )
handle_command, input_command_flags
)
command_handler.handling(response) command_handler.handling(response)
else: else:
response.status = Status.ALL_FLAGS_VALID response.status = Status.ALL_FLAGS_VALID