Skip to content

Commit 422ac75

Browse files
committed
Adding the package.json
1 parent 02d8d49 commit 422ac75

File tree

2 files changed

+109
-47
lines changed

2 files changed

+109
-47
lines changed

package-lock.json

Lines changed: 38 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/core/src/codewhispererChat/tools/grepSearch.ts

Lines changed: 71 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ export interface GrepSearchParams {
2121
}
2222

2323
export class GrepSearch {
24-
private fsPath: string | undefined
24+
private path: string
2525
private query: string
2626
private caseSensitive: boolean
2727
private excludePattern?: string
2828
private includePattern?: string
2929
private readonly logger = getLogger('grepSearch')
3030

3131
constructor(params: GrepSearchParams) {
32-
this.fsPath = params.path
32+
this.path = this.getSearchDirectory(params.path)
3333
this.query = params.query
3434
this.caseSensitive = params.caseSensitive ?? false
3535
this.excludePattern = params.excludePattern
@@ -41,61 +41,58 @@ export class GrepSearch {
4141
throw new Error('Grep search query cannot be empty.')
4242
}
4343

44-
// Handle optional path parameter
45-
if (!this.fsPath || this.fsPath.trim().length === 0) {
46-
// Use current workspace folder as default if path is not provided
47-
const workspaceFolders = vscode.workspace.workspaceFolders
48-
if (!workspaceFolders || workspaceFolders.length === 0) {
49-
throw new Error('Path cannot be empty and no workspace folder is available.')
50-
}
51-
this.fsPath = workspaceFolders[0].uri.fsPath
52-
this.logger.debug(`Using default workspace folder: ${this.fsPath}`)
44+
if (this.path.trim().length === 0) {
45+
throw new Error('Path cannot be empty and no workspace folder is available.')
5346
}
5447

55-
const sanitized = sanitizePath(this.fsPath)
56-
this.fsPath = sanitized
48+
const sanitized = sanitizePath(this.path)
49+
this.path = sanitized
5750

58-
const pathUri = vscode.Uri.file(this.fsPath)
51+
const pathUri = vscode.Uri.file(this.path)
5952
let pathExists: boolean
6053
try {
6154
pathExists = await fs.existsDir(pathUri)
6255
if (!pathExists) {
63-
throw new Error(`Path: "${this.fsPath}" does not exist or cannot be accessed.`)
56+
throw new Error(`Path: "${this.path}" does not exist or cannot be accessed.`)
6457
}
6558
} catch (err) {
66-
throw new Error(`Path: "${this.fsPath}" does not exist or cannot be accessed. (${err})`)
59+
throw new Error(`Path: "${this.path}" does not exist or cannot be accessed. (${err})`)
6760
}
6861
}
6962

7063
public queueDescription(updates: Writable): void {
71-
const searchDirectory = this.getSearchDirectory(this.fsPath)
72-
updates.write(`Grepping for "${this.query}" in directory: ${searchDirectory}`)
64+
updates.write(`Grepping for "${this.query}" in directory: ${this.path}`)
7365
updates.end()
7466
}
7567

7668
public async invoke(updates?: Writable): Promise<InvokeOutput> {
77-
const searchDirectory = this.getSearchDirectory(this.fsPath)
7869
try {
7970
const results = await this.executeRipgrep(updates)
8071
return this.createOutput(results)
8172
} catch (error: any) {
82-
this.logger.error(`Failed to search in "${searchDirectory}": ${error.message || error}`)
83-
throw new Error(`Failed to search in "${searchDirectory}": ${error.message || error}`)
73+
this.logger.error(`Failed to search in "${this.path}": ${error.message || error}`)
74+
throw new Error(`Failed to search in "${this.path}": ${error.message || error}`)
8475
}
8576
}
8677

87-
private getSearchDirectory(fsPath?: string): string {
88-
const workspaceFolders = vscode.workspace.workspaceFolders
89-
const searchLocation = fsPath
90-
? fsPath
91-
: !workspaceFolders || workspaceFolders.length === 0
92-
? ''
93-
: workspaceFolders[0].uri.fsPath
78+
private getSearchDirectory(path?: string): string {
79+
let searchLocation = ''
80+
if (path && path.trim().length !== 0) {
81+
searchLocation = path
82+
} else {
83+
// Handle optional path parameter
84+
// Use current workspace folder as default if path is not provided
85+
const workspaceFolders = vscode.workspace.workspaceFolders
86+
this.logger.info(`Using default workspace folder: ${workspaceFolders?.length}`)
87+
if (workspaceFolders && workspaceFolders.length !== 0) {
88+
searchLocation = workspaceFolders[0].uri.fsPath
89+
this.logger.debug(`Using default workspace folder: ${searchLocation}`)
90+
}
91+
}
9492
return searchLocation
9593
}
9694

9795
private async executeRipgrep(updates?: Writable): Promise<string> {
98-
const searchDirectory = this.getSearchDirectory(this.fsPath)
9996
return new Promise(async (resolve, reject) => {
10097
const args: string[] = []
10198

@@ -129,7 +126,7 @@ export class GrepSearch {
129126
}
130127

131128
// Add search pattern and path
132-
args.push(this.query, searchDirectory)
129+
args.push(this.query, this.path)
133130

134131
this.logger.debug(`Executing ripgrep with args: ${args.join(' ')}`)
135132

@@ -171,36 +168,63 @@ export class GrepSearch {
171168
* 1. Remove matched content (keep only file:line)
172169
* 2. Add file URLs for clickable links
173170
*/
171+
/**
172+
* Process ripgrep output to:
173+
* 1. Group results by file
174+
* 2. Format as collapsible sections
175+
* 3. Add file URLs for clickable links
176+
*/
174177
private processRipgrepOutput(output: string): string {
175178
if (!output || output.trim() === '') {
176179
return 'No matches found.'
177180
}
178181

179182
const lines = output.split('\n')
180-
const processedLines = lines
181-
.map((line) => {
182-
if (!line || line.trim() === '') {
183-
return ''
184-
}
185183

186-
// Extract file path and line number
187-
const parts = line.split(':')
188-
if (parts.length < 2) {
189-
return line
190-
}
184+
// Group by file path
185+
const fileGroups: Record<string, string[]> = {}
186+
187+
for (const line of lines) {
188+
if (!line || line.trim() === '') {
189+
continue
190+
}
191191

192-
const filePath = parts[0]
193-
const lineNumber = parts[1]
192+
// Extract file path and line number
193+
const parts = line.split(':')
194+
if (parts.length < 2) {
195+
continue
196+
}
197+
198+
const filePath = parts[0]
199+
const lineNumber = parts[1]
200+
// Don't include match content
194201

202+
if (!fileGroups[filePath]) {
203+
fileGroups[filePath] = []
204+
}
205+
206+
// Create a clickable link with line number only
207+
fileGroups[filePath].push(`- [Line ${lineNumber}](${vscode.Uri.file(filePath).toString()}:${lineNumber})`)
208+
}
209+
210+
// Sort files by match count (most matches first)
211+
const sortedFiles = Object.entries(fileGroups).sort((a, b) => b[1].length - a[1].length)
212+
213+
// Format as collapsible sections
214+
const processedOutput = sortedFiles
215+
.map(([filePath, matches]) => {
195216
const fileName = path.basename(filePath)
196-
const fileUri = vscode.Uri.file(filePath)
217+
const matchCount = matches.length
218+
219+
return `<details>
220+
<summary><strong>${fileName} (${matchCount})</strong></summary>
197221
198-
// Format as a markdown link
199-
return `[${fileName}:${lineNumber}](${fileUri}:${lineNumber})`
222+
${matches.join('\n')}
223+
</details>`
200224
})
201-
.filter(Boolean)
225+
.join('\n\n')
202226

203-
return processedLines.join('\n')
227+
return processedOutput
204228
}
205229

206230
private createOutput(content: string): InvokeOutput {

0 commit comments

Comments
 (0)