/** `grep` (legacy `search`) — ripgrep content search across workspace files. */ import type { ReactNode } from "react"; import { Badge, Badges, InvalidArg, Note, ResultText } from "../parts"; import type { ToolRenderer, ToolRenderProps } from "../types"; import { detailsRecord, num, resultTextOf, scopePaths, shortenPath, str } from "../util"; /** Grep scope: current `path` (string, delimited, or JSON array) or legacy `paths`; defaults to workspace root. */ function pathsOf(args: Record): string[] { const list = scopePaths(args).map(shortenPath); return list.length ? list : ["."]; } /** Flag badges covering current and legacy arg dialects. */ function argBadges(args: Record): ReactNode[] { const badges: ReactNode[] = []; const glob = str(args.glob); if (glob) badges.push(`glob=${glob}`); const type = str(args.type); if (type) badges.push(`type=${type}`); if (args.i === true) badges.push("i"); if (args.multiline === true) badges.push("multiline"); if (args.gitignore === false) badges.push("no-gitignore"); const skip = num(args.skip); if (skip !== null && skip > 0) badges.push(`skip=${skip}`); return badges; } function Pattern({ args }: { args: Record }): ReactNode { const pattern = str(args.pattern); if (pattern === null) return ; return /{pattern}/; } function Summary({ args }: ToolRenderProps): ReactNode { return ( in{" "} {pathsOf(args).join(", ")} ); } function Body({ args, result }: ToolRenderProps): ReactNode { const details = detailsRecord(result); const matchCount = num(details?.matchCount); const fileCount = num(details?.fileCount); const truncated = details?.truncated === true; const error = str(details?.error); const missing: string[] = []; if (details && Array.isArray(details.missingPaths)) { for (const p of details.missingPaths) { if (typeof p === "string") missing.push(shortenPath(p)); } } const badges = argBadges(args); if (matchCount !== null) badges.push(`${matchCount} ${matchCount === 1 ? "match" : "matches"}`); if (fileCount !== null) badges.push(`${fileCount} ${fileCount === 1 ? "file" : "files"}`); return ( <>
in{" "} {pathsOf(args).join(", ")} {truncated && ( <> {" "} truncated )}
{missing.length > 0 && skipped missing: {missing.join(", ")}} {error !== null && !resultTextOf(result).trim() && {error}} ); } export const grepRenderer: ToolRenderer = { Summary, Body };