Skip to content

Commit

Permalink
Collapse search results when there is too many. Also sort results by …
Browse files Browse the repository at this point in the history
…line number
  • Loading branch information
brendan-kellam committed Sep 6, 2024
1 parent 687ebe9 commit 9c7db75
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 22 deletions.
6 changes: 3 additions & 3 deletions src/app/search/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ export default function SearchPage() {
<ResizablePanel minSize={20}>
<SearchResults
fileMatches={fileMatches}
onOpenFileMatch={(match) => {
setSelectedFile(match);
setSelectedMatchIndex(0);
onOpenFileMatch={(fileMatch, matchIndex) => {
setSelectedFile(fileMatch);
setSelectedMatchIndex(matchIndex);
}}
/>
</ResizablePanel>
Expand Down
50 changes: 41 additions & 9 deletions src/app/search/searchResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ import { ScrollArea } from "@/components/ui/scroll-area";
import { Separator } from "@/components/ui/separator";
import { ZoektFileMatch } from "@/lib/types";
import { Scrollbar } from "@radix-ui/react-scroll-area";
import { useMemo, useState } from "react";
import { DoubleArrowDownIcon, DoubleArrowUpIcon } from "@radix-ui/react-icons";

const MAX_MATCHES_TO_PREVIEW = 5;

interface SearchResultsProps {
fileMatches: ZoektFileMatch[];
onOpenFileMatch: (match: ZoektFileMatch) => void;
onOpenFileMatch: (fileMatch: ZoektFileMatch, matchIndex: number) => void;
}

export const SearchResults = ({
Expand All @@ -17,12 +21,12 @@ export const SearchResults = ({
return (
<ScrollArea className="h-full">
<div className="flex flex-col gap-2">
{fileMatches.map((match, index) => (
{fileMatches.map((fileMatch, index) => (
<FileMatch
key={index}
match={match}
onOpenFile={() => {
onOpenFileMatch(match);
match={fileMatch}
onOpenFile={(matchIndex) => {
onOpenFileMatch(fileMatch, matchIndex);
}}
/>
))}
Expand All @@ -34,35 +38,63 @@ export const SearchResults = ({

interface FileMatchProps {
match: ZoektFileMatch;
onOpenFile: () => void;
onOpenFile: (matchIndex: number) => void;
}

const FileMatch = ({
match,
onOpenFile,
}: FileMatchProps) => {

const [showAll, setShowAll] = useState(false);
const matchCount = useMemo(() => {
return match.Matches.length;
}, [match]);

const matches = useMemo(() => {
const sortedMatches = match.Matches.sort((a, b) => {
return a.LineNum - b.LineNum;
});

if (!showAll) {
return sortedMatches.slice(0, MAX_MATCHES_TO_PREVIEW);
}

return sortedMatches;
}, [match, showAll]);

return (
<div>
<div className="bg-cyan-200 dark:bg-cyan-900 primary-foreground px-2">
<span>{match.Repo} · {match.FileName}</span>
</div>
{match.Matches.map((match, index) => {
{matches.map((match, index) => {
const fragment = match.Fragments[0];

return (
<div
key={index}
className="font-mono px-4 py-0.5 text-sm cursor-pointer"
onClick={() => {
onOpenFile();
onOpenFile(index);
}}
>
<p>{match.LineNum}: {fragment.Pre}<span className="font-bold">{fragment.Match}</span>{fragment.Post}</p>
<p>{match.LineNum > 0 ? match.LineNum : "file match"}: {fragment.Pre}<span className="font-bold">{fragment.Match}</span>{fragment.Post}</p>
<Separator />
</div>
);
})}
{matchCount > MAX_MATCHES_TO_PREVIEW && (
<div className="px-4">
<p
onClick={() => setShowAll(!showAll)}
className="text-blue-500 cursor-pointer text-sm flex flex-row items-center gap-2"
>
{showAll ? <DoubleArrowUpIcon className="w-3 h-3" /> : <DoubleArrowDownIcon className="w-3 h-3" />}
{showAll ? `Show fewer matching lines` : `Show ${matchCount - MAX_MATCHES_TO_PREVIEW} more matching lines`}
</p>
</div>
)}
</div>
);
}
26 changes: 16 additions & 10 deletions src/lib/extensions/searchResultHighlightExtension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@ const matchHighlighter = StateField.define<DecorationSet>({
if (effect.is(setMatchState)) {
const { matches, selectedMatchIndex } = effect.value;

const decorations = matches.map((match, index) => {
const { from, to } = getMatchRange(match, transaction.newDoc);
const mark = index === selectedMatchIndex ? selectedMatchMark : matchMark;
return mark.range(from, to);
});
const decorations = matches
.filter((match) => match.LineNum > 0)
.map((match, index) => {
const { from, to } = getMatchRange(match, transaction.newDoc);
const mark = index === selectedMatchIndex ? selectedMatchMark : matchMark;
return mark.range(from, to);
});

highlights = Decoration.set(decorations)
}
Expand Down Expand Up @@ -77,11 +79,15 @@ export const markMatches = (selectedMatchIndex: number, matches: ZoektMatch[], v

if (selectedMatchIndex >= 0 && selectedMatchIndex < matches.length) {
const match = matches[selectedMatchIndex];
const { from, to } = getMatchRange(match, view.state.doc);
const selection = EditorSelection.range(from, to);
effects.push(EditorView.scrollIntoView(selection, {
y: "start",
}));

// Don't scroll if the match is on the filename.
if (match.LineNum > 0) {
const { from, to } = getMatchRange(match, view.state.doc);
const selection = EditorSelection.range(from, to);
effects.push(EditorView.scrollIntoView(selection, {
y: "start",
}));
}
};

view.dispatch({ effects });
Expand Down

0 comments on commit 9c7db75

Please sign in to comment.