Skip to content

Commit 053b792

Browse files
committed
feat: support nested commands option
1 parent 269b9c3 commit 053b792

File tree

8 files changed

+638
-65
lines changed

8 files changed

+638
-65
lines changed

modules/commands.nix

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,48 @@
11
{ lib, config, pkgs, ... }:
22
let
3-
inherit (import ../nix/commands/convert.nix { inherit pkgs; }) commandsToMenu commandToPackage;
4-
inherit (import ../nix/commands/devshellMenu.nix { inherit pkgs; }) mkDevshellMenuCommand;
5-
inherit (import ../nix/commands/types.nix { inherit pkgs; }) commandsFlatType;
3+
inherit (import ../nix/commands/lib.nix { inherit pkgs; })
4+
commandsType
5+
commandToPackage
6+
mkDevshellMenuCommand
7+
;
68
in
79
{
810
options.commands = lib.mkOption {
9-
type = commandsFlatType;
11+
type = commandsType;
1012
default = [ ];
1113
description = ''
1214
Add commands to the environment.
1315
'';
1416
example = lib.literalExpression ''
15-
[
16-
{
17-
help = "print hello";
18-
name = "hello";
19-
command = "echo hello";
20-
}
21-
22-
{
23-
package = "nixpkgs-fmt";
24-
category = "formatter";
25-
}
26-
]
17+
{
18+
packages = [
19+
"diffutils"
20+
"goreleaser"
21+
];
22+
scripts = [
23+
{
24+
prefix = "nix run .#";
25+
inherit packages;
26+
}
27+
{
28+
name = "nix fmt";
29+
help = "format Nix files";
30+
}
31+
];
32+
utilites = [
33+
[ "GitHub utility" "gitAndTools.hub" ]
34+
[ "golang linter" "golangci-lint" ]
35+
];
36+
}
2737
'';
2838
};
2939

3040
# Add the commands to the devshell packages. Either as wrapper scripts, or
3141
# the whole package.
32-
config.devshell.packages = map commandToPackage ([ (mkDevshellMenuCommand config.commands) ] ++ config.commands);
42+
config.devshell.packages =
43+
lib.filter
44+
(x: x != null)
45+
(map commandToPackage ([ (mkDevshellMenuCommand config.commands) ] ++ config.commands));
46+
3347
# config.devshell.motd = "$(motd)";
3448
}

modules/modules-docs.nix

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ let
4747
in
4848
map (p: repack (unpack p));
4949

50+
mkUrl = root: path: "${root.url}/tree/${root.branch}/${path}";
51+
5052
# Transforms a module path into a (path, url) tuple where path is relative
5153
# to the repo root, and URL points to an online view of the module.
5254
mkDeclaration =
@@ -69,7 +71,7 @@ let
6971
else
7072
rec {
7173
path = removePrefix root.prefix decl;
72-
url = "${root.url}/tree/${root.branch}/${path}";
74+
url = mkUrl root path;
7375
};
7476

7577
# Sort modules and put "enable" and "package" declarations first.
@@ -80,7 +82,7 @@ let
8082
compareWithPrio = pred: cmp: splitByAndCompare pred compare cmp;
8183
moduleCmp = compareWithPrio isEnable (compareWithPrio isPackage compare);
8284
in
83-
compareLists moduleCmp a.loc b.loc < 0;
85+
compareLists moduleCmp (map toString a.loc) (map toString b.loc) < 0;
8486

8587
# Replace functions by the string <function>
8688
substFunction = x:
@@ -114,11 +116,22 @@ let
114116
)
115117
);
116118

119+
inherit (import ../nix/commands/lib.nix { inherit pkgs; }) mkLocSuffix nestedOptionsType flatOptionsType;
120+
117121
# TODO: display values like TOML instead.
118122
toMarkdown = optionsDocs:
119123
let
120-
optionsDocsPartitioned = partition (opt: head opt.loc != "_module") optionsDocs;
121-
124+
optionsDocsPartitionedIsMain = partition (opt: head opt.loc != "_module") optionsDocs;
125+
nixOnlyLocPrefix = [ "commands" "<name>" ];
126+
optionsDocsPartitionedIsNixOnly = partition (opt: (take 2 opt.loc) == nixOnlyLocPrefix) optionsDocsPartitionedIsMain.right;
127+
nixOnly = optionsDocsPartitionedIsNixOnly.right;
128+
nixOnlyPartitionedIsTop = partition (opt: opt.loc == nixOnlyLocPrefix ++ [ "*" ]) nixOnly;
129+
nixOnlyPartitionedHasSuffix = partition (opt: ("${last opt.loc}" == "${mkLocSuffix nestedOptionsType.name}")) nixOnlyPartitionedIsTop.wrong;
130+
nixOnlyOrdered = nixOnlyPartitionedIsTop.right ++ nixOnlyPartitionedHasSuffix.right ++ nixOnlyPartitionedHasSuffix.wrong;
131+
nixAndTOMLOrdered = optionsDocsPartitionedIsNixOnly.wrong;
132+
nixExtra = optionsDocsPartitionedIsMain.wrong;
133+
concatOpts = opts: (concatStringsSep "\n\n" (map optToMd opts));
134+
122135
# TODO: handle opt.relatedPackages. What is it for?
123136
optToMd = opt:
124137
let heading = (lib.showOption (filter isString opt.loc)) + (concatStrings (filter (x: !(isString x)) opt.loc)); in
@@ -165,13 +178,30 @@ let
165178
opt.declarations
166179
)
167180
)
168-
+ "\n"
169181
;
170182
doc = [
171-
"## Options\n"
172-
(concatStringsSep "\n" (map optToMd optionsDocsPartitioned.right))
173-
"## Extra options\n"
174-
(concatStringsSep "\n" (map optToMd optionsDocsPartitioned.wrong))
183+
"# Options\n"
184+
"## Available only in `Nix`\n"
185+
(
186+
let
187+
root = head cfg.roots;
188+
pathExamples = "nix/commands/examples.nix";
189+
pathExamplesReal = ../${pathExamples};
190+
pathCommandsLib = "tests/extra/commands.lib.nix";
191+
pathCommandsLibReal = ../${pathCommandsLib};
192+
mkLink = path: "[link](${mkUrl root path})";
193+
in
194+
assert lib.assertMsg (lib.pathExists pathExamplesReal) "Path `${pathExamplesReal} doesn't exist.`";
195+
assert lib.assertMsg (lib.pathExists pathCommandsLibReal) "Path `${pathCommandsLibReal} doesn't exist.`";
196+
''
197+
See how `commands.<name>` (${mkLink pathExamples}) maps to `commands.*` (${mkLink pathCommandsLib}).
198+
''
199+
)
200+
(concatOpts nixOnlyOrdered)
201+
"## Available in `Nix` and `TOML`\n"
202+
(concatOpts nixAndTOMLOrdered)
203+
"## Extra options available only in `Nix`\n"
204+
(concatOpts nixExtra)
175205
];
176206
in
177207
concatStringsSep "\n" doc;

nix/commands/examples.nix

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
{ system ? builtins.currentSystem
2+
, pkgs ? import ../nixpkgs.nix { inherit system; }
3+
}:
4+
let inherit (pkgs) lib; in
5+
{
6+
nested = {
7+
"category 1" = [
8+
{
9+
prefix = "nix run .#";
10+
prefixes = {
11+
a.b = {
12+
d = "nix run ../#";
13+
};
14+
};
15+
packages = {
16+
a.b = {
17+
jq-1 = [ "[package] jq description" pkgs.jq ];
18+
yq-1 = pkgs.yq-go;
19+
yq-2 = pkgs.yq-go;
20+
};
21+
npm = "nodePackages.npm";
22+
};
23+
help = "[package] default description";
24+
helps = {
25+
a.b = {
26+
jq-1 = "[package] another jq description";
27+
yq-1 = "[package] yq description";
28+
};
29+
};
30+
}
31+
{
32+
packages.a.b = { inherit (pkgs) hyperfine findutils; };
33+
expose = true;
34+
exposes.a.b.hyperfine = false;
35+
}
36+
{
37+
commands.a.b.awk = ''${lib.getExe pkgs.gawk} $@'';
38+
helps.a.b.awk = "[command] run awk";
39+
40+
commands.a.b.jq-2 = [ "[command] run jq" "${lib.getExe pkgs.jq} $@" ];
41+
42+
commands."command with spaces" = ''printf "hello\n"'';
43+
helps."command with spaces" = ''[command] print "hello"'';
44+
}
45+
pkgs.python3
46+
[ "[package] vercel description" "nodePackages.vercel" ]
47+
"nodePackages.yarn"
48+
{
49+
package = pkgs.gnugrep;
50+
}
51+
{
52+
name = "run cowsay";
53+
help = "run hello";
54+
package = "cowsay";
55+
}
56+
{
57+
name = "run perl";
58+
help = "run perl";
59+
command = "${lib.getExe pkgs.perl} $@";
60+
}
61+
{
62+
name = "nix fmt";
63+
help = "format Nix files";
64+
}
65+
];
66+
category-2 = [
67+
{
68+
package = pkgs.go;
69+
}
70+
[ "[package] run hello " "hello" ]
71+
pkgs.nixpkgs-fmt
72+
];
73+
};
74+
75+
flat = [
76+
{
77+
category = "scripts";
78+
package = "black";
79+
}
80+
[ "[package] print hello" "hello" ]
81+
"nodePackages.yarn"
82+
83+
# uncomment to trigger errors:
84+
# [ "a" ]
85+
# [ "a" "b" "c" ]
86+
];
87+
}

nix/commands/lib.nix

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{ system ? builtins.currentSystem
2+
, pkgs ? import ../nixpkgs.nix { inherit system; }
3+
}:
4+
(import ./types.nix { inherit pkgs; }) //
5+
(import ./convert.nix { inherit pkgs; }) //
6+
(import ./typesCommands.nix { inherit pkgs; }) //
7+
(import ./devshellMenu.nix { inherit pkgs; })

0 commit comments

Comments
 (0)