···66 and returning a set with TOML-specific attributes `type` and
67 `generate` as specified [below](#pkgs-formats-result).
6800000000000000000000000000000000000000069::: {#pkgs-formats-result}
70These functions all return an attribute set with these values:
71:::
···73`type`
7475: A module system type representing a value of the format
0000007677`generate` *`filename jsonValue`*
78
···66 and returning a set with TOML-specific attributes `type` and
67 `generate` as specified [below](#pkgs-formats-result).
6869+`pkgs.formats.elixirConf { elixir ? pkgs.elixir }`
70+71+: A function taking an attribute set with values
72+73+ `elixir`
74+75+ : The Elixir package which will be used to format the generated output
76+77+ It returns a set with Elixir-Config-specific attributes `type`, `lib`, and
78+ `generate` as specified [below](#pkgs-formats-result).
79+80+ The `lib` attribute contains functions to be used in settings, for
81+ generating special Elixir values:
82+83+ `mkRaw elixirCode`
84+85+ : Outputs the given string as raw Elixir code
86+87+ `mkGetEnv { envVariable, fallback ? null }`
88+89+ : Makes the configuration fetch an environment variable at runtime
90+91+ `mkAtom atom`
92+93+ : Outputs the given string as an Elixir atom, instead of the default
94+ Elixir binary string. Note: lowercase atoms still needs to be prefixed
95+ with `:`
96+97+ `mkTuple array`
98+99+ : Outputs the given array as an Elixir tuple, instead of the default
100+ Elixir list
101+102+ `mkMap attrset`
103+104+ : Outputs the given attribute set as an Elixir map, instead of the
105+ default Elixir keyword list
106+107+108::: {#pkgs-formats-result}
109These functions all return an attribute set with these values:
110:::
···112`type`
113114: A module system type representing a value of the format
115+116+`lib`
117+118+: Utility functions for convenience, or special interactions with the format.
119+ This attribute is optional. It may contain inside a `types` attribute
120+ containing types specific to this format.
121122`generate` *`filename jsonValue`*
123
···137 </para>
138 </listitem>
139 </varlistentry>
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140 </variablelist>
141 <para xml:id="pkgs-formats-result">
142 These functions all return an attribute set with these values:
···149 <listitem>
150 <para>
151 A module system type representing a value of the format
0000000000000152 </para>
153 </listitem>
154 </varlistentry>
···137 </para>
138 </listitem>
139 </varlistentry>
140+ <varlistentry>
141+ <term>
142+ <literal>pkgs.formats.elixirConf { elixir ? pkgs.elixir }</literal>
143+ </term>
144+ <listitem>
145+ <para>
146+ A function taking an attribute set with values
147+ </para>
148+ <variablelist>
149+ <varlistentry>
150+ <term>
151+ <literal>elixir</literal>
152+ </term>
153+ <listitem>
154+ <para>
155+ The Elixir package which will be used to format the
156+ generated output
157+ </para>
158+ </listitem>
159+ </varlistentry>
160+ </variablelist>
161+ <para>
162+ It returns a set with Elixir-Config-specific attributes
163+ <literal>type</literal>, <literal>lib</literal>, and
164+ <literal>generate</literal> as specified
165+ <link linkend="pkgs-formats-result">below</link>.
166+ </para>
167+ <para>
168+ The <literal>lib</literal> attribute contains functions to
169+ be used in settings, for generating special Elixir values:
170+ </para>
171+ <variablelist>
172+ <varlistentry>
173+ <term>
174+ <literal>mkRaw elixirCode</literal>
175+ </term>
176+ <listitem>
177+ <para>
178+ Outputs the given string as raw Elixir code
179+ </para>
180+ </listitem>
181+ </varlistentry>
182+ <varlistentry>
183+ <term>
184+ <literal>mkGetEnv { envVariable, fallback ? null }</literal>
185+ </term>
186+ <listitem>
187+ <para>
188+ Makes the configuration fetch an environment variable
189+ at runtime
190+ </para>
191+ </listitem>
192+ </varlistentry>
193+ <varlistentry>
194+ <term>
195+ <literal>mkAtom atom</literal>
196+ </term>
197+ <listitem>
198+ <para>
199+ Outputs the given string as an Elixir atom, instead of
200+ the default Elixir binary string. Note: lowercase
201+ atoms still needs to be prefixed with
202+ <literal>:</literal>
203+ </para>
204+ </listitem>
205+ </varlistentry>
206+ <varlistentry>
207+ <term>
208+ <literal>mkTuple array</literal>
209+ </term>
210+ <listitem>
211+ <para>
212+ Outputs the given array as an Elixir tuple, instead of
213+ the default Elixir list
214+ </para>
215+ </listitem>
216+ </varlistentry>
217+ <varlistentry>
218+ <term>
219+ <literal>mkMap attrset</literal>
220+ </term>
221+ <listitem>
222+ <para>
223+ Outputs the given attribute set as an Elixir map,
224+ instead of the default Elixir keyword list
225+ </para>
226+ </listitem>
227+ </varlistentry>
228+ </variablelist>
229+ </listitem>
230+ </varlistentry>
231 </variablelist>
232 <para xml:id="pkgs-formats-result">
233 These functions all return an attribute set with these values:
···240 <listitem>
241 <para>
242 A module system type representing a value of the format
243+ </para>
244+ </listitem>
245+ </varlistentry>
246+ <varlistentry>
247+ <term>
248+ <literal>lib</literal>
249+ </term>
250+ <listitem>
251+ <para>
252+ Utility functions for convenience, or special interactions
253+ with the format. This attribute is optional. It may contain
254+ inside a <literal>types</literal> attribute containing types
255+ specific to this format.
256 </para>
257 </listitem>
258 </varlistentry>
···4 pname = "nerd-font-patcher";
5 version = "2.1.0";
67- # The size of the nerd fonts repository is bigger than 2GB, because it
8- # contains a lot of fonts and the patcher.
9- # until https://github.com/ryanoasis/nerd-fonts/issues/484 is not fixed,
10- # we download the patcher from an alternative repository
11 src = fetchFromGitHub {
12- owner = "betaboon";
13- repo = "nerd-fonts-patcher";
14- rev = "180684d7a190f75fd2fea7ca1b26c6540db8d3c0";
15- sha256 = "sha256-FAbdLf0XiUXGltAgmq33Wqv6PFo/5qCv62UxXnj3SgI=";
000016 };
1718 propagatedBuildInputs = with python3Packages; [ fontforge ];
···4 pname = "nerd-font-patcher";
5 version = "2.1.0";
67+ # This uses a sparse checkout because the repo is >2GB without it
0008 src = fetchFromGitHub {
9+ owner = "ryanoasis";
10+ repo = "nerd-fonts";
11+ rev = "v${version}";
12+ sparseCheckout = ''
13+ font-patcher
14+ /src/glyphs
15+ '';
16+ sha256 = "sha256-ePBlEVjzAJ7g6iAGIqPfgZ8bwtNILmyEVm0zD+xNN6k=";
17 };
1819 propagatedBuildInputs = with python3Packages; [ fontforge ];
···14 # The description needs to be overwritten for recursive types
15 type = ...;
1600000000017 # generate :: Name -> Value -> Path
18 # A function for generating a file with a value of such a type
19 generate = ...;
···147 '';
148149 };
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000150}
···14 # The description needs to be overwritten for recursive types
15 type = ...;
1617+ # Utility functions for convenience, or special interactions with the
18+ # format (optional)
19+ lib = {
20+ exampleFunction = ...
21+ # Types specific to the format (optional)
22+ types = { ... };
23+ ...
24+ };
25+26 # generate :: Name -> Value -> Path
27 # A function for generating a file with a value of such a type
28 generate = ...;
···156 '';
157158 };
159+160+ /* For configurations of Elixir project, like config.exs or runtime.exs
161+162+ Most Elixir project are configured using the [Config] Elixir DSL
163+164+ Since Elixir has more types than Nix, we need a way to map Nix types to
165+ more than 1 Elixir type. To that end, this format provides its own library,
166+ and its own set of types.
167+168+ To be more detailed, a Nix attribute set could correspond in Elixir to a
169+ [Keyword list] (the more common type), or it could correspond to a [Map].
170+171+ A Nix string could correspond in Elixir to a [String] (also called
172+ "binary"), an [Atom], or a list of chars (usually discouraged).
173+174+ A Nix array could correspond in Elixir to a [List] or a [Tuple].
175+176+ Some more types exists, like records, regexes, but since they are less used,
177+ we can leave the `mkRaw` function as an escape hatch.
178+179+ For more information on how to use this format in modules, please refer to
180+ the Elixir section of the Nixos documentation.
181+182+ TODO: special Elixir values doesn't show up nicely in the documentation
183+184+ [Config]: <https://hexdocs.pm/elixir/Config.html>
185+ [Keyword list]: <https://hexdocs.pm/elixir/Keyword.html>
186+ [Map]: <https://hexdocs.pm/elixir/Map.html>
187+ [String]: <https://hexdocs.pm/elixir/String.html>
188+ [Atom]: <https://hexdocs.pm/elixir/Atom.html>
189+ [List]: <https://hexdocs.pm/elixir/List.html>
190+ [Tuple]: <https://hexdocs.pm/elixir/Tuple.html>
191+ */
192+ elixirConf = { elixir ? pkgs.elixir }:
193+ with lib; let
194+ toElixir = value: with builtins;
195+ if value == null then "nil" else
196+ if value == true then "true" else
197+ if value == false then "false" else
198+ if isInt value || isFloat value then toString value else
199+ if isString value then string value else
200+ if isAttrs value then attrs value else
201+ if isList value then list value else
202+ abort "formats.elixirConf: should never happen (value = ${value})";
203+204+ escapeElixir = escape [ "\\" "#" "\"" ];
205+ string = value: "\"${escapeElixir value}\"";
206+207+ attrs = set:
208+ if set ? _elixirType then specialType set
209+ else
210+ let
211+ toKeyword = name: value: "${name}: ${toElixir value}";
212+ keywordList = concatStringsSep ", " (mapAttrsToList toKeyword set);
213+ in
214+ "[" + keywordList + "]";
215+216+ listContent = values: concatStringsSep ", " (map toElixir values);
217+218+ list = values: "[" + (listContent values) + "]";
219+220+ specialType = { value, _elixirType }:
221+ if _elixirType == "raw" then value else
222+ if _elixirType == "atom" then value else
223+ if _elixirType == "map" then elixirMap value else
224+ if _elixirType == "tuple" then tuple value else
225+ abort "formats.elixirConf: should never happen (_elixirType = ${_elixirType})";
226+227+ elixirMap = set:
228+ let
229+ toEntry = name: value: "${toElixir name} => ${toElixir value}";
230+ entries = concatStringsSep ", " (mapAttrsToList toEntry set);
231+ in
232+ "%{${entries}}";
233+234+ tuple = values: "{${listContent values}}";
235+236+ toConf = values:
237+ let
238+ keyConfig = rootKey: key: value:
239+ "config ${rootKey}, ${key}, ${toElixir value}";
240+ keyConfigs = rootKey: values: mapAttrsToList (keyConfig rootKey) values;
241+ rootConfigs = flatten (mapAttrsToList keyConfigs values);
242+ in
243+ ''
244+ import Config
245+246+ ${concatStringsSep "\n" rootConfigs}
247+ '';
248+ in
249+ {
250+ type = with lib.types; let
251+ valueType = nullOr
252+ (oneOf [
253+ bool
254+ int
255+ float
256+ str
257+ (attrsOf valueType)
258+ (listOf valueType)
259+ ]) // {
260+ description = "Elixir value";
261+ };
262+ in
263+ attrsOf (attrsOf (valueType));
264+265+ lib =
266+ let
267+ mkRaw = value: {
268+ inherit value;
269+ _elixirType = "raw";
270+ };
271+272+ in
273+ {
274+ inherit mkRaw;
275+276+ /* Fetch an environment variable at runtime, with optional fallback
277+ */
278+ mkGetEnv = { envVariable, fallback ? null }:
279+ mkRaw "System.get_env(${toElixir envVariable}, ${toElixir fallback})";
280+281+ /* Make an Elixir atom.
282+283+ Note: lowercase atoms still need to be prefixed by ':'
284+ */
285+ mkAtom = value: {
286+ inherit value;
287+ _elixirType = "atom";
288+ };
289+290+ /* Make an Elixir tuple out of a list.
291+ */
292+ mkTuple = value: {
293+ inherit value;
294+ _elixirType = "tuple";
295+ };
296+297+ /* Make an Elixir map out of an attribute set.
298+ */
299+ mkMap = value: {
300+ inherit value;
301+ _elixirType = "map";
302+ };
303+304+ /* Contains Elixir types. Every type it exports can also be replaced
305+ by raw Elixir code (i.e. every type is `either type rawElixir`).
306+307+ It also reexports standard types, wrapping them so that they can
308+ also be raw Elixir.
309+ */
310+ types = with lib.types; let
311+ isElixirType = type: x: (x._elixirType or "") == type;
312+313+ rawElixir = mkOptionType {
314+ name = "rawElixir";
315+ description = "raw elixir";
316+ check = isElixirType "raw";
317+ };
318+319+ elixirOr = other: either other rawElixir;
320+ in
321+ {
322+ inherit rawElixir elixirOr;
323+324+ atom = elixirOr (mkOptionType {
325+ name = "elixirAtom";
326+ description = "elixir atom";
327+ check = isElixirType "atom";
328+ });
329+330+ tuple = elixirOr (mkOptionType {
331+ name = "elixirTuple";
332+ description = "elixir tuple";
333+ check = isElixirType "tuple";
334+ });
335+336+ map = elixirOr (mkOptionType {
337+ name = "elixirMap";
338+ description = "elixir map";
339+ check = isElixirType "map";
340+ });
341+ # Wrap standard types, since anything in the Elixir configuration
342+ # can be raw Elixir
343+ } // lib.mapAttrs (_name: type: elixirOr type) lib.types;
344+ };
345+346+ generate = name: value: pkgs.runCommandNoCC name
347+ {
348+ value = toConf value;
349+ passAsFile = [ "value" ];
350+ nativeBuildInputs = [ elixir ];
351+ } ''
352+ cp "$valuePath" "$out"
353+ mix format "$out"
354+ '';
355+ };
356+357}