Skip to content

Instantly share code, notes, and snippets.

@BongoKnight
Created January 29, 2025 14:55
Show Gist options
  • Select an option

  • Save BongoKnight/7e5c936f988305d5360113030d0cb0b5 to your computer and use it in GitHub Desktop.

Select an option

Save BongoKnight/7e5c936f988305d5360113030d0cb0b5 to your computer and use it in GitHub Desktop.
Butoon.Pressed vs Provider callback
from functools import partial
import traceback
from textual import on
from textual.reactive import reactive
from textual.app import App
from textual.app import ComposeResult
from textual.screen import Screen
from textual.widgets import TextArea, Input, Button
from textual.containers import Horizontal
from textual.command import Hit, Hits, Provider
ACTIONS = ["Action 1", "Action 2", "Action 3"]
class ActionCommands(Provider):
"""A command provider to return all actions for the current text."""
def recover_actions(self) -> list[str]:
"""Get a list of all actions."""
return ACTIONS
async def startup(self) -> None:
"""Called once when the command palette is opened, prior to searching."""
worker = self.app.run_worker(self.recover_actions, thread=True)
self.actions = await worker.wait()
async def search(self, query: str) -> Hits:
"""Search for action."""
matcher = self.matcher(query)
for value in self.actions:
score = matcher.match(value)
if score > 0:
yield Hit(
value,
matcher.highlight(value),
partial(self.app.get_param, value),
help=matcher.highlight(f"Executing {value}"),
)
class ParamScreen(Screen):
def compose(self) -> ComposeResult:
yield Input(placeholder="Enter name:")
yield Button("Save params", variant="primary", id="save")
yield Button("Cancel", variant="error", id="cancel")
def on_button_pressed(self, event: Button.Pressed) -> None:
if event.button.id == "cancel":
self.app.pop_screen()
elif event.button.id == "save":
self.dismiss(result=self.query_one(Input).value)
class ActionButton(Button):
actionnable = reactive("")
def __init__(self, label = None, variant = "default", *, name = None, id = None, classes = None, disabled = False, tooltip = None, action = None, actionnable=""):
super().__init__(label, variant, name=name, id=id, classes=classes, disabled=disabled, tooltip=tooltip, action=action)
self.actionnable = actionnable
def on_mount(self) -> None:
self.label = self.actionnable
@on(Button.Pressed)
def execute_option_action(self, event: Button.Pressed) -> None:
"""Event handler called when a button is pressed."""
self.app.get_param(self.actionnable)
class ClipBrowser(App):
COMMANDS = {ActionCommands}
text = reactive("")
def compose(self) -> ComposeResult:
yield TextArea()
yield Horizontal(*[ActionButton(actionnable=action) for action in ACTIONS])
def watch_text(self, new_text: str) -> None:
self.query_one(TextArea).load_text(new_text)
def get_param(self, action: str):
if action:
param_screen = ParamScreen()
param_screen.border_title = f"Parameters for '{action}'"
try:
self.push_screen(param_screen, partial(self.handle_param, action))
except:
self.notify(f"Error while executing action : {traceback.format_exc()}", severity="error")
else:
self.handle_param("No text entered")
def handle_param(self, action: str, param: str = ""):
self.text = f"{action}\n{param}"
if __name__ == "__main__":
cyberClip = ClipBrowser()
cyberClip.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment