RustImplementation #25
@@ -1,6 +1,6 @@
|
||||
import difflib
|
||||
|
||||
from textual.containers import Horizontal
|
||||
from textual.containers import Horizontal, Vertical
|
||||
from textual.css.query import NoMatches
|
||||
from textual.message import Message
|
||||
from textual.widget import Widget
|
||||
@@ -16,7 +16,7 @@ class MultiAgentSelector(Widget):
|
||||
def __init__(self, all_agents: list[dict]):
|
||||
super().__init__()
|
||||
self.all_agents = all_agents
|
||||
self._match_type = "fuzzy"
|
||||
self._match_type = "exact"
|
||||
|
||||
@property
|
||||
def match_type(self):
|
||||
@@ -27,43 +27,73 @@ class MultiAgentSelector(Widget):
|
||||
self._match_type = value
|
||||
|
||||
def compose(self):
|
||||
yield Static("🔍 Multi-Agent Selector", id="selector_title")
|
||||
text_area = TextArea(
|
||||
id="device_input",
|
||||
placeholder="Paste device names here (one per line)",
|
||||
)
|
||||
text_area.styles.height = 10
|
||||
text_area.styles.overflow_y = "auto"
|
||||
yield text_area
|
||||
title_text = Static("🖧 Multi-Agent Selector", id="selector_title")
|
||||
title_text.styles.margin = (0, 0, 0, 1)
|
||||
yield title_text
|
||||
|
||||
with Horizontal() as switch_container:
|
||||
switch_container.styles.height = "auto"
|
||||
switch_container.styles.align = ("left", "middle")
|
||||
switch_label = Static("Match Type: Fuzzy", id="match_switch_label")
|
||||
switch_label.styles.width = "auto"
|
||||
switch_label.styles.padding = (0, 1)
|
||||
yield switch_label
|
||||
with Horizontal() as main_layout:
|
||||
main_layout.styles.height = "auto"
|
||||
|
||||
switch = Switch(value=False, id="match_switch")
|
||||
switch.styles.width = "auto"
|
||||
yield switch
|
||||
# Left side - Input and controls
|
||||
with Vertical() as left_pane:
|
||||
left_pane.styles.width = "1fr"
|
||||
left_pane.styles.height = "auto"
|
||||
|
||||
yield Button("Search", id="search_button")
|
||||
text_area = TextArea(
|
||||
id="device_input",
|
||||
placeholder="Paste device names here (one per line). Supports wildcards: * and ?",
|
||||
)
|
||||
text_area.styles.height = 10
|
||||
text_area.styles.overflow_y = "auto"
|
||||
yield text_area
|
||||
|
||||
yield SelectionList(id="match_results")
|
||||
yield Static(id="unmatched_label")
|
||||
with Horizontal(id="switch_search_container") as switch_search:
|
||||
|
||||
yield Horizontal(
|
||||
Button("Select All", id="select_all"),
|
||||
Button("Select None", id="select_none"),
|
||||
)
|
||||
switch = Switch(value=False, id="match_switch")
|
||||
switch.styles.width = "auto"
|
||||
switch.styles.margin = (1, 0, 0, 0)
|
||||
switch.styles.padding = (0, 0, 0, 0)
|
||||
yield switch
|
||||
|
||||
yield Button("Continue with Selected", id="submit_selection", variant="primary")
|
||||
switch_label = Static("Match: Exact", id="match_switch_label")
|
||||
switch_label.styles.width = "auto"
|
||||
switch_label.styles.margin = (2, 1, 0, 0)
|
||||
yield switch_label
|
||||
|
||||
search = Button("🔍 Search", id="search_button")
|
||||
search.styles.margin = (1, 0, 0, 0)
|
||||
|
||||
yield search
|
||||
|
||||
with Horizontal() as select_buttons:
|
||||
select_buttons.styles.margin = (0, 0, 0, 0)
|
||||
|
||||
select_all_button = Button("✅ Select All", id="select_all")
|
||||
select_all_button.styles.margin = (1, 1, 0, 1)
|
||||
yield select_all_button
|
||||
|
||||
select_none_button = Button("🚫 Select None", id="select_none")
|
||||
select_none_button.styles.margin = (1, 0, 0, 1)
|
||||
yield select_none_button
|
||||
|
||||
submit_button = Button(
|
||||
"► Continue with Selected", id="submit_selection", variant="primary"
|
||||
)
|
||||
submit_button.styles.margin = (0, 5, 2, 1)
|
||||
submit_button.styles.padding = (0, 6, 0, 0)
|
||||
yield submit_button
|
||||
|
||||
# Right side - Results
|
||||
with Vertical() as right_pane:
|
||||
right_pane.styles.width = "2fr"
|
||||
|
||||
yield SelectionList(id="match_results")
|
||||
yield Static(id="unmatched_label")
|
||||
|
||||
def on_switch_changed(self, event: Switch.Changed):
|
||||
self.match_type = "exact" if event.value else "fuzzy"
|
||||
self.match_type = "fuzzy" if event.value else "exact"
|
||||
self.query_one("#match_switch_label", Static).update(
|
||||
f"Match Type: {self.match_type.capitalize()}"
|
||||
f"Match: {self.match_type.capitalize()}"
|
||||
)
|
||||
|
||||
def on_button_pressed(self, event: Button.Pressed):
|
||||
@@ -111,7 +141,28 @@ class MultiAgentSelector(Widget):
|
||||
matched = set()
|
||||
unmatched = []
|
||||
for name in device_names:
|
||||
if self.match_type == "exact":
|
||||
# Check if the name contains wildcards
|
||||
has_wildcards = "*" in name or "?" in name
|
||||
|
||||
if has_wildcards:
|
||||
# Use regex for wildcard matching
|
||||
import re
|
||||
|
||||
# Escape special regex characters except * and ?
|
||||
pattern = re.escape(name)
|
||||
# Convert wildcards to regex
|
||||
pattern = pattern.replace(r"\*", ".*").replace(r"\?", ".")
|
||||
# Make it case-insensitive and match full string
|
||||
regex = re.compile(f"^{pattern}$", re.IGNORECASE)
|
||||
|
||||
wildcard_matches = [
|
||||
agent_name for agent_name in agent_names if regex.match(agent_name)
|
||||
]
|
||||
if wildcard_matches:
|
||||
matched.update(wildcard_matches)
|
||||
else:
|
||||
unmatched.append(name)
|
||||
elif self.match_type == "exact":
|
||||
# Case-insensitive exact match
|
||||
name_lower = name.lower()
|
||||
exact_match = None
|
||||
|
||||
Reference in New Issue
Block a user