diff options
| author | Kujtim Hoxha <[email protected]> | 2025-04-18 20:17:38 +0200 |
|---|---|---|
| committer | Kujtim Hoxha <[email protected]> | 2025-04-21 13:42:27 +0200 |
| commit | 333ea6ec4b2abfc2c1a9c3f6b0918ca5d296347f (patch) | |
| tree | e0d456417368e8716c81ee43b82be3d6ed39c59e /internal/llm/tools/grep.go | |
| parent | 05d0e86f10369fd0e51a924ac88029fb92591499 (diff) | |
| download | opencode-333ea6ec4b2abfc2c1a9c3f6b0918ca5d296347f.tar.gz opencode-333ea6ec4b2abfc2c1a9c3f6b0918ca5d296347f.zip | |
implement patch, update ui, improve rendering
Diffstat (limited to 'internal/llm/tools/grep.go')
| -rw-r--r-- | internal/llm/tools/grep.go | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/internal/llm/tools/grep.go b/internal/llm/tools/grep.go index 3436dd7eb..086a5e686 100644 --- a/internal/llm/tools/grep.go +++ b/internal/llm/tools/grep.go @@ -17,9 +17,10 @@ import ( ) type GrepParams struct { - Pattern string `json:"pattern"` - Path string `json:"path"` - Include string `json:"include"` + Pattern string `json:"pattern"` + Path string `json:"path"` + Include string `json:"include"` + LiteralText bool `json:"literal_text"` } type grepMatch struct { @@ -45,11 +46,12 @@ WHEN TO USE THIS TOOL: HOW TO USE: - Provide a regex pattern to search for within file contents +- Set literal_text=true if you want to search for the exact text with special characters (recommended for non-regex users) - Optionally specify a starting directory (defaults to current working directory) - Optionally provide an include pattern to filter which files to search - Results are sorted with most recently modified files first -REGEX PATTERN SYNTAX: +REGEX PATTERN SYNTAX (when literal_text=false): - Supports standard regular expression syntax - 'function' searches for the literal text "function" - 'log\..*Error' finds text starting with "log." and ending with "Error" @@ -69,7 +71,8 @@ LIMITATIONS: TIPS: - For faster, more targeted searches, first use Glob to find relevant files, then use Grep - When doing iterative exploration that may require multiple rounds of searching, consider using the Agent tool instead -- Always check if results are truncated and refine your search pattern if needed` +- Always check if results are truncated and refine your search pattern if needed +- Use literal_text=true when searching for exact text containing special characters like dots, parentheses, etc.` ) func NewGrepTool() BaseTool { @@ -93,11 +96,27 @@ func (g *grepTool) Info() ToolInfo { "type": "string", "description": "File pattern to include in the search (e.g. \"*.js\", \"*.{ts,tsx}\")", }, + "literal_text": map[string]any{ + "type": "boolean", + "description": "If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.", + }, }, Required: []string{"pattern"}, } } +// escapeRegexPattern escapes special regex characters so they're treated as literal characters +func escapeRegexPattern(pattern string) string { + specialChars := []string{"\\", ".", "+", "*", "?", "(", ")", "[", "]", "{", "}", "^", "$", "|"} + escaped := pattern + + for _, char := range specialChars { + escaped = strings.ReplaceAll(escaped, char, "\\"+char) + } + + return escaped +} + func (g *grepTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error) { var params GrepParams if err := json.Unmarshal([]byte(call.Input), ¶ms); err != nil { @@ -108,12 +127,18 @@ func (g *grepTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error) return NewTextErrorResponse("pattern is required"), nil } + // If literal_text is true, escape the pattern + searchPattern := params.Pattern + if params.LiteralText { + searchPattern = escapeRegexPattern(params.Pattern) + } + searchPath := params.Path if searchPath == "" { searchPath = config.WorkingDirectory() } - matches, truncated, err := searchFiles(params.Pattern, searchPath, params.Include, 100) + matches, truncated, err := searchFiles(searchPattern, searchPath, params.Include, 100) if err != nil { return ToolResponse{}, fmt.Errorf("error searching files: %w", err) } |
