mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-12 04:15:30 +00:00
update docs and remove uneeded test file
This commit is contained in:
parent
d9ff676579
commit
aac88a6db1
3 changed files with 145 additions and 117 deletions
|
|
@ -4,32 +4,51 @@ title: Writing search queries
|
||||||
|
|
||||||
Sourcebot uses a powerful regex-based query language that enabled precise code search within large codebases.
|
Sourcebot uses a powerful regex-based query language that enabled precise code search within large codebases.
|
||||||
|
|
||||||
|
|
||||||
## Syntax reference guide
|
## 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 |
|
| Example | Explanation |
|
||||||
| :--- | :--- |
|
| :--- | :--- |
|
||||||
| `foo` | Match files with regex `/foo/` |
|
| `foo` | Match files with regex `/foo/` |
|
||||||
| `foo bar` | Match files with regex `/foo/` **and** `/bar/` |
|
| `foo.*bar` | Match files with regex `/foo.*bar/` (foo followed by any characters, then bar) |
|
||||||
| `"foo bar"` | Match files with regex `/foo 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 |
|
Search queries (keyword or regex) can include multiple search filters to further refine the search results. Some filters can be negated using the `-` prefix.
|
||||||
| :--- | :--- |
|
|
||||||
| `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.
|
|
||||||
|
|
||||||
| Prefix | Description | Example |
|
| 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$/` |
|
| `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/` |
|
| `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 |
|
| `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/` |
|
| `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`. |
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
|
|
@ -15,6 +15,7 @@ import { useCallback, useRef } from "react";
|
||||||
import { useHotkeys } from "react-hotkeys-hook";
|
import { useHotkeys } from "react-hotkeys-hook";
|
||||||
import { useSyntaxGuide } from "./syntaxGuideProvider";
|
import { useSyntaxGuide } from "./syntaxGuideProvider";
|
||||||
import { CodeSnippet } from "@/app/components/codeSnippet";
|
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 LINGUIST_LINK = "https://github.com/github-linguist/linguist/blob/main/lib/linguist/languages.yml";
|
||||||
const CTAGS_LINK = "https://ctags.io/";
|
const CTAGS_LINK = "https://ctags.io/";
|
||||||
|
|
@ -61,70 +62,92 @@ export const SyntaxReferenceGuide = () => {
|
||||||
onOpenChange={handleOpenChange}
|
onOpenChange={handleOpenChange}
|
||||||
>
|
>
|
||||||
<DialogContent
|
<DialogContent
|
||||||
className="max-h-[80vh] max-w-[700px] overflow-scroll"
|
className="max-h-[80vh] max-w-[700px] overflow-scroll gap-2"
|
||||||
>
|
>
|
||||||
<DialogHeader>
|
<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">
|
<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>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</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"/>
|
<div>
|
||||||
<p className="text-sm">
|
<h3 className="text-lg font-semibold mt-4 mb-0">Keyword search (default)</h3>
|
||||||
{`Multiple expressions can be or'd together with `}<CodeSnippet>or</CodeSnippet>, negated with <CodeSnippet>-</CodeSnippet>, or grouped with <CodeSnippet>()</CodeSnippet>.
|
<p className="text-sm mb-2 mt-0">
|
||||||
</p>
|
Keyword search matches search patterns exactly in file contents. Wrapping search patterns in <CodeSnippet>{`""`}</CodeSnippet> combines them as a single expression.
|
||||||
<Table>
|
</p>
|
||||||
<TableHeader>
|
<Table>
|
||||||
<TableRow>
|
<TableHeader>
|
||||||
<TableHead className="py-2">Example</TableHead>
|
<TableRow>
|
||||||
<TableHead className="py-2">Explanation</TableHead>
|
<TableHead className="py-2">Example</TableHead>
|
||||||
</TableRow>
|
<TableHead className="py-2">Explanation</TableHead>
|
||||||
</TableHeader>
|
</TableRow>
|
||||||
<TableBody>
|
</TableHeader>
|
||||||
<TableRow>
|
<TableBody>
|
||||||
<TableCell className="py-2"><CodeSnippet>foo <Highlight>or</Highlight> bar</CodeSnippet></TableCell>
|
<TableRow>
|
||||||
<TableCell className="py-2">Match files with regex <CodeSnippet>/foo/</CodeSnippet> <b>or</b> <CodeSnippet>/bar/</CodeSnippet></TableCell>
|
<TableCell className="py-2"><CodeSnippet>foo</CodeSnippet></TableCell>
|
||||||
</TableRow>
|
<TableCell className="py-2">Match files containing the keyword <CodeSnippet>foo</CodeSnippet></TableCell>
|
||||||
<TableRow>
|
</TableRow>
|
||||||
<TableCell className="py-2"><CodeSnippet>foo -bar</CodeSnippet></TableCell>
|
<TableRow>
|
||||||
<TableCell className="py-2">Match files with regex <CodeSnippet>/foo/</CodeSnippet> but <b>not</b> <CodeSnippet>/bar/</CodeSnippet></TableCell>
|
<TableCell className="py-2"><CodeSnippet>foo bar</CodeSnippet></TableCell>
|
||||||
</TableRow>
|
<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 <Highlight>or</Highlight> baz)</CodeSnippet></TableCell>
|
<TableRow>
|
||||||
<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>
|
<TableCell className="py-2"><CodeSnippet>{`"foo bar"`}</CodeSnippet></TableCell>
|
||||||
</TableRow>
|
<TableCell className="py-2">Match files containing the phrase <CodeSnippet>foo bar</CodeSnippet></TableCell>
|
||||||
</TableBody>
|
</TableRow>
|
||||||
</Table>
|
<TableRow>
|
||||||
|
<TableCell className="py-2"><CodeSnippet>{'"foo \\"bar\\""'}</CodeSnippet></TableCell>
|
||||||
|
<TableCell className="py-2">Match files containing <CodeSnippet>foo "bar"</CodeSnippet> exactly (escaped quotes)</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Separator className="my-2"/>
|
<Separator className="my-4"/>
|
||||||
<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>
|
|
||||||
|
|
||||||
<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>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableHead className="py-2">Prefix</TableHead>
|
<TableHead className="py-2">Prefix</TableHead>
|
||||||
|
|
@ -219,7 +242,39 @@ export const SyntaxReferenceGuide = () => {
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Separator className="my-4"/>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="text-lg font-semibold mt-4 mb-0">Boolean operators & grouping</h3>
|
||||||
|
<p className="text-sm mb-2 mt-0">
|
||||||
|
By default, space-seperated expressions are and'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>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue