Verified Commit 5fee6ef1 authored by TECHNOFAB's avatar TECHNOFAB 🐈
Browse files

chore: format and add meta module

parent 223000e4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
{
  outputs = i: {
  outputs = _i: {
    lib = import ./.;
  };
}
+1 −0
Original line number Diff line number Diff line
@@ -2,5 +2,6 @@
  imports = [
    ./main.nix
    ./env.nix
    ./meta.nix
  ];
}
+10 −1
Original line number Diff line number Diff line
@@ -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";
      };
    };
  };
}
+5 −1
Original line number Diff line number Diff line
@@ -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;
      };
    };
  };
}

lib/modules/meta.nix

0 → 100644
+211 −0
Original line number Diff line number Diff line
{
  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
        ''
    );
  };
}
Loading