diff --git a/.github/workflows/github_pages.yml b/.github/workflows/github_pages.yml index 238cb8436df5..32e670e8a607 100644 --- a/.github/workflows/github_pages.yml +++ b/.github/workflows/github_pages.yml @@ -22,7 +22,7 @@ jobs: nix-build -A docs.html cp -r result/share/doc/home-manager public - name: Deploy - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./public diff --git a/flake.lock b/flake.lock index f8efa105a5db..629407310339 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1711703276, - "narHash": "sha256-iMUFArF0WCatKK6RzfUJknjem0H9m4KgorO/p3Dopkk=", + "lastModified": 1712791164, + "narHash": "sha256-3sbWO1mbpWsLepZGbWaMovSO7ndZeFqDSdX0hZ9nVyw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d8fe5e6c92d0d190646fb9f1056741a229980089", + "rev": "1042fd8b148a9105f3c0aca3a6177fd1d9360ba5", "type": "github" }, "original": { diff --git a/modules/files.nix b/modules/files.nix index 50f6ca8124fd..59e9c25783c7 100644 --- a/modules/files.nix +++ b/modules/files.nix @@ -79,59 +79,14 @@ in (mapAttrsToList (n: v: v.target) (filterAttrs (n: v: v.force) cfg)); - check = pkgs.writeText "check" '' - ${config.lib.bash.initHomeManagerLib} - - # A symbolic link whose target path matches this pattern will be - # considered part of a Home Manager generation. - homeFilePattern="$(readlink -e ${escapeShellArg builtins.storeDir})/*-home-manager-files/*" - - forcedPaths=(${forcedPaths}) - - newGenFiles="$1" - shift - for sourcePath in "$@" ; do - relativePath="''${sourcePath#$newGenFiles/}" - targetPath="$HOME/$relativePath" + storeDir = escapeShellArg builtins.storeDir; - forced="" - for forcedPath in "''${forcedPaths[@]}"; do - if [[ $targetPath == $forcedPath* ]]; then - forced="yeah" - break - fi - done - - if [[ -n $forced ]]; then - verboseEcho "Skipping collision check for $targetPath" - elif [[ -e "$targetPath" \ - && ! "$(readlink "$targetPath")" == $homeFilePattern ]] ; then - # The target file already exists and it isn't a symlink owned by Home Manager. - if cmp -s "$sourcePath" "$targetPath"; then - # First compare the files' content. If they're equal, we're fine. - warnEcho "Existing file '$targetPath' is in the way of '$sourcePath', will be skipped since they are the same" - elif [[ ! -L "$targetPath" && -n "$HOME_MANAGER_BACKUP_EXT" ]] ; then - # Next, try to move the file to a backup location if configured and possible - backup="$targetPath.$HOME_MANAGER_BACKUP_EXT" - if [[ -e "$backup" ]]; then - errorEcho "Existing file '$backup' would be clobbered by backing up '$targetPath'" - collision=1 - else - warnEcho "Existing file '$targetPath' is in the way of '$sourcePath', will be moved to '$backup'" - fi - else - # Fail if nothing else works - errorEcho "Existing file '$targetPath' is in the way of '$sourcePath'" - collision=1 - fi - fi - done + check = pkgs.substituteAll { + src = ./files/check-link-targets.sh; - if [[ -v collision ]] ; then - errorEcho "Please move the above files and try again or use 'home-manager switch -b backup' to back up existing files automatically." - exit 1 - fi - ''; + inherit (config.lib.bash) initHomeManagerLib; + inherit forcedPaths storeDir; + }; in '' function checkNewGenCollision() { diff --git a/modules/files/check-link-targets.sh b/modules/files/check-link-targets.sh new file mode 100644 index 000000000000..c3200d336fb6 --- /dev/null +++ b/modules/files/check-link-targets.sh @@ -0,0 +1,53 @@ +# -*- mode: sh; sh-shell: bash -*- + +@initHomeManagerLib@ + +# A symbolic link whose target path matches this pattern will be +# considered part of a Home Manager generation. +homeFilePattern="$(readlink -e @storeDir@)/*-home-manager-files/*" + +forcedPaths=(@forcedPaths@) + +newGenFiles="$1" +shift +for sourcePath in "$@" ; do + relativePath="${sourcePath#$newGenFiles/}" + targetPath="$HOME/$relativePath" + + forced="" + for forcedPath in "${forcedPaths[@]}"; do + if [[ $targetPath == $forcedPath* ]]; then + forced="yeah" + break + fi + done + + if [[ -n $forced ]]; then + verboseEcho "Skipping collision check for $targetPath" + elif [[ -e "$targetPath" \ + && ! "$(readlink "$targetPath")" == $homeFilePattern ]] ; then + # The target file already exists and it isn't a symlink owned by Home Manager. + if cmp -s "$sourcePath" "$targetPath"; then + # First compare the files' content. If they're equal, we're fine. + warnEcho "Existing file '$targetPath' is in the way of '$sourcePath', will be skipped since they are the same" + elif [[ ! -L "$targetPath" && -n "$HOME_MANAGER_BACKUP_EXT" ]] ; then + # Next, try to move the file to a backup location if configured and possible + backup="$targetPath.$HOME_MANAGER_BACKUP_EXT" + if [[ -e "$backup" ]]; then + errorEcho "Existing file '$backup' would be clobbered by backing up '$targetPath'" + collision=1 + else + warnEcho "Existing file '$targetPath' is in the way of '$sourcePath', will be moved to '$backup'" + fi + else + # Fail if nothing else works + errorEcho "Existing file '$targetPath' is in the way of '$sourcePath'" + collision=1 + fi + fi +done + +if [[ -v collision ]] ; then + errorEcho "Please move the above files and try again or use 'home-manager switch -b backup' to back up existing files automatically." + exit 1 +fi diff --git a/modules/lib/maintainers.nix b/modules/lib/maintainers.nix index 174a7d363d4f..276d3dae2e00 100644 --- a/modules/lib/maintainers.nix +++ b/modules/lib/maintainers.nix @@ -77,6 +77,12 @@ githubId = 32838899; name = "Daniel Wagenknecht"; }; + jack5079 = { + name = "Jack W."; + email = "nix@jack.cab"; + github = "jack5079"; + githubId = 29169102; + }; jkarlson = { email = "jekarlson@gmail.com"; github = "jkarlson"; @@ -512,4 +518,10 @@ github = "zorrobert"; githubId = 118135271; }; + diniamo = { + name = "diniamo"; + email = "diniamo69@gmail.com"; + github = "diniamo"; + githubId = 55629891; + }; } diff --git a/modules/misc/news.nix b/modules/misc/news.nix index 70a943de3324..088bc6a58d92 100644 --- a/modules/misc/news.nix +++ b/modules/misc/news.nix @@ -1469,6 +1469,20 @@ in { A new module is available: 'services.activitywatch'. ''; } + + { + time = "2024-03-24T20:58:23+00:00"; + message = '' + A new module is available: 'programs.spotify-player'. + ''; + } + + { + time = "2024-04-08T21:43:38+00:00"; + message = '' + A new module is available: 'programs.bun'. + ''; + } ]; }; } diff --git a/modules/modules.nix b/modules/modules.nix index cd4abb722241..03ee241b87f3 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -72,6 +72,7 @@ let ./programs/broot.nix ./programs/browserpass.nix ./programs/btop.nix + ./programs/bun.nix ./programs/carapace.nix ./programs/cava.nix ./programs/chromium.nix @@ -209,6 +210,7 @@ let ./programs/sioyek.nix ./programs/skim.nix ./programs/sm64ex.nix + ./programs/spotify-player.nix ./programs/sqls.nix ./programs/ssh.nix ./programs/starship.nix diff --git a/modules/programs/bun.nix b/modules/programs/bun.nix new file mode 100644 index 000000000000..f186982e2761 --- /dev/null +++ b/modules/programs/bun.nix @@ -0,0 +1,59 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.programs.bun; + tomlFormat = pkgs.formats.toml { }; +in { + meta.maintainers = [ lib.hm.maintainers.jack5079 ]; + + options.programs.bun = { + enable = lib.mkEnableOption "Bun JavaScript runtime"; + + package = lib.mkPackageOption pkgs "bun" { }; + + settings = lib.mkOption { + type = tomlFormat.type; + default = { }; + example = lib.literalExpression '' + { + smol = true; + telemetry = false; + test = { + coverage = true; + coverageThreshold = 0.9; + }; + install.lockfile = { + print = "yarn"; + }; + } + ''; + description = '' + Configuration written to + {file}`$XDG_CONFIG_HOME/.bunfig.toml`. + + See + for the full list of options. + ''; + }; + + enableGitIntegration = lib.mkEnableOption "Git integration" // { + default = true; + }; + }; + + config = lib.mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile.".bunfig.toml" = lib.mkIf (cfg.settings != { }) { + source = tomlFormat.generate "bun-config" cfg.settings; + }; + + # https://bun.sh/docs/install/lockfile#how-do-i-git-diff-bun-s-lockfile + programs.git.attributes = + lib.mkIf cfg.enableGitIntegration [ "*.lockb binary diff=lockb" ]; + programs.git.extraConfig.diff.lockb = lib.mkIf cfg.enableGitIntegration { + textconv = lib.getExe cfg.package; + binary = true; + }; + }; +} diff --git a/modules/programs/firefox.nix b/modules/programs/firefox.nix index 8ce84fcba721..cbf78fb0404f 100644 --- a/modules/programs/firefox.nix +++ b/modules/programs/firefox.nix @@ -573,6 +573,17 @@ in { }; }; + containersForce = mkOption { + type = types.bool; + default = false; + description = '' + Whether to force replace the existing containers + configuration. This is recommended since Firefox will + replace the symlink on every launch, but note that you'll + lose any existing configuration by enabling this. + ''; + }; + containers = mkOption { type = types.attrsOf (types.submodule ({ name, ... }: { options = { @@ -762,6 +773,7 @@ in { "${profilesPath}/${profile.path}/containers.json" = mkIf (profile.containers != { }) { + force = profile.containersForce; text = mkContainersJson profile.containers; }; diff --git a/modules/programs/fish.nix b/modules/programs/fish.nix index 473d816007b8..fc11e512414f 100644 --- a/modules/programs/fish.nix +++ b/modules/programs/fish.nix @@ -459,14 +459,14 @@ in { ${cfg.shellInit} - status --is-login; and begin + status is-login; and begin # Login shell initialisation ${cfg.loginShellInit} end - status --is-interactive; and begin + status is-interactive; and begin # Abbreviations ${abbrsStr} diff --git a/modules/programs/foot.nix b/modules/programs/foot.nix index 79832dced7e0..52bab9383483 100644 --- a/modules/programs/foot.nix +++ b/modules/programs/foot.nix @@ -68,6 +68,7 @@ in { }; Service = { + Environment = "PATH=${makeBinPath [ cfg.package ]}"; ExecStart = "${cfg.package}/bin/foot --server"; Restart = "on-failure"; OOMPolicy = "continue"; diff --git a/modules/programs/fzf.nix b/modules/programs/fzf.nix index 062df18645ed..31df95de6305 100644 --- a/modules/programs/fzf.nix +++ b/modules/programs/fzf.nix @@ -10,6 +10,35 @@ let concatStringsSep "," (mapAttrsToList (name: value: "${name}:${value}") colors); + hasShellIntegrationEmbedded = lib.versionAtLeast cfg.package.version "0.48.0"; + + bashIntegration = if hasShellIntegrationEmbedded then '' + if [[ :$SHELLOPTS: =~ :(vi|emacs): ]]; then + eval "$(${getExe cfg.package} --bash)" + fi + '' else '' + if [[ :$SHELLOPTS: =~ :(vi|emacs): ]]; then + . ${cfg.package}/share/fzf/completion.bash + . ${cfg.package}/share/fzf/key-bindings.bash + fi + ''; + + zshIntegration = if hasShellIntegrationEmbedded then '' + if [[ $options[zle] = on ]]; then + eval "$(${getExe cfg.package} --zsh)" + fi + '' else '' + if [[ $options[zle] = on ]]; then + . ${cfg.package}/share/fzf/completion.zsh + . ${cfg.package}/share/fzf/key-bindings.zsh + fi + ''; + + fishIntegration = if hasShellIntegrationEmbedded then '' + ${getExe cfg.package} --fish | source + '' else '' + source ${cfg.package}/share/fzf/key-bindings.fish && fzf_key_bindings + ''; in { imports = [ (mkRemovedOptionModule [ "programs" "fzf" "historyWidgetCommand" ] @@ -173,26 +202,16 @@ in { # Note, since fzf unconditionally binds C-r we use `mkOrder` to make the # initialization show up a bit earlier. This is to make initialization of # other history managers, like mcfly or atuin, take precedence. - programs.bash.initExtra = mkIf cfg.enableBashIntegration (mkOrder 200 '' - if [[ :$SHELLOPTS: =~ :(vi|emacs): ]]; then - . ${cfg.package}/share/fzf/completion.bash - . ${cfg.package}/share/fzf/key-bindings.bash - fi - ''); + programs.bash.initExtra = + mkIf cfg.enableBashIntegration (mkOrder 200 bashIntegration); # Note, since fzf unconditionally binds C-r we use `mkOrder` to make the # initialization show up a bit earlier. This is to make initialization of # other history managers, like mcfly or atuin, take precedence. - programs.zsh.initExtra = mkIf cfg.enableZshIntegration (mkOrder 200 '' - if [[ $options[zle] = on ]]; then - . ${cfg.package}/share/fzf/completion.zsh - . ${cfg.package}/share/fzf/key-bindings.zsh - fi - ''); - - programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration - (mkOrder 200 '' - source ${cfg.package}/share/fzf/key-bindings.fish && fzf_key_bindings - ''); + programs.zsh.initExtra = + mkIf cfg.enableZshIntegration (mkOrder 200 zshIntegration); + + programs.fish.interactiveShellInit = + mkIf cfg.enableFishIntegration (mkOrder 200 fishIntegration); }; } diff --git a/modules/programs/k9s.nix b/modules/programs/k9s.nix index 900e129e1034..6ef53291adfd 100644 --- a/modules/programs/k9s.nix +++ b/modules/programs/k9s.nix @@ -6,6 +6,7 @@ let cfg = config.programs.k9s; yamlFormat = pkgs.formats.yaml { }; + inherit (pkgs.stdenv.hostPlatform) isDarwin; in { meta.maintainers = with maintainers; [ @@ -33,7 +34,8 @@ in { type = yamlFormat.type; default = { }; description = '' - Configuration written to {file}`$XDG_CONFIG_HOME/k9s/config.yaml`. See + Configuration written to {file}`$XDG_CONFIG_HOME/k9s/config.yaml` (linux) + or {file}`Library/Application Support/k9s/config.yaml` (darwin), See for supported values. ''; example = literalExpression '' @@ -47,7 +49,8 @@ in { type = types.attrsOf yamlFormat.type; default = { }; description = '' - Skin files written to {file}`$XDG_CONFIG_HOME/k9s/skins/`. See + Skin files written to {file}`$XDG_CONFIG_HOME/k9s/skins/` (linux) + or {file}`Library/Application Support/k9s/skins/` (darwin). See for supported values. ''; example = literalExpression '' @@ -65,7 +68,8 @@ in { type = yamlFormat.type; default = { }; description = '' - Aliases written to {file}`$XDG_CONFIG_HOME/k9s/aliases.yaml`. See + Aliases written to {file}`$XDG_CONFIG_HOME/k9s/aliases.yaml` (linux) + or {file}`Library/Application Support/k9s/aliases.yaml` (darwin). See for supported values. ''; example = literalExpression '' @@ -80,7 +84,8 @@ in { type = yamlFormat.type; default = { }; description = '' - Hotkeys written to {file}`$XDG_CONFIG_HOME/k9s/hotkey.yaml`. See + Hotkeys written to {file}`$XDG_CONFIG_HOME/k9s/hotkeys.yaml` (linux) + or {file}`Library/Application Support/k9s/hotkeys.yaml` (darwin). See for supported values. ''; example = literalExpression '' @@ -101,7 +106,8 @@ in { type = yamlFormat.type; default = { }; description = '' - Plugins written to {file}`$XDG_CONFIG_HOME/k9s/plugin.yaml`. See + Plugins written to {file}`$XDG_CONFIG_HOME/k9s/plugins.yaml (linux)` + or {file}`Library/Application Support/k9s/plugins.yaml` (darwin). See for supported values. ''; example = literalExpression '' @@ -132,7 +138,9 @@ in { type = yamlFormat.type; default = { }; description = '' - Resource column views written to {file}`$XDG_CONFIG_HOME/k9s/views.yaml`. + Resource column views written to + {file}`$XDG_CONFIG_HOME/k9s/views.yaml (linux)` + or {file}`Library/Application Support/k9s/views.yaml` (darwin). See for supported values. ''; example = literalExpression '' @@ -162,13 +170,19 @@ in { { }; skinFiles = mapAttrs' (name: value: - nameValuePair "k9s/skins/${name}.yaml" { - source = yamlFormat.generate "k9s-skin-${name}.yaml" value; - }) cfg.skins; + nameValuePair (if !(isDarwin && !config.xdg.enable) then + "k9s/skins/${name}.yaml" + else + "Library/Application Support/k9s/skins/${name}.yaml") { + source = yamlFormat.generate "k9s-skin-${name}.yaml" value; + }) cfg.skins; + + enableXdgConfig = !isDarwin || config.xdg.enable; + in mkIf cfg.enable { home.packages = [ cfg.package ]; - xdg.configFile = { + xdg.configFile = mkIf enableXdgConfig ({ "k9s/config.yaml" = mkIf (cfg.settings != { }) { source = yamlFormat.generate "k9s-config" (lib.recursiveUpdate skinSetting cfg.settings); @@ -178,17 +192,44 @@ in { source = yamlFormat.generate "k9s-aliases" cfg.aliases; }; - "k9s/hotkey.yaml" = mkIf (cfg.hotkey != { }) { + "k9s/hotkeys.yaml" = mkIf (cfg.hotkey != { }) { source = yamlFormat.generate "k9s-hotkey" cfg.hotkey; }; - "k9s/plugin.yaml" = mkIf (cfg.plugin != { }) { + "k9s/plugins.yaml" = mkIf (cfg.plugin != { }) { source = yamlFormat.generate "k9s-plugin" cfg.plugin; }; "k9s/views.yaml" = mkIf (cfg.views != { }) { source = yamlFormat.generate "k9s-views" cfg.views; }; - } // skinFiles; + } // skinFiles); + + home.file = mkIf (!enableXdgConfig) ({ + "Library/Application Support/k9s/config.yaml" = + mkIf (cfg.settings != { }) { + source = yamlFormat.generate "k9s-config" + (lib.recursiveUpdate skinSetting cfg.settings); + }; + + "Library/Application Support/k9s/aliases.yaml" = + mkIf (cfg.aliases != { }) { + source = yamlFormat.generate "k9s-aliases" cfg.aliases; + }; + + "Library/Application Support/k9s/hotkeys.yaml" = + mkIf (cfg.hotkey != { }) { + source = yamlFormat.generate "k9s-hotkey" cfg.hotkey; + }; + + "Library/Application Support/k9s/plugins.yaml" = + mkIf (cfg.plugin != { }) { + source = yamlFormat.generate "k9s-plugin" cfg.plugin; + }; + + "Library/Application Support/k9s/views.yaml" = mkIf (cfg.views != { }) { + source = yamlFormat.generate "k9s-views" cfg.views; + }; + } // skinFiles); }; } diff --git a/modules/programs/neovim.nix b/modules/programs/neovim.nix index a3b87ea24e1c..fad05c1c4936 100644 --- a/modules/programs/neovim.nix +++ b/modules/programs/neovim.nix @@ -198,6 +198,28 @@ in { ''; }; + extraWrapperArgs = mkOption { + type = with types; listOf str; + default = [ ]; + example = literalExpression '' + [ + "--suffix" + "LIBRARY_PATH" + ":" + "''${lib.makeLibraryPath [ pkgs.stdenv.cc.cc pkgs.zlib ]}" + "--suffix" + "PKG_CONFIG_PATH" + ":" + "''${lib.makeSearchPathOutput "dev" "lib/pkgconfig" [ pkgs.stdenv.cc.cc pkgs.zlib ]}" + ] + ''; + description = '' + Extra arguments to be passed to the neovim wrapper. + This option sets environment variables required for building and running binaries + with external package managers like mason.nvim. + ''; + }; + generatedConfigViml = mkOption { type = types.lines; visible = true; @@ -415,7 +437,8 @@ in { programs.neovim.finalPackage = pkgs.wrapNeovimUnstable cfg.package (neovimConfig // { - wrapperArgs = (lib.escapeShellArgs neovimConfig.wrapperArgs) + " " + wrapperArgs = (lib.escapeShellArgs + (neovimConfig.wrapperArgs ++ cfg.extraWrapperArgs)) + " " + extraMakeWrapperArgs + " " + extraMakeWrapperLuaCArgs + " " + extraMakeWrapperLuaArgs; wrapRc = false; diff --git a/modules/programs/nushell.nix b/modules/programs/nushell.nix index 5141997168c5..2ebd9554c929 100644 --- a/modules/programs/nushell.nix +++ b/modules/programs/nushell.nix @@ -6,7 +6,7 @@ let cfg = config.programs.nushell; - configDir = if pkgs.stdenv.isDarwin then + configDir = if pkgs.stdenv.isDarwin && !config.xdg.enable then "Library/Application Support/nushell" else "${config.xdg.configHome}/nushell"; diff --git a/modules/programs/rio.nix b/modules/programs/rio.nix index 58c4720de1b4..5a5ce6fa3e97 100644 --- a/modules/programs/rio.nix +++ b/modules/programs/rio.nix @@ -6,7 +6,7 @@ let in { options.programs.rio = { enable = lib.mkEnableOption null // { - description = lib.mdDoc '' + description = '' Enable Rio, a terminal built to run everywhere, as a native desktop applications by Rust/WebGPU or even in the browsers powered by WebAssembly/WebGPU. ''; diff --git a/modules/programs/spotify-player.nix b/modules/programs/spotify-player.nix new file mode 100644 index 000000000000..84aceca1a87a --- /dev/null +++ b/modules/programs/spotify-player.nix @@ -0,0 +1,150 @@ +{ config, lib, pkgs, ... }: +let + inherit (lib) + mkEnableOption mkPackageOption mkOption types literalExpression mkIf; + + cfg = config.programs.spotify-player; + tomlFormat = pkgs.formats.toml { }; +in { + meta.maintainers = with lib.hm.maintainers; [ diniamo ]; + + options.programs.spotify-player = { + enable = mkEnableOption "spotify-player"; + + package = mkPackageOption pkgs "spotify-player" { }; + + settings = mkOption { + type = tomlFormat.type; + default = { }; + example = literalExpression '' + { + theme = "default"; + playback_window_position = "Top"; + copy_command = { + command = "wl-copy"; + args = []; + }; + device = { + audio_cache = false; + normalization = false; + }; + } + ''; + description = '' + Configuration written to + {file}`$XDG_CONFIG_HOME/spotify-player/app.toml`. + + See + + for the full list of options. + ''; + }; + + themes = mkOption { + type = types.listOf tomlFormat.type; + default = [ ]; + example = literalExpression '' + [ + { + name = "default2"; + palette = { + black = "black"; + red = "red"; + green = "green"; + yellow = "yellow"; + blue = "blue"; + magenta = "magenta"; + cyan = "cyan"; + white = "white"; + bright_black = "bright_black"; + bright_red = "bright_red"; + bright_green = "bright_green"; + bright_yellow = "bright_yellow"; + bright_blue = "bright_blue"; + bright_magenta = "bright_magenta"; + bright_cyan = "bright_cyan"; + bright_white = "bright_white"; + }; + component_style = { + block_title = { fg = "Magenta"; }; + border = {}; + playback_track = { fg = "Cyan"; modifiers = ["Bold"]; }; + playback_artists = { fg = "Cyan"; modifiers = ["Bold"]; }; + playback_album = { fg = "Yellow"; }; + playback_metadata = { fg = "BrightBlack"; }; + playback_progress_bar = { bg = "BrightBlack"; fg = "Green"; }; + current_playing = { fg = "Green"; modifiers = ["Bold"]; }; + page_desc = { fg = "Cyan"; modifiers = ["Bold"]; }; + table_header = { fg = "Blue"; }; + selection = { modifiers = ["Bold" "Reversed"]; }; + }; + } + ] + ''; + description = '' + Configuration written to the `themes` field of + {file}`$XDG_CONFIG_HOME/spotify-player/theme.toml`. + + See + + for the full list of options. + ''; + }; + + keymaps = mkOption { + type = types.listOf tomlFormat.type; + default = [ ]; + example = literalExpression '' + [ + { + command = "NextTrack"; + key_sequence = "g n"; + } + { + command = "PreviousTrack"; + key_sequence = "g p"; + } + { + command = "Search"; + key_sequence = "C-c C-x /"; + } + { + command = "ResumePause"; + key_sequence = "M-enter"; + } + { + command = "None"; + key_sequence = "q"; + } + ] + ''; + description = '' + Configuration written to the `keymaps` field of + {file}`$XDG_CONFIG_HOME/spotify-player/keymap.toml`. + + See + + for the full list of options. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile = { + "spotify-player/app.toml" = mkIf (cfg.settings != { }) { + source = tomlFormat.generate "spotify-player-app" cfg.settings; + }; + "spotify-player/theme.toml" = mkIf (cfg.themes != [ ]) { + source = + tomlFormat.generate "spotify-player-theme" { inherit (cfg) themes; }; + }; + "spotify-player/keymap.toml" = mkIf (cfg.keymaps != [ ]) { + source = tomlFormat.generate "spotify-player-keymap" { + inherit (cfg) keymaps; + }; + }; + }; + }; +} diff --git a/modules/services/espanso.nix b/modules/services/espanso.nix index 404dfecd8582..a466b6f740a9 100644 --- a/modules/services/espanso.nix +++ b/modules/services/espanso.nix @@ -1,11 +1,9 @@ { pkgs, config, lib, ... }: let inherit (lib) - mkOption mkEnableOption mkIf maintainers literalExpression types platforms + mkOption mkEnableOption mkIf maintainers literalExpression types mkRemovedOptionModule versionAtLeast; - inherit (lib.hm.assertions) assertPlatform; - cfg = config.services.espanso; espansoVersion = cfg.package.version; @@ -99,15 +97,12 @@ in { }; config = mkIf cfg.enable { - assertions = [ - (assertPlatform "services.espanso" pkgs platforms.linux) - { - assertion = versionAtLeast espansoVersion "2"; - message = '' - The services.espanso module only supports Espanso version 2 or later. - ''; - } - ]; + assertions = [{ + assertion = versionAtLeast espansoVersion "2"; + message = '' + The services.espanso module only supports Espanso version 2 or later. + ''; + }]; home.packages = [ cfg.package ]; @@ -131,5 +126,20 @@ in { }; Install = { WantedBy = [ "default.target" ]; }; }; + + launchd.agents.espanso = { + enable = true; + config = { + ProgramArguments = [ "${cfg.package}/bin/espanso" "launcher" ]; + EnvironmentVariables.PATH = + "${cfg.package}/bin:/usr/bin:/bin:/usr/sbin:/sbin"; + KeepAlive = { + Crashed = true; + SuccessfulExit = false; + }; + ProcessType = "Background"; + RunAtLoad = true; + }; + }; }; } diff --git a/tests/default.nix b/tests/default.nix index 567b75d5a890..faa0ef121fb8 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -140,6 +140,7 @@ in import nmtSrc { ./modules/programs/sftpman ./modules/programs/sioyek ./modules/programs/sm64ex + ./modules/programs/spotify-player ./modules/programs/ssh ./modules/programs/starship ./modules/programs/taskwarrior @@ -163,6 +164,7 @@ in import nmtSrc { ./modules/xresources ] ++ lib.optionals isDarwin [ ./modules/launchd + ./modules/services/espanso-darwin ./modules/services/git-sync-darwin ./modules/services/imapnotify-darwin ./modules/services/nix-gc-darwin diff --git a/tests/modules/programs/carapace/nushell.nix b/tests/modules/programs/carapace/nushell.nix index a025da18c35d..d97fa8985850 100644 --- a/tests/modules/programs/carapace/nushell.nix +++ b/tests/modules/programs/carapace/nushell.nix @@ -1,4 +1,4 @@ -{ pkgs, ... }: +{ pkgs, config, ... }: { programs = { @@ -7,7 +7,7 @@ }; nmt.script = let - configDir = if pkgs.stdenv.isDarwin then + configDir = if pkgs.stdenv.isDarwin && !config.xdg.enable then "home-files/Library/Application Support/nushell" else "home-files/.config/nushell"; diff --git a/tests/modules/programs/direnv/nushell.nix b/tests/modules/programs/direnv/nushell.nix index 46f34ebd8a4c..6655f01a8c6d 100644 --- a/tests/modules/programs/direnv/nushell.nix +++ b/tests/modules/programs/direnv/nushell.nix @@ -1,4 +1,4 @@ -{ pkgs, ... }: +{ pkgs, config, ... }: { programs.nushell.enable = true; @@ -7,7 +7,7 @@ test.stubs.nushell = { }; nmt.script = let - configFile = if pkgs.stdenv.isDarwin then + configFile = if pkgs.stdenv.isDarwin && !config.xdg.enable then "home-files/Library/Application Support/nushell/config.nu" else "home-files/.config/nushell/config.nu"; diff --git a/tests/modules/programs/foot/systemd-user-service-expected.service b/tests/modules/programs/foot/systemd-user-service-expected.service index 517344e531d6..0c452b9df5cf 100644 --- a/tests/modules/programs/foot/systemd-user-service-expected.service +++ b/tests/modules/programs/foot/systemd-user-service-expected.service @@ -2,6 +2,7 @@ WantedBy=graphical-session.target [Service] +Environment=PATH=@foot@/bin ExecStart=@foot@/bin/foot --server OOMPolicy=continue Restart=on-failure diff --git a/tests/modules/programs/k9s/empty-settings.nix b/tests/modules/programs/k9s/empty-settings.nix index 5084be4fe065..355340054e90 100644 --- a/tests/modules/programs/k9s/empty-settings.nix +++ b/tests/modules/programs/k9s/empty-settings.nix @@ -1,11 +1,17 @@ -{ ... }: +{ pkgs, lib, ... }: { -{ programs.k9s.enable = true; + xdg.enable = lib.mkIf pkgs.stdenv.isDarwin (lib.mkForce false); + test.stubs.k9s = { }; - nmt.script = '' - assertPathNotExists home-files/.config/k9s + nmt.script = let + configDir = if !pkgs.stdenv.isDarwin then + ".config/k9s" + else + "Library/Application Support/k9s"; + in '' + assertPathNotExists home-files/${configDir} ''; } diff --git a/tests/modules/programs/k9s/example-settings.nix b/tests/modules/programs/k9s/example-settings.nix index 7816a050fd2a..23a42120b394 100644 --- a/tests/modules/programs/k9s/example-settings.nix +++ b/tests/modules/programs/k9s/example-settings.nix @@ -1,6 +1,8 @@ -{ config, ... }: +{ config, pkgs, lib, ... }: { + xdg.enable = lib.mkIf pkgs.stdenv.isDarwin (lib.mkForce false); + programs.k9s = { enable = true; package = config.lib.test.mkStubPackage { }; @@ -76,34 +78,39 @@ }; }; - nmt.script = '' - assertFileExists home-files/.config/k9s/config.yaml + nmt.script = let + configDir = if !pkgs.stdenv.isDarwin then + ".config/k9s" + else + "Library/Application Support/k9s"; + in '' + assertFileExists "home-files/${configDir}/config.yaml" assertFileContent \ - home-files/.config/k9s/config.yaml \ + "home-files/${configDir}/config.yaml" \ ${./example-config-expected.yaml} - assertFileExists home-files/.config/k9s/skins/default.yaml + assertFileExists "home-files/${configDir}/skins/default.yaml" assertFileContent \ - home-files/.config/k9s/skins/default.yaml \ + "home-files/${configDir}/skins/default.yaml" \ ${./example-skin-expected.yaml} - assertFileExists home-files/.config/k9s/skins/alt-skin.yaml + assertFileExists "home-files/${configDir}/skins/alt-skin.yaml" assertFileContent \ - home-files/.config/k9s/skins/alt-skin.yaml \ + "home-files/${configDir}/skins/alt-skin.yaml" \ ${./example-skin-expected-alt.yaml} - assertFileExists home-files/.config/k9s/hotkey.yaml + assertFileExists "home-files/${configDir}/hotkeys.yaml" assertFileContent \ - home-files/.config/k9s/hotkey.yaml \ + "home-files/${configDir}/hotkeys.yaml" \ ${./example-hotkey-expected.yaml} - assertFileExists home-files/.config/k9s/aliases.yaml + assertFileExists "home-files/${configDir}/aliases.yaml" assertFileContent \ - home-files/.config/k9s/aliases.yaml \ + "home-files/${configDir}/aliases.yaml" \ ${./example-aliases-expected.yaml} - assertFileExists home-files/.config/k9s/plugin.yaml + assertFileExists "home-files/${configDir}/plugins.yaml" assertFileContent \ - home-files/.config/k9s/plugin.yaml \ + "home-files/${configDir}/plugins.yaml" \ ${./example-plugin-expected.yaml} - assertFileExists home-files/.config/k9s/views.yaml + assertFileExists "home-files/${configDir}/views.yaml" assertFileContent \ - home-files/.config/k9s/views.yaml \ + "home-files/${configDir}/views.yaml" \ ${./example-views-expected.yaml} ''; } diff --git a/tests/modules/programs/neovim/runtime.nix b/tests/modules/programs/neovim/runtime.nix index b9d9638a8bf3..7f39c84616d5 100644 --- a/tests/modules/programs/neovim/runtime.nix +++ b/tests/modules/programs/neovim/runtime.nix @@ -20,6 +20,17 @@ with lib; }; } ]; + extraWrapperArgs = let buildDeps = with pkgs; [ stdenv.cc.cc zlib ]; + in [ + "--suffix" + "LIBRARY_PATH" + ":" + "${lib.makeLibraryPath buildDeps}" + "--suffix" + "PKG_CONFIG_PATH" + ":" + "${lib.makeSearchPathOutput "dev" "lib/pkgconfig" buildDeps}" + ]; } { extraPython3Packages = ps: with ps; [ jedi pynvim ]; @@ -33,7 +44,10 @@ with lib; nmt.script = '' ftplugin="home-files/.config/nvim/after/ftplugin/c.vim" + nvimbin="home-path/bin/nvim" assertFileExists "$ftplugin" + assertFileRegex "$nvimbin" 'LIBRARY_PATH' + assertFileRegex "$nvimbin" 'PKG_CONFIG_PATH' ''; }; } diff --git a/tests/modules/programs/nushell/example-settings.nix b/tests/modules/programs/nushell/example-settings.nix index 73038584b628..d870eb9db0ee 100644 --- a/tests/modules/programs/nushell/example-settings.nix +++ b/tests/modules/programs/nushell/example-settings.nix @@ -1,4 +1,4 @@ -{ pkgs, ... }: +{ pkgs, config, ... }: { programs.nushell = { @@ -34,7 +34,7 @@ test.stubs.nushell = { }; nmt.script = let - configDir = if pkgs.stdenv.isDarwin then + configDir = if pkgs.stdenv.isDarwin && !config.xdg.enable then "home-files/Library/Application Support/nushell" else "home-files/.config/nushell"; diff --git a/tests/modules/programs/oh-my-posh/nushell.nix b/tests/modules/programs/oh-my-posh/nushell.nix index ad77f821aa14..da4ffafd360b 100644 --- a/tests/modules/programs/oh-my-posh/nushell.nix +++ b/tests/modules/programs/oh-my-posh/nushell.nix @@ -1,4 +1,4 @@ -{ pkgs, ... }: +{ pkgs, config, ... }: { programs = { @@ -16,12 +16,12 @@ }; nmt.script = let - configFile = if pkgs.stdenv.isDarwin then + configFile = if pkgs.stdenv.isDarwin && !config.xdg.enable then "home-files/Library/Application Support/nushell/config.nu" else "home-files/.config/nushell/config.nu"; - envFile = if pkgs.stdenv.isDarwin then + envFile = if pkgs.stdenv.isDarwin && !config.xdg.enable then "home-files/Library/Application Support/nushell/env.nu" else "home-files/.config/nushell/env.nu"; diff --git a/tests/modules/programs/spotify-player/app.toml b/tests/modules/programs/spotify-player/app.toml new file mode 100644 index 000000000000..408e84b0dd24 --- /dev/null +++ b/tests/modules/programs/spotify-player/app.toml @@ -0,0 +1,9 @@ +playback_window_position = "Top" +theme = "default" +[copy_command] +args = [] +command = "wl-copy" + +[device] +audio_cache = false +normalization = false diff --git a/tests/modules/programs/spotify-player/default.nix b/tests/modules/programs/spotify-player/default.nix new file mode 100644 index 000000000000..9812b12812e2 --- /dev/null +++ b/tests/modules/programs/spotify-player/default.nix @@ -0,0 +1 @@ +{ spotify-player-settings = ./settings.nix; } diff --git a/tests/modules/programs/spotify-player/keymap.toml b/tests/modules/programs/spotify-player/keymap.toml new file mode 100644 index 000000000000..d11c86e41fc6 --- /dev/null +++ b/tests/modules/programs/spotify-player/keymap.toml @@ -0,0 +1,19 @@ +[[keymaps]] +command = "NextTrack" +key_sequence = "g n" + +[[keymaps]] +command = "PreviousTrack" +key_sequence = "g p" + +[[keymaps]] +command = "Search" +key_sequence = "C-c C-x /" + +[[keymaps]] +command = "ResumePause" +key_sequence = "M-enter" + +[[keymaps]] +command = "None" +key_sequence = "q" diff --git a/tests/modules/programs/spotify-player/settings.nix b/tests/modules/programs/spotify-player/settings.nix new file mode 100644 index 000000000000..dc7fe8c6af1b --- /dev/null +++ b/tests/modules/programs/spotify-player/settings.nix @@ -0,0 +1,103 @@ +{ + programs.spotify-player = { + enable = true; + + settings = { + theme = "default"; + playback_window_position = "Top"; + copy_command = { + command = "wl-copy"; + args = [ ]; + }; + device = { + audio_cache = false; + normalization = false; + }; + }; + + themes = [{ + name = "default2"; + palette = { + black = "black"; + red = "red"; + green = "green"; + yellow = "yellow"; + blue = "blue"; + magenta = "magenta"; + cyan = "cyan"; + white = "white"; + bright_black = "bright_black"; + bright_red = "bright_red"; + bright_green = "bright_green"; + bright_yellow = "bright_yellow"; + bright_blue = "bright_blue"; + bright_magenta = "bright_magenta"; + bright_cyan = "bright_cyan"; + bright_white = "bright_white"; + }; + component_style = { + block_title = { fg = "Magenta"; }; + border = { }; + playback_track = { + fg = "Cyan"; + modifiers = [ "Bold" ]; + }; + playback_artists = { + fg = "Cyan"; + modifiers = [ "Bold" ]; + }; + playback_album = { fg = "Yellow"; }; + playback_metadata = { fg = "BrightBlack"; }; + playback_progress_bar = { + bg = "BrightBlack"; + fg = "Green"; + }; + current_playing = { + fg = "Green"; + modifiers = [ "Bold" ]; + }; + page_desc = { + fg = "Cyan"; + modifiers = [ "Bold" ]; + }; + table_header = { fg = "Blue"; }; + selection = { modifiers = [ "Bold" "Reversed" ]; }; + }; + }]; + + keymaps = [ + { + command = "NextTrack"; + key_sequence = "g n"; + } + { + command = "PreviousTrack"; + key_sequence = "g p"; + } + { + command = "Search"; + key_sequence = "C-c C-x /"; + } + { + command = "ResumePause"; + key_sequence = "M-enter"; + } + { + command = "None"; + key_sequence = "q"; + } + ]; + }; + + test.stubs.spotify-player = { }; + + nmt.script = '' + assertFileContent home-files/.config/spotify-player/app.toml ${./app.toml} + assertFileContent home-files/.config/spotify-player/theme.toml ${ + ./theme.toml + } + assertFileContent home-files/.config/spotify-player/keymap.toml ${ + ./keymap.toml + } + ''; +} diff --git a/tests/modules/programs/spotify-player/theme.toml b/tests/modules/programs/spotify-player/theme.toml new file mode 100644 index 000000000000..cb5fa99d49ee --- /dev/null +++ b/tests/modules/programs/spotify-player/theme.toml @@ -0,0 +1,58 @@ +[[themes]] +name = "default2" + +[themes.component_style] +[themes.component_style.block_title] +fg = "Magenta" + +[themes.component_style.border] + +[themes.component_style.current_playing] +fg = "Green" +modifiers = ["Bold"] + +[themes.component_style.page_desc] +fg = "Cyan" +modifiers = ["Bold"] + +[themes.component_style.playback_album] +fg = "Yellow" + +[themes.component_style.playback_artists] +fg = "Cyan" +modifiers = ["Bold"] + +[themes.component_style.playback_metadata] +fg = "BrightBlack" + +[themes.component_style.playback_progress_bar] +bg = "BrightBlack" +fg = "Green" + +[themes.component_style.playback_track] +fg = "Cyan" +modifiers = ["Bold"] + +[themes.component_style.selection] +modifiers = ["Bold", "Reversed"] + +[themes.component_style.table_header] +fg = "Blue" + +[themes.palette] +black = "black" +blue = "blue" +bright_black = "bright_black" +bright_blue = "bright_blue" +bright_cyan = "bright_cyan" +bright_green = "bright_green" +bright_magenta = "bright_magenta" +bright_red = "bright_red" +bright_white = "bright_white" +bright_yellow = "bright_yellow" +cyan = "cyan" +green = "green" +magenta = "magenta" +red = "red" +white = "white" +yellow = "yellow" diff --git a/tests/modules/programs/yazi/nushell-integration-enabled.nix b/tests/modules/programs/yazi/nushell-integration-enabled.nix index ddd041dc043b..9adbaa982899 100644 --- a/tests/modules/programs/yazi/nushell-integration-enabled.nix +++ b/tests/modules/programs/yazi/nushell-integration-enabled.nix @@ -1,4 +1,4 @@ -{ pkgs, ... }: +{ pkgs, config, ... }: let shellIntegration = '' @@ -23,7 +23,7 @@ in { test.stubs.yazi = { }; nmt.script = let - configPath = if pkgs.stdenv.isDarwin then + configPath = if pkgs.stdenv.isDarwin && !config.xdg.enable then "home-files/Library/Application Support/nushell/config.nu" else "home-files/.config/nushell/config.nu"; diff --git a/tests/modules/services/espanso-darwin/basic-configuration.nix b/tests/modules/services/espanso-darwin/basic-configuration.nix new file mode 100644 index 000000000000..4a2f2ee778de --- /dev/null +++ b/tests/modules/services/espanso-darwin/basic-configuration.nix @@ -0,0 +1,55 @@ +{ ... }: { + services.espanso = { + enable = true; + configs = { default = { show_notifications = false; }; }; + matches = { + base = { + matches = [ + { + trigger = ":now"; + replace = "It's {{currentdate}} {{currenttime}}"; + } + { + trigger = ":hello"; + replace = '' + line1 + line2''; + } + { + regex = ":hi(?P.*)\\."; + replace = "Hi {{person}}!"; + } + ]; + global_vars = [ + { + name = "currentdate"; + type = "date"; + params = { format = "%d/%m/%Y"; }; + } + { + name = "currenttime"; + type = "date"; + params = { format = "%R"; }; + } + ]; + }; + }; + }; + + test.stubs.espanso = { }; + + nmt.script = '' + serviceFile="LaunchAgents/org.nix-community.home.espanso.plist" + serviceFileNormalized="$(normalizeStorePaths "$serviceFile")" + assertFileExists $serviceFile + assertFileContent $serviceFileNormalized ${./launchd.plist} + + configFile=home-files/.config/espanso/config/default.yml + assertFileExists "$configFile" + assertFileContent "$configFile" ${../espanso/basic-configuration.yaml} + + matchFile=home-files/.config/espanso/match/base.yml + assertFileExists "$matchFile" + assertFileContent "$matchFile" ${../espanso/basic-matches.yaml} + ''; +} diff --git a/tests/modules/services/espanso-darwin/default.nix b/tests/modules/services/espanso-darwin/default.nix new file mode 100644 index 000000000000..6acb2f8d469c --- /dev/null +++ b/tests/modules/services/espanso-darwin/default.nix @@ -0,0 +1 @@ +{ espanso-darwin-basic-configuration = ./basic-configuration.nix; } diff --git a/tests/modules/services/espanso-darwin/launchd.plist b/tests/modules/services/espanso-darwin/launchd.plist new file mode 100644 index 000000000000..8cbc4af032f9 --- /dev/null +++ b/tests/modules/services/espanso-darwin/launchd.plist @@ -0,0 +1,29 @@ + + + + + EnvironmentVariables + + PATH + @espanso@/bin:/usr/bin:/bin:/usr/sbin:/sbin + + KeepAlive + + Crashed + + SuccessfulExit + + + Label + org.nix-community.home.espanso + ProcessType + Background + ProgramArguments + + @espanso@/bin/espanso + launcher + + RunAtLoad + + + \ No newline at end of file