feat: expand smart-explore to 24 languages with markdown support and user-installable grammars
Add 15 new tree-sitter language grammars (Kotlin, Swift, PHP, Elixir, Lua, Scala, Bash, Haskell, Zig, CSS, SCSS, TOML, YAML, SQL, Markdown) with verified SCM queries. Add markdown-specific formatting with heading hierarchy, code block detection, and section-aware unfold. Add user-installable grammar system via .claude-mem.json config with custom query file support. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
|
||||
import { readFile, readdir, stat } from "node:fs/promises";
|
||||
import { join, relative } from "node:path";
|
||||
import { parseFilesBatch, formatFoldedView, type FoldedFile } from "./parser.js";
|
||||
import { parseFilesBatch, formatFoldedView, loadUserGrammars, type FoldedFile } from "./parser.js";
|
||||
|
||||
const CODE_EXTENSIONS = new Set([
|
||||
".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs",
|
||||
@@ -22,11 +22,22 @@ const CODE_EXTENSIONS = new Set([
|
||||
".rb",
|
||||
".java",
|
||||
".cs",
|
||||
".cpp", ".c", ".h", ".hpp",
|
||||
".cpp", ".cc", ".cxx", ".c", ".h", ".hpp", ".hh",
|
||||
".swift",
|
||||
".kt",
|
||||
".kt", ".kts",
|
||||
".php",
|
||||
".vue", ".svelte",
|
||||
".ex", ".exs",
|
||||
".lua",
|
||||
".scala", ".sc",
|
||||
".sh", ".bash", ".zsh",
|
||||
".hs",
|
||||
".zig",
|
||||
".css", ".scss",
|
||||
".toml",
|
||||
".yml", ".yaml",
|
||||
".sql",
|
||||
".md", ".mdx",
|
||||
]);
|
||||
|
||||
const IGNORE_DIRS = new Set([
|
||||
@@ -59,8 +70,9 @@ export interface SymbolMatch {
|
||||
|
||||
/**
|
||||
* Walk a directory recursively, yielding file paths.
|
||||
* extraExtensions: additional file extensions to include (from user grammar config).
|
||||
*/
|
||||
async function* walkDir(dir: string, rootDir: string, maxDepth: number = 20): AsyncGenerator<string> {
|
||||
async function* walkDir(dir: string, rootDir: string, maxDepth: number = 20, extraExtensions?: Set<string>): AsyncGenerator<string> {
|
||||
if (maxDepth <= 0) return;
|
||||
|
||||
let entries;
|
||||
@@ -77,10 +89,10 @@ async function* walkDir(dir: string, rootDir: string, maxDepth: number = 20): As
|
||||
const fullPath = join(dir, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
yield* walkDir(fullPath, rootDir, maxDepth - 1);
|
||||
yield* walkDir(fullPath, rootDir, maxDepth - 1, extraExtensions);
|
||||
} else if (entry.isFile()) {
|
||||
const ext = entry.name.slice(entry.name.lastIndexOf("."));
|
||||
if (CODE_EXTENSIONS.has(ext)) {
|
||||
if (CODE_EXTENSIONS.has(ext) || (extraExtensions && extraExtensions.has(ext))) {
|
||||
yield fullPath;
|
||||
}
|
||||
}
|
||||
@@ -121,16 +133,29 @@ export async function searchCodebase(
|
||||
maxResults?: number;
|
||||
includeImports?: boolean;
|
||||
filePattern?: string;
|
||||
projectRoot?: string;
|
||||
} = {}
|
||||
): Promise<SearchResult> {
|
||||
const maxResults = options.maxResults || 20;
|
||||
const queryLower = query.toLowerCase();
|
||||
const queryParts = queryLower.split(/[\s_\-./]+/).filter(p => p.length > 0);
|
||||
|
||||
// Load user grammar config for extra file extensions
|
||||
const projectRoot = options.projectRoot || rootDir;
|
||||
const userConfig = loadUserGrammars(projectRoot);
|
||||
const extraExtensions = new Set<string>();
|
||||
for (const entry of Object.values(userConfig.grammars)) {
|
||||
for (const ext of entry.extensions) {
|
||||
if (!CODE_EXTENSIONS.has(ext)) {
|
||||
extraExtensions.add(ext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 1: Collect files
|
||||
const filesToParse: Array<{ absolutePath: string; relativePath: string; content: string }> = [];
|
||||
|
||||
for await (const filePath of walkDir(rootDir, rootDir)) {
|
||||
for await (const filePath of walkDir(rootDir, rootDir, 20, extraExtensions.size > 0 ? extraExtensions : undefined)) {
|
||||
if (options.filePattern) {
|
||||
const relPath = relative(rootDir, filePath);
|
||||
if (!relPath.toLowerCase().includes(options.filePattern.toLowerCase())) continue;
|
||||
@@ -147,7 +172,7 @@ export async function searchCodebase(
|
||||
}
|
||||
|
||||
// Phase 2: Batch parse (one CLI call per language)
|
||||
const parsedFiles = parseFilesBatch(filesToParse);
|
||||
const parsedFiles = parseFilesBatch(filesToParse, projectRoot);
|
||||
|
||||
// Phase 3: Match query against symbols
|
||||
const foldedFiles: FoldedFile[] = [];
|
||||
|
||||
Reference in New Issue
Block a user