mirror of
https://github.com/koloideal/Argenta.git
synced 2026-06-10 18:15:28 +03:00
final work on autocomplete
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
__all__ = ["Autocompleter"]
|
__all__ = ["AutoCompleter"]
|
||||||
|
|
||||||
|
|
||||||
from argenta.app.autocompleter.models import Autocompleter
|
from argenta.app.autocompleter.entity import AutoCompleter
|
||||||
|
|||||||
@@ -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)]
|
||||||
|
|
||||||
@@ -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()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -5,4 +5,5 @@ from dataclasses import dataclass
|
|||||||
class PredeterminedMessages:
|
class PredeterminedMessages:
|
||||||
USAGE = '[b dim]Usage[/b dim]: [i]<command> <[green]flags[/green]>[/i]'
|
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]'
|
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>'
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import re
|
|||||||
from argenta.command.models import Command, InputCommand
|
from argenta.command.models import Command, InputCommand
|
||||||
from argenta.router import Router
|
from argenta.router import Router
|
||||||
from argenta.router.defaults import system_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.app.dividing_line.models import StaticDividingLine, DynamicDividingLine
|
||||||
from argenta.command.exceptions import (UnprocessedInputFlagException,
|
from argenta.command.exceptions import (UnprocessedInputFlagException,
|
||||||
RepeatedInputFlagsException,
|
RepeatedInputFlagsException,
|
||||||
@@ -34,7 +34,7 @@ class AppInit:
|
|||||||
dividing_line: StaticDividingLine | DynamicDividingLine = StaticDividingLine(),
|
dividing_line: StaticDividingLine | DynamicDividingLine = StaticDividingLine(),
|
||||||
repeat_command_groups: bool = True,
|
repeat_command_groups: bool = True,
|
||||||
full_override_system_messages: bool = False,
|
full_override_system_messages: bool = False,
|
||||||
autocompleter: Autocompleter = Autocompleter(),
|
autocompleter: AutoCompleter = AutoCompleter(),
|
||||||
print_func: Callable[[str], None] = Console().print) -> None:
|
print_func: Callable[[str], None] = Console().print) -> None:
|
||||||
self._prompt = prompt
|
self._prompt = prompt
|
||||||
self._print_func = print_func
|
self._print_func = print_func
|
||||||
@@ -45,6 +45,7 @@ class AppInit:
|
|||||||
self._ignore_command_register = ignore_command_register
|
self._ignore_command_register = ignore_command_register
|
||||||
self._repeat_command_groups_description = repeat_command_groups
|
self._repeat_command_groups_description = repeat_command_groups
|
||||||
self._full_override_system_messages = full_override_system_messages
|
self._full_override_system_messages = full_override_system_messages
|
||||||
|
self._autocompleter = autocompleter
|
||||||
|
|
||||||
self._farewell_message = farewell_message
|
self._farewell_message = farewell_message
|
||||||
self._initial_message = initial_message
|
self._initial_message = initial_message
|
||||||
@@ -189,6 +190,7 @@ class AppSetups(AppValidators, AppPrinters):
|
|||||||
self._setup_system_router()
|
self._setup_system_router()
|
||||||
self._validate_number_of_routers()
|
self._validate_number_of_routers()
|
||||||
self._validate_included_routers()
|
self._validate_included_routers()
|
||||||
|
self._autocompleter.initial_setup()
|
||||||
|
|
||||||
self._print_func(self._initial_message)
|
self._print_func(self._initial_message)
|
||||||
|
|
||||||
@@ -223,6 +225,7 @@ class App(AppSetters, AppNonStandardHandlers, AppSetups):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if self._is_exit_command(input_command):
|
if self._is_exit_command(input_command):
|
||||||
|
self._autocompleter.exit_setup()
|
||||||
return
|
return
|
||||||
|
|
||||||
if self._is_unknown_command(input_command):
|
if self._is_unknown_command(input_command):
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
test
|
||||||
|
q
|
||||||
|
P
|
||||||
|
q
|
||||||
|
S
|
||||||
|
S --host 125
|
||||||
|
q
|
||||||
|
S --host 125.0123
|
||||||
|
0
|
||||||
|
U
|
||||||
|
q
|
||||||
+23
-49
@@ -1,58 +1,32 @@
|
|||||||
import readline
|
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():
|
def get_history_items():
|
||||||
return [readline.get_history_item(i) for i in range(1, readline.get_current_history_length() + 1)]
|
return [readline.get_history_item(i) for i in range(1, readline.get_current_history_length() + 1)]
|
||||||
|
|
||||||
|
while True:
|
||||||
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:
|
try:
|
||||||
response = self.matches[state]
|
line = input('> ')
|
||||||
except IndexError:
|
except EOFError:
|
||||||
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()}')
|
|
||||||
try:
|
|
||||||
while True:
|
|
||||||
line = input('!("stop" to quit) Ввод текста: => ')
|
|
||||||
if line == 'stop':
|
|
||||||
break
|
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()
|
|
||||||
@@ -1,36 +1,32 @@
|
|||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
|
|
||||||
from argenta.command import Command
|
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.command.flag.defaults import PredeterminedFlags
|
||||||
from argenta.router import Router
|
from argenta.router import Router
|
||||||
from .handlers_implementation.help_command import help_command
|
from .handlers_implementation.help_command import help_command
|
||||||
|
|
||||||
|
|
||||||
work_router: Router = Router(title='Work points:')
|
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:')
|
settings_router: Router = Router(title='Settings points:')
|
||||||
|
|
||||||
|
|
||||||
console = Console()
|
console = Console()
|
||||||
|
|
||||||
flag = Flag('test')
|
|
||||||
|
|
||||||
|
|
||||||
@work_router.command(Command('0', 'Get Help'))
|
@work_router.command(Command('0', 'Get Help'))
|
||||||
def command_help():
|
def command_help():
|
||||||
help_command()
|
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):
|
def command_start_solving(args: InputFlags):
|
||||||
print(args.get_flag('test'))
|
print(args.get_flag('test'))
|
||||||
|
|
||||||
|
|
||||||
@settings_router.command(Command('U', 'Update WordMath'))
|
@settings_router.command(Command('U', 'Update WordMath'))
|
||||||
def command_update():
|
def command_update():
|
||||||
pass
|
print('eeeeeee')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,15 +3,19 @@ from mock.mock_app.handlers.routers import work_router, settings_router
|
|||||||
from argenta.app import App
|
from argenta.app import App
|
||||||
from argenta.app.defaults import PredeterminedMessages
|
from argenta.app.defaults import PredeterminedMessages
|
||||||
from argenta.app.dividing_line import DynamicDividingLine
|
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():
|
def main():
|
||||||
app.include_routers(work_router, settings_router)
|
app.include_routers(work_router, settings_router)
|
||||||
|
|
||||||
app.add_message_on_startup(PredeterminedMessages.USAGE)
|
app.add_message_on_startup(PredeterminedMessages.USAGE)
|
||||||
|
app.add_message_on_startup(PredeterminedMessages.AUTOCOMPLETE)
|
||||||
app.add_message_on_startup(PredeterminedMessages.HELP + '\n\n')
|
app.add_message_on_startup(PredeterminedMessages.HELP + '\n\n')
|
||||||
|
|
||||||
app.start_polling()
|
app.start_polling()
|
||||||
|
|||||||
Reference in New Issue
Block a user