semantic markup update
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
# [SECTION: IMPORTS]
|
||||
import sys
|
||||
from typing import List, Tuple, Optional, Any
|
||||
from .logger import belief_scope
|
||||
# [/SECTION]
|
||||
|
||||
# [DEF:menu:Function]
|
||||
@@ -15,17 +16,20 @@ from typing import List, Tuple, Optional, Any
|
||||
# @PARAM: title (str) - Заголовок меню.
|
||||
# @PARAM: prompt (str) - Приглашение к вводу.
|
||||
# @PARAM: choices (List[str]) - Список вариантов для выбора.
|
||||
# @PRE: choices must be a non-empty list of strings.
|
||||
# @POST: Returns a tuple with return code and selected choice.
|
||||
# @RETURN: Tuple[int, Optional[str]] - Кортеж (код возврата, выбранный элемент). rc=0 - успех.
|
||||
def menu(title: str, prompt: str, choices: List[str], **kwargs) -> Tuple[int, Optional[str]]:
|
||||
print(f"\n=== {title} ===\n{prompt}")
|
||||
for idx, item in enumerate(choices, 1):
|
||||
print(f"{idx}) {item}")
|
||||
try:
|
||||
raw = input("\nВведите номер (0 – отмена): ").strip()
|
||||
sel = int(raw)
|
||||
return (0, choices[sel - 1]) if 0 < sel <= len(choices) else (1, None)
|
||||
except (ValueError, IndexError):
|
||||
return 1, None
|
||||
with belief_scope("menu"):
|
||||
print(f"\n=== {title} ===\n{prompt}")
|
||||
for idx, item in enumerate(choices, 1):
|
||||
print(f"{idx}) {item}")
|
||||
try:
|
||||
raw = input("\nВведите номер (0 – отмена): ").strip()
|
||||
sel = int(raw)
|
||||
return (0, choices[sel - 1]) if 0 < sel <= len(choices) else (1, None)
|
||||
except (ValueError, IndexError):
|
||||
return 1, None
|
||||
# [/DEF:menu:Function]
|
||||
|
||||
# [DEF:checklist:Function]
|
||||
@@ -33,72 +37,121 @@ def menu(title: str, prompt: str, choices: List[str], **kwargs) -> Tuple[int, Op
|
||||
# @PARAM: title (str) - Заголовок.
|
||||
# @PARAM: prompt (str) - Приглашение к вводу.
|
||||
# @PARAM: options (List[Tuple[str, str]]) - Список кортежей (значение, метка).
|
||||
# @PRE: options must be a list of (value, label) tuples.
|
||||
# @POST: Returns a list of selected values.
|
||||
# @RETURN: Tuple[int, List[str]] - Кортеж (код возврата, список выбранных значений).
|
||||
def checklist(title: str, prompt: str, options: List[Tuple[str, str]], **kwargs) -> Tuple[int, List[str]]:
|
||||
print(f"\n=== {title} ===\n{prompt}")
|
||||
for idx, (val, label) in enumerate(options, 1):
|
||||
print(f"{idx}) [{val}] {label}")
|
||||
raw = input("\nВведите номера через запятую (пустой ввод → отказ): ").strip()
|
||||
if not raw: return 1, []
|
||||
try:
|
||||
indices = {int(x.strip()) for x in raw.split(",") if x.strip()}
|
||||
selected_values = [options[i - 1][0] for i in indices if 0 < i <= len(options)]
|
||||
return 0, selected_values
|
||||
except (ValueError, IndexError):
|
||||
return 1, []
|
||||
with belief_scope("checklist"):
|
||||
print(f"\n=== {title} ===\n{prompt}")
|
||||
for idx, (val, label) in enumerate(options, 1):
|
||||
print(f"{idx}) [{val}] {label}")
|
||||
raw = input("\nВведите номера через запятую (пустой ввод → отказ): ").strip()
|
||||
if not raw: return 1, []
|
||||
try:
|
||||
indices = {int(x.strip()) for x in raw.split(",") if x.strip()}
|
||||
selected_values = [options[i - 1][0] for i in indices if 0 < i <= len(options)]
|
||||
return 0, selected_values
|
||||
except (ValueError, IndexError):
|
||||
return 1, []
|
||||
# [/DEF:checklist:Function]
|
||||
|
||||
# [DEF:yesno:Function]
|
||||
# @PURPOSE: Задает вопрос с ответом да/нет.
|
||||
# @PARAM: title (str) - Заголовок.
|
||||
# @PARAM: question (str) - Вопрос для пользователя.
|
||||
# @PRE: question must be a string.
|
||||
# @POST: Returns boolean based on user input.
|
||||
# @RETURN: bool - `True`, если пользователь ответил "да".
|
||||
def yesno(title: str, question: str, **kwargs) -> bool:
|
||||
ans = input(f"\n=== {title} ===\n{question} (y/n): ").strip().lower()
|
||||
return ans in ("y", "yes", "да", "д")
|
||||
with belief_scope("yesno"):
|
||||
ans = input(f"\n=== {title} ===\n{question} (y/n): ").strip().lower()
|
||||
return ans in ("y", "yes", "да", "д")
|
||||
# [/DEF:yesno:Function]
|
||||
|
||||
# [DEF:msgbox:Function]
|
||||
# @PURPOSE: Отображает информационное сообщение.
|
||||
# @PARAM: title (str) - Заголовок.
|
||||
# @PARAM: msg (str) - Текст сообщения.
|
||||
# @PRE: msg must be a string.
|
||||
# @POST: Message is printed to console.
|
||||
def msgbox(title: str, msg: str, **kwargs) -> None:
|
||||
print(f"\n=== {title} ===\n{msg}\n")
|
||||
with belief_scope("msgbox"):
|
||||
print(f"\n=== {title} ===\n{msg}\n")
|
||||
# [/DEF:msgbox:Function]
|
||||
|
||||
# [DEF:inputbox:Function]
|
||||
# @PURPOSE: Запрашивает у пользователя текстовый ввод.
|
||||
# @PARAM: title (str) - Заголовок.
|
||||
# @PARAM: prompt (str) - Приглашение к вводу.
|
||||
# @PRE: prompt must be a string.
|
||||
# @POST: Returns user input string.
|
||||
# @RETURN: Tuple[int, Optional[str]] - Кортеж (код возврата, введенная строка).
|
||||
def inputbox(title: str, prompt: str, **kwargs) -> Tuple[int, Optional[str]]:
|
||||
print(f"\n=== {title} ===")
|
||||
val = input(f"{prompt}\n")
|
||||
return (0, val) if val else (1, None)
|
||||
with belief_scope("inputbox"):
|
||||
print(f"\n=== {title} ===")
|
||||
val = input(f"{prompt}\n")
|
||||
return (0, val) if val else (1, None)
|
||||
# [/DEF:inputbox:Function]
|
||||
|
||||
# [DEF:_ConsoleGauge:Class]
|
||||
# @PURPOSE: Контекстный менеджер для имитации `whiptail gauge` в консоли.
|
||||
class _ConsoleGauge:
|
||||
# [DEF:__init__:Function]
|
||||
# @PURPOSE: Initializes the gauge.
|
||||
# @PRE: title must be a string.
|
||||
# @POST: Instance initialized.
|
||||
def __init__(self, title: str, **kwargs):
|
||||
self.title = title
|
||||
with belief_scope("__init__"):
|
||||
self.title = title
|
||||
# [/DEF:__init__:Function]
|
||||
|
||||
# [DEF:__enter__:Function]
|
||||
# @PURPOSE: Enters the context.
|
||||
# @PRE: Instance initialized.
|
||||
# @POST: Header printed, returns self.
|
||||
def __enter__(self):
|
||||
print(f"\n=== {self.title} ===")
|
||||
return self
|
||||
with belief_scope("__enter__"):
|
||||
print(f"\n=== {self.title} ===")
|
||||
return self
|
||||
# [/DEF:__enter__:Function]
|
||||
|
||||
# [DEF:__exit__:Function]
|
||||
# @PURPOSE: Exits the context.
|
||||
# @PRE: Context entered.
|
||||
# @POST: Newline printed.
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
sys.stdout.write("\n"); sys.stdout.flush()
|
||||
with belief_scope("__exit__"):
|
||||
sys.stdout.write("\n"); sys.stdout.flush()
|
||||
# [/DEF:__exit__:Function]
|
||||
|
||||
# [DEF:set_text:Function]
|
||||
# @PURPOSE: Sets the gauge text.
|
||||
# @PRE: txt must be a string.
|
||||
# @POST: Text written to stdout.
|
||||
def set_text(self, txt: str) -> None:
|
||||
sys.stdout.write(f"\r{txt} "); sys.stdout.flush()
|
||||
with belief_scope("set_text"):
|
||||
sys.stdout.write(f"\r{txt} "); sys.stdout.flush()
|
||||
# [/DEF:set_text:Function]
|
||||
|
||||
# [DEF:set_percent:Function]
|
||||
# @PURPOSE: Sets the gauge percentage.
|
||||
# @PRE: percent must be an integer.
|
||||
# @POST: Percentage written to stdout.
|
||||
def set_percent(self, percent: int) -> None:
|
||||
sys.stdout.write(f"{percent}%"); sys.stdout.flush()
|
||||
with belief_scope("set_percent"):
|
||||
sys.stdout.write(f"{percent}%"); sys.stdout.flush()
|
||||
# [/DEF:set_percent:Function]
|
||||
# [/DEF:_ConsoleGauge:Class]
|
||||
|
||||
# [DEF:gauge:Function]
|
||||
# @PURPOSE: Создает и возвращает экземпляр `_ConsoleGauge`.
|
||||
# @PRE: title must be a string.
|
||||
# @POST: Returns an instance of _ConsoleGauge.
|
||||
# @PARAM: title (str) - Заголовок для индикатора прогресса.
|
||||
# @RETURN: _ConsoleGauge - Экземпляр контекстного менеджера.
|
||||
def gauge(title: str, **kwargs) -> _ConsoleGauge:
|
||||
return _ConsoleGauge(title, **kwargs)
|
||||
with belief_scope("gauge"):
|
||||
return _ConsoleGauge(title, **kwargs)
|
||||
# [/DEF:gauge:Function]
|
||||
|
||||
# [/DEF:superset_tool.utils.whiptail_fallback:Module]
|
||||
|
||||
Reference in New Issue
Block a user