update docs and remove uneeded test file

This commit is contained in:
bkellam 2025-11-22 15:02:49 -08:00
parent d9ff676579
commit aac88a6db1
3 changed files with 145 additions and 117 deletions

View file

@ -4,32 +4,51 @@ title: Writing search queries
Sourcebot uses a powerful regex-based query language that enabled precise code search within large codebases.
## Syntax reference guide
Queries consist of space-separated regular expressions. Wrapping expressions in `""` combines them. By default, a file must have at least one match for each expression to be included.
Queries consist of space-separated search patterns that are matched against file contents. A file must have at least one match for each expression to be included. Queries can optionally contain search filters to further refine the search results.
## Keyword search (default)
Keyword search matches search patterns exactly in file contents. Wrapping search patterns in `""` combines them as a single expression.
| Example | Explanation |
| :--- | :--- |
| `foo` | Match files containing the keyword `foo` |
| `foo bar` | Match files containing both `foo` **and** `bar` |
| `"foo bar"` | Match files containing the phrase `foo bar` |
| `"foo \"bar\""` | Match files containing `foo "bar"` exactly (escaped quotes) |
## Regex search
Toggle the regex button (`.*`) in the search bar to interpret search patterns as regular expressions.
| Example | Explanation |
| :--- | :--- |
| `foo` | Match files with regex `/foo/` |
| `foo bar` | Match files with regex `/foo/` **and** `/bar/` |
| `"foo bar"` | Match files with regex `/foo bar/` |
| `foo.*bar` | Match files with regex `/foo.*bar/` (foo followed by any characters, then bar) |
| `^function\s+\w+` | Match files with regex `/^function\s+\w+/` (function at start of line, followed by whitespace and word characters) |
| `"foo bar"` | Match files with regex `/foo bar/`. Quotes are not matched. |
Multiple expressions can be or'd together with `or`, negated with `-`, or grouped with `()`.
## Search filters
| Example | Explanation |
| :--- | :--- |
| `foo or bar` | Match files with regex `/foo/` **or** `/bar/` |
| `foo -bar` | Match files with regex `/foo/` but **not** `/bar/` |
| `foo (bar or baz)` | Match files with regex `/foo/` **and** either `/bar/` **or** `/baz/` |
Expressions can be prefixed with certain keywords to modify search behavior. Some keywords can be negated using the `-` prefix.
Search queries (keyword or regex) can include multiple search filters to further refine the search results. Some filters can be negated using the `-` prefix.
| Prefix | Description | Example |
| :--- | :--- | :--- |
| `file:` | Filter results from filepaths that match the regex. By default all files are searched. | `file:README` - Filter results to filepaths that match regex `/README/`<br/>`file:"my file"` - Filter results to filepaths that match regex `/my file/`<br/>`-file:test\.ts$` - Ignore results from filepaths match regex `/test\.ts$/` |
| `repo:` | Filter results from repos that match the regex. By default all repos are searched. | `repo:linux` - Filter results to repos that match regex `/linux/`<br/>`-repo:^web/.*` - Ignore results from repos that match regex `/^web\/.*` |
| `repo:` | Filter results from repos that match the regex. By default all repos are searched. | `repo:linux` - Filter results to repos that match regex `/linux/`<br/>`-repo:^web/.*` - Ignore results from repos that match regex `/^web\/.*/` |
| `rev:` | Filter results from a specific branch or tag. By default **only** the default branch is searched. | `rev:beta` - Filter results to branches that match regex `/beta/` |
| `lang:` | Filter results by language (as defined by [linguist](https://github.com/github-linguist/linguist/blob/main/lib/linguist/languages.yml)). By default all languages are searched. | `lang:TypeScript` - Filter results to TypeScript files<br/>`-lang:YAML` - Ignore results from YAML files |
| `sym:` | Match symbol definitions created by [universal ctags](https://ctags.io/) at index time. | `sym:\bmain\b` - Filter results to symbols that match regex `/\bmain\b/` |
| `context:` | Filter results to a predefined [search context](/docs/features/search/search-contexts). | `context:web` - Filter results to the web context<br/>`-context:pipelines` - Ignore results from the pipelines context |
| `context:` | Filter results to a predefined [search context](/docs/features/search/search-contexts). | `context:web` - Filter results to the web context<br/>`-context:pipelines` - Ignore results from the pipelines context |
## Boolean operators & grouping
By default, space-separated expressions are and'd together. Using the `or` keyword as well as parentheses `()` can be used to create more complex boolean logic. Parentheses can be negated using the `-` prefix.
| Example | Explanation |
| :--- | :--- |
| `foo or bar` | Match files containing `foo` **or** `bar` |
| `foo (bar or baz)` | Match files containing `foo` **and** either `bar` **or** `baz`. |
| `-(foo) bar` | Match files containing `bar` **and not** `foo`. |

View file

@ -1,46 +0,0 @@
import { parser } from "./src/parser";
const input = "hello case:yes";
const tree = parser.parse(input);
const prettyPrint = (tree: ReturnType<typeof parser.parse>, input: string) => {
let result = "";
let lastPos = 0;
tree.iterate({
enter: (node) => {
// If this is a leaf node (terminal), collect its text
if (node.from >= node.to) {
// Empty node, skip
return;
}
// Check if this node has any children by checking the tree structure
const nodeTree = node.node;
const isLeaf = !nodeTree.firstChild;
if (isLeaf) {
// Add any whitespace between the last position and this node
if (node.from > lastPos) {
result += input.slice(lastPos, node.from);
}
// Add the node's text
result += input.slice(node.from, node.to);
lastPos = node.to;
}
}
});
// Add any trailing content
if (lastPos < input.length) {
result += input.slice(lastPos, input.length);
}
return result;
}
const reconstructed = prettyPrint(tree, input);
console.log("Original:", input);
console.log("Reconstructed:", reconstructed);
console.log("Match:", input === reconstructed);

View file

@ -15,6 +15,7 @@ import { useCallback, useRef } from "react";
import { useHotkeys } from "react-hotkeys-hook";
import { useSyntaxGuide } from "./syntaxGuideProvider";
import { CodeSnippet } from "@/app/components/codeSnippet";
import { ExternalLinkIcon, RegexIcon } from "lucide-react";
const LINGUIST_LINK = "https://github.com/github-linguist/linguist/blob/main/lib/linguist/languages.yml";
const CTAGS_LINK = "https://ctags.io/";
@ -61,70 +62,92 @@ export const SyntaxReferenceGuide = () => {
onOpenChange={handleOpenChange}
>
<DialogContent
className="max-h-[80vh] max-w-[700px] overflow-scroll"
className="max-h-[80vh] max-w-[700px] overflow-scroll gap-2"
>
<DialogHeader>
<DialogTitle>Syntax Reference Guide</DialogTitle>
<DialogTitle>Syntax Reference Guide <Link href="https://docs.sourcebot.dev/docs/features/search/syntax-reference"><ExternalLinkIcon className="inline w-4 h-4 ml-1 mb-1 text-muted-foreground cursor-pointer" /></Link></DialogTitle>
<DialogDescription className="text-sm text-foreground">
Queries consist of space-seperated regular expressions. Wrapping expressions in <CodeSnippet>{`""`}</CodeSnippet> combines them. By default, a file must have at least one match for each expression to be included.
Queries consist of space-separated search patterns that are matched against file contents. A file must have at least one match for each expression to be included. Queries can optionally contain search filters to further refine the search results.
</DialogDescription>
</DialogHeader>
<Table>
<TableHeader>
<TableRow>
<TableHead className="py-2">Example</TableHead>
<TableHead className="py-2">Explanation</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell className="py-2"><CodeSnippet>foo</CodeSnippet></TableCell>
<TableCell className="py-2">Match files with regex <CodeSnippet>/foo/</CodeSnippet></TableCell>
</TableRow>
<TableRow>
<TableCell className="py-2"><CodeSnippet>foo bar</CodeSnippet></TableCell>
<TableCell className="py-2">Match files with regex <CodeSnippet>/foo/</CodeSnippet> <b>and</b> <CodeSnippet>/bar/</CodeSnippet></TableCell>
</TableRow>
<TableRow>
<TableCell className="py-2"><CodeSnippet>{`"foo bar"`}</CodeSnippet></TableCell>
<TableCell className="py-2">Match files with regex <CodeSnippet>/foo bar/</CodeSnippet></TableCell>
</TableRow>
</TableBody>
</Table>
<Separator className="my-2"/>
<p className="text-sm">
{`Multiple expressions can be or'd together with `}<CodeSnippet>or</CodeSnippet>, negated with <CodeSnippet>-</CodeSnippet>, or grouped with <CodeSnippet>()</CodeSnippet>.
</p>
<Table>
<TableHeader>
<TableRow>
<TableHead className="py-2">Example</TableHead>
<TableHead className="py-2">Explanation</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell className="py-2"><CodeSnippet>foo <Highlight>or</Highlight> bar</CodeSnippet></TableCell>
<TableCell className="py-2">Match files with regex <CodeSnippet>/foo/</CodeSnippet> <b>or</b> <CodeSnippet>/bar/</CodeSnippet></TableCell>
</TableRow>
<TableRow>
<TableCell className="py-2"><CodeSnippet>foo -bar</CodeSnippet></TableCell>
<TableCell className="py-2">Match files with regex <CodeSnippet>/foo/</CodeSnippet> but <b>not</b> <CodeSnippet>/bar/</CodeSnippet></TableCell>
</TableRow>
<TableRow>
<TableCell className="py-2"><CodeSnippet>foo (bar <Highlight>or</Highlight> baz)</CodeSnippet></TableCell>
<TableCell className="py-2">Match files with regex <CodeSnippet>/foo/</CodeSnippet> <b>and</b> either <CodeSnippet>/bar/</CodeSnippet> <b>or</b> <CodeSnippet>/baz/</CodeSnippet></TableCell>
</TableRow>
</TableBody>
</Table>
<div>
<h3 className="text-lg font-semibold mt-4 mb-0">Keyword search (default)</h3>
<p className="text-sm mb-2 mt-0">
Keyword search matches search patterns exactly in file contents. Wrapping search patterns in <CodeSnippet>{`""`}</CodeSnippet> combines them as a single expression.
</p>
<Table>
<TableHeader>
<TableRow>
<TableHead className="py-2">Example</TableHead>
<TableHead className="py-2">Explanation</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell className="py-2"><CodeSnippet>foo</CodeSnippet></TableCell>
<TableCell className="py-2">Match files containing the keyword <CodeSnippet>foo</CodeSnippet></TableCell>
</TableRow>
<TableRow>
<TableCell className="py-2"><CodeSnippet>foo bar</CodeSnippet></TableCell>
<TableCell className="py-2">Match files containing both <CodeSnippet>foo</CodeSnippet> <b>and</b> <CodeSnippet>bar</CodeSnippet></TableCell>
</TableRow>
<TableRow>
<TableCell className="py-2"><CodeSnippet>{`"foo bar"`}</CodeSnippet></TableCell>
<TableCell className="py-2">Match files containing the phrase <CodeSnippet>foo bar</CodeSnippet></TableCell>
</TableRow>
<TableRow>
<TableCell className="py-2"><CodeSnippet>{'"foo \\"bar\\""'}</CodeSnippet></TableCell>
<TableCell className="py-2">Match files containing <CodeSnippet>foo &quot;bar&quot;</CodeSnippet> exactly (escaped quotes)</TableCell>
</TableRow>
</TableBody>
</Table>
</div>
<Separator className="my-2"/>
<p className="text-sm">
Expressions can be prefixed with certain keywords to modify search behavior. Some keywords can be negated using the <CodeSnippet>-</CodeSnippet> prefix.
</p>
<Separator className="my-4"/>
<Table>
<div>
<h3 className="text-lg font-semibold mt-4 mb-0">Regex search</h3>
<p className="text-sm mb-2 mt-0">
Toggle the <RegexIcon className="inline w-4 h-4 align-middle mx-0.5 border rounded px-0.5 py-0.5" /> button to interpret search patterns as regular expressions.
</p>
<Table>
<TableHeader>
<TableRow>
<TableHead className="py-2">Example</TableHead>
<TableHead className="py-2">Explanation</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell className="py-2"><CodeSnippet>foo</CodeSnippet></TableCell>
<TableCell className="py-2">Match files with regex <CodeSnippet>/foo/</CodeSnippet></TableCell>
</TableRow>
<TableRow>
<TableCell className="py-2"><CodeSnippet>foo.*bar</CodeSnippet></TableCell>
<TableCell className="py-2">Match files with regex <CodeSnippet>/foo.*bar/</CodeSnippet> (foo followed by any characters, then bar)</TableCell>
</TableRow>
<TableRow>
<TableCell className="py-2"><CodeSnippet>{`^function\\s+\\w+`}</CodeSnippet></TableCell>
<TableCell className="py-2">Match files with regex <CodeSnippet>/^function\s+\w+/</CodeSnippet> (function at start of line, followed by whitespace and word characters)</TableCell>
</TableRow>
<TableRow>
<TableCell className="py-2"><CodeSnippet>{`"foo bar"`}</CodeSnippet></TableCell>
<TableCell className="py-2">Match files with regex <CodeSnippet>/foo bar/</CodeSnippet>. Quotes are not matched.</TableCell>
</TableRow>
</TableBody>
</Table>
</div>
<Separator className="my-4"/>
<div>
<h3 className="text-lg font-semibold mt-4 mb-0">Search filters</h3>
<p className="text-sm mb-2 mt-0">
Search queries (keyword or regex) can include multiple search filters to further refine the search results. Some filters can be negated using the <CodeSnippet>-</CodeSnippet> prefix.
</p>
<Table>
<TableHeader>
<TableRow>
<TableHead className="py-2">Prefix</TableHead>
@ -219,7 +242,39 @@ export const SyntaxReferenceGuide = () => {
</TableCell>
</TableRow>
</TableBody>
</Table>
</Table>
</div>
<Separator className="my-4"/>
<div>
<h3 className="text-lg font-semibold mt-4 mb-0">Boolean operators &amp; grouping</h3>
<p className="text-sm mb-2 mt-0">
By default, space-seperated expressions are and&apos;d together. Using the <CodeSnippet>or</CodeSnippet> keyword as well as parantheses <CodeSnippet>()</CodeSnippet> can be used to create more complex boolean logic. Parantheses can be negated using the <CodeSnippet>-</CodeSnippet> prefix.
</p>
<Table>
<TableHeader>
<TableRow>
<TableHead className="py-2">Example</TableHead>
<TableHead className="py-2">Explanation</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell className="py-2"><CodeSnippet>foo <Highlight>or</Highlight> bar</CodeSnippet></TableCell>
<TableCell className="py-2">Match files containing <CodeSnippet>foo</CodeSnippet> <b>or</b> <CodeSnippet>bar</CodeSnippet></TableCell>
</TableRow>
<TableRow>
<TableCell className="py-2"><CodeSnippet>foo (bar <Highlight>or</Highlight> baz)</CodeSnippet></TableCell>
<TableCell className="py-2">Match files containing <CodeSnippet>foo</CodeSnippet> <b>and</b> either <CodeSnippet>bar</CodeSnippet> <b>or</b> <CodeSnippet>baz</CodeSnippet>.</TableCell>
</TableRow>
<TableRow>
<TableCell className="py-2"><CodeSnippet>-(foo) bar</CodeSnippet></TableCell>
<TableCell className="py-2">Match files containing <CodeSnippet>bar</CodeSnippet> <b>and not</b> <CodeSnippet>foo</CodeSnippet>.</TableCell>
</TableRow>
</TableBody>
</Table>
</div>
</DialogContent>
</Dialog>
)