trashclaw / plugins /regex_test.py
elyanlabs's picture
Source snapshot of github.com/Scottcjn/trashclaw@6dce9ed
53b2ac9 verified
Raw History Blame Contribute Delete
2.66 kB
# SPDX-License-Identifier: MIT
"""
Regex Test Plugin for TrashClaw
Test regular expressions against input text. Shows matches, groups, and positions.
Plugin contract:
TOOL_DEF = dict with name, description, parameters (OpenAI function schema)
run(**kwargs) -> str
"""
import re
TOOL_DEF = {
"name": "regex_test",
"description": "Test a regular expression pattern against input text. Shows all matches with positions and groups.",
"parameters": {
"type": "object",
"properties": {
"pattern": {
"type": "string",
"description": "Regular expression pattern to test"
},
"text": {
"type": "string",
"description": "Text to match against"
},
"flags": {
"type": "string",
"description": "Regex flags: i (ignore case), m (multiline), s (dotall), x (verbose). Combine: 'im'"
}
},
"required": ["pattern", "text"]
}
}
def _parse_flags(flags_str: str) -> int:
flag_map = {
"i": re.IGNORECASE,
"m": re.MULTILINE,
"s": re.DOTALL,
"x": re.VERBOSE,
}
result = 0
for ch in flags_str.lower():
if ch in flag_map:
result |= flag_map[ch]
return result
def run(pattern: str = "", text: str = "", flags: str = "", **kwargs) -> str:
if not pattern:
return "Error: 'pattern' is required."
if not text:
return "Error: 'text' is required."
try:
compiled = re.compile(pattern, _parse_flags(flags))
except re.error as e:
return f"Regex compile error: {e}"
matches = list(compiled.finditer(text))
if not matches:
return f"Pattern: /{pattern}/{''.join(sorted(flags.lower()))}\nNo matches found."
lines = [
f"Pattern: /{pattern}/{''.join(sorted(flags.lower()))}",
f"Matches: {len(matches)}",
"",
]
for i, m in enumerate(matches[:50]): # cap at 50 matches
line = f" [{i}] \"{m.group()}\" at {m.start()}-{m.end()}"
if m.groups():
groups = ", ".join(
f"${j+1}=\"{g}\"" for j, g in enumerate(m.groups()) if g is not None
)
line += f" groups: {groups}"
if m.groupdict():
named = ", ".join(
f"{k}=\"{v}\"" for k, v in m.groupdict().items() if v is not None
)
if named:
line += f" named: {named}"
lines.append(line)
if len(matches) > 50:
lines.append(f" ... and {len(matches) - 50} more matches")
return "\n".join(lines)