argenta 0.4.10__py3-none-any.whl → 0.5.0a0__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.
@@ -0,0 +1,4 @@
1
+ __all__ = ["AutoCompleter"]
2
+
3
+
4
+ from argenta.app.autocompleter.entity import AutoCompleter
@@ -0,0 +1,48 @@
1
+ import os
2
+
3
+ import readline
4
+
5
+
6
+ class AutoCompleter:
7
+ def __init__(self, history_filename: str = False, autocomplete_button: str = 'tab'):
8
+ self.history_filename = history_filename
9
+ self.autocomplete_button = autocomplete_button
10
+ self.matches = []
11
+
12
+ def complete(self, text, state):
13
+ matches = sorted(cmd for cmd in self.get_history_items() if cmd.startswith(text))
14
+ if len(matches) > 1:
15
+ common_prefix = matches[0]
16
+ for match in matches[1:]:
17
+ i = 0
18
+ while i < len(common_prefix) and i < len(match) and common_prefix[i] == match[i]:
19
+ i += 1
20
+ common_prefix = common_prefix[:i]
21
+ if state == 0:
22
+ readline.insert_text(common_prefix[len(text):])
23
+ readline.redisplay()
24
+ return None
25
+ elif len(matches) == 1:
26
+ return matches[0] if state == 0 else None
27
+ else:
28
+ return None
29
+
30
+ def initial_setup(self, all_commands: list[str]):
31
+ if self.history_filename:
32
+ if os.path.exists(self.history_filename):
33
+ readline.read_history_file(self.history_filename)
34
+ else:
35
+ for line in all_commands:
36
+ readline.add_history(line)
37
+
38
+ readline.set_completer(self.complete)
39
+ readline.set_completer_delims(readline.get_completer_delims().replace(' ', ''))
40
+ readline.parse_and_bind(f'{self.autocomplete_button}: complete')
41
+
42
+ def exit_setup(self):
43
+ if self.history_filename:
44
+ readline.write_history_file(self.history_filename)
45
+
46
+ @staticmethod
47
+ def get_history_items():
48
+ return [readline.get_history_item(i) for i in range(1, readline.get_current_history_length() + 1)]
argenta/app/defaults.py CHANGED
@@ -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
 
argenta/app/exceptions.py CHANGED
@@ -3,16 +3,6 @@ class InvalidRouterInstanceException(Exception):
3
3
  return "Invalid Router Instance"
4
4
 
5
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
6
  class NoRegisteredRoutersException(Exception):
17
7
  def __str__(self):
18
8
  return "No Registered Router Found"
argenta/app/models.py CHANGED
@@ -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,28 +27,29 @@ 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: str = 'Q',
30
- exit_command_description: str = 'Exit command',
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
  full_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
45
  self._full_override_system_messages = full_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
- self._description_message_pattern: str = '[bold red][{command}][/bold red] [blue dim]*=*=*[/blue dim] [bold yellow italic]{description}'
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
 
@@ -59,14 +61,8 @@ class AppInit:
59
61
 
60
62
 
61
63
  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)
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
- self._print_func(registered_router.get_title())
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._description_message_pattern.format(
98
- command=command_handler.get_handled_command().get_trigger(),
99
- description=command_handler.get_handled_command().get_description()))
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,7 +108,7 @@ 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
@@ -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(Command(self._exit_command, self._exit_command_description))
173
+ @system_router.command(self._exit_command)
171
174
  def exit_command():
172
175
  self._exit_command_handler()
173
176
 
@@ -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):
argenta/command/models.py CHANGED
@@ -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
argenta/router/entity.py CHANGED
@@ -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
  Metadata-Version: 2.3
2
2
  Name: argenta
3
- Version: 0.4.10
3
+ Version: 0.5.0a0
4
4
  Summary: Python library for creating TUI
5
5
  License: MIT
6
6
  Author: kolo
@@ -1,10 +1,12 @@
1
1
  argenta/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  argenta/app/__init__.py,sha256=I8FTXU17ajDI-hbC6Rw0LxLmvDYipdQaos3v1pmu14E,57
3
- argenta/app/defaults.py,sha256=7ej4G-4dieMlichfuQhw5XgabF15X-vAa8k02ZfkdUs,234
3
+ argenta/app/autocompleter/__init__.py,sha256=VT_p3QA78UnczV7pYR2NnwQ0Atd8mnDUnLazvUQNqJk,93
4
+ argenta/app/autocompleter/entity.py,sha256=ah85zH_RdibypTXQmgzjUU13TdhKdGpep0BgNcT_w_o,1827
5
+ argenta/app/defaults.py,sha256=D0z9yGnfF8hhWUxHCvBhxTrxg6a9rPiySAn2Fyy7TXQ,311
4
6
  argenta/app/dividing_line/__init__.py,sha256=jJZDDZix8XYCAUWW4FzGJH0JmJlchYcx0FPWifjgv1I,147
