diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 090d1a18..6fb012e7 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -147,6 +147,9 @@ /modules/programs/nix-index.nix @ambroisie /tests/modules/programs/nix-index @ambroisie +/modules/programs/nnn.nix @thiagokokada +/tests/modules/programs/nnn @thiagokokada + /modules/programs/noti.nix @marsam /modules/programs/nushell.nix @Philipp-M diff --git a/modules/misc/news.nix b/modules/misc/news.nix index 68eadae2..38ef04ce 100644 --- a/modules/misc/news.nix +++ b/modules/misc/news.nix @@ -2221,6 +2221,13 @@ in A new module is available: 'programs.atuin'. ''; } + + { + time = "2021-10-05T22:15:00+00:00"; + message = '' + A new module is available: 'programs.nnn'. + ''; + } ]; }; } diff --git a/modules/modules.nix b/modules/modules.nix index d9667a92..e7dc912c 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -105,6 +105,7 @@ let ./programs/neovim.nix ./programs/newsboat.nix ./programs/nix-index.nix + ./programs/nnn.nix ./programs/noti.nix ./programs/notmuch.nix ./programs/nushell.nix diff --git a/modules/programs/nnn.nix b/modules/programs/nnn.nix new file mode 100644 index 00000000..a6c64cb2 --- /dev/null +++ b/modules/programs/nnn.nix @@ -0,0 +1,129 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.nnn; + + renderSetting = key: value: "${key}:${value}"; + + renderSettings = settings: + concatStringsSep ";" (mapAttrsToList renderSetting settings); + + pluginModule = types.submodule ({ ... }: { + options = { + src = mkOption { + type = with types; nullOr path; + example = literalExample '' + (pkgs.fetchFromGitHub { + owner = "jarun"; + repo = "nnn"; + rev = "v4.0"; + sha256 = "sha256-Hpc8YaJeAzJoEi7aJ6DntH2VLkoR6ToP6tPYn3llR7k="; + }) + "/plugins"; + ''; + default = null; + description = '' + Path to the plugin folder. + ''; + }; + + mappings = mkOption { + type = with types; attrsOf str; + description = '' + Key mappings to the plugins. + ''; + default = { }; + example = literalExample '' + { + c = "fzcd"; + f = "finder"; + v = "imgview"; + }; + ''; + }; + }; + }); +in { + meta.maintainers = with maintainers; [ thiagokokada ]; + + options = { + programs.nnn = { + enable = mkEnableOption "nnn"; + + package = mkOption { + type = types.package; + default = pkgs.nnn; + defaultText = literalExample "pkgs.nnn"; + example = + literalExample "pkgs.nnn.override ({ withNerdIcons = true; });"; + description = '' + Package containing the nnn program. + ''; + }; + + finalPackage = mkOption { + type = types.package; + readOnly = true; + visible = false; + description = '' + Resulting nnn package. + ''; + }; + + bookmarks = mkOption { + type = with types; attrsOf str; + description = '' + Directory bookmarks. + ''; + example = literalExample '' + { + d = "~/Documents"; + D = "~/Downloads"; + p = "~/Pictures"; + v = "~/Videos"; + }; + ''; + default = { }; + }; + + extraPackages = mkOption { + type = with types; listOf package; + example = + literalExample "with pkgs; [ ffmpegthumbnailer mediainfo sxiv ]"; + description = '' + Extra packages available to nnn. + ''; + default = [ ]; + }; + + plugins = mkOption { + type = pluginModule; + description = '' + Manage nnn plugins. + ''; + default = { }; + }; + }; + }; + + config = let + nnnPackage = cfg.package.overrideAttrs (oldAttrs: { + nativeBuildInputs = (oldAttrs.nativeBuildInputs or [ ]) + ++ [ pkgs.makeWrapper ]; + postInstall = '' + ${oldAttrs.postInstall or ""} + + wrapProgram $out/bin/nnn \ + --prefix PATH : "${makeBinPath cfg.extraPackages}" \ + --prefix NNN_BMS : "${renderSettings cfg.bookmarks}" \ + --prefix NNN_PLUG : "${renderSettings cfg.plugins.mappings}" + ''; + }); + in mkIf cfg.enable { + programs.nnn.finalPackage = nnnPackage; + home.packages = [ nnnPackage ]; + xdg.configFile."nnn/plugins" = + mkIf (cfg.plugins.src != null) { source = cfg.plugins.src; }; + }; +} diff --git a/tests/default.nix b/tests/default.nix index 8066433f..b08d7407 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -76,6 +76,7 @@ import nmt { ./modules/programs/neomutt ./modules/programs/newsboat ./modules/programs/nix-index + ./modules/programs/nnn ./modules/programs/nushell ./modules/programs/pet ./modules/programs/powerline-go diff --git a/tests/modules/programs/nnn/default.nix b/tests/modules/programs/nnn/default.nix new file mode 100644 index 00000000..6ba66beb --- /dev/null +++ b/tests/modules/programs/nnn/default.nix @@ -0,0 +1 @@ +{ nnn = ./nnn.nix; } diff --git a/tests/modules/programs/nnn/nnn.nix b/tests/modules/programs/nnn/nnn.nix new file mode 100644 index 00000000..aeb7d3fc --- /dev/null +++ b/tests/modules/programs/nnn/nnn.nix @@ -0,0 +1,57 @@ +{ config, lib, pkgs, ... }: + +{ + config = { + programs.nnn = { + enable = true; + bookmarks = { + d = "~/Documents"; + D = "~/Downloads"; + p = "~/Pictures"; + v = "~/Videos"; + }; + package = pkgs.nnnDummy; + extraPackages = with pkgs; [ foo bar ]; + plugins = { + src = ./plugins; + mappings = { + c = "fzcd"; + f = "finder"; + v = "imgview"; + }; + }; + }; + + test.stubs = { + nnnDummy.buildScript = '' + mkdir -p "$out/bin" + touch "$out/bin/nnn" + chmod +x "$out/bin/nnn" + + runHook postInstall + ''; + foo = { name = "foo"; }; + bar = { name = "bar"; }; + }; + + nmt = { + description = + "Check if the binary is correctly wrapped and if the symlinks are made"; + script = '' + assertDirectoryExists home-files/.config/nnn/plugins + + assertFileRegex \ + home-path/bin/nnn \ + "^export NNN_BMS='D:~/Downloads;d:~/Documents;p:~/Pictures;v:~/Videos'\''${NNN_BMS:+':'}\$NNN_BMS$" + + assertFileRegex \ + home-path/bin/nnn \ + "^export NNN_PLUG='c:fzcd;f:finder;v:imgview'\''${NNN_PLUG:+':'}\$NNN_PLUG$" + + assertFileRegex \ + home-path/bin/nnn \ + "/nix/store/.*-"{foo,bar}"/bin" + ''; + }; + }; +} diff --git a/tests/modules/programs/nnn/plugins/.keep b/tests/modules/programs/nnn/plugins/.keep new file mode 100644 index 00000000..e69de29b