mirror of
https://github.com/koloideal/Argenta.git
synced 2026-06-10 10:05:28 +03:00
start work
This commit is contained in:
+93
-52
@@ -1,61 +1,102 @@
|
|||||||
import math
|
__all__ = ["AutoCompleter"]
|
||||||
|
|
||||||
|
from prompt_toolkit import PromptSession, HTML
|
||||||
|
from prompt_toolkit.completion import Completer, Completion
|
||||||
|
from prompt_toolkit.document import Document
|
||||||
|
from prompt_toolkit.history import History, ThreadedHistory, FileHistory, InMemoryHistory
|
||||||
|
from prompt_toolkit.key_binding import KeyBindings
|
||||||
|
|
||||||
|
|
||||||
def estimate_nth_prime_upper_bound(n: int):
|
class HistoryCompleter(Completer):
|
||||||
if n < 6:
|
def __init__(self, history_container: History, static_commands: set[str]) -> None:
|
||||||
return 15
|
self.history_container: History = history_container
|
||||||
|
self.static_commands: set[str] = static_commands
|
||||||
|
|
||||||
log_n = math.log(n)
|
def get_completions(self, document: Document, complete_event):
|
||||||
log_log_n = math.log(log_n)
|
text: str = document.text_before_cursor
|
||||||
|
history_items: set[str] = set(self.history_container.load_history_strings())
|
||||||
|
all_candidates: set[str] = history_items.union(self.static_commands)
|
||||||
|
matches: list[str] = sorted(cmd for cmd in all_candidates if cmd.startswith(text))
|
||||||
|
|
||||||
if n < 100:
|
if not matches:
|
||||||
return int(n * (log_n + log_log_n) * 1.5)
|
return
|
||||||
elif n < 1000:
|
|
||||||
return int(n * (log_n + log_log_n) * 1.3)
|
for match in matches:
|
||||||
elif n >= 8009824:
|
yield Completion(
|
||||||
return int(n * (log_n + log_log_n - 1 + 1.8 * log_log_n / log_n))
|
match,
|
||||||
|
start_position=-len(text),
|
||||||
|
display=match
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _find_common_prefix(matches: list[str]) -> str:
|
||||||
|
if not matches:
|
||||||
|
return ""
|
||||||
|
common: str = matches[0]
|
||||||
|
for match in matches[1:]:
|
||||||
|
i: int = 0
|
||||||
|
while i < len(common) and i < len(match) and common[i] == match[i]:
|
||||||
|
i += 1
|
||||||
|
common = common[:i]
|
||||||
|
return common
|
||||||
|
|
||||||
|
|
||||||
|
class AutoCompleter:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
history_filename: str | None = None,
|
||||||
|
autocomplete_button: str = "tab"
|
||||||
|
) -> None:
|
||||||
|
self.history_filename: str | None = history_filename
|
||||||
|
self.autocomplete_button: str = autocomplete_button
|
||||||
|
self._session: PromptSession | None = None
|
||||||
|
|
||||||
|
def initial_setup(self, all_commands: set[str]) -> None:
|
||||||
|
kb = KeyBindings()
|
||||||
|
|
||||||
|
def _(event):
|
||||||
|
buff = event.app.current_buffer
|
||||||
|
|
||||||
|
if buff.complete_state:
|
||||||
|
buff.complete_next()
|
||||||
else:
|
else:
|
||||||
return int(n * (log_n + log_log_n - 1 + 2.0 * log_log_n / log_n))
|
completions = list(buff.completer.get_completions(buff.document, None))
|
||||||
|
if len(completions) == 1:
|
||||||
|
buff.apply_completion(completions[0])
|
||||||
|
else:
|
||||||
|
buff.start_completion(select_first=False)
|
||||||
|
|
||||||
|
kb.add(self.autocomplete_button)(_)
|
||||||
|
|
||||||
|
if self.history_filename:
|
||||||
|
history = FileHistory(self.history_filename)
|
||||||
|
history = ThreadedHistory(history)
|
||||||
|
else:
|
||||||
|
history = InMemoryHistory()
|
||||||
|
|
||||||
|
self._session = PromptSession(
|
||||||
|
history=history,
|
||||||
|
completer=HistoryCompleter(history, all_commands),
|
||||||
|
complete_while_typing=False,
|
||||||
|
key_bindings=kb,
|
||||||
|
)
|
||||||
|
|
||||||
|
def prompt(self, prompt_text: str | HTML = ">>> ") -> str:
|
||||||
|
if self._session is None:
|
||||||
|
raise RuntimeError("Call initial_setup() before using prompt()")
|
||||||
|
return self._session.prompt(
|
||||||
|
HTML(f"<b><gray>{prompt_text}</gray></b>") if isinstance(prompt_text, str) else prompt_text
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def odd_dig_primes(n: int) -> list[int]:
|
if __name__ == "__main__":
|
||||||
nums = {k: True for k in range(2, n+1)}
|
test_commands: set[str] = {"start", "qwertyu", "stop", "exit"}
|
||||||
|
hist_file: str = "history.txt"
|
||||||
|
|
||||||
for num, is_checkable in nums.items():
|
ac: AutoCompleter = AutoCompleter(autocomplete_button='tab')
|
||||||
if not is_checkable:
|
ac.initial_setup(test_commands)
|
||||||
continue
|
|
||||||
|
|
||||||
if nums[2]:
|
while True:
|
||||||
nums[2] = False
|
inp: str = ac.prompt(">>> ").strip()
|
||||||
|
if inp == "exit":
|
||||||
for x in range(num * num, n, num):
|
break
|
||||||
nums[x] = False
|
|
||||||
|
|
||||||
primes = len([x for x in nums.items() if x[1]])
|
|
||||||
max_prime = max([x[0] for x in nums.items() if x[1]])
|
|
||||||
|
|
||||||
upper_bound = estimate_nth_prime_upper_bound(primes+1)
|
|
||||||
print(upper_bound)
|
|
||||||
nums2 = {k: True for k in range(2, upper_bound)}
|
|
||||||
|
|
||||||
for num, is_checkable in nums2.items():
|
|
||||||
if not is_checkable:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if nums2[2]:
|
|
||||||
nums2[2] = False
|
|
||||||
|
|
||||||
for x in range(num * num, upper_bound, num):
|
|
||||||
nums2[x] = False
|
|
||||||
|
|
||||||
print([x for x in nums2.items() if x[1]])
|
|
||||||
|
|
||||||
next_prime_after_max = [x[0] for x in nums2.items() if x[1]][-1]
|
|
||||||
|
|
||||||
return [
|
|
||||||
primes,
|
|
||||||
max_prime,
|
|
||||||
next_prime_after_max
|
|
||||||
]
|
|
||||||
|
|
||||||
print(odd_dig_primes(13))
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ dependencies = [
|
|||||||
"art (>=6.4,<7.0)",
|
"art (>=6.4,<7.0)",
|
||||||
"pyreadline3>=3.5.4; sys_platform == 'win32'",
|
"pyreadline3>=3.5.4; sys_platform == 'win32'",
|
||||||
"dishka>=1.7.2",
|
"dishka>=1.7.2",
|
||||||
|
"prompt-toolkit>=3.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[dependency-groups]
|
[dependency-groups]
|
||||||
|
|||||||
@@ -1,97 +1,89 @@
|
|||||||
__all__ = ["AutoCompleter"]
|
__all__ = ["AutoCompleter"]
|
||||||
|
|
||||||
import os
|
from prompt_toolkit import PromptSession, HTML
|
||||||
import readline
|
from prompt_toolkit.completion import Completer, Completion
|
||||||
from typing import Never
|
from prompt_toolkit.document import Document
|
||||||
|
from prompt_toolkit.history import History, ThreadedHistory, FileHistory, InMemoryHistory
|
||||||
|
from prompt_toolkit.key_binding import KeyBindings
|
||||||
|
|
||||||
|
|
||||||
|
class HistoryCompleter(Completer):
|
||||||
|
def __init__(self, history_container: History, static_commands: set[str]) -> None:
|
||||||
|
self.history_container: History = history_container
|
||||||
|
self.static_commands: set[str] = static_commands
|
||||||
|
|
||||||
|
def get_completions(self, document: Document, complete_event):
|
||||||
|
text: str = document.text_before_cursor
|
||||||
|
history_items: set[str] = set(self.history_container.load_history_strings())
|
||||||
|
all_candidates: set[str] = history_items.union(self.static_commands)
|
||||||
|
matches: list[str] = sorted(cmd for cmd in all_candidates if cmd.startswith(text))
|
||||||
|
|
||||||
|
if not matches:
|
||||||
|
return
|
||||||
|
|
||||||
|
for match in matches:
|
||||||
|
yield Completion(
|
||||||
|
match,
|
||||||
|
start_position=-len(text),
|
||||||
|
display=match
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _find_common_prefix(matches: list[str]) -> str:
|
||||||
|
if not matches:
|
||||||
|
return ""
|
||||||
|
common: str = matches[0]
|
||||||
|
for match in matches[1:]:
|
||||||
|
i: int = 0
|
||||||
|
while i < len(common) and i < len(match) and common[i] == match[i]:
|
||||||
|
i += 1
|
||||||
|
common = common[:i]
|
||||||
|
return common
|
||||||
|
|
||||||
|
|
||||||
class AutoCompleter:
|
class AutoCompleter:
|
||||||
def __init__(
|
def __init__(
|
||||||
self, history_filename: str | None = None, autocomplete_button: str = "tab"
|
self,
|
||||||
|
history_filename: str | None = None,
|
||||||
|
autocomplete_button: str = "tab"
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
|
||||||
Public. Configures and implements auto-completion of input command
|
|
||||||
:param history_filename: the name of the file for saving the history of the autocompleter
|
|
||||||
:param autocomplete_button: the button for auto-completion
|
|
||||||
:return: None
|
|
||||||
"""
|
|
||||||
self.history_filename: str | None = history_filename
|
self.history_filename: str | None = history_filename
|
||||||
self.autocomplete_button: str = autocomplete_button
|
self.autocomplete_button: str = autocomplete_button
|
||||||
|
self._session: PromptSession | None = None
|
||||||
def _complete(self, text: str, state: int) -> str | None:
|
|
||||||
"""
|
|
||||||
Private. Auto-completion function
|
|
||||||
:param text: part of the command being entered
|
|
||||||
:param state: the current cursor position is relative to the beginning of the line
|
|
||||||
:return: the desired candidate as str or None
|
|
||||||
"""
|
|
||||||
matches: list[str] = 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
|
|
||||||
|
|
||||||
def initial_setup(self, all_commands: set[str]) -> None:
|
def initial_setup(self, all_commands: set[str]) -> None:
|
||||||
"""
|
kb = KeyBindings()
|
||||||
Private. Initial setup function
|
|
||||||
:param all_commands: Registered commands for adding them to the autocomplete history
|
def _(event):
|
||||||
:return: None
|
buff = event.app.current_buffer
|
||||||
"""
|
|
||||||
if self.history_filename:
|
if buff.complete_state:
|
||||||
if os.path.exists(self.history_filename):
|
buff.complete_next()
|
||||||
readline.read_history_file(self.history_filename)
|
|
||||||
else:
|
else:
|
||||||
for line in all_commands:
|
completions = list(buff.completer.get_completions(buff.document, None))
|
||||||
readline.add_history(line)
|
if len(completions) == 1:
|
||||||
|
buff.apply_completion(completions[0])
|
||||||
|
else:
|
||||||
|
buff.start_completion(select_first=False)
|
||||||
|
|
||||||
if not self.history_filename:
|
kb.add(self.autocomplete_button)(_)
|
||||||
for line in all_commands:
|
|
||||||
readline.add_history(line)
|
|
||||||
|
|
||||||
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, all_commands: set[str]) -> None:
|
|
||||||
"""
|
|
||||||
Private. Exit setup function
|
|
||||||
:return: None
|
|
||||||
"""
|
|
||||||
if self.history_filename:
|
if self.history_filename:
|
||||||
readline.write_history_file(self.history_filename)
|
history = FileHistory(self.history_filename)
|
||||||
with open(self.history_filename, "r") as history_file:
|
history = ThreadedHistory(history)
|
||||||
raw_history = history_file.read()
|
else:
|
||||||
pretty_history: list[str] = []
|
history = InMemoryHistory()
|
||||||
for line in set(raw_history.strip().split("\n")):
|
|
||||||
if line.split()[0] in all_commands:
|
|
||||||
pretty_history.append(line)
|
|
||||||
with open(self.history_filename, "w") as history_file:
|
|
||||||
_ = history_file.write("\n".join(pretty_history))
|
|
||||||
|
|
||||||
|
self._session = PromptSession(
|
||||||
|
history=history,
|
||||||
|
completer=HistoryCompleter(history, all_commands),
|
||||||
|
complete_while_typing=False,
|
||||||
|
key_bindings=kb,
|
||||||
|
)
|
||||||
|
|
||||||
def _get_history_items() -> list[str] | list[Never]:
|
def prompt(self, prompt_text: str | HTML = ">>> ") -> str:
|
||||||
"""
|
if self._session is None:
|
||||||
Private. Returns a list of all commands entered by the user
|
raise RuntimeError("Call initial_setup() before using prompt()")
|
||||||
:return: all commands entered by the user as list[str] | list[Never]
|
return self._session.prompt(
|
||||||
"""
|
HTML(f"<b><gray>{prompt_text}</gray></b>") if isinstance(prompt_text, str) else prompt_text
|
||||||
return [
|
)
|
||||||
readline.get_history_item(i)
|
|
||||||
for i in range(1, readline.get_current_history_length() + 1)
|
|
||||||
]
|
|
||||||
@@ -44,6 +44,7 @@ source = { editable = "." }
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "art" },
|
{ name = "art" },
|
||||||
{ name = "dishka" },
|
{ name = "dishka" },
|
||||||
|
{ name = "prompt-toolkit" },
|
||||||
{ name = "pyreadline3", marker = "sys_platform == 'win32'" },
|
{ name = "pyreadline3", marker = "sys_platform == 'win32'" },
|
||||||
{ name = "rich" },
|
{ name = "rich" },
|
||||||
]
|
]
|
||||||
@@ -75,6 +76,7 @@ typecheckers = [
|
|||||||
requires-dist = [
|
requires-dist = [
|
||||||
{ name = "art", specifier = ">=6.4,<7.0" },
|
{ name = "art", specifier = ">=6.4,<7.0" },
|
||||||
{ name = "dishka", specifier = ">=1.7.2" },
|
{ name = "dishka", specifier = ">=1.7.2" },
|
||||||
|
{ name = "prompt-toolkit", specifier = ">=3.0.52" },
|
||||||
{ name = "pyreadline3", marker = "sys_platform == 'win32'", specifier = ">=3.5.4" },
|
{ name = "pyreadline3", marker = "sys_platform == 'win32'", specifier = ">=3.5.4" },
|
||||||
{ name = "rich", specifier = ">=14.0.0,<15.0.0" },
|
{ name = "rich", specifier = ">=14.0.0,<15.0.0" },
|
||||||
]
|
]
|
||||||
@@ -589,6 +591,18 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
|
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prompt-toolkit"
|
||||||
|
version = "3.0.52"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "wcwidth" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pycodestyle"
|
name = "pycodestyle"
|
||||||
version = "2.14.0"
|
version = "2.14.0"
|
||||||
@@ -1023,6 +1037,15 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/e3/bd/fa9bb053192491b3867ba07d2343d9f2252e00811567d30ae8d0f78136fe/watchfiles-1.1.1-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:a916a2932da8f8ab582f242c065f5c81bed3462849ca79ee357dd9551b0e9b01", size = 622112, upload-time = "2025-10-14T15:05:50.941Z" },
|
{ url = "https://files.pythonhosted.org/packages/e3/bd/fa9bb053192491b3867ba07d2343d9f2252e00811567d30ae8d0f78136fe/watchfiles-1.1.1-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:a916a2932da8f8ab582f242c065f5c81bed3462849ca79ee357dd9551b0e9b01", size = 622112, upload-time = "2025-10-14T15:05:50.941Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wcwidth"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/38/75/2144b65e4fba12a2d9868e9a3f99db7fa0760670d064603634bef9ff1709/wcwidth-0.3.0.tar.gz", hash = "sha256:af1a2fb0b83ef4a7fc0682a4c95ca2576e14d0280bca2a9e67b7dc9f2733e123", size = 172238, upload-time = "2026-01-21T17:44:09.508Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/18/0e/a5f0257ab47492b7afb5fb60347d14ba19445e2773fc8352d4be6bd2f6f8/wcwidth-0.3.0-py3-none-any.whl", hash = "sha256:073a1acb250e4add96cfd5ef84e0036605cd6e0d0782c8c15c80e42202348458", size = 85520, upload-time = "2026-01-21T17:44:08.002Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "websockets"
|
name = "websockets"
|
||||||
version = "15.0.1"
|
version = "15.0.1"
|
||||||
|
|||||||
Reference in New Issue
Block a user