Skip to content

Commit d4e6410

Browse files
Fix zoekt language parsing and add more token coloring (#115)
1 parent f71a83a commit d4e6410

File tree

2 files changed

+81
-20
lines changed

2 files changed

+81
-20
lines changed

packages/web/src/app/components/searchBar/searchBar.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,18 @@ export const SearchBar = ({
144144
tag: t.keyword,
145145
color: tailwind.theme.colors.highlight,
146146
},
147+
{
148+
tag: t.string,
149+
color: '#2aa198',
150+
},
151+
{
152+
tag: t.operator,
153+
color: '#d33682',
154+
},
147155
{
148156
tag: t.paren,
149157
color: tailwind.theme.colors.highlight,
150-
}
158+
},
151159
],
152160
});
153161
}, [tailwind]);
@@ -333,4 +341,4 @@ const SearchHistoryButton = ({
333341
</TooltipContent>
334342
</Tooltip>
335343
)
336-
}
344+
}
Lines changed: 71 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,78 @@
11
import { LanguageSupport, StreamLanguage } from "@codemirror/language";
2-
import { tags as t } from '@lezer/highlight';
2+
import { tags as t } from "@lezer/highlight";
33

4-
const zoektLanguage = StreamLanguage.define({
5-
token: (stream) => {
6-
if (stream.match(/-?(file|branch|revision|rev|case|repo|lang|content|sym|archived|fork|public):/)) {
7-
return t.keyword.toString();
8-
}
4+
export const zoekt = () => {
5+
const zoektLanguage = StreamLanguage.define({
6+
startState() {
7+
return {
8+
inString: false,
9+
escaped: false
10+
};
11+
},
12+
token(stream, state) {
13+
// Handle strings
14+
if (state.inString) {
15+
if (state.escaped) {
16+
state.escaped = false;
17+
stream.next();
18+
return t.string.toString();
19+
}
20+
const ch = stream.next();
21+
if (ch === "\\") {
22+
state.escaped = true;
23+
return t.string.toString();
24+
} else if (ch === '"') {
25+
// End of string
26+
state.inString = false;
27+
return t.string.toString();
28+
} else {
29+
return t.string.toString();
30+
}
31+
}
932

10-
if (stream.match(/\bor\b/)) {
11-
return t.keyword.toString();
12-
}
33+
// Skip whitespace
34+
if (stream.eatSpace()) {
35+
return null;
36+
}
1337

14-
if (stream.match(/(\(|\))/)) {
15-
return t.paren.toString();
16-
}
38+
// Negation operator
39+
if (stream.match(/-/)) {
40+
return t.operator.toString();
41+
}
1742

18-
stream.next();
19-
return null;
20-
},
21-
});
43+
// Parentheses
44+
if (stream.match("(") || stream.match(")")) {
45+
return t.paren.toString();
46+
}
47+
48+
// Check for prefixes first
49+
// If these match, we return 'keyword'
50+
if (stream.match(/(archived:|branch:|b:|c:|case:|content:|f:|file:|fork:|public:|r:|repo:|regex:|lang:|sym:|t:|type:)/)) {
51+
return t.keyword.toString();
52+
}
53+
54+
// Now try matching a standalone word
55+
// If the word is "or", return keyword; else nothing special
56+
if (stream.match(/[A-Za-z0-9_]+/)) {
57+
const word = stream.current();
58+
if (word === "or") {
59+
return t.keyword.toString();
60+
}
61+
return null;
62+
}
63+
64+
// Double-quoted string start
65+
if (stream.peek() === '"') {
66+
stream.next(); // consume opening quote
67+
state.inString = true;
68+
return t.string.toString();
69+
}
70+
71+
// If we reach here, consume a single character and return null
72+
stream.next();
73+
return null;
74+
}
75+
});
2276

23-
export const zoekt = () => {
2477
return new LanguageSupport(zoektLanguage);
25-
}
78+
};

0 commit comments

Comments
 (0)