final work on autocomplete

This commit is contained in:
2025-04-09 23:32:21 +03:00
parent 592d128ef6
commit 8b496aa782
10 changed files with 100 additions and 124 deletions
+2 -2
View File
@@ -1,4 +1,4 @@
__all__ = ["Autocompleter"]
__all__ = ["AutoCompleter"]
from argenta.app.autocompleter.models import Autocompleter
from argenta.app.autocompleter.entity import AutoCompleter
+45
View File
@@ -0,0 +1,45 @@
import readline
import os
class AutoCompleter:
def __init__(self, history_filename: str = False, autocomplete_button: str = 'tab'):
self.history_filename = history_filename
self.autocomplete_button = autocomplete_button
self.matches = []
def complete(self, text, state):
matches = sorted(cmd for cmd in self.get_history_items() if cmd.startswith(text))
if len(matches) > 1:
common_prefix = matches[0]
for match in matches[1:]:
i = 0
while i < len(common_prefix) and i < len(match) and common_prefix[i] == match[i]:
i += 1
common_prefix = common_prefix[:i]
if state == 0:
readline.insert_text(common_prefix[len(text):])
readline.redisplay()
return None
elif len(matches) == 1:
return matches[0] if state == 0 else None
else:
return None
def initial_setup(self):
if self.history_filename:
if os.path.exists(self.history_filename):
readline.read_history_file(self.history_filename)
readline.set_completer(self.complete)
readline.set_completer_delims(readline.get_completer_delims().replace(' ', ''))
readline.parse_and_bind(f'{self.autocomplete_button}: complete')
def exit_setup(self):
if self.history_filename:
readline.write_history_file(self.history_filename)
@staticmethod
def get_history_items():
return [readline.get_history_item(i) for i in range(1, readline.get_current_history_length() + 1)]
-58
View File
@@ -1,58 +0,0 @@
import readline
import os
class Autocompleter:
def __init__(self, history_filename: str = './completer.hist', autocomplete_button: str = 'tab'):
self.history_filename = history_filename
self.autocomplete_button = autocomplete_button
self.matches = []
def complete(self, text, state):
if state == 0:
history_values = self.get_history_items()
if text:
self.matches = sorted(h for h in history_values if h and h.startswith(text))
else:
self.matches = []
try:
response = self.matches[state]
except IndexError:
response = None
return response
def initial_setup(self):
if os.path.exists(self.history_filename):
readline.read_history_file(self.history_filename)
readline.set_completer(self.complete)
readline.parse_and_bind(f'{self.autocomplete_button}: complete')
def write_command_to_history(self):
readline.write_history_file(self.history_filename)
@staticmethod
def get_history_items():
return [readline.get_history_item(i) for i in range(1, readline.get_current_history_length() + 1)]
def inputting():
autocompleter = Autocompleter()
autocompleter.initial_setup()
print(f'Максимальная длина файла истории: {readline.get_history_length()}')
print(f'История запуска:{autocompleter.get_history_items()}')
while True:
line = input('\n!("stop" to quit) Ввод текста: => ')
if line == 'stop':
print(f'Конец записи истории: {autocompleter.get_history_items()}')
autocompleter.write_command_to_history()
break
inputting()
+1
View File
@@ -5,4 +5,5 @@ from dataclasses import dataclass
class PredeterminedMessages:
USAGE = '[b dim]Usage[/b dim]: [i]<command> <[green]flags[/green]>[/i]'
HELP = '[b dim]Help[/b dim]: [i]<command>[/i] [b red]--help[/b red]'
AUTOCOMPLETE = '[b dim]Autocomplete[/b dim]: [i]<part>[/i] [bold]<tab>'
+5 -2
View File
@@ -8,7 +8,7 @@ import re
from argenta.command.models import Command, InputCommand
from argenta.router import Router
from argenta.router.defaults import system_router
from argenta.app.autocompleter import Autocompleter
from argenta.app.autocompleter import AutoCompleter
from argenta.app.dividing_line.models import StaticDividingLine, DynamicDividingLine
from argenta.command.exceptions import (UnprocessedInputFlagException,
RepeatedInputFlagsException,
@@ -34,7 +34,7 @@ class AppInit:
dividing_line: StaticDividingLine | DynamicDividingLine = StaticDividingLine(),
repeat_command_groups: bool = True,
full_override_system_messages: bool = False,
autocompleter: Autocompleter = Autocompleter(),
autocompleter: AutoCompleter = AutoCompleter(),
print_func: Callable[[str], None] = Console().print) -> None:
self._prompt = prompt
self._print_func = print_func
@@ -45,6 +45,7 @@ class AppInit:
self._ignore_command_register = ignore_command_register
self._repeat_command_groups_description = repeat_command_groups
self._full_override_system_messages = full_override_system_messages
self._autocompleter = autocompleter
self._farewell_message = farewell_message
self._initial_message = initial_message
@@ -189,6 +190,7 @@ class AppSetups(AppValidators, AppPrinters):
self._setup_system_router()
self._validate_number_of_routers()
self._validate_included_routers()
self._autocompleter.initial_setup()
self._print_func(self._initial_message)
@@ -223,6 +225,7 @@ class App(AppSetters, AppNonStandardHandlers, AppSetups):
continue
if self._is_exit_command(input_command):
self._autocompleter.exit_setup()
return
if self._is_unknown_command(input_command):
+4 -4
View File
@@ -7,10 +7,10 @@ from argenta.router.command_handlers.entity import CommandHandlers
from argenta.router.command_handler.entity import CommandHandler
from argenta.command.flag.models import Flag, Flags, InputFlags
from argenta.router.exceptions import (RepeatedFlagNameException,
TooManyTransferredArgsException,
RequiredArgumentNotPassedException,
IncorrectNumberOfHandlerArgsException,
TriggerCannotContainSpacesException)
TooManyTransferredArgsException,
RequiredArgumentNotPassedException,
IncorrectNumberOfHandlerArgsException,
TriggerCannotContainSpacesException)
class Router:
+11
View File
@@ -0,0 +1,11 @@
test
q
P
q
S
S --host 125
q
S --host 125.0123
0
U
q
+24 -50
View File
@@ -1,58 +1,32 @@
import readline
import os
HISTORY_FILENAME = 'completer.hist'
def completer(text, state):
matches = sorted(cmd for cmd in get_history_items() if cmd.startswith(text))
if len(matches) > 1:
common_prefix = matches[0]
for match in matches[1:]:
i = 0
while i < len(common_prefix) and i < len(match) and common_prefix[i] == match[i]:
i += 1
common_prefix = common_prefix[:i]
if state == 0:
readline.insert_text(common_prefix[len(text):])
readline.redisplay()
return None
elif len(matches) == 1:
return matches[0] if state == 0 else None
else:
return None
readline.set_completer(completer)
readline.parse_and_bind("tab: complete")
def get_history_items():
return [readline.get_history_item(i) for i in range(1, readline.get_current_history_length() + 1)]
class HistoryCompleter:
def __init__(self):
self.matches = []
return
def complete(self, text, state):
response = None
if state == 0:
history_values = get_history_items()
if text:
self.matches = sorted(h
for h in history_values
if h and h.startswith(text))
else:
self.matches = []
try:
response = self.matches[state]
except IndexError:
response = None
return response
def inputing():
if os.path.exists(HISTORY_FILENAME):
readline.read_history_file(HISTORY_FILENAME)
print(f'Максимальная длина файла истории: {readline.get_history_length()}')
print(f'История запуска:{get_history_items()}')
while True:
try:
while True:
line = input('!("stop" to quit) Ввод текста: => ')
if line == 'stop':
break
if line:
print(f'Добавление "{line}" в файл истории.')
finally:
print(f'Конец записи истории: {get_history_items()}')
readline.write_history_file(HISTORY_FILENAME)
# Регистрация класса 'HistoryCompleter'
readline.set_completer(HistoryCompleter().complete)
# Регистрация клавиши `tab` для автодополнения
readline.parse_and_bind('tab: complete')
# Запрос текста
inputing()
line = input('> ')
except EOFError:
break
+3 -7
View File
@@ -1,36 +1,32 @@
from rich.console import Console
from argenta.command import Command
from argenta.command.flag import Flags, InputFlags, Flag
from argenta.command.flag import Flags, InputFlags
from argenta.command.flag.defaults import PredeterminedFlags
from argenta.router import Router
from .handlers_implementation.help_command import help_command
work_router: Router = Router(title='Work points:')
work_router.set_invalid_input_flag_handler(lambda flag: print(f'Invalid input flag: {flag.get_string_entity()} {flag.get_value() if flag.get_value() else ''}'))
settings_router: Router = Router(title='Settings points:')
console = Console()
flag = Flag('test')
@work_router.command(Command('0', 'Get Help'))
def command_help():
help_command()
@work_router.command(Command('S', 'Start Solving', Flags(PredeterminedFlags.HOST, PredeterminedFlags.PORT, flag)))
@work_router.command(Command('S', 'Start Solving', Flags(PredeterminedFlags.HOST, PredeterminedFlags.PORT)))
def command_start_solving(args: InputFlags):
print(args.get_flag('test'))
@settings_router.command(Command('U', 'Update WordMath'))
def command_update():
pass
print('eeeeeee')
+5 -1
View File
@@ -3,15 +3,19 @@ from mock.mock_app.handlers.routers import work_router, settings_router
from argenta.app import App
from argenta.app.defaults import PredeterminedMessages
from argenta.app.dividing_line import DynamicDividingLine
from argenta.app.autocompleter import AutoCompleter
app: App = App(dividing_line=DynamicDividingLine())
autocompleter = AutoCompleter('./mock/.history')
app: App = App(dividing_line=DynamicDividingLine(),
autocompleter=autocompleter)
def main():
app.include_routers(work_router, settings_router)
app.add_message_on_startup(PredeterminedMessages.USAGE)
app.add_message_on_startup(PredeterminedMessages.AUTOCOMPLETE)
app.add_message_on_startup(PredeterminedMessages.HELP + '\n\n')
app.start_polling()