Query syntax
The query syntax of neogrok is controlled by zoekt, the code search engine for which neogrok is a frontend. Because zoekt does not have good documentation covering this syntax, we describe it here.
Everything is regex
In zoekt, all queries are parsed by Go's regexp package, the syntax of which is documented here. There is no way to disable this functionality; queries that want to use regex control characters literally must escape them.
Queries cannot control the
regex flags
that zoekt uses; they are hardcoded. As can be seen
here, the flags are ClassNL
, PerlX
, and
UnicodeGroups
. Together, these flags notably allow multiline
regex matches using character classes like
[[:space:]]
, but not using the dot.
Queries are composed of one or more space-separated expressions
If your query contains no spaces, its behavior is pretty intuitive.
foo
displays all matches for the regex
/foo/
. That query contains a single
expression, namely a regex expression. (We'll introduce
more kinds of expressions below.)
But what about foo bar
? This query has two
expressions, which makes its behavior more complicated: it returns all
matches for the regex /foo/
or the regex /bar/
, but only in files that have matches for both /foo/
and /bar/
.
First of all, if you wanted this query to behave as if it had only one
expression, literally matching /foo bar/
, you can
either wrap it in double quotes, like
"foo bar"
, or by escaping the space, like
foo\ bar
; both of those queries are equivalent.
(Single quotes have no special meaning in this regard.
'foo bar'
contains two expressions, the first being
/'foo/
and the second being
/bar'/
.)
Multiple expressions are combined with boolean logic
As described above, expressions are conjunctive by default: a
file must have at least one match for each expression to be included in
the query results. Expressions may be made disjunctive by
joining them with the special expression infix operator or
.
foo or bar
returns all matches for
/foo/
or /bar/
in all files
that have matches for at least one of
/foo/
or /bar/
. (To
use or
as a literal expression and not as an operator,
double quote it: foo "or" bar
has three conjunctive
expressions.)
Expressions can be logically grouped with parentheses: foo (bar or baz)
produces results from files with matches for both /foo/
and at least one of /bar/
or /baz/
. These groupings can be nested arbitrarily.
To complete the boolean logic, expressions can be negated with a leading
dash. foo -bar
returns all matches for
/foo/
in files that do not have matches for
/bar/
. foo -(bar or baz)
returns all matches for /foo/
in files that do
not have matches for either /bar/
or
/baz/
. foo -(bar baz)
returns all matches for /foo/
in files that do not
have matches for both /bar/
and
/baz/
.
Certain prefixes have special effects on expressions
In addition to the default regex expressions you've already seen, special kinds of expressions can be created by prefixing them with certain flags, which are themselves composed of a few characters ending with a colon.
Consider that regex expressions can produce matches both in the content of
a file and in the name of the file:
README
matches both file names and file contents (though
the search engine tends to rank files containing file name matches higher than
those containing only content matches, so you may have to scroll down or increase
the number of files displayed to see the content matches for this query). If
you only want the expression to match file names, use an expression prefixed
with
file:
, like file:README
. (
f:
is an equivalent abbreviation for file:
).
The inverse of file:
's specialization of regex
expressions is content:
or c:
.
content:README
produces only matches that occur in
the content of files.
There are a few more kinds of prefix expressions than those two. They're all tabulated below.
Finally, note that the boolean logic described above applies to prefix
expressions just like normal ones: -f:test assert
shows matches for /assert/
except for those in files
whose names match /test/
.
Prefix(es) | Description | Examples |
---|---|---|
file: , f: | Regex match file names only, instead of the default file names and file contents | f:README f:README neogrok f:"evil file with spaces" |
content: , c: | Regex match file contents only, instead of the default file names and file contents | c:README |
repo: , r: | Regex match repository names; by default all repositories are searched | r:linux driver |
branch: , b: | Regex match branch names; by default all branches are searched | b:prerelease foo |
lang: | Constrain files to those in the given language (or language alias) as defined by linguist and computed probabilistically from file name and contents at index time by go-enry. This is not a regex or a substring, though it is case-insensitive; each expression can only contain one language. | lang:typescript type |
sym: | Regex match symbol definitions, as determined by universal ctags at index time, if it was present during indexing | sym:\bmain\b |
case: | Unlike most other expressions, does not do anything on its own, but
rather modifies other expressions in the query.
case:yes makes other expressions case-sensitive;
case:no makes them case-insensitive, and
case:auto (the default behavior) makes them case-sensitive
if they have any uppercase characters and case-insensitive otherwise | case:no TEST |
archived: | archived:no excludes archived repositories while
archived:yes excludes non-archived repositories. The default
is to exclude neither. | archived:no readme |
fork: | fork:no excludes repositories that are forks of another
while fork:yes excludes repositories that are not forks of
another. The default is to exclude neither. | fork:no readme |
public: | public:no excludes public repositories while
public:yes excludes private repositories. The default is to
exclude neither. | public:no readme |