diff --git a/docs/code_snippets/flag/snippet5.py b/docs/code_snippets/flag/snippet5.py index 7200566..cc892ec 100644 --- a/docs/code_snippets/flag/snippet5.py +++ b/docs/code_snippets/flag/snippet5.py @@ -3,7 +3,7 @@ from argenta.command import Flag verbose_flag = Flag(name="verbose", prefix="--") short_flag = Flag(name="v", prefix="-") -# Debug view +# Debug presentation print(repr(verbose_flag)) # Flag print(repr(short_flag)) # Flag diff --git a/docs/locales/en/LC_MESSAGES/root/contributing.po b/docs/locales/en/LC_MESSAGES/root/contributing.po index dcedf27..071af73 100644 --- a/docs/locales/en/LC_MESSAGES/root/contributing.po +++ b/docs/locales/en/LC_MESSAGES/root/contributing.po @@ -579,7 +579,7 @@ msgstr "" msgid "" "Откройте `127.0.0.1:8000` в браузере, чтобы просмотреть сгенерированную " "документацию." -msgstr "Open `127.0.0.1:8000` in your browser to view the generated documentation." +msgstr "Open `127.0.0.1:8000` in your browser to presentation the generated documentation." #: ../../root/contributing.rst:233 msgid "" diff --git a/mock/local_test.py b/mock/local_test.py index e69de29..a4f7ca2 100644 --- a/mock/local_test.py +++ b/mock/local_test.py @@ -0,0 +1,14 @@ +from rich.console import Console + +from argenta.app.presentation.renderers import RichRenderer, Renderer, PlainRenderer, RendererMixin + + +def main(rend: Renderer): + pass + +def mm(tr) -> str | None: + pass + +main(RichRenderer(print, mm)) +main(PlainRenderer(print, mm)) +main() \ No newline at end of file diff --git a/src/argenta/app/models.py b/src/argenta/app/models.py index 29842db..5e9dcdd 100644 --- a/src/argenta/app/models.py +++ b/src/argenta/app/models.py @@ -8,7 +8,7 @@ from typing import Callable, Never, TypeAlias from rich.console import Console from argenta.app.autocompleter import AutoCompleter -from argenta.app.view_renderer.entity import PlainRenderer, RichRenderer, ViewRenderer +from argenta.app.presentation.renderers import PlainRenderer, RichRenderer, Renderer from argenta.app.dividing_line.models import DynamicDividingLine, StaticDividingLine from argenta.app.protocols import ( DescriptionMessageGenerator, @@ -27,6 +27,7 @@ from argenta.command.models import Command, InputCommand from argenta.response import Response from argenta.router import Router + Matches: TypeAlias = list[str] | list[Never] _ANSI_ESCAPE_RE: re.Pattern[str] = re.compile(r"\u001b\[[0-9;]*m") @@ -60,12 +61,12 @@ class BaseApp: self._messages_on_startup: list[str] = [] if self._override_system_messages: - self.view: ViewRenderer = PlainRenderer( + self.view: Renderer = PlainRenderer( print_func=self._print_func, most_similar_command_getter=self._most_similar_command ) else: - self.view: ViewRenderer = RichRenderer( + self.view: Renderer = RichRenderer( print_func=self._print_func, most_similar_command_getter=self._most_similar_command ) diff --git a/src/argenta/app/view_renderer/__init__.py b/src/argenta/app/presentation/__init__.py similarity index 100% rename from src/argenta/app/view_renderer/__init__.py rename to src/argenta/app/presentation/__init__.py diff --git a/src/argenta/app/view_renderer/entity.py b/src/argenta/app/presentation/renderers.py similarity index 61% rename from src/argenta/app/view_renderer/entity.py rename to src/argenta/app/presentation/renderers.py index 5633186..30101ab 100644 --- a/src/argenta/app/view_renderer/entity.py +++ b/src/argenta/app/presentation/renderers.py @@ -1,8 +1,10 @@ +from abc import ABC, abstractmethod from typing import Protocol, Iterable from art import text2art from rich.markup import escape +from argenta.app.registered_routers.entity import RegisteredRouters from argenta.response.entity import Response from argenta.command.models import InputCommand from argenta.app.protocols import ( @@ -10,23 +12,62 @@ from argenta.app.protocols import ( EmptyCommandHandler, MostSimilarCommandGetter, NonStandardBehaviorHandler, - Printer, + Printer ) -class ConcatenateRenderer: - def render_concatenated_messages_on_startup(self, messages: Iterable[str]) -> str: +class RendererMixin(ABC): + def __init__(self, print_func: Printer, most_similar_command_getter: MostSimilarCommandGetter) -> None: + self._print_func = print_func + self._most_similar_command_getter = most_similar_command_getter + + self._cached_command_groups_description: str | None = None + + @staticmethod + @abstractmethod + def generate_formatted_description_message_gen() -> DescriptionMessageGenerator: + raise NotImplementedError + + @staticmethod + def render_messages_on_startup(messages: Iterable[str]) -> str: return "\n".join(messages) + def render_command_groups_description(self, registered_routers: RegisteredRouters) -> str: + if self._cached_command_groups_description: + return self._cached_command_groups_description + command_groups_description = "" + for registered_router in registered_routers: + command_groups_description += "\n" + registered_router.title + for command_handler in registered_router.command_handlers: + handled_command = command_handler.handled_command + command_groups_description += self.generate_formatted_description_message_gen()( + handled_command.trigger, + handled_command.description, + ) + self._cached_command_groups_description = command_groups_description + return command_groups_description -class ViewRenderer(Protocol): - def render_prompt(self, text: str) -> str: ... + def generate_formatted_exit_command_handler(self, farewell_message: str) -> NonStandardBehaviorHandler[Response]: + return lambda _: self._print_func(farewell_message) - def render_initial_message(self, text: str) -> str: ... - def render_farewell_message(self, text: str) -> str: ... +class Renderer(Protocol): + @staticmethod + def render_prompt(text: str) -> str: ... - def generate_formatted_description_message_gen(self) -> DescriptionMessageGenerator: ... + @staticmethod + def render_initial_message(text: str) -> str: ... + + @staticmethod + def render_farewell_message(text: str) -> str: ... + + @staticmethod + def render_messages_on_startup(messages: Iterable[str]) -> str: ... + + @staticmethod + def generate_formatted_description_message_gen() -> DescriptionMessageGenerator: ... + + def render_command_groups_description(self, registered_routers: RegisteredRouters) -> str: ... def generate_formatted_incorrect_input_syntax_handler(self) -> NonStandardBehaviorHandler[str]: ... @@ -39,18 +80,17 @@ class ViewRenderer(Protocol): def generate_formatted_exit_command_handler(self, farewell_message: str) -> NonStandardBehaviorHandler[Response]: ... -class RichRenderer(ViewRenderer): - def __init__(self, print_func: Printer, most_similar_command_getter: MostSimilarCommandGetter) -> None: - self._print_func = print_func - self._most_similar_command_getter = most_similar_command_getter - - def render_prompt(self, text: str) -> str: +class RichRenderer(RendererMixin): + @staticmethod + def render_prompt(text: str) -> str: return f"{text}" - def render_initial_message(self, text: str) -> str: + @staticmethod + def render_initial_message(text: str) -> str: return f"[bold red]{text2art(text, font='tarty1')}[/bold red]" - def render_farewell_message(self, text: str) -> str: + @staticmethod + def render_farewell_message(text: str) -> str: return ( "[bold red]" + str(text2art(text, font="chanky")) @@ -58,7 +98,8 @@ class RichRenderer(ViewRenderer): + "[red i]https://github.com/koloideal/Argenta[/red i] | [red bold i]made by kolo[/red bold i]" ) - def generate_formatted_description_message_gen(self) -> DescriptionMessageGenerator: + @staticmethod + def generate_formatted_description_message_gen() -> DescriptionMessageGenerator: return lambda command, description: ( f"[bold red]{escape('[' + command + ']')}[/bold red] " f"[blue dim]*=*=*[/blue dim] " @@ -79,33 +120,28 @@ class RichRenderer(ViewRenderer): cmd_trg: str = command.trigger mst_sim_cmd: str | None = self._most_similar_command_getter(cmd_trg) self._print_func( - f"[red]Unknown command:[/red][blue]{escape(cmd_trg)}[/blue][red]" + - (f", most similar:[/red][blue]{mst_sim_cmd}[/blue]" - if mst_sim_cmd - else "") + f"[red]Unknown command:[/red][blue]{escape(cmd_trg)}[/blue][red]" + + (f", most similar:[/red][blue]{mst_sim_cmd}[/blue]" if mst_sim_cmd else "") ) return unknown_command_handler - def generate_formatted_exit_command_handler(self, farewell_message: str) -> NonStandardBehaviorHandler[Response]: - return lambda _: self._print_func(farewell_message) - -class PlainRenderer(ViewRenderer): - def __init__(self, print_func: Printer, most_similar_command_getter: MostSimilarCommandGetter) -> None: - self._print_func = print_func - self._most_similar_command_getter = most_similar_command_getter - - def render_prompt(self, text: str) -> str: +class PlainRenderer(RendererMixin): + @staticmethod + def render_prompt(text: str) -> str: return text - def render_initial_message(self, text: str) -> str: + @staticmethod + def render_initial_message(text: str) -> str: return text - def render_farewell_message(self, text: str) -> str: + @staticmethod + def render_farewell_message(text: str) -> str: return f"{text} | https://github.com/koloideal/Argenta | made by kolo" - def generate_formatted_description_message_gen(self) -> DescriptionMessageGenerator: + @staticmethod + def generate_formatted_description_message_gen() -> DescriptionMessageGenerator: return lambda command, description: f"{command} *=*=* {description}" def generate_formatted_incorrect_input_syntax_handler(self) -> NonStandardBehaviorHandler[str]: @@ -127,6 +163,3 @@ class PlainRenderer(ViewRenderer): ) return unknown_command_handler - - def generate_formatted_exit_command_handler(self, farewell_message: str) -> NonStandardBehaviorHandler[Response]: - return lambda _: self._print_func(farewell_message) diff --git a/src/argenta/app/presentation/viewers.py b/src/argenta/app/presentation/viewers.py new file mode 100644 index 0000000..e69de29