Skip to content

Commit c74f282

Browse files
W-Floydclaude
andauthored
feat: add JQ syntax highlighting lexer (#1290)
Closes #1135 ## Summary - Adds `lexers/embedded/jq.xml` with full JQ syntax highlighting - 188 builtins cross-referenced against the real [jq source](https://github.com/jqlang/jq) - Keywords (`if/then/else/end`, `def`, `try/catch`, `reduce`, `foreach`, `label/break`, `module/import/include`) - `and`/`or`/`not` as word operators - `true`/`false`/`null` constants - Format filters (`@base64`, `@html`, `@uri`, etc.) as builtins - String interpolation (`\(...)`) via push/pop states - `$variables`, `.field` access, `.` identity, `..` recurse - Operators (`|`, `//`, `//=`, `|=`, `+=`, `==`, `!=`, etc.) - Test file (`jq.actual`) exercises every single builtin ## Test plan - [x] `go test ./lexers/ -run TestLexers/JQ` passes - [x] `go test ./lexers/ -run TestCompileAllRegexes` passes - [x] Visual inspection with `chroma -l jq --style=dracula` Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent ff53760 commit c74f282

4 files changed

Lines changed: 1532 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ translators for Pygments lexers and styles.
4848
| G | GAS, GDScript, GDScript3, Gemtext, Genshi, Genshi HTML, Genshi Text, Gettext, Gherkin, Gleam, GLSL, Gnuplot, Go, Go HTML Template, Go Template, Go Text Template, GraphQL, Groff, Groovy
4949
| H | Handlebars, Hare, Haskell, Haxe, HCL, Hexdump, HLB, HLSL, HolyC, HTML, HTTP, Hy
5050
| I | Idris, Igor, INI, Io, ISCdhcpd
51-
| J | J, Janet, Java, JavaScript, JSON, JSONata, Jsonnet, Julia, Jungle
51+
| J | J, Janet, Java, JavaScript, JSON, JSONata, JQ, Jsonnet, Julia, Jungle
5252
| K | Kakoune, KDL, Kotlin
5353
| L | Lateralus, Lean4, Lighttpd configuration file, LilyPond, LLVM, lox, Lua, Luau
5454
| M | Makefile, Mako, markdown, Markless, Mason, Materialize SQL dialect, Mathematica, Matlab, MCFunction, Meson, Metal, microcad, MiniZinc, MLIR, Modelica, Modula-2, Mojo, MonkeyC, MoonBit, MoonScript, MorrowindScript, Myghty, MySQL

lexers/embedded/jq.xml

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<lexer>
2+
<config>
3+
<name>JQ</name>
4+
<alias>jq</alias>
5+
<filename>*.jq</filename>
6+
<mime_type>application/x-jq</mime_type>
7+
<dot_all>true</dot_all>
8+
<ensure_nl>true</ensure_nl>
9+
</config>
10+
<rules>
11+
<state name="root">
12+
<rule pattern="\s+">
13+
<token type="Text"/>
14+
</rule>
15+
<rule pattern="#[^\n]*">
16+
<token type="CommentSingle"/>
17+
</rule>
18+
<rule pattern="@(?:base64d|base64|uri|csv|tsv|html|json|text|yaml|sh)\b">
19+
<token type="NameBuiltin"/>
20+
</rule>
21+
<rule pattern="\b(if|then|elif|else|end|try|catch|reduce|foreach|as|def|label|break|module|import|include)\b">
22+
<token type="Keyword"/>
23+
</rule>
24+
<rule pattern="\b(and|or|not)\b">
25+
<token type="OperatorWord"/>
26+
</rule>
27+
<rule pattern="\b(true|false|null)\b">
28+
<token type="KeywordConstant"/>
29+
</rule>
30+
<rule pattern="\b(IN|INDEX|JOIN|abs|acos|acosh|add|all|any|arrays|ascii_downcase|ascii_upcase|asin|asinh|atan|atan2|atanh|booleans|bsearch|capture|cbrt|ceil|combinations|contains|copysign|cos|cosh|debug|del|delpaths|empty|endswith|env|erf|erfc|error|exp|exp10|exp2|explode|expm1|fabs|fdim|finites|first|flatten|floor|fma|fmax|fmin|fmod|format|frexp|from_entries|fromdate|fromdateiso8601|fromjson|fromstream|gamma|getpath|gmtime|group_by|gsub|halt|halt_error|has|hypot|implode|in|index|indices|infinite|input|input_filename|input_line_number|inputs|inside|isempty|isfinite|isinfinite|isnan|isnormal|iterables|j0|j1|jn|join|keys|keys_unsorted|last|ldexp|length|lgamma|limit|localtime|log|log10|log1p|log2|logb|ltrim|ltrimstr|map|map_values|match|max|max_by|min|min_by|mktime|modf|modulemeta|nan|nearbyint|nextafter|nexttoward|normals|now|nth|nulls|numbers|objects|path|paths|pick|pow|range|recurse|remainder|repeat|reverse|rindex|rint|round|rtrim|rtrimstr|scalars|scalb|scalbln|scan|select|setpath|significand|sin|sinh|skip|sort|sort_by|split|splits|sqrt|startswith|stderr|strflocaltime|strftime|strings|strptime|sub|tan|tanh|test|tgamma|to_entries|toboolean|todate|todateiso8601|tojson|tonumber|tostream|tostring|transpose|trim|trimstr|trunc|truncate_stream|type|unique|unique_by|until|utf8bytelength|values|walk|while|with_entries|y0|y1|yn)\b">
31+
<token type="NameBuiltin"/>
32+
</rule>
33+
<rule pattern="\$[A-Za-z_][A-Za-z0-9_]*|\$ENV\b">
34+
<token type="NameVariable"/>
35+
</rule>
36+
<rule pattern="\.\.">
37+
<token type="NameBuiltin"/>
38+
</rule>
39+
<rule pattern="\.[A-Za-z_][A-Za-z0-9_]*">
40+
<token type="NameAttribute"/>
41+
</rule>
42+
<rule pattern="\.">
43+
<token type="NameBuiltin"/>
44+
</rule>
45+
<rule pattern="-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?">
46+
<token type="LiteralNumber"/>
47+
</rule>
48+
<rule pattern="&#34;">
49+
<token type="LiteralStringDouble"/>
50+
<push state="string"/>
51+
</rule>
52+
<rule pattern="//=|[|][=]|\+=|-=|\*=|/=|%=|==|!=|&lt;=|&gt;=|&lt;|&gt;|//|\?//|\|">
53+
<token type="Operator"/>
54+
</rule>
55+
<rule pattern="[-+*/%?]">
56+
<token type="Operator"/>
57+
</rule>
58+
<rule pattern="[{}()\[\],;:]">
59+
<token type="Punctuation"/>
60+
</rule>
61+
<rule pattern="[A-Za-z_][A-Za-z0-9_]*">
62+
<token type="NameOther"/>
63+
</rule>
64+
</state>
65+
<state name="string">
66+
<rule pattern="&#34;">
67+
<token type="LiteralStringDouble"/>
68+
<pop depth="1"/>
69+
</rule>
70+
<rule pattern="\\(?:[&#34;\\/bfnrt]|u[0-9a-fA-F]{4})">
71+
<token type="LiteralStringEscape"/>
72+
</rule>
73+
<rule pattern="\\[(]">
74+
<token type="LiteralStringInterpol"/>
75+
<push state="interpolation"/>
76+
</rule>
77+
<rule pattern="[^&#34;\\]+">
78+
<token type="LiteralStringDouble"/>
79+
</rule>
80+
</state>
81+
<state name="interpolation">
82+
<rule pattern="[)]">
83+
<token type="LiteralStringInterpol"/>
84+
<pop depth="1"/>
85+
</rule>
86+
<rule>
87+
<include state="root"/>
88+
</rule>
89+
</state>
90+
</rules>
91+
</lexer>

lexers/testdata/jq.actual

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
# JQ lexer test — covers every builtin, keyword, operator, and literal
2+
3+
# Keywords and control flow
4+
def greet($name): "Hello, \($name)!";
5+
if .x then .y elif .z then .w else empty end
6+
try .foo catch "default"
7+
reduce .[] as $x (0; . + $x)
8+
foreach .[] as $x (0; . + $x; . * 2)
9+
label $out | foreach .[] as $x (0; . + $x; if . > 10 then ., break $out else . end)
10+
module {}; import "foo" as foo; include "bar";
11+
12+
# Boolean/null literals and word operators
13+
true, false, null
14+
.x and .y or not .z
15+
16+
# Format strings
17+
.name | @html
18+
.data | @base64
19+
.bytes | @base64d
20+
.url | @uri
21+
.row | @csv
22+
.row | @tsv
23+
.code | @sh
24+
.val | @json
25+
.val | @text
26+
.val | @yaml
27+
28+
# String interpolation
29+
"result: \(.count * 2)"
30+
31+
# Numbers
32+
42, 3.14, 1e10, -7
33+
34+
# Identity and recurse
35+
.
36+
..
37+
38+
# Field access and variables
39+
.foo.bar
40+
$ENV.HOME
41+
$__loc__
42+
43+
# Type and structure builtins
44+
type
45+
length
46+
utf8bytelength
47+
keys
48+
keys_unsorted
49+
values
50+
has("foo")
51+
in({"a":1})
52+
contains({"a":1})
53+
inside({"a":1})
54+
arrays, objects, iterables, booleans, numbers, normals, nulls, strings, scalars, finites
55+
56+
# Path builtins
57+
path(.foo)
58+
paths
59+
getpath(["a","b"])
60+
setpath(["a"]; 1)
61+
delpaths([["a"]])
62+
63+
# Entry builtins
64+
to_entries
65+
from_entries
66+
with_entries(.value += 1)
67+
68+
# Array builtins
69+
add
70+
flatten
71+
flatten(1)
72+
reverse
73+
sort
74+
sort_by(.x)
75+
group_by(.x)
76+
unique
77+
unique_by(.x)
78+
max
79+
max_by(.x)
80+
min
81+
min_by(.x)
82+
indices(1)
83+
index(1)
84+
rindex(1)
85+
combinations
86+
combinations(2)
87+
transpose
88+
first
89+
last
90+
nth(2; range(10))
91+
range(5)
92+
range(0;10)
93+
range(0;10;2)
94+
limit(3; .[] )
95+
until(. > 10; . * 2)
96+
while(. < 10; . + 1)
97+
repeat(. * 2) | first
98+
skip(2; range(10))
99+
recurse
100+
recurse(.children[]?)
101+
walk(if type == "number" then . + 1 else . end)
102+
pick(.a, .b)
103+
del(.foo)
104+
105+
# String builtins
106+
split(",")
107+
splits(",")
108+
join(",")
109+
startswith("foo")
110+
endswith("foo")
111+
ltrimstr("foo")
112+
rtrimstr("foo")
113+
ltrim
114+
rtrim
115+
trim
116+
trimstr("x";"y")
117+
ascii_downcase
118+
ascii_upcase
119+
explode
120+
implode
121+
tojson
122+
fromjson
123+
tostring
124+
tonumber
125+
toboolean
126+
format("html")
127+
test("foo")
128+
test("foo"; "g")
129+
match("foo")
130+
capture("(?P<a>.*)")
131+
scan("\\d+")
132+
sub("foo"; "bar")
133+
gsub("foo"; "bar")
134+
135+
# Math builtins
136+
sqrt
137+
floor
138+
ceil
139+
round
140+
fabs
141+
pow(.; 2)
142+
log
143+
log2
144+
log10
145+
log1p
146+
log2
147+
logb
148+
exp
149+
exp2
150+
exp10
151+
expm1
152+
significand
153+
sin
154+
cos
155+
tan
156+
asin
157+
acos
158+
atan
159+
atan2(1; 2)
160+
sinh
161+
cosh
162+
tanh
163+
asinh
164+
acosh
165+
atanh
166+
cbrt
167+
fma(1;2;3)
168+
fmax(1;2)
169+
fmin(1;2)
170+
fmod(10;3)
171+
hypot(3;4)
172+
copysign(1;-1)
173+
remainder(10;3)
174+
frexp
175+
modf
176+
ldexp(1; 2)
177+
scalb(1;2)
178+
scalbln(1;2)
179+
logb
180+
nearbyint
181+
rint
182+
trunc
183+
erf
184+
erfc
185+
tgamma
186+
lgamma
187+
gamma
188+
j0
189+
j1
190+
jn(2;1)
191+
y0
192+
y1
193+
yn(2;1)
194+
nextafter(1;2)
195+
nexttoward(1;2)
196+
fdim(2;1)
197+
cbrt
198+
abs
199+
nan
200+
infinite
201+
isinfinite
202+
isnan
203+
isnormal
204+
isfinite
205+
isempty(empty)
206+
207+
# Date/time builtins
208+
now
209+
gmtime
210+
mktime
211+
strftime("%Y-%m-%d")
212+
strptime("%Y-%m-%d")
213+
todate
214+
fromdate
215+
todateiso8601
216+
fromdateiso8601
217+
strflocaltime("%Y")
218+
localtime
219+
220+
# Map/select builtins
221+
map(. + 1)
222+
map_values(. + 1)
223+
select(. > 0)
224+
any(.[]; . > 0)
225+
all(.[]; . > 0)
226+
any(. > 0)
227+
all(. > 0)
228+
isempty(.[])
229+
230+
# Index/search builtins
231+
INDEX(.[]; .id)
232+
IN(.[]; 1)
233+
JOIN(.[]; .id; .[]; .id)
234+
bsearch(3)
235+
236+
# Streaming builtins
237+
tostream
238+
fromstream(tostream)
239+
truncate_stream(tostream; 1)
240+
241+
# I/O and debug builtins
242+
debug
243+
debug("msg")
244+
stderr
245+
error
246+
error("msg")
247+
halt
248+
halt_error
249+
halt_error(1)
250+
input
251+
inputs
252+
input_line_number
253+
input_filename
254+
255+
# Misc builtins
256+
env
257+
modulemeta
258+
not
259+
empty

0 commit comments

Comments
 (0)