-
Notifications
You must be signed in to change notification settings - Fork 3
/
module.nix
195 lines (167 loc) · 4.93 KB
/
module.nix
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
{ pkgs, lib, config, ... }:
with lib;
let
enabledFormatters = filter (f: f.enable) (attrValues config.formatters);
buildCommand = commandFn: checkOnly:
let
command = commandFn {
inherit checkOnly;
files = "\"\${FILE_PATHS[@]}\"";
};
in
"${command} || LOCAL_RESULT=$?";
commands =
concatMapStringsSep
"\n"
(formatter: ''
logInfo "Running ${formatter.name}..."
LOCAL_RESULT=0
if [[ -n "$CHECK_ONLY" ]]; then
${buildCommand formatter.commandFn true}
else
${buildCommand formatter.commandFn false}
fi
if (( LOCAL_RESULT > 0 )); then
RESULT=1
logWarn "Failed with exit code: $LOCAL_RESULT"
fi
echo
'')
enabledFormatters;
script = pkgs.writeShellApplication {
name = "nix-formatter-pack";
runtimeInputs = with pkgs; [ ncurses ];
text = ''
COLOR_RESET=
COLOR_ERROR=
COLOR_WARN=
COLOR_INFO=
if [[ -t 1 ]]; then
COLOR_RESET="$(tput sgr0)"
COLOR_ERROR="$(tput bold)$(tput setaf 1)"
COLOR_WARN="$(tput setaf 3)"
COLOR_INFO="$(tput bold)$(tput setaf 6)"
fi
function logError() {
echo >&2 "$COLOR_ERROR$*$COLOR_RESET"
}
function logWarn() {
echo "$COLOR_WARN$*$COLOR_RESET"
}
function logInfo() {
echo "$COLOR_INFO$*$COLOR_RESET"
}
function doHelp() {
echo "Usage: $0 [OPTION] [--] FILES"
echo
echo "Formats nix source files. Enabled formatters are ${concatMapStringsSep ", " (f: "'${f.name}'") enabledFormatters}."
echo
echo "Options"
echo
echo " -h|--help Print this help"
echo " -c|--check Check only (useful for CI)"
}
CHECK_ONLY=
FILE_PATHS=()
RESULT=0
while [[ $# -gt 0 ]]; do
opt="$1"
shift
case "$opt" in
-c|--check)
CHECK_ONLY=1
;;
-h|--help)
doHelp
exit 0
;;
--)
FILE_PATHS+=("$@")
break
;;
-*)
logError "$0: unknown option '$opt'"
logError "Run '$0 --help' for usage help"
exit 2
;;
*)
FILE_PATHS+=("$opt")
;;
esac
done
# default to current directory
if [[ "''${#FILE_PATHS[@]}" -eq 0 ]]; then
FILE_PATHS+=(.)
fi
${commands}
exit $RESULT
'';
};
failedAssertions = map (x: x.message) (filter (x: !x.assertion) config.assertions);
throwAssertions = res:
if (failedAssertions != [ ])
then throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}"
else res;
in
{
options = {
formatters = mkOption {
type = types.attrsOf (types.submodule (
{ name, ... }:
{
options = {
enable = mkEnableOption "formatter" // { default = true; };
name = mkOption {
type = types.str;
default = name;
description = "Name of formatter.";
};
commandFn = mkOption {
type = types.functionTo types.singleLineStr;
example = literalExpression ''
{ checkOnly, files, ... }:
'''
''${pkgs.nixpkgs-fmt}/bin/nixpkgs-fmt ''${lib.optionalString checkOnly "--check"} ''${files}
'''
'';
description = ''
Command for formatter. Receives at least <varname>checkOnly</varname> as boolean
and <varname>files</varname> as a string.
Must return a non-zero exit code when <varname>checkOnly</varname> is true and the
check fails. Should return zero exit code when <varname>checkOnly</varname> is false
and all issues could be fixed.
For more complex commands, use <varname>pkgs.writeScript</varname> like
<programlisting language="nix">
{ checkOnly, files, ... }:
"''${pkgs.writeScript
"nixpkgs-fmt"
'''
''${pkgs.nixpkgs-fmt}/bin/nixpkgs-fmt ''${lib.optionalString checkOnly "--check"} "$@"
'''
} ''${files}";
</programlisting>
'';
};
};
}
));
default = { };
description = "Set of all formatters to run on script execution.";
};
script = mkOption {
type = types.package;
internal = true;
readOnly = true;
description = "Final script.";
};
};
config = {
assertions = [
{
assertion = enabledFormatters != [ ];
message = "At least one formatter needs to be enabled.";
}
];
script = throwAssertions (showWarnings config.warnings script);
};
}