Skip to content

Commit 12bda33

Browse files
committed
WIP nix
1 parent 7b1c316 commit 12bda33

File tree

7 files changed

+278
-36
lines changed

7 files changed

+278
-36
lines changed

topiary-cli/Cargo.toml

+32-24
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ name = "topiary-cli"
33
description = "CLI app for Topiary, the universal code formatter."
44
categories = ["command-line-utilities", "development-tools", "text-processing"]
55
keywords = [
6-
"cli",
7-
"code-formatter",
8-
"formatter",
9-
"text",
10-
"tree-sitter",
11-
"utility",
6+
"cli",
7+
"code-formatter",
8+
"formatter",
9+
"text",
10+
"tree-sitter",
11+
"utility",
1212
]
1313
version.workspace = true
1414
edition.workspace = true
@@ -35,7 +35,12 @@ itertools = { workspace = true }
3535
log = { workspace = true }
3636
serde = { workspace = true, features = ["derive"] }
3737
tempfile = { workspace = true }
38-
tokio = { workspace = true, features = ["fs", "rt-multi-thread", "sync", "macros"] }
38+
tokio = { workspace = true, features = [
39+
"fs",
40+
"rt-multi-thread",
41+
"sync",
42+
"macros",
43+
] }
3944
toml = { workspace = true }
4045
topiary-core = { path = "../topiary-core" }
4146
topiary-config = { path = "../topiary-config" }
@@ -58,34 +63,37 @@ predicates = { workspace = true }
5863

5964
[features]
6065
default = [
61-
"contributed",
62-
"json",
63-
"nickel",
64-
"ocaml",
65-
"ocaml_interface",
66-
"ocamllex",
67-
"toml",
68-
"tree_sitter_query"
66+
"contributed",
67+
"json",
68+
"nickel",
69+
"nix",
70+
"ocaml",
71+
"ocaml_interface",
72+
"ocamllex",
73+
"toml",
74+
"tree_sitter_query",
6975
]
7076

7177
# Included by default
72-
contributed = [
73-
"css"
74-
]
78+
contributed = ["css"]
7579

7680
# Excluded by default
77-
experimental = [
78-
"bash",
79-
"rust",
80-
]
81+
experimental = ["bash", "rust"]
8182

83+
nix = ["topiary-config/nix", "topiary-queries/nix"]
8284
bash = ["topiary-config/bash", "topiary-queries/bash"]
8385
css = ["topiary-config/css", "topiary-queries/css"]
8486
json = ["topiary-config/json", "topiary-queries/json"]
8587
nickel = ["topiary-config/nickel", "topiary-queries/nickel"]
8688
ocaml = ["topiary-config/ocaml", "topiary-queries/ocaml"]
87-
ocaml_interface = ["topiary-config/ocaml_interface", "topiary-queries/ocaml_interface"]
89+
ocaml_interface = [
90+
"topiary-config/ocaml_interface",
91+
"topiary-queries/ocaml_interface",
92+
]
8893
ocamllex = ["topiary-config/ocamllex", "topiary-queries/ocamllex"]
8994
rust = ["topiary-config/rust", "topiary-queries/rust"]
9095
toml = ["topiary-config/toml", "topiary-queries/toml"]
91-
tree_sitter_query = ["topiary-config/tree_sitter_query", "topiary-queries/tree_sitter_query"]
96+
tree_sitter_query = [
97+
"topiary-config/tree_sitter_query",
98+
"topiary-queries/tree_sitter_query",
99+
]

topiary-cli/src/io.rs

+3
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,9 @@ where
350350
#[cfg(feature = "toml")]
351351
"toml" => Ok(topiary_queries::toml().into()),
352352

353+
#[cfg(feature = "nix")]
354+
"nix" => Ok(topiary_queries::nix().into()),
355+
353356
#[cfg(feature = "tree_sitter_query")]
354357
"tree_sitter_query" => Ok(topiary_queries::tree_sitter_query().into()),
355358

topiary-config/Cargo.toml

+14-12
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ git2.workspace = true
3333
libloading.workspace = true
3434

3535
[features]
36-
default = [ "parallel" ]
36+
default = ["parallel"]
3737

3838
# Enabling the `parallel` feature enables parallel computation where possible.
3939
# At the moment, this is only in grammar prefetching
40-
parallel = [ "dep:rayon" ]
40+
parallel = ["dep:rayon"]
4141

4242
bash = []
4343
css = []
@@ -46,21 +46,23 @@ nickel = []
4646
ocaml = []
4747
ocaml_interface = []
4848
ocamllex = []
49+
nix = []
4950
rust = []
5051
toml = []
5152
tree_sitter_query = []
5253

5354
# This a convenience for the sake of downstream applications which don't
5455
# wish to cherry-pick grammars (e.g., the playground)
5556
all = [
56-
"bash",
57-
"css",
58-
"json",
59-
"nickel",
60-
"ocaml",
61-
"ocaml_interface",
62-
"ocamllex",
63-
"rust",
64-
"toml",
65-
"tree_sitter_query"
57+
"bash",
58+
"css",
59+
"json",
60+
"nickel",
61+
"ocaml",
62+
"ocaml_interface",
63+
"ocamllex",
64+
"rust",
65+
"nix",
66+
"toml",
67+
"tree_sitter_query",
6668
]

topiary-config/languages.ncl

+8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@
1616
},
1717
},
1818

19+
nix = {
20+
extensions = ["nix"],
21+
grammar = {
22+
git = "https://github.com/nix-community/tree-sitter-nix",
23+
rev = "456b14a2fa6315abc7e02fcffaf4a1f35d4955d3",
24+
},
25+
},
26+
1927
json = {
2028
extensions = [
2129
"json",

topiary-queries/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@ ocaml_interface = []
2424
ocamllex = []
2525
rust = []
2626
toml = []
27+
nix = []
2728
tree_sitter_query = []

topiary-queries/queries/nix.scm

+214
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
;; Nix Formatter based on RFC 166
2+
3+
; Leaf nodes
4+
[
5+
(string_expression)
6+
(integer_expression)
7+
(float_expression)
8+
(uri_expression)
9+
(path_expression)
10+
(hpath_expression)
11+
(spath_expression)
12+
] @leaf
13+
14+
; Comments
15+
(comment) @comment
16+
17+
; Convert single-line /* */ comments to #
18+
(comment) @convert_to_hash_comment
19+
20+
; Preserve multiline comments
21+
(comment) @preserve_multiline_comment
22+
23+
; Append space after specific tokens
24+
":" @append_space
25+
"=" @prepend_space @append_space
26+
"," @append_spaced_softline
27+
28+
; Handle indentation and line breaks
29+
; Define softline breaks and indentation starts/ends
30+
"{" @append_spaced_softline @append_indent_start
31+
"}" @prepend_spaced_softline @prepend_indent_end
32+
"[" @append_spaced_softline @append_indent_start
33+
"]" @prepend_spaced_softline @prepend_indent_end
34+
35+
; Functions
36+
37+
(function_expression
38+
formals: (formals
39+
"{" @append_spaced_softline @append_indent_start
40+
(formal) @formal_param
41+
"}" @prepend_spaced_softline @prepend_indent_end
42+
)
43+
body: (_) @function_body
44+
) @function_declaration
45+
46+
; Ensure each parameter is on a new line with proper indentation
47+
(formal) @prepend_spaced_softline
48+
49+
; Attribute Sets
50+
51+
(attrset_expression
52+
"{" @append_spaced_softline @append_indent_start
53+
(binding_set
54+
(binding) @attr_binding
55+
)
56+
"}" @prepend_spaced_softline @prepend_indent_end
57+
) @attribute_set
58+
59+
; Ensure each key-value pair is on its own line
60+
(binding
61+
attrpath: (_) @attr_key
62+
"=" @append_space
63+
(_) @attr_value
64+
";" @append_spaced_softline
65+
)
66+
67+
; Lists
68+
69+
(list_expression
70+
"[" @append_spaced_softline @append_indent_start
71+
(_) @list_item
72+
"]" @prepend_spaced_softline @prepend_indent_end
73+
) @list
74+
75+
; If-Then-Else Expressions
76+
77+
(if_expression
78+
"if" @keyword_if @append_space @prepend_spaced_softline
79+
condition: (_) @if_condition
80+
"then" @keyword_then @append_space @prepend_spaced_softline @append_indent_start
81+
body: (_) @if_body @append_indent_end
82+
"else" @keyword_else @append_space @prepend_spaced_softline @append_indent_start
83+
alternative: (_) @else_body @append_indent_end
84+
)
85+
86+
; Let-In Expressions
87+
88+
(let_expression
89+
"let" @keyword_let @append_spaced_softline @append_indent_start
90+
(binding_set
91+
(binding
92+
attrpath: (_) @let_binding_name
93+
"=" @append_space
94+
(_) @let_binding_value
95+
";" @append_spaced_softline
96+
)+
97+
)
98+
"in" @keyword_in @prepend_spaced_softline @prepend_indent_end @append_spaced_softline
99+
body: (_) @let_body
100+
)
101+
102+
; With Expressions
103+
104+
(with_expression
105+
"with" @keyword_with @append_space
106+
(_) @with_expression
107+
";" @append_spaced_softline
108+
body: (_) @with_body
109+
)
110+
111+
; Assert Expressions
112+
113+
(assert_expression
114+
"assert" @keyword_assert @append_space
115+
(_) @assert_condition
116+
";" @append_spaced_softline
117+
body: (_) @assert_body
118+
)
119+
120+
; Operator Formatting
121+
122+
(binary_expression
123+
left: (_) @op_left
124+
right: (_) @op_right
125+
)
126+
127+
; Ensure operators start on new lines if they don't fit on a single line
128+
(binary_expression
129+
(_) @prepend_spaced_softline
130+
)
131+
132+
; Inherit Statements
133+
134+
(inherit
135+
"inherit" @keyword_inherit @append_space
136+
(inherited_attrs
137+
(identifier) @inherit_item
138+
)+
139+
";" @inherit_semicolon
140+
)
141+
142+
; Handle inherit with source
143+
(inherit_from
144+
"inherit" @keyword_inherit @append_space
145+
"(" @inherit_parentheses_start
146+
(_) @inherit_source
147+
")" @inherit_parentheses_end
148+
(inherited_attrs
149+
(identifier) @inherit_item
150+
)+
151+
";" @inherit_semicolon
152+
)
153+
154+
; Empty Objects and Arrays
155+
156+
(attrset_expression
157+
"{" @object_open
158+
"}" @object_close
159+
) @empty_attribute_set
160+
161+
(list_expression
162+
"[" @array_open
163+
"]" @array_close
164+
) @empty_array
165+
166+
; String Interpolation
167+
168+
(interpolation
169+
"${" @interp_start
170+
(_) @interp_content
171+
"}" @interp_end
172+
)
173+
174+
; Additional Rules
175+
176+
; Handle let bindings indentation
177+
(let_expression
178+
(binding_set
179+
(binding) @let_binding_indent
180+
)
181+
)
182+
183+
; Handle assertions
184+
(assert_expression
185+
"assert" @keyword_assert @append_space
186+
(_) @assert_condition
187+
";" @assert_semicolon
188+
)
189+
190+
; Handle comments within expressions
191+
(comment) @comment_within_expr
192+
193+
; Leaf Nodes Preservation
194+
(_) @leaf
195+
196+
; Handle semicolon placement in bindings
197+
(binding
198+
";" @semicolon_end
199+
)
200+
201+
; Handle indentation for nested attribute sets
202+
(attrset_expression
203+
(binding_set
204+
(binding
205+
(attrset_expression) @nested_attribute_set
206+
)
207+
)
208+
)
209+
210+
; Handle newline preservation rules
211+
(ERROR) @collapse_empty_lines
212+
213+
; Ensure consistent indentation levels
214+
(_) @indent_block

topiary-queries/src/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ pub fn toml() -> &'static str {
5252
include_str!("../queries/toml.scm")
5353
}
5454

55+
/// Returns the Topiary-compatible query file for Nix.
56+
#[cfg(feature = "nix")]
57+
pub fn nix() -> &'static str {
58+
include_str!("../queries/nix.scm")
59+
}
60+
5561
/// Returns the Topiary-compatible query file for the
5662
/// Tree-sitter query language.
5763
#[cfg(feature = "tree_sitter_query")]

0 commit comments

Comments
 (0)