aboutsummaryrefslogtreecommitdiffstats
path: root/modules/lib
diff options
context:
space:
mode:
authorArpit Chakladar <arpitchakladar+git@gmail.com>2026-08-29 02:02:23 +0530
committerArpit Chakladar <arpitchakladar+git@gmail.com>2026-08-29 03:50:32 +0530
commit41bdeb88009dd232808edee9fc0e4ae94358d8d6 (patch)
treec1a41f54e086064dac178ebed24d36ab34087c32 /modules/lib
parent530299d97926d45939f831dc3ea5e444d2839d08 (diff)
downloadhome-manager-config-41bdeb88009dd232808edee9fc0e4ae94358d8d6.tar.gz
home-manager-config-41bdeb88009dd232808edee9fc0e4ae94358d8d6.zip
refactor: moving script into modules that makes sense
- instead of collecting all scripts into modules/scripts we are moving them to modules that makes sense (yazi-file-chooser.sh into yazi)
Diffstat (limited to 'modules/lib')
-rw-r--r--modules/lib/default.nix48
-rw-r--r--modules/lib/script.nix146
2 files changed, 194 insertions, 0 deletions
diff --git a/modules/lib/default.nix b/modules/lib/default.nix
new file mode 100644
index 0000000..fd54fa2
--- /dev/null
+++ b/modules/lib/default.nix
@@ -0,0 +1,48 @@
+# Internal aggregation for script modules registered via mkScriptModule
+{
+ config,
+ lib,
+ ...
+}:
+{
+ options.scriptPaths = lib.mkOption {
+ type = lib.types.listOf (lib.types.listOf lib.types.str);
+ default = [ ];
+ internal = true;
+ description = "Attr paths of script modules registered via mkScriptModule.";
+ };
+
+ config = {
+ home.packages = lib.filter (p: p != null) (
+ map (path: (lib.getAttrFromPath path config).package) config.scriptPaths
+ );
+
+ xdg.desktopEntries = lib.listToAttrs (
+ map
+ (
+ path:
+ let
+ name = lib.last path;
+ sc = lib.getAttrFromPath path config;
+ in
+ lib.nameValuePair name {
+ name = sc.desktop.displayName;
+ exec = "${lib.getExe config.terminal.kitty.package} --class ${name} -e ${lib.getExe sc.package}";
+ icon = sc.desktop.icon;
+ categories = [ "Utility" ];
+ terminal = false;
+ type = "Application";
+ }
+ )
+ (
+ lib.filter (
+ path:
+ let
+ sc = lib.getAttrFromPath path config;
+ in
+ sc.enable && sc.desktop.enable
+ ) config.scriptPaths
+ )
+ );
+ };
+}
diff --git a/modules/lib/script.nix b/modules/lib/script.nix
new file mode 100644
index 0000000..9871b88
--- /dev/null
+++ b/modules/lib/script.nix
@@ -0,0 +1,146 @@
+# Library for creating script modules
+{
+ lib,
+ pkgs,
+}:
+let
+ shellArgs = {
+ zsh = name: file: "--zsh --name _${name} ${file}";
+ bash = name: file: "--bash --name ${name}.bash ${file}";
+ };
+
+ mkScript =
+ name: path: description: env: deps: completion:
+ let
+ descLines = lib.filter (s: s != "") (lib.splitString "\n" description);
+ descComment =
+ if descLines == [ ] then "" else lib.concatMapStringsSep "\n" (line: "# ${line}") descLines + "\n";
+ envVars = lib.concatStringsSep "\n" (
+ lib.mapAttrsToList (n: v: "export ${n}=${lib.escapeShellArg (toString v)}") env
+ );
+ base = pkgs.writeShellApplication {
+ inherit name;
+ runtimeInputs = deps;
+ text = ''
+ ${descComment}${envVars}
+ ${builtins.readFile path}
+ '';
+ };
+ completionDrv =
+ pkgs.runCommand "${name}-completion"
+ {
+ nativeBuildInputs = [ pkgs.installShellFiles ];
+ }
+ (
+ "mkdir -p $out\n"
+ + lib.concatStringsSep "\n" (
+ lib.mapAttrsToList (shell: content: ''
+ installShellCompletion ${shellArgs.${shell} name (pkgs.writeText "_${name}.${shell}" content)}
+ '') completion
+ )
+ );
+ in
+ if completion == { } then
+ base
+ else
+ pkgs.symlinkJoin {
+ name = name;
+ paths = [
+ base
+ completionDrv
+ ];
+ meta = base.meta or { };
+ };
+
+ mkScriptModule =
+ {
+ scope ? [ ],
+ name,
+ path,
+ env ? { },
+ deps ? [ ],
+ desktop ? null,
+ extraLinks ? [ ],
+ config,
+ description ? "",
+ completion ? { },
+ }:
+ let
+ scriptAttrs = scope ++ [ name ];
+ dottedName = lib.concatStringsSep "." scriptAttrs;
+ c = lib.getAttrFromPath scriptAttrs config;
+ scriptDrv = mkScript name path description env deps completion;
+ in
+ {
+ options = lib.setAttrByPath scriptAttrs {
+ enable = lib.mkOption {
+ type = lib.types.bool;
+ default = true;
+ description = "Whether to enable the ${name} script.";
+ };
+ package = lib.mkOption {
+ type = lib.types.nullOr lib.types.package;
+ readOnly = true;
+ description = "The derivation for the ${name} script.";
+ };
+ completion.enable = lib.mkOption {
+ type = lib.types.bool;
+ default = completion != { };
+ description = "Whether to install completions for the ${name} script.";
+ };
+ desktop = {
+ enable = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ description = "Whether to create a .desktop entry for this script.";
+ };
+ displayName = lib.mkOption {
+ type = lib.types.str;
+ default = name;
+ description = "Display name for the .desktop entry.";
+ };
+ icon = lib.mkOption {
+ type = lib.types.str;
+ default = "kitty";
+ description = "Icon for the .desktop entry.";
+ };
+ };
+ };
+
+ config =
+ lib.setAttrByPath scriptAttrs (
+ lib.mkIf c.enable (
+ {
+ package = scriptDrv;
+ }
+ // lib.optionalAttrs (desktop != null) { inherit desktop; }
+ )
+ )
+ // {
+ home.file = lib.mkIf c.enable (
+ builtins.listToAttrs (
+ map (linkPath: {
+ name = lib.removePrefix "~/" linkPath;
+ value = {
+ source = "${scriptDrv}/bin/${name}";
+ };
+ }) extraLinks
+ )
+ );
+ assertions = [
+ {
+ assertion = !c.enable || !c.desktop.enable || config.terminal.kitty.enable;
+ message = "${dottedName}.desktop.enable requires terminal.kitty.enable because desktop entries launch scripts in kitty.";
+ }
+ {
+ assertion = !c.completion.enable || completion != { };
+ message = "${dottedName}.completion.enable is true but no completion text was provided to mkScriptModule.";
+ }
+ ];
+ scriptPaths = [ scriptAttrs ];
+ };
+ };
+in
+{
+ inherit mkScript mkScriptModule;
+}