(dir: string)
| 128 | let count = 0; |
| 129 | |
| 130 | async function walk(dir: string): Promise<void> { |
| 131 | if (count >= opts.maxCount || opts.signal?.aborted) return; |
| 132 | let entries: any[]; |
| 133 | try { |
| 134 | entries = await fs.readdir(dir, { withFileTypes: true }); |
| 135 | } catch { return; } |
| 136 | |
| 137 | for (const entry of entries) { |
| 138 | if (count >= opts.maxCount || opts.signal?.aborted) return; |
| 139 | if (entry.name.startsWith('.') && entry.name !== '.env') continue; |
| 140 | const full = path.join(dir, entry.name); |
| 141 | if (entry.isDirectory()) { |
| 142 | if (IGNORED_DIRS.has(entry.name)) continue; |
| 143 | await walk(full); |
| 144 | } else if (entry.isFile()) { |
| 145 | if (exts && !exts.includes(path.extname(full).toLowerCase())) continue; |
| 146 | let buf: Buffer; |
| 147 | try { |
| 148 | const st = await fs.stat(full); |
| 149 | if (st.size > MAX_FILE_SIZE) continue; |
| 150 | buf = await fs.readFile(full); |
| 151 | } catch { continue; } |
| 152 | if (isBinaryBuffer(buf)) continue; |
| 153 | const lines = buf.toString('utf-8').split('\n'); |
| 154 | for (let i = 0; i < lines.length; i++) { |
| 155 | if (re.test(lines[i]!)) { |
| 156 | out.push(`${full}:${i + 1}:${lines[i]}`); |
| 157 | count++; |
| 158 | if (count >= opts.maxCount) break; |
| 159 | } |
| 160 | } |
| 161 | } |
| 162 | } |
| 163 | } |
| 164 | |
| 165 | // Allow searching a single file path too (matches ripgrep's behaviour). |
| 166 | try { |
no test coverage detected