From 18163edab9d6fee11efe0c0de6fad76631e3bf99 Mon Sep 17 00:00:00 2001 From: Roland Thomas Date: Thu, 24 Apr 2025 19:08:37 -0400 Subject: [PATCH] bottom_bar remove _items, add remove_item and clear functions --- falyx/bottom_bar.py | 24 ++++++++++++++++++++---- falyx/command.py | 2 +- falyx/falyx.py | 2 +- falyx/hooks.py | 2 ++ 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/falyx/bottom_bar.py b/falyx/bottom_bar.py index dda54f3..ebe7726 100644 --- a/falyx/bottom_bar.py +++ b/falyx/bottom_bar.py @@ -30,7 +30,6 @@ class BottomBar: ) -> None: self.columns = columns self.console = Console() - self._items: list[Callable[[], HTML]] = [] self._named_items: dict[str, Callable[[], HTML]] = {} self._value_getters: dict[str, Callable[[], Any]] = CaseInsensitiveDict() self.toggle_keys: list[str] = [] @@ -99,6 +98,7 @@ class BottomBar: total: int, fg: str = OneColors.BLACK, bg: str = OneColors.WHITE, + enforce_total: bool = True, ) -> None: if not callable(get_current): raise ValueError("`get_current` must be a callable returning int") @@ -108,7 +108,7 @@ class BottomBar: def render(): get_current_ = self._value_getters[name] current_value = get_current_() - if current_value > total: + if current_value > total and enforce_total: raise ValueError( f"Current value {current_value} is greater than total value {total}" ) @@ -169,6 +169,7 @@ class BottomBar: bg_on: str = OneColors.GREEN, bg_off: str = OneColors.DARK_RED, ) -> None: + """Add a toggle to the bottom bar based on an option from OptionsManager.""" self.add_toggle( key=key, label=label, @@ -185,15 +186,30 @@ class BottomBar: return {label: getter() for label, getter in self._value_getters.items()} def get_value(self, name: str) -> Any: + """Get the current value of a registered item.""" if name not in self._value_getters: raise ValueError(f"No value getter registered under name: '{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: if name in self._named_items: raise ValueError(f"Bottom bar item '{name}' already exists") self._named_items[name] = render_fn - self._items = list(self._named_items.values()) 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()]) + diff --git a/falyx/command.py b/falyx/command.py index 96a2431..3914f5a 100644 --- a/falyx/command.py +++ b/falyx/command.py @@ -159,7 +159,7 @@ class Command(BaseModel): elif callable(self.action): console.print(f"{label}") 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]" ) else: diff --git a/falyx/falyx.py b/falyx/falyx.py index e2a3c86..c1f3e59 100644 --- a/falyx/falyx.py +++ b/falyx/falyx.py @@ -335,7 +335,7 @@ class Falyx: def _get_bottom_bar_render(self) -> Callable[[], Any] | str | None: """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 elif callable(self._bottom_bar): return self._bottom_bar diff --git a/falyx/hooks.py b/falyx/hooks.py index 66773ef..3c394ef 100644 --- a/falyx/hooks.py +++ b/falyx/hooks.py @@ -19,6 +19,8 @@ class ResultReporter: return "ResultReporter" async def report(self, context: ExecutionContext): + if not callable(self.formatter): + raise TypeError("formatter must be callable") if context.result is not None: result_text = self.formatter(context.result) duration = f"{context.duration:.3f}s" if context.duration is not None else "n/a"