Download plugins/regex_test.py from elyanlabs/trashclaw: direct link, hf CLI and curl.
- Browser
- Download file 2.66 kB
-
https://huggingface.co/elyanlabs/trashclaw/resolve/main/plugins/regex_test.py
- Command line
-
hf download hf://elyanlabs/trashclaw/plugins/regex_test.py
-
curl -L -o regex_test.py https://huggingface.co/elyanlabs/trashclaw/resolve/main/plugins/regex_test.py
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) | |