5
7
  argenta/app/dividing_line/models.py,sha256=ueBDmy1hfYzGAr1X2G2Mw0hjES7YQBtP7N3TLBDz9h0,700
6
- argenta/app/exceptions.py,sha256=uCkb1VqEIZQuVDY0ZsfDc3yCbySwLpV5CdIT7iaGYRM,928
7
- argenta/app/models.py,sha256=burvSSmUW-1FnhGYgHwLTW6jcW3ENFoB1wdmwwyYAog,12121
8
+ argenta/app/exceptions.py,sha256=oTvec3ZGX_tS1nqa0pLLAPqMlhrLS6SsXY2lYiOwIVM,465
9
+ argenta/app/models.py,sha256=yH6LGq_bA525JCq-cCl-O8v_JLbYLC6q30ZftPW5e2k,12736
8
10
  argenta/app/registered_routers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
11
  argenta/app/registered_routers/entity.py,sha256=OQZyrF4eoCoDHzRJ22zZxhNEx-bOUDu7NZIFDfO-fuY,688
10
12
  argenta/command/__init__.py,sha256=Plo2Da0fhq8H1eo2mg7nA1-OBLuGjK2BYpDGRvGGMIU,67
@@ -12,16 +14,16 @@ argenta/command/exceptions.py,sha256=HOgddtXLDgk9Wx6c_GnzW3bMAMU5CuUnUyxjW3cVHRo
12
14
  argenta/command/flag/__init__.py,sha256=PaZAaqU3DgyO1o5do-xKhWV6TyEuOSaQTmE4VbPY6JA,136
13
15
  argenta/command/flag/defaults.py,sha256=ktKmDT0rSSBoFUghTlEQ6OletoFxCiD37hRzO73mUUc,875
14
16
  argenta/command/flag/models.py,sha256=IY0FHyAFD9O1ZxSaq6NR9gSTkldoQGrKVoGrAbnmEuA,3769
15
- argenta/command/models.py,sha256=1p_QZ5cQq47t915zHehEx-S0smTqj4DDnjZGn_qZlOA,4436
17
+ argenta/command/models.py,sha256=QhpxFuq-yLoxxegEQay0ZFFJT4-W1GOayDzM0gz_41Q,4594
16
18
  argenta/router/__init__.py,sha256=ldrIWTXNLXUAMAGQ8ex4e8nMso_fhi01nZi2DVzHnnk,66
17
19
  argenta/router/command_handler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- argenta/router/command_handler/entity.py,sha256=8sWhP89c0FavFBITJmH9c8wNn2ipW_6-_obzjkwXueU,646
20
+ argenta/router/command_handler/entity.py,sha256=wVBl-Z3oq3aDUYmGBeudM7TxPZZrUEdZw7BImWJL5LE,652
19
21
  argenta/router/command_handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
22
  argenta/router/command_handlers/entity.py,sha256=KgFKjAMUr_mOcn9xahTxMUKB6lIxXgqCuAsuc4TgP6E,747
21
23
  argenta/router/defaults.py,sha256=huftOg1HMjrT_R2SHHOL4eJ5uZHspNEYBSg-mCq9xhU,126
22
- argenta/router/entity.py,sha256=afQn5jrDBrcd5QUzeBwRPfazOO6x0yYSXcmvHYhJpDw,4997
24
+ argenta/router/entity.py,sha256=d9S9Af9vACAgUaiPq-CgVGrb7KcAZYfYm3oavVAceI8,5900
23
25
  argenta/router/exceptions.py,sha256=tdeaR8zDvnytgRYo_wQWKHt3if2brapgauIhhMIsTsA,678
24
- argenta-0.4.10.dist-info/LICENSE,sha256=zmqoGh2n5rReBv4s8wPxF_gZEZDgauJYSPMuPczgOiU,1082
25
- argenta-0.4.10.dist-info/METADATA,sha256=uVIrDo-uxIWV7qS1pGXZAHL95Sok2KQ-U8tJoZxovGg,20986
26
- argenta-0.4.10.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
27
- argenta-0.4.10.dist-info/RECORD,,
26
+ argenta-0.5.0a0.dist-info/LICENSE,sha256=zmqoGh2n5rReBv4s8wPxF_gZEZDgauJYSPMuPczgOiU,1082
27
+ argenta-0.5.0a0.dist-info/METADATA,sha256=5sPiqrm-Ab3I3exQFI1FtBNmPOwXgJqICYpVzkLLcWc,20987
28
+ argenta-0.5.0a0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
29
+ argenta-0.5.0a0.dist-info/RECORD,,