bottom_bar remove _items, add remove_item and clear functions

This commit is contained in:
Roland Thomas Jr 2025-04-24 19:08:37 -04:00
parent 6c72e22415
commit 18163edab9
Signed by: roland
GPG Key ID: 7C3C2B085A4C2872
4 changed files with 24 additions and 6 deletions

View File

@ -30,7 +30,6 @@ class BottomBar:
) -> None: ) -> None:
self.columns = columns self.columns = columns
self.console = Console() self.console = Console()
self._items: list[Callable[[], HTML]] = []
self._named_items: dict[str, Callable[[], HTML]] = {} self._named_items: dict[str, Callable[[], HTML]] = {}
self._value_getters: dict[str, Callable[[], Any]] = CaseInsensitiveDict() self._value_getters: dict[str, Callable[[], Any]] = CaseInsensitiveDict()
self.toggle_keys: list[str] = [] self.toggle_keys: list[str] = []
@ -99,6 +98,7 @@ class BottomBar:
total: int, total: int,
fg: str = OneColors.BLACK, fg: str = OneColors.BLACK,
bg: str = OneColors.WHITE, bg: str = OneColors.WHITE,
enforce_total: bool = True,
) -> None: ) -> None:
if not callable(get_current): if not callable(get_current):
raise ValueError("`get_current` must be a callable returning int") raise ValueError("`get_current` must be a callable returning int")
@ -108,7 +108,7 @@ class BottomBar:
def render(): def render():
get_current_ = self._value_getters[name] get_current_ = self._value_getters[name]
current_value = get_current_() current_value = get_current_()
if current_value > total: if current_value > total and enforce_total:
raise ValueError( raise ValueError(
f"Current value {current_value} is greater than total value {total}" f"Current value {current_value} is greater than total value {total}"
) )
@ -169,6 +169,7 @@ class BottomBar:
bg_on: str = OneColors.GREEN, bg_on: str = OneColors.GREEN,
bg_off: str = OneColors.DARK_RED, bg_off: str = OneColors.DARK_RED,
) -> None: ) -> None:
"""Add a toggle to the bottom bar based on an option from OptionsManager."""
self.add_toggle( self.add_toggle(
key=key, key=key,
label=label, label=label,
@ -185,15 +186,30 @@ class BottomBar:
return {label: getter() for label, getter in self._value_getters.items()} return {label: getter() for label, getter in self._value_getters.items()}
def get_value(self, name: str) -> Any: def get_value(self, name: str) -> Any:
"""Get the current value of a registered item."""
if name not in self._value_getters: if name not in self._value_getters:
raise ValueError(f"No value getter registered under name: '{name}'") raise ValueError(f"No value getter registered under name: '{name}'")
return self._value_getters[name]() return self._value_getters[name]()
def remove_item(self, name: str) -> None:
"""Remove an item from the bottom bar."""
self._named_items.pop(name, None)
self._value_getters.pop(name, None)
if name in self.toggle_keys:
self.toggle_keys.remove(name)
def clear(self) -> None:
"""Clear all items from the bottom bar."""
self._value_getters.clear()
self._named_items.clear()
self.toggle_keys.clear()
def _add_named(self, name: str, render_fn: Callable[[], HTML]) -> None: def _add_named(self, name: str, render_fn: Callable[[], HTML]) -> None:
if name in self._named_items: if name in self._named_items:
raise ValueError(f"Bottom bar item '{name}' already exists") raise ValueError(f"Bottom bar item '{name}' already exists")
self._named_items[name] = render_fn self._named_items[name] = render_fn
self._items = list(self._named_items.values())
def render(self): def render(self):
return merge_formatted_text([fn() for fn in self._items]) """Render the bottom bar."""
return merge_formatted_text([fn() for fn in self._named_items.values()])

View File

@ -159,7 +159,7 @@ class Command(BaseModel):
elif callable(self.action): elif callable(self.action):
console.print(f"{label}") console.print(f"{label}")
console.print( console.print(
f"[{OneColors.LIGHT_RED_b}]→ Would call:[/] {self.action.__name__} " f"[{OneColors.LIGHT_RED_b}]→ Would call:[/] {self.action.__name__}"
f"[dim](args={self.args}, kwargs={self.kwargs})[/dim]" f"[dim](args={self.args}, kwargs={self.kwargs})[/dim]"
) )
else: else:

View File

@ -335,7 +335,7 @@ class Falyx:
def _get_bottom_bar_render(self) -> Callable[[], Any] | str | None: def _get_bottom_bar_render(self) -> Callable[[], Any] | str | None:
"""Returns the bottom bar for the menu.""" """Returns the bottom bar for the menu."""
if isinstance(self.bottom_bar, BottomBar) and self.bottom_bar._items: if isinstance(self.bottom_bar, BottomBar) and self.bottom_bar._named_items:
return self._bottom_bar.render return self._bottom_bar.render
elif callable(self._bottom_bar): elif callable(self._bottom_bar):
return self._bottom_bar return self._bottom_bar

View File

@ -19,6 +19,8 @@ class ResultReporter:
return "ResultReporter" return "ResultReporter"
async def report(self, context: ExecutionContext): async def report(self, context: ExecutionContext):
if not callable(self.formatter):
raise TypeError("formatter must be callable")
if context.result is not None: if context.result is not None:
result_text = self.formatter(context.result) result_text = self.formatter(context.result)
duration = f"{context.duration:.3f}s" if context.duration is not None else "n/a" duration = f"{context.duration:.3f}s" if context.duration is not None else "n/a"