Files
2024-12-27 22:31:23 +09:00

112 lines
3.3 KiB
Python

from typing import Any, Dict, List, Union
from rich.console import Console, RenderableType
from rich.theme import Theme
from .styles.base import BaseStyle
from .input import Input
from .menu import Menu, Option, ReturnValue
from .progress import Progress
class RichToolkitTheme:
def __init__(self, style: BaseStyle, theme: Dict[str, str]) -> None:
self.style = style
self.rich_theme = Theme(theme)
class RichToolkit:
def __init__(
self,
theme: RichToolkitTheme,
handle_keyboard_interrupts: bool = True,
) -> None:
self.console = Console(theme=theme.rich_theme)
self.theme = theme
self.handle_keyboard_interrupts = handle_keyboard_interrupts
def __enter__(self):
self.console.print()
return self
def __exit__(
self, exc_type: Any, exc_value: Any, traceback: Any
) -> Union[bool, None]:
if self.handle_keyboard_interrupts and exc_type is KeyboardInterrupt:
# we want to handle keyboard interrupts gracefully, instead of showing a traceback
# or any other error message
return True
self.console.print()
def print_title(self, title: str, **metadata: Any) -> None:
self.console.print(
self.theme.style.with_decoration(title, title=True, **metadata)
)
def print(self, *renderables: RenderableType, **metadata: Any) -> None:
self.console.print(self.theme.style.with_decoration(*renderables, **metadata))
def print_as_string(self, *renderables: RenderableType, **metadata: Any) -> str:
with self.console.capture() as capture:
self.print(*renderables, **metadata)
return capture.get().rstrip()
def print_line(self) -> None:
self.console.print(self.theme.style.empty_line())
def confirm(self, title: str, **metadata: Any) -> bool:
return self.ask(
title=title,
options=[
Option({"value": True, "name": "Yes"}),
Option({"value": False, "name": "No"}),
],
inline=True,
**metadata,
)
def ask(
self,
title: str,
options: List[Option[ReturnValue]],
inline: bool = False,
allow_filtering: bool = False,
**metadata: Any,
) -> ReturnValue:
return Menu(
title=title,
options=options,
console=self.console,
style=self.theme.style,
inline=inline,
allow_filtering=allow_filtering,
cursor_offset=self.theme.style.cursor_offset,
**metadata,
).ask()
def input(
self, title: str, default: str = "", password: bool = False, **metadata: Any
) -> str:
return Input(
console=self.console,
style=self.theme.style,
title=title,
default=default,
cursor_offset=self.theme.style.cursor_offset,
password=password,
**metadata,
).ask()
def progress(
self, title: str, transient: bool = False, transient_on_error: bool = False
) -> Progress:
return Progress(
title=title,
console=self.console,
style=self.theme.style,
transient=transient,
transient_on_error=transient_on_error,
)