mirror of
https://gitlab.com/rensa-nix/devshell.git
synced 2025-12-11 22:00:08 +01:00
chore: format and add meta module
This commit is contained in:
parent
223000e43c
commit
5fee6ef12a
7 changed files with 238 additions and 8 deletions
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
outputs = i: {
|
||||
outputs = _i: {
|
||||
lib = import ./.;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,5 +2,6 @@
|
|||
imports = [
|
||||
./main.nix
|
||||
./env.nix
|
||||
./meta.nix
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
prefix,
|
||||
...
|
||||
} @ args: let
|
||||
vals = filter (key: args.${key} != null && args.${key} != false) [
|
||||
vals = filter (key: args.${key} != null && args.${key}) [
|
||||
"eval"
|
||||
"prefix"
|
||||
"unset"
|
||||
|
|
@ -122,5 +122,14 @@ in {
|
|||
};
|
||||
enterShellCommands."env".text = concatStringsSep "\n" (map envToBash (builtins.attrValues config.env));
|
||||
# TODO: collect all env vars, then add them to the menu if they have a description and "visibile == true"
|
||||
|
||||
meta = {
|
||||
sections."Environment Variables".color = "red";
|
||||
entries."XDG_DATA_DIRS" = {
|
||||
description = "Hello world";
|
||||
section = "Environment Variables";
|
||||
subEntries."Usage" = "hello world";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,8 +124,12 @@ in {
|
|||
meta.mainProgram = "devshell-${config.name}";
|
||||
};
|
||||
finalPackage = mkNakedShell {
|
||||
name = config.name;
|
||||
inherit (config) name;
|
||||
profile = config.shell.finalProfile;
|
||||
passthru = {
|
||||
metadata = config.meta.finalMetadata;
|
||||
metadataJson = config.meta.finalJson;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
211
lib/modules/meta.nix
Normal file
211
lib/modules/meta.nix
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkOption types optional mkIf concatMapStrings concatMapStringsSep toUpper splitString;
|
||||
cfg = config.meta;
|
||||
|
||||
printSubtext = subtext:
|
||||
# sh
|
||||
''
|
||||
printf " $FG_GRAY ↳ $RESET''${BOLD}${subtext.text}$RESET: ${subtext.desc}\n"
|
||||
'';
|
||||
|
||||
printEntry = entry:
|
||||
# sh
|
||||
''
|
||||
printf " $FG_${entry.color}› %-*s$RESET $FG_GRAY%s$RESET\n" "${maxWidth}" "${entry.text}" "${entry.desc}"
|
||||
${concatMapStrings printSubtext entry.subtexts}
|
||||
'';
|
||||
printGroup = group:
|
||||
# sh
|
||||
''
|
||||
printf " $FG_WHITE$RESET$BG_WHITE$FG_BLACK %s $RESET$FG_WHITE$RESET\n" "${group.title}"
|
||||
${concatMapStrings printEntry group.entries}
|
||||
'';
|
||||
|
||||
calculateMaxWidth = groups: let
|
||||
lengths = builtins.concatLists (builtins.map (
|
||||
group:
|
||||
builtins.map (entry: builtins.stringLength entry.text) group.entries
|
||||
)
|
||||
groups);
|
||||
|
||||
max = a: b:
|
||||
if a > b
|
||||
then a
|
||||
else b;
|
||||
maxLength =
|
||||
if lengths == []
|
||||
then 0
|
||||
else builtins.foldl' max 0 lengths;
|
||||
in
|
||||
maxLength;
|
||||
maxWidth = builtins.toString (calculateMaxWidth result);
|
||||
|
||||
printHeaderDescription = text:
|
||||
concatMapStringsSep "\n" (line:
|
||||
# sh
|
||||
''
|
||||
printf " $FG_BLUE│$RESET $FG_WHITE%s$RESET\n" "${line}"
|
||||
'') (splitString "\n" text);
|
||||
|
||||
menuPackage = pkgs.writeTextFile {
|
||||
name = "menu";
|
||||
destination = "/bin/menu";
|
||||
executable = true;
|
||||
text =
|
||||
# sh
|
||||
''
|
||||
BOLD=$(tput bold)
|
||||
RESET=$(tput sgr0)
|
||||
FG_BLACK=$(tput setaf 0)
|
||||
FG_RED=$(tput setaf 1)
|
||||
FG_GREEN=$(tput setaf 2)
|
||||
FG_YELLOW=$(tput setaf 3)
|
||||
FG_BLUE=$(tput setaf 4)
|
||||
FG_MAGENTA=$(tput setaf 5)
|
||||
FG_CYAN=$(tput setaf 6)
|
||||
FG_WHITE=$(tput setaf 7)
|
||||
BG_WHITE=$(tput setab 7)
|
||||
FG_GRAY=$(tput setaf 8)
|
||||
|
||||
printf " $FG_BLUE╭─┄┄┈┈$RESET\n"
|
||||
printf " $FG_BLUE│$RESET $FG_YELLOW$BOLD%s$RESET\n" "${config.name}"
|
||||
${printHeaderDescription cfg.description}
|
||||
printf " $FG_BLUE╰─┄┄┈┈$RESET\n"
|
||||
printf "\n"
|
||||
|
||||
${concatMapStringsSep "printf '\n'\n" printGroup result}
|
||||
'';
|
||||
};
|
||||
|
||||
groupedEntries = builtins.foldl' (
|
||||
acc: entryName: let
|
||||
entry = cfg.entries.${entryName};
|
||||
sectionName = entry.section;
|
||||
section = cfg.sections.${sectionName} or {};
|
||||
|
||||
newEntry = {
|
||||
text = entry.name;
|
||||
desc = entry.description or "";
|
||||
color = section.color or "BLUE";
|
||||
subtexts = map (name: {
|
||||
text = name;
|
||||
desc = entry.subEntries.${name};
|
||||
}) (builtins.attrNames entry.subEntries);
|
||||
};
|
||||
|
||||
updatedSection =
|
||||
if acc ? ${sectionName}
|
||||
then acc.${sectionName} ++ [newEntry]
|
||||
else [newEntry];
|
||||
in
|
||||
acc // {${sectionName} = updatedSection;}
|
||||
) {} (builtins.attrNames cfg.entries);
|
||||
|
||||
result = builtins.map (sectionName: {
|
||||
title = sectionName;
|
||||
entries = groupedEntries.${sectionName} or [];
|
||||
}) (builtins.attrNames groupedEntries);
|
||||
in {
|
||||
options.meta = {
|
||||
enableMenu = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Add a `menu` command which shows a nice overview/summary of the devshell.
|
||||
'';
|
||||
};
|
||||
showMenu = mkOption {
|
||||
type = types.enum ["always" "once" "never"];
|
||||
default = "once";
|
||||
description = ''
|
||||
When to show the devshell menu. `once` uses a state file in `$REN_STATE`
|
||||
to keep track of the first time.
|
||||
'';
|
||||
};
|
||||
description = mkOption {
|
||||
type = types.str;
|
||||
default = "Welcome to the devshell.";
|
||||
description = '''';
|
||||
};
|
||||
sections = mkOption {
|
||||
type = types.attrsOf (types.submodule ({name, ...}: {
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
};
|
||||
color = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = "blue";
|
||||
apply = toUpper;
|
||||
};
|
||||
};
|
||||
}));
|
||||
default = {
|
||||
"general" = {};
|
||||
};
|
||||
};
|
||||
entries = mkOption {
|
||||
type = types.attrsOf (types.submodule ({name, ...}: {
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
};
|
||||
section = mkOption {
|
||||
type = types.str;
|
||||
default = "general";
|
||||
};
|
||||
description = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
subEntries = mkOption {
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
}));
|
||||
default = {};
|
||||
};
|
||||
finalMetadata = mkOption {
|
||||
type = types.attrs;
|
||||
internal = true;
|
||||
};
|
||||
finalJson = mkOption {
|
||||
type = types.package;
|
||||
internal = true;
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
meta = rec {
|
||||
finalMetadata = {
|
||||
inherit (config) name;
|
||||
# inherit (cfg) sections entries;
|
||||
sections = result;
|
||||
};
|
||||
finalJson = builtins.toFile "meta.json" (builtins.toJSON finalMetadata);
|
||||
};
|
||||
|
||||
packages = optional cfg.enableMenu menuPackage;
|
||||
# shows the menu when entering the devshell
|
||||
enterShellCommands."menu".text = mkIf (cfg.enableMenu && cfg.showMenu != "never") (
|
||||
if cfg.showMenu == "always"
|
||||
then "menu"
|
||||
else
|
||||
# sh
|
||||
''
|
||||
if [[ ! -f "$REN_STATE/${config.name}_menu_shown" ]]; then
|
||||
touch "$REN_STATE/${config.name}_menu_shown"
|
||||
menu
|
||||
fi
|
||||
''
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
@ -30,7 +30,7 @@ in
|
|||
(derivation {
|
||||
inherit name;
|
||||
|
||||
system = stdenv.hostPlatform.system;
|
||||
inherit (stdenv.hostPlatform) system;
|
||||
|
||||
# `nix develop` actually checks and uses builder. And it must be bash.
|
||||
builder = bashPath;
|
||||
|
|
|
|||
|
|
@ -13,10 +13,15 @@ in {
|
|||
};
|
||||
})
|
||||
];
|
||||
env."HELLO".value = "world!";
|
||||
enterShellCommands.test = {
|
||||
text = "echo Hello $HELLO";
|
||||
deps = ["env"];
|
||||
meta = {
|
||||
enableMenu = true;
|
||||
showMenu = "always";
|
||||
entries = {
|
||||
"World" = {
|
||||
section = "Hello";
|
||||
description = "meow";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue