diff --git a/modules/misc/news/2025/09/2025-09-03_18-44-34.nix b/modules/misc/news/2025/09/2025-09-03_18-44-34.nix new file mode 100644 index 000000000..08175ce69 --- /dev/null +++ b/modules/misc/news/2025/09/2025-09-03_18-44-34.nix @@ -0,0 +1,11 @@ +{ + time = "2025-09-03T21:44:34+00:00"; + condition = true; + message = '' + A new module is available: `programs.vivid` + + Vivid is a generator for the LS_COLORS environment variable + that controls the colorized output of ls, tree, fd, bfs, dust + and many other tools. + ''; +} diff --git a/modules/programs/vivid.nix b/modules/programs/vivid.nix new file mode 100644 index 000000000..cdb77fc40 --- /dev/null +++ b/modules/programs/vivid.nix @@ -0,0 +1,134 @@ +{ + lib, + pkgs, + config, + ... +}: +let + inherit (lib) + mkIf + mkEnableOption + mkPackageOption + mkOption + types + ; + + inherit (lib.hm.shell) + mkBashIntegrationOption + mkZshIntegrationOption + mkFishIntegrationOption + ; + + cfg = config.programs.vivid; + yamlFormat = pkgs.formats.yaml { }; +in +{ + meta.maintainers = with lib.hm.maintainers; [ aguirre-matteo ]; + + options.programs.vivid = { + enable = mkEnableOption "vivid"; + package = mkPackageOption pkgs "vivid" { nullable = true; }; + + enableBashIntegration = mkBashIntegrationOption { inherit config; }; + enableZshIntegration = mkZshIntegrationOption { inherit config; }; + enableFishIntegration = mkFishIntegrationOption { inherit config; }; + + colorMode = mkOption { + type = with types; nullOr str; + default = null; + example = "8-bit"; + description = '' + Color mode for vivid. + ''; + }; + + filetypes = mkOption { + inherit (yamlFormat) type; + default = { }; + example = { + text = { + special = [ + "CHANGELOG.md" + "CODE_OF_CONDUCT.md" + "CONTRIBUTING.md" + ]; + + todo = [ + "TODO.md" + "TODO.txt" + ]; + + licenses = [ + "LICENCE" + "COPYRIGHT" + ]; + }; + }; + description = '' + Filetype database for vivid. You can find an example config at: + . + ''; + }; + + activeTheme = mkOption { + type = with types; nullOr str; + default = null; + example = "molokai"; + description = '' + Active theme for vivid. + ''; + }; + + themes = mkOption { + type = with types; attrsOf path; + default = { }; + example = lib.literalExpression '' + { + ayu = builtins.fetchurl { + url = "https://raw.githubusercontent.com/NearlyTRex/Vivid/refs/heads/master/themes/ayu.yml"; + hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; + }; + + mocha = builtins.fetchurl { + url = "https://raw.githubusercontent.com/NearlyTRex/Vivid/refs/heads/master/themes/catppuccin-mocha.yml"; + hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; + }; + } + ''; + description = "Theme for vivid"; + }; + }; + + config = + let + vividCommand = "vivid ${ + lib.optionalString (cfg.colorMode != null) "-m ${cfg.colorMode}" + } generate ${lib.optionalString (cfg.activeTheme != null) cfg.activeTheme}"; + in + mkIf cfg.enable { + home.packages = mkIf (cfg.package != null) [ cfg.package ]; + + home.sessionVariables = mkIf (cfg.activeTheme != null) { VIVID_THEME = cfg.activeTheme; }; + + xdg.configFile = { + "vivid/filetypes.yml" = mkIf (cfg.filetypes != { }) { + source = yamlFormat.generate "vivid-filetypes" cfg.filetypes; + }; + } + // (lib.mapAttrs' ( + name: path: lib.nameValuePair "vivid/themes/${name}.yml" { source = path; } + ) cfg.themes); + + programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + export LS_COLORS="$(${vividCommand})" + ''; + + programs.zsh.initContent = mkIf cfg.enableZshIntegration '' + export LS_COLORS="$(${vividCommand})" + ''; + + programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration '' + set -gx LS_COLORS "$(${vividCommand})" + ''; + }; +} diff --git a/tests/modules/programs/vivid/default.nix b/tests/modules/programs/vivid/default.nix new file mode 100644 index 000000000..5b860f644 --- /dev/null +++ b/tests/modules/programs/vivid/default.nix @@ -0,0 +1 @@ +{ vivid-example-config = ./example-config.nix; } diff --git a/tests/modules/programs/vivid/example-config.nix b/tests/modules/programs/vivid/example-config.nix new file mode 100644 index 000000000..e46f0ab21 --- /dev/null +++ b/tests/modules/programs/vivid/example-config.nix @@ -0,0 +1,45 @@ +{ + programs.vivid = { + enable = true; + colorMode = "8-bit"; + filetypes = { + text = { + special = [ + "CHANGELOG.md" + "CODE_OF_CONDUCT.md" + "CONTRIBUTING.md" + ]; + + todo = [ + "TODO.md" + "TODO.txt" + ]; + + licenses = [ + "LICENCE" + "COPYRIGHT" + ]; + }; + }; + + activeTheme = "mocha"; + themes = { + ayu = ./themes/ayu.yml; + mocha = ./themes/mocha.yml; + }; + }; + + nmt.script = '' + assertFileExists home-files/.config/vivid/filetypes.yml + assertFileContent home-files/.config/vivid/filetypes.yml \ + ${./filetypes.yml} + + assertFileExists home-files/.config/vivid/themes/ayu.yml + assertFileContent home-files/.config/vivid/themes/ayu.yml \ + ${./themes/ayu.yml} + + assertFileExists home-files/.config/vivid/themes/mocha.yml + assertFileContent home-files/.config/vivid/themes/mocha.yml \ + ${./themes/mocha.yml} + ''; +} diff --git a/tests/modules/programs/vivid/filetypes.yml b/tests/modules/programs/vivid/filetypes.yml new file mode 100644 index 000000000..01a570c05 --- /dev/null +++ b/tests/modules/programs/vivid/filetypes.yml @@ -0,0 +1,11 @@ +text: + licenses: + - LICENCE + - COPYRIGHT + special: + - CHANGELOG.md + - CODE_OF_CONDUCT.md + - CONTRIBUTING.md + todo: + - TODO.md + - TODO.txt diff --git a/tests/modules/programs/vivid/themes/ayu.yml b/tests/modules/programs/vivid/themes/ayu.yml new file mode 100644 index 000000000..382409ac2 --- /dev/null +++ b/tests/modules/programs/vivid/themes/ayu.yml @@ -0,0 +1,120 @@ +colors: + # Based on original "ayu" theme: + # https://github.com/ayu-theme/ayu-colors + background_color: 'fafafa' + black: '000' + apricot: 'ed9366' + green: '318866' + sienna: 'ed666a' + blue: '1b7dc4' + pink: 'f07171' + lime: '86b300' + + light_green: '9ae845' + + gray: '666666' + lightgray: 'aaa' + +core: + normal_text: {} + regular_file: {} + reset_to_normal: {} + + directory: + foreground: blue + + symlink: + foreground: pink + + multi_hard_link: {} + + fifo: + foreground: black + background: blue + + socket: + foreground: black + background: pink + + door: + foreground: black + background: pink + + block_device: + foreground: black + background: sienna + + character_device: + foreground: black + background: lime + + broken_symlink: + foreground: black + background: sienna + + missing_symlink_target: + foreground: black + background: sienna + + setuid: {} + + setgid: {} + + file_with_capability: {} + + sticky_other_writable: {} + + other_writable: {} + + sticky: {} + + executable_file: + foreground: sienna + font-style: bold + +text: + special: + foreground: black + background: apricot + + todo: + font-style: bold + + licenses: + foreground: gray + + configuration: + foreground: apricot + + other: + foreground: apricot + +markup: + foreground: apricot + +programming: + source: + foreground: green + + tooling: + foreground: light_green + + continuous-integration: + foreground: green + +media: + foreground: pink + +office: + foreground: sienna + +archives: + foreground: lime + font-style: underline + +executable: + foreground: sienna + font-style: bold + +unimportant: + foreground: lightgray diff --git a/tests/modules/programs/vivid/themes/mocha.yml b/tests/modules/programs/vivid/themes/mocha.yml new file mode 100644 index 000000000..1c460f636 --- /dev/null +++ b/tests/modules/programs/vivid/themes/mocha.yml @@ -0,0 +1,136 @@ +colors: + # Original "catppuccin" theme + # https://github.com/catppuccin/catppuccin + + rosewater: 'f5e0dc' + flamingo: 'f2cdcd' + pink: 'f5c2e7' + mauve: 'cba6f7' + red: 'f38ba8' + maroon: 'eba0ac' + peach: 'fab387' + yellow: 'f9e2af' + green: 'a6e3a1' + teal: '94e2d5' + sky: '89dceb' + sapphire: '74c7ec' + blue: '89b4fa' + lavender: 'b4befe' + + text: 'cdd6f4' + subtext1: 'bac2de' + subtext0: 'a6adc8' + overlay2: '9399b2' + overlay1: '7f849c' + overlay0: '6c7086' + surface2: '585b70' + surface1: '45475a' + surface0: '313244' + + base: '1e1e2e' + mantle: '181825' + crust: '11111b' + +core: + normal_text: {} + regular_file: {} + reset_to_normal: {} + + directory: + foreground: blue + + symlink: + foreground: pink + + multi_hard_link: {} + + fifo: + foreground: crust + background: blue + + socket: + foreground: crust + background: pink + + door: + foreground: crust + background: pink + + block_device: + foreground: sapphire + background: surface0 + + character_device: + foreground: pink + background: surface0 + + broken_symlink: + foreground: crust + background: red + + missing_symlink_target: + foreground: crust + background: red + + setuid: {} + + setgid: {} + + file_with_capability: {} + + sticky_other_writable: {} + + other_writable: {} + + sticky: {} + + executable_file: + foreground: red + font-style: bold + +text: + special: + foreground: base + background: yellow + + todo: + font-style: bold + + licenses: + foreground: overlay2 + + configuration: + foreground: yellow + + other: + foreground: yellow + +markup: + foreground: yellow + +programming: + source: + foreground: green + + tooling: + foreground: teal + + continuous-integration: + foreground: green + +media: + foreground: flamingo + +office: + foreground: red + +archives: + foreground: sapphire + font-style: underline + +executable: + foreground: red + font-style: bold + +unimportant: + foreground: surface2