Skip to content

Commit 2fcbe50

Browse files
committed
plugins/lint: init + test
1 parent bbbbfa2 commit 2fcbe50

File tree

3 files changed

+372
-0
lines changed

3 files changed

+372
-0
lines changed

plugins/default.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
./languages/julia/julia-cell.nix
4646
./languages/lean.nix
4747
./languages/ledger.nix
48+
./languages/lint.nix
4849
./languages/markdown-preview.nix
4950
./languages/nix.nix
5051
./languages/nvim-jdtls.nix

plugins/languages/lint.nix

Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
{
2+
lib,
3+
helpers,
4+
config,
5+
pkgs,
6+
...
7+
}:
8+
with lib; let
9+
cfg = config.plugins.lint;
10+
11+
linterOptions = with types; {
12+
cmd = {
13+
type = str;
14+
description = "The command to call the linter";
15+
example = "linter_cmd";
16+
mandatory = true;
17+
};
18+
19+
stdin = {
20+
type = bool;
21+
description = ''
22+
Whether this parser supports content input via stdin.
23+
In that case the filename is automatically added to the arguments.
24+
25+
Default: `true`
26+
'';
27+
example = false;
28+
};
29+
30+
append_fname = {
31+
type = bool;
32+
description = ''
33+
Automatically append the file name to `args` if `stdin = false`
34+
Whether this parser supports content input via stdin.
35+
In that case the filename is automatically added to the arguments.
36+
37+
Default: `true`
38+
'';
39+
example = false;
40+
};
41+
42+
args = {
43+
type = listOf (either str helpers.rawType);
44+
description = ''
45+
List of arguments.
46+
Can contain functions with zero arguments that will be evaluated once the linter is used.
47+
48+
Default: `[]`
49+
'';
50+
};
51+
52+
stream = {
53+
type = enum ["stdout" "stderr" "both"];
54+
description = ''
55+
configure the stream to which the linter outputs the linting result.
56+
57+
Default: `"stdout"`
58+
'';
59+
example = "stderr";
60+
};
61+
62+
ignore_exitcode = {
63+
type = bool;
64+
description = ''
65+
Whether the linter exiting with a code !=0 should be considered normal.
66+
67+
Default: `false`
68+
'';
69+
example = true;
70+
};
71+
72+
env = {
73+
type = attrsOf str;
74+
description = ''
75+
Custom environment table to use with the external process.
76+
Note that this replaces the **entire** environment, it is not additive.
77+
'';
78+
example = {
79+
FOO = "bar";
80+
};
81+
};
82+
83+
parser = {
84+
type = str;
85+
description = "The code for your parser function.";
86+
example = ''
87+
require('lint.parser').from_pattern(pattern, groups, severity_map, defaults, opts)
88+
'';
89+
apply = s: helpers.ifNonNull' s (helpers.mkRaw s);
90+
mandatory = true;
91+
};
92+
};
93+
94+
mkLinterOpts = noDefaults:
95+
types.submodule {
96+
freeformType = types.attrs;
97+
98+
options =
99+
mapAttrs
100+
(
101+
optionName: (
102+
{
103+
mandatory ? false,
104+
apply ? x: x,
105+
example ? null,
106+
type,
107+
description,
108+
}:
109+
mkOption (
110+
{
111+
inherit
112+
apply
113+
description
114+
example
115+
;
116+
}
117+
// (
118+
if noDefaults && mandatory
119+
# Make this option mandatory
120+
then {
121+
inherit type;
122+
}
123+
# make it optional
124+
else {
125+
type = types.nullOr type;
126+
default = null;
127+
}
128+
)
129+
)
130+
)
131+
)
132+
linterOptions;
133+
};
134+
in {
135+
options.plugins.lint =
136+
helpers.extraOptionsOptions
137+
// {
138+
enable = mkEnableOption "nvim-lint";
139+
140+
package = helpers.mkPackageOption "nvim-lint" pkgs.vimPlugins.nvim-lint;
141+
142+
lintersByFt = mkOption {
143+
type = with types; attrsOf (listOf str);
144+
default = {};
145+
description = ''
146+
Configure the linters you want to run per file type.
147+
148+
Default:
149+
```nix
150+
{
151+
text = ["vale"];
152+
json = ["jsonlint"];
153+
markdown = ["vale"];
154+
rst = ["vale"];
155+
ruby = ["ruby"];
156+
janet = ["janet"];
157+
inko = ["inko"];
158+
clojure = ["clj-kondo"];
159+
dockerfile = ["hadolint"];
160+
terraform = ["tflint"];
161+
}
162+
```
163+
'';
164+
example = {
165+
markdown = ["vale"];
166+
};
167+
};
168+
169+
linters = mkOption {
170+
type = with types;
171+
attrsOf
172+
(mkLinterOpts false);
173+
default = {};
174+
description = ''
175+
Customize the existing linters by overriding some of their properties.
176+
'';
177+
example = {
178+
phpcs.args = [
179+
"-q"
180+
"--report=json"
181+
"-"
182+
];
183+
};
184+
};
185+
186+
customLinters = mkOption {
187+
type = with types;
188+
attrsOf
189+
(
190+
either
191+
str
192+
(mkLinterOpts true)
193+
);
194+
default = {};
195+
description = ''
196+
Configure the linters you want to run per file type.
197+
It can be both an attrs or a string containing the lua code that returns the appropriate
198+
table.
199+
'';
200+
example = {
201+
};
202+
};
203+
204+
autoCmd = let
205+
defaultEvent = "BufWritePost";
206+
defaultCallback = helpers.mkRaw ''
207+
function()
208+
require('lint').try_lint()
209+
end
210+
'';
211+
in
212+
mkOption {
213+
type = with types;
214+
nullOr (submodule {
215+
options =
216+
helpers.autocmd.autoCmdOptions
217+
// {
218+
event = mkOption {
219+
type = with types;
220+
nullOr
221+
(
222+
either
223+
str
224+
(listOf str)
225+
);
226+
default = defaultEvent;
227+
description = "The event or events that should trigger linting.";
228+
};
229+
230+
callback = mkOption {
231+
type = with types;
232+
nullOr (either str helpers.rawType);
233+
default = defaultCallback;
234+
description = "What action to perform for linting";
235+
};
236+
};
237+
});
238+
description = ''
239+
The configuration for the linting autocommand.
240+
You can disable it by setting this option to `null`.
241+
'';
242+
default = {
243+
event = defaultEvent;
244+
callback = defaultCallback;
245+
};
246+
};
247+
};
248+
249+
config = mkIf cfg.enable {
250+
extraPlugins = [cfg.package];
251+
252+
extraConfigLua =
253+
''
254+
__lint = require('lint')
255+
__lint.linters_by_ft = ${helpers.toLuaObject cfg.lintersByFt}
256+
''
257+
+ (
258+
optionalString
259+
(cfg.linters != {})
260+
(
261+
concatLines
262+
(
263+
flatten
264+
(
265+
mapAttrsToList
266+
(
267+
linter: linterConfig:
268+
mapAttrsToList
269+
(
270+
propName: propValue:
271+
optionalString
272+
(propValue != null)
273+
"__lint.linters.${linter}.${propName} = ${helpers.toLuaObject propValue}"
274+
)
275+
linterConfig
276+
)
277+
cfg.linters
278+
)
279+
)
280+
)
281+
)
282+
+ (
283+
optionalString
284+
(cfg.customLinters != {})
285+
(
286+
concatLines
287+
(
288+
mapAttrsToList
289+
(customLinter: linterConfig: let
290+
linterConfig' =
291+
if isString linterConfig
292+
then helpers.mkRaw linterConfig
293+
else linterConfig;
294+
in "__lint.linters.${customLinter} = ${helpers.toLuaObject linterConfig'}")
295+
cfg.customLinters
296+
)
297+
)
298+
);
299+
300+
# autoCmd = optional (cfg.autoCmd != null) cfg.autoCmd;
301+
};
302+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
{
2+
empty = {
3+
plugins.lint.enable = true;
4+
};
5+
6+
example = {
7+
plugins.lint = {
8+
enable = true;
9+
10+
lintersByFt = {
11+
text = ["vale"];
12+
json = ["jsonlint"];
13+
markdown = ["vale"];
14+
rst = ["vale"];
15+
ruby = ["ruby"];
16+
janet = ["janet"];
17+
inko = ["inko"];
18+
clojure = ["clj-kondo"];
19+
dockerfile = ["hadolint"];
20+
terraform = ["tflint"];
21+
};
22+
linters = {
23+
phpcs.args = [
24+
"-q"
25+
"--report=json"
26+
"-"
27+
];
28+
};
29+
customLinters = {
30+
foo = {
31+
cmd = "foo_cmd";
32+
stdin = true;
33+
append_fname = false;
34+
args = [];
35+
stream = "stderr";
36+
ignore_exitcode = false;
37+
env = {
38+
FOO = "bar";
39+
};
40+
parser = ''
41+
require('lint.parser').from_pattern(pattern, groups, severity_map, defaults, opts)
42+
'';
43+
};
44+
foo2 = {
45+
cmd = "foo2_cmd";
46+
parser = ''
47+
require('lint.parser').from_pattern(pattern, groups, severity_map, defaults, opts)
48+
'';
49+
};
50+
bar.__raw = ''
51+
function()
52+
return {
53+
cmd = "foo_cmd",
54+
stdin = true,
55+
append_fname = false,
56+
args = {},
57+
stream = "stderr",
58+
ignore_exitcode = false,
59+
env = {
60+
["FOO"] = "bar",
61+
},
62+
parser = require('lint.parser').from_pattern(pattern, groups, severity_map, defaults, opts),
63+
}
64+
end
65+
'';
66+
};
67+
};
68+
};
69+
}

0 commit comments

Comments
 (0)