GrepRaw 实现 BackendProtocol.GrepRaw
(ctx context.Context, pattern, path, glob string)
| 156 | |
| 157 | // GrepRaw 实现 BackendProtocol.GrepRaw |
| 158 | func (b *FilesystemBackend) GrepRaw(ctx context.Context, pattern, path, glob string) ([]GrepMatch, error) { |
| 159 | // 编译正则表达式 |
| 160 | re, err := regexp.Compile(pattern) |
| 161 | if err != nil { |
| 162 | return nil, fmt.Errorf("invalid regex pattern: %w", err) |
| 163 | } |
| 164 | |
| 165 | if path == "" { |
| 166 | path = "." |
| 167 | } |
| 168 | |
| 169 | // 使用 Glob 查找匹配的文件 |
| 170 | var searchPattern string |
| 171 | if glob != "" { |
| 172 | searchPattern = filepath.Join(path, "**", glob) |
| 173 | } else { |
| 174 | searchPattern = filepath.Join(path, "**", "*") |
| 175 | } |
| 176 | |
| 177 | files, err := b.fs.Glob(ctx, searchPattern, &sandbox.GlobOptions{ |
| 178 | Dot: true, |
| 179 | }) |
| 180 | if err != nil { |
| 181 | return nil, fmt.Errorf("glob files: %w", err) |
| 182 | } |
| 183 | |
| 184 | var matches []GrepMatch |
| 185 | |
| 186 | for _, filePath := range files { |
| 187 | // 检查是否是文件 |
| 188 | stat, err := b.fs.Stat(ctx, filePath) |
| 189 | if err != nil || stat.IsDir { |
| 190 | continue |
| 191 | } |
| 192 | |
| 193 | // 读取文件内容 |
| 194 | content, err := b.fs.Read(ctx, filePath) |
| 195 | if err != nil { |
| 196 | continue |
| 197 | } |
| 198 | |
| 199 | // 搜索每一行 |
| 200 | lines := strings.Split(content, "\n") |
| 201 | for lineNum, line := range lines { |
| 202 | if re.MatchString(line) { |
| 203 | matches = append(matches, GrepMatch{ |
| 204 | Path: filePath, |
| 205 | LineNumber: lineNum + 1, // 1-based |
| 206 | Line: line, |
| 207 | Match: re.FindString(line), |
| 208 | }) |
| 209 | } |
| 210 | } |
| 211 | } |
| 212 | |
| 213 | return matches, nil |
| 214 | } |
| 215 |