Matt Rubens пре 9 месеци
родитељ
комит
dca4563b9a
1 измењених фајлова са 68 додато и 21 уклоњено
  1. 68 21
      src/services/search/file-search.ts

+ 68 - 21
src/services/search/file-search.ts

@@ -15,6 +15,7 @@ async function executeRipgrepForFiles(
 		const args = [
 			"--files",
 			"--follow",
+			"--hidden",
 			"-g",
 			"!**/node_modules/**",
 			"-g",
@@ -32,18 +33,29 @@ async function executeRipgrepForFiles(
 			crlfDelay: Infinity,
 		})
 
-		const results: { path: string; type: "file" | "folder"; label?: string }[] = []
+		const fileResults: { path: string; type: "file" | "folder"; label?: string }[] = []
+		const dirSet = new Set<string>() // Track unique directory paths
 		let count = 0
 
 		rl.on("line", (line) => {
 			if (count < limit) {
 				try {
 					const relativePath = path.relative(workspacePath, line)
-					results.push({
+
+					// Add the file itself
+					fileResults.push({
 						path: relativePath,
 						type: "file",
 						label: path.basename(relativePath),
 					})
+
+					// Extract and store all parent directory paths
+					let dirPath = path.dirname(relativePath)
+					while (dirPath && dirPath !== "." && dirPath !== "/") {
+						dirSet.add(dirPath)
+						dirPath = path.dirname(dirPath)
+					}
+
 					count++
 				} catch (error) {
 					// Silently ignore errors processing individual paths
@@ -60,10 +72,18 @@ async function executeRipgrepForFiles(
 		})
 
 		rl.on("close", () => {
-			if (errorOutput && results.length === 0) {
+			if (errorOutput && fileResults.length === 0) {
 				reject(new Error(`ripgrep process error: ${errorOutput}`))
 			} else {
-				resolve(results)
+				// Convert directory set to array of directory objects
+				const dirResults = Array.from(dirSet).map((dirPath) => ({
+					path: dirPath,
+					type: "folder" as const,
+					label: path.basename(dirPath),
+				}))
+
+				// Combine files and directories and resolve
+				resolve([...fileResults, ...dirResults])
 			}
 		})
 
@@ -86,40 +106,67 @@ export async function searchWorkspaceFiles(
 			throw new Error("Could not find ripgrep binary")
 		}
 
-		const allFiles = await executeRipgrepForFiles(rgPath, workspacePath, 5000)
+		// Get all files and directories (from our modified function)
+		const allItems = await executeRipgrepForFiles(rgPath, workspacePath, 5000)
 
+		// If no query, just return the top items
 		if (!query.trim()) {
-			return allFiles.slice(0, limit)
+			return allItems.slice(0, limit)
 		}
 
-		const searchItems = allFiles.map((file) => ({
-			original: file,
-			searchStr: `${file.path} ${file.label || ""}`,
+		// Create search items for all files AND directories
+		const searchItems = allItems.map((item) => ({
+			original: item,
+			searchStr: `${item.path} ${item.label || ""}`,
 		}))
 
+		// Run fzf search on all items
 		const fzf = new Fzf(searchItems, {
 			selector: (item) => item.searchStr,
 		})
 
-		const results = fzf
-			.find(query)
-			.slice(0, limit)
-			.map((result) => result.item.original)
+		// Get all matching results from fzf
+		const fzfResults = fzf.find(query)
 
-		const resultsWithDirectoryCheck = await Promise.all(
-			results.map(async (result) => {
-				const fullPath = path.join(workspacePath, result.path)
-				const isDirectory = fs.existsSync(fullPath) && fs.lstatSync(fullPath).isDirectory()
+		// First, sort all results by path length (shortest first)
+		fzfResults.sort((a, b) => {
+			return a.item.original.path.length - b.item.original.path.length
+		})
+
+		// Take the top N (limit) shortest results
+		const shortestResults = fzfResults.slice(0, limit).map((result) => result.item.original)
 
-				return {
-					...result,
-					type: isDirectory ? ("folder" as const) : ("file" as const),
+		// Verify types of the shortest results
+		const verifiedResults = await Promise.all(
+			shortestResults.map(async (result) => {
+				const fullPath = path.join(workspacePath, result.path)
+				// Verify if the path exists and is actually a directory
+				if (fs.existsSync(fullPath)) {
+					const isDirectory = fs.lstatSync(fullPath).isDirectory()
+					return {
+						...result,
+						type: isDirectory ? ("folder" as const) : ("file" as const),
+					}
 				}
+				// If path doesn't exist, keep original type
+				return result
 			}),
 		)
 
-		return resultsWithDirectoryCheck
+		// Final sort to put directories first within the shortest results
+		verifiedResults.sort((a, b) => {
+			if (a.type === "folder" && b.type !== "folder") {
+				return -1
+			}
+			if (a.type !== "folder" && b.type === "folder") {
+				return 1
+			}
+			return 0 // Keep original sorting by path length
+		})
+
+		return verifiedResults
 	} catch (error) {
+		console.error("Error in searchWorkspaceFiles:", error)
 		return []
 	}
 }