sourcebot/packages/web/src/app/[domain]/components/searchBar/zoektLanguageExtension.ts
Brendan Kellam f3a8fa3dab
Some checks failed
Publish to ghcr / build (linux/amd64, blacksmith-4vcpu-ubuntu-2404) (push) Has been cancelled
Publish to ghcr / build (linux/arm64, blacksmith-8vcpu-ubuntu-2204-arm) (push) Has been cancelled
Update Roadmap Released / update (push) Has been cancelled
Publish to ghcr / merge (push) Has been cancelled
feat(web): Streamed code search (#623)
* generate protobuf types

* stream poc over SSE

* wip: make stream search api follow existing schema. Modify UI to support streaming

* fix scrolling issue

* Dockerfile

* wip on lezer parser grammar for query language

* add lezer tree -> grpc transformer

* remove spammy log message

* fix syntax highlighting by adding a module resolution for @lezer/common

* further wip on query language

* Add case sensitivity and regexp toggles

* Improved type safety / cleanup for query lang

* support search contexts

* update Dockerfile with query langauge package

* fix filter

* Add skeletons to filter panel when search is streaming

* add client side caching

* improved cancelation handling

* add isSearchExausted flag for flagging when a search captured all results

* Add back posthog search_finished event

* remove zoekt tenant enforcement

* migrate blocking search over to grpc. Centralize everything in searchApi

* branch handling

* plumb file weburl

* add repo_sets filter for repositories a user has access to

* refactor a bunch of stuff + add support for passing in Query IR to search api

* refactor

* dev README

* wip on better error handling

* error handling for stream path

* update mcp

* changelog wip

* type fix

* style

* Support rev:* wildcard

* changelog

* changelog nit

* feedback

* fix build

* update docs and remove uneeded test file
2025-11-22 15:33:31 -08:00

78 lines
2.5 KiB
TypeScript

import { LanguageSupport, StreamLanguage } from "@codemirror/language";
import { tags as t } from "@lezer/highlight";
export const zoekt = () => {
const zoektLanguage = StreamLanguage.define({
startState() {
return {
inString: false,
escaped: false
};
},
token(stream, state) {
// Handle strings
if (state.inString) {
if (state.escaped) {
state.escaped = false;
stream.next();
return t.string.toString();
}
const ch = stream.next();
if (ch === "\\") {
state.escaped = true;
return t.string.toString();
} else if (ch === '"') {
// End of string
state.inString = false;
return t.string.toString();
} else {
return t.string.toString();
}
}
// Skip whitespace
if (stream.eatSpace()) {
return null;
}
// Negation operator
if (stream.match(/-/)) {
return t.operator.toString();
}
// Parentheses
if (stream.match("(") || stream.match(")")) {
return t.paren.toString();
}
// Check for prefixes first
// If these match, we return 'keyword'
if (stream.match(/(archived:|rev:|content:|f:|file:|fork:|visibility:|r:|repo:|regex:|lang:|sym:|t:|type:|context:)/)) {
return t.keyword.toString();
}
// Now try matching a standalone word
// If the word is "or", return keyword; else nothing special
if (stream.match(/[A-Za-z0-9_]+/)) {
const word = stream.current();
if (word === "or") {
return t.keyword.toString();
}
return null;
}
// Double-quoted string start
if (stream.peek() === '"') {
stream.next(); // consume opening quote
state.inString = true;
return t.string.toString();
}
// If we reach here, consume a single character and return null
stream.next();
return null;
}
});
return new LanguageSupport(zoektLanguage);
};