diff --git a/.editorconfig b/.editorconfig index a41f0862b..c036a7541 100644 --- a/.editorconfig +++ b/.editorconfig @@ -19,3 +19,6 @@ indent_style = tab [*.md] trim_trailing_whitespace = false + +[*.plist] +insert_final_newline = false diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 6ba7256db..2aea2da27 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,14 +8,6 @@ updates: commit-message: prefix: "ci:" - - package-ecosystem: "github-actions" - directory: "/" - target-branch: "release-23.11" - schedule: - interval: "weekly" - commit-message: - prefix: "ci:" - - package-ecosystem: "github-actions" directory: "/" target-branch: "release-24.05" diff --git a/.github/workflows/github_pages.yml b/.github/workflows/github_pages.yml index 9f49d49a8..4e10f9ccb 100644 --- a/.github/workflows/github_pages.yml +++ b/.github/workflows/github_pages.yml @@ -11,7 +11,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v27 + - uses: cachix/install-nix-action@v30 with: nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@v15 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 05d04163b..ff67b6760 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,7 +12,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v27 + - uses: cachix/install-nix-action@v30 with: nix_path: nixpkgs=channel:nixos-unstable - run: | @@ -25,3 +25,5 @@ jobs: - run: nix-shell --show-trace . -A install - run: yes | home-manager -I home-manager=. uninstall - run: nix-shell --show-trace --arg enableBig false --pure tests -A run.all + # Somebody please help us fix the macos tests. + if: matrix.os != 'macos-latest' diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index 8ba9264d3..9b0e4b443 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -12,9 +12,9 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Install Nix - uses: cachix/install-nix-action@v27 + uses: cachix/install-nix-action@v30 - name: Update flake.lock - uses: DeterminateSystems/update-flake-lock@v23 + uses: DeterminateSystems/update-flake-lock@v24 with: token: ${{ secrets.GH_TOKEN_FOR_UPDATES }} pr-labels: dependencies diff --git a/docs/default.nix b/docs/default.nix index 21f00fb48..dd79c4590 100644 --- a/docs/default.nix +++ b/docs/default.nix @@ -147,7 +147,7 @@ in { substitute \ ${hmOptionsDocs.optionsJSON}/nix-support/hydra-build-products \ $out/nix-support/hydra-build-products \ - --replace \ + --replace-fail \ '${hmOptionsDocs.optionsJSON}/share/doc/nixos' \ "$out/share/doc/home-manager" ''; diff --git a/docs/home-manager-manual.nix b/docs/home-manager-manual.nix index 23b2d1e65..f87803962 100644 --- a/docs/home-manager-manual.nix +++ b/docs/home-manager-manual.nix @@ -59,5 +59,7 @@ in stdenv.mkDerivation { echo "doc manual $dest index.html" >> $out/nix-support/hydra-build-products ''; + passthru = { inherit home-manager-options; }; + meta = { maintainers = [ lib.maintainers.considerate ]; }; } diff --git a/docs/manual/usage.md b/docs/manual/usage.md index 2a569aaf9..88e884546 100644 --- a/docs/manual/usage.md +++ b/docs/manual/usage.md @@ -59,5 +59,6 @@ usage/configuration.md usage/rollbacks.md usage/dotfiles.md usage/graphical.md +usage/gpu-non-nixos.md usage/updating.md ``` diff --git a/docs/manual/usage/gpu-non-nixos.md b/docs/manual/usage/gpu-non-nixos.md new file mode 100644 index 000000000..0aefa4ae3 --- /dev/null +++ b/docs/manual/usage/gpu-non-nixos.md @@ -0,0 +1,81 @@ +# GPU on non-NixOS systems {#sec-usage-gpu-non-nixos} + +To access the GPU, programs need access to OpenGL and Vulkan libraries. While +this works transparently on NixOS, it does not on other Linux systems. A +solution is provided by [NixGL](https://github.com/nix-community/nixGL), which +can be integrated into Home Manager. + +To enable the integration, import NixGL into your home configuration, either as +a channel, or as a flake input passed via `extraSpecialArgs`. Then, set the +`nixGL.packages` option to the package set provided by NixGL. + +Once integration is enabled, it can be used in two ways: as Nix functions for +wrapping programs installed via Home Manager, and as shell commands for running +programs installed by other means (such as `nix shell`). In either case, there +are several wrappers available. They can be broadly categorized + +- by vendor: as Mesa (for Free drivers of all vendors) and Nvidia (for + Nvidia-specific proprietary drivers). +- by GPU selection: as primary and secondary (offloading). + +For example, the `mesa` wrapper provides support for running programs on the +primary GPU for Intel, AMD and Nouveau drivers, while the `mesaPrime` wrapper +does the same for the secondary GPU. + +**Note:** when using Nvidia wrappers together with flakes, your home +configuration will not be pure and needs to be built using `home-manager switch +--impure`. Otherwise, the build will fail, complaining about missing attribute +`currentTime`. + +Wrapper functions are available under `config.lib.nixGL.wrappers`. However, it +can be more convenient to use the `config.lib.nixGL.wrap` alias, which can be +configured to use any of the wrappers. It is intended to provide a customization +point when the same home configuration is used across several machines with +different hardware. There is also the `config.lib.nixGL.wrapOffload` alias for +two-GPU systems. + +Another convenience is that all wrapper functions are always available. However, +when `nixGL.packages` option is unset, they are no-ops. This allows them to be +used even when the home configuration is used on NixOS machines. The exception +is the `prime-offload` script which ignores `nixGL.packages` and is installed +into the environment whenever `nixGL.prime.installScript` is set. This script, +which can be used to start a program on a secondary GPU, does not depend on +NixGL and is useful on NixOS systems as well. + +Below is an abbreviated example for an Optimus laptop that makes use of both +Mesa and Nvidia wrappers, where the latter is used in dGPU offloading mode. It +demonstrates how to wrap `mpv` to run on the integrated Intel GPU, wrap FreeCAD +to run on the Nvidia dGPU, and how to install the wrapper scripts. It also wraps +Xonotic to run on the dGPU, but uses the wrapper function directly for +demonstration purposes. + +```nix +{ config, lib, pkgs, nixgl, ... }: +{ + nixGL.packages = nixgl.packages; + nixGL.defaultWrapper = "mesa"; + nixGL.offloadWrapper = "nvidiaPrime"; + nixGL.installScripts = [ "mesa" "nvidiaPrime" ]; + + programs.mpv = { + enable = true; + package = config.lib.nixGL.wrap pkgs.mpv; + }; + + home.packages = [ + (config.lib.nixGL.wrapOffload pkgs.freecad) + (config.lib.nixGL.wrappers.nvidiaPrime pkgs.xonotic) + ]; +} +``` + +The above example assumes a flake-based setup where `nixgl` was passed from the +flake. When using channels, the example would instead begin with + +```nix +{ config, lib, pkgs, ... }: +{ + nixGL.packages = import { inherit pkgs; }; + # The rest is the same as above + ... +``` diff --git a/docs/release-notes/rl-2411.md b/docs/release-notes/rl-2411.md index 85eae034f..626624640 100644 --- a/docs/release-notes/rl-2411.md +++ b/docs/release-notes/rl-2411.md @@ -7,7 +7,21 @@ is therefore not final. This release has the following notable changes: -- No changes. +- The swayidle module behavior has changed. Specifically, swayidle was + previously always called with a `-w` flag. This flag is now moved to + the default + [services.swayidle.extraArgs](#opt-services.swayidle.extraArgs) + value to make it optional. + + Your configuration may break if you already set this option and also + rely on the flag being automatically added. To resolve this, please + add `-w` to your assignment of + [services.swayidle.extraArgs](#opt-services.swayidle.extraArgs). + +- Support for Boolean values in the option + [programs.eza.icons](#opt-programs.eza.icons) is deprecated for + future removal. The new value for `true` is `"auto"`, and for + `false` it is `null`. ## State Version Changes {#sec-release-24.11-state-version-changes} diff --git a/flake.lock b/flake.lock index 4f6c687e9..b03cf135b 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1723175592, - "narHash": "sha256-M0xJ3FbDUc4fRZ84dPGx5VvgFsOzds77KiBMW/mMTnI=", + "lastModified": 1729880355, + "narHash": "sha256-RP+OQ6koQQLX5nw0NmcDrzvGL8HDLnyXt/jHhL1jwjM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5e0ca22929f3342b19569b21b2f3462f053e497b", + "rev": "18536bf04cd71abd345f9579158841376fdd0c5a", "type": "github" }, "original": { diff --git a/home-manager/default.nix b/home-manager/default.nix index 5e0e1e462..50fda77e5 100644 --- a/home-manager/default.nix +++ b/home-manager/default.nix @@ -1,5 +1,5 @@ { runCommand, lib, bash, callPackage, coreutils, findutils, gettext, gnused, jq -, less, ncurses, unixtools +, less, ncurses, inetutils # used for pkgs.path for nixos-option , pkgs @@ -38,7 +38,7 @@ in runCommand "home-manager" { less ncurses nixos-option - unixtools.hostname + inetutils # for `hostname` ] }" \ --subst-var-by HOME_MANAGER_LIB '${../lib/bash/home-manager.sh}' \ diff --git a/home-manager/home-manager b/home-manager/home-manager index ab4de5387..5bf796b47 100644 --- a/home-manager/home-manager +++ b/home-manager/home-manager @@ -198,19 +198,9 @@ function setFlakeAttribute() { ;; *) local name="$USER" - - local hostnameArray=() - # FQDN lookup can fail depending on the resolver. - local fqdn - fqdn="$(hostname -f 2> /dev/null)" - if [[ $? -eq 0 ]]; then - hostnameArray+=( "$USER@$fqdn" ) - fi # Check FQDN, long, and short hostnames; long first to preserve # pre-existing behaviour in case both happen to be defined. - hostnameArray+=( "$USER@$(hostname)" "$USER@$(hostname -s)" ) - - for n in "${hostnameArray[@]}"; do + for n in "$USER@$(hostname -f)" "$USER@$(hostname)" "$USER@$(hostname -s)"; do if [[ "$(nix eval "$flake#homeConfigurations" --apply "x: x ? \"$n\"")" == "true" ]]; then name="$n" if [[ -v VERBOSE ]]; then diff --git a/home-manager/po/hi.po b/home-manager/po/hi.po new file mode 100644 index 000000000..3921eff11 --- /dev/null +++ b/home-manager/po/hi.po @@ -0,0 +1,220 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2024-04-17 23:19+0200\n" +"PO-Revision-Date: 2024-10-09 14:31+0000\n" +"Last-Translator: Utkarsh Sharma \n" +"Language-Team: Hindi \n" +"Language: hi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 5.8-dev\n" + +#. translators: For example: "home-manager: missing argument for --cores" +#: home-manager/home-manager:16 +msgid "%s: missing argument for %s" +msgstr "%s: ‌%s के लिए कोई आर्ग्यूमेंट नहीं दिया" + +#: home-manager/home-manager:64 +msgid "No configuration file found at %s" +msgstr "%s में कोई कन्फि़गरेशन फाइल नहीं मिली" + +#. translators: The first '%s' specifier will be replaced by either +#. 'home.nix' or 'flake.nix'. +#: home-manager/home-manager:81 home-manager/home-manager:85 +#: home-manager/home-manager:184 +msgid "" +"Keeping your Home Manager %s in %s is deprecated,\n" +"please move it to %s" +msgstr "" +"अपने Home Manager %s को %s में रखना अप्रचलित है,\n" +"कृपया इसे %s में स्थानांतरित करें" + +#: home-manager/home-manager:92 +msgid "No configuration file found. Please create one at %s" +msgstr "कोई कॉन्फ़िगरेशन फ़ाइल नहीं मिली। कृपया %s पर एक फ़ाइल बनाएं।" + +#: home-manager/home-manager:107 +msgid "Home Manager not found at %s." +msgstr "%s पर Home Manager नहीं मिला।" + +#. translators: This message will be seen by very few users that likely are familiar with English. So feel free to leave this untranslated. +#: home-manager/home-manager:115 +msgid "" +"The fallback Home Manager path %s has been deprecated and a file/directory " +"was found there." +msgstr "" + +#. translators: This message will be seen by very few users that likely are familiar with English. So feel free to leave this untranslated. +#: home-manager/home-manager:118 +msgid "" +"To remove this warning, do one of the following.\n" +"\n" +"1. Explicitly tell Home Manager to use the path, for example by adding\n" +"\n" +" { programs.home-manager.path = \"%s\"; }\n" +"\n" +" to your configuration.\n" +"\n" +" If you import Home Manager directly, you can use the `path` parameter\n" +"\n" +" pkgs.callPackage /path/to/home-manager-package { path = \"%s\"; }\n" +"\n" +" when calling the Home Manager package.\n" +"\n" +"2. Remove the deprecated path.\n" +"\n" +" $ rm -r \"%s\"" +msgstr "" + +#: home-manager/home-manager:146 +msgid "Sanity checking Nix" +msgstr "" + +#: home-manager/home-manager:166 +msgid "Could not find suitable profile directory, tried %s and %s" +msgstr "" + +#. translators: Here "flake" is a noun that refers to the Nix Flakes feature. +#: home-manager/home-manager:221 +msgid "Can't inspect options of a flake configuration" +msgstr "" + +#: home-manager/home-manager:296 home-manager/home-manager:319 +#: home-manager/home-manager:1051 +msgid "%s: unknown option '%s'" +msgstr "" + +#: home-manager/home-manager:301 home-manager/home-manager:1052 +msgid "Run '%s --help' for usage help" +msgstr "" + +#: home-manager/home-manager:327 home-manager/home-manager:431 +msgid "The file %s already exists, leaving it unchanged..." +msgstr "" + +#: home-manager/home-manager:329 home-manager/home-manager:433 +msgid "Creating %s..." +msgstr "" + +#: home-manager/home-manager:475 +msgid "Creating initial Home Manager generation..." +msgstr "" + +#. translators: The "%s" specifier will be replaced by a file path. +#: home-manager/home-manager:480 +msgid "" +"All done! The home-manager tool should now be installed and you can edit\n" +"\n" +" %s\n" +"\n" +"to configure Home Manager. Run 'man home-configuration.nix' to\n" +"see all available options." +msgstr "" + +#. translators: The "%s" specifier will be replaced by a URL. +#: home-manager/home-manager:485 +msgid "" +"Uh oh, the installation failed! Please create an issue at\n" +"\n" +" %s\n" +"\n" +"if the error seems to be the fault of Home Manager." +msgstr "" + +#. translators: Here "flake" is a noun that refers to the Nix Flakes feature. +#: home-manager/home-manager:496 +msgid "Can't instantiate a flake configuration" +msgstr "" + +#: home-manager/home-manager:572 +msgid "" +"There is %d unread and relevant news item.\n" +"Read it by running the command \"%s news\"." +msgid_plural "" +"There are %d unread and relevant news items.\n" +"Read them by running the command \"%s news\"." +msgstr[0] "" +msgstr[1] "" + +#: home-manager/home-manager:586 +msgid "Unknown \"news.display\" setting \"%s\"." +msgstr "" + +#: home-manager/home-manager:594 +#, sh-format +msgid "Please set the $EDITOR or $VISUAL environment variable" +msgstr "" + +#: home-manager/home-manager:612 +msgid "Cannot run build in read-only directory" +msgstr "" + +#: home-manager/home-manager:693 +msgid "No generation with ID %s" +msgstr "" + +#: home-manager/home-manager:695 +msgid "Cannot remove the current generation %s" +msgstr "" + +#: home-manager/home-manager:697 +msgid "Removing generation %s" +msgstr "" + +#: home-manager/home-manager:718 +msgid "No generations to expire" +msgstr "" + +#: home-manager/home-manager:729 +msgid "No home-manager packages seem to be installed." +msgstr "" + +#: home-manager/home-manager:811 +msgid "Unknown argument %s" +msgstr "" + +#: home-manager/home-manager:835 +msgid "This will remove Home Manager from your system." +msgstr "" + +#: home-manager/home-manager:838 +msgid "This is a dry run, nothing will actually be uninstalled." +msgstr "" + +#: home-manager/home-manager:842 +msgid "Really uninstall Home Manager?" +msgstr "" + +#: home-manager/home-manager:848 +msgid "Switching to empty Home Manager configuration..." +msgstr "" + +#: home-manager/home-manager:863 +msgid "Yay!" +msgstr "" + +#: home-manager/home-manager:868 +msgid "Home Manager is uninstalled but your home.nix is left untouched." +msgstr "" + +#: home-manager/home-manager:1091 +msgid "expire-generations expects one argument, got %d." +msgstr "" + +#: home-manager/home-manager:1113 +msgid "Unknown command: %s" +msgstr "" + +#: home-manager/install.nix:18 +msgid "This derivation is not buildable, please run it using nix-shell." +msgstr "" diff --git a/home-manager/po/hu.po b/home-manager/po/hu.po index a127cf1b0..3cfab2551 100644 --- a/home-manager/po/hu.po +++ b/home-manager/po/hu.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: Home Manager\n" "Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" "POT-Creation-Date: 2024-04-17 23:19+0200\n" -"PO-Revision-Date: 2024-07-05 14:09+0000\n" +"PO-Revision-Date: 2024-09-02 17:09+0000\n" "Last-Translator: Ferenci Ákos \n" "Language-Team: Hungarian \n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.7-dev\n" +"X-Generator: Weblate 5.8-dev\n" #. translators: For example: "home-manager: missing argument for --cores" #: home-manager/home-manager:16 @@ -54,6 +54,8 @@ msgid "" "The fallback Home Manager path %s has been deprecated and a file/directory " "was found there." msgstr "" +"A tartalék Home Manager fájlútvonal %s elavult és fájl/könyvtár található " +"itt." #. translators: This message will be seen by very few users that likely are familiar with English. So feel free to leave this untranslated. #: home-manager/home-manager:118 @@ -76,19 +78,37 @@ msgid "" "\n" " $ rm -r \"%s\"" msgstr "" +"A felmerült hiba elhárítására a következőket tegye:\n" +"\n" +"1. Közvetlen adja át a Home Manager-nek a fájlútvonalat, pl.:\n" +"\n" +" { programs.home-manager.path = \"%s\"; }\n" +"\n" +" sor konfigurációhoz való hozzáadásával.\n" +"\n" +" Amennyiben a Home Manager-t közvetlen importolja, használhatja a 'path' " +"paramétert\n" +"\n" +" pkgs.callPackage/path/tohome-manager-package{path = \"%s\"; }\n" +" a Home Manager csomag meghívásakor.\n" +"\n" +" 2. Távolítsa el az elavult fájlútvonalat.\n" +"\n" +" $ rm -r \"$s\"" #: home-manager/home-manager:146 msgid "Sanity checking Nix" -msgstr "" +msgstr "Nix épségének ellenőrzése" #: home-manager/home-manager:166 msgid "Could not find suitable profile directory, tried %s and %s" msgstr "" +"Nem található megfelelő profil mappa, %s és %s útvonalak lettek kipróbálva." #. translators: Here "flake" is a noun that refers to the Nix Flakes feature. #: home-manager/home-manager:221 msgid "Can't inspect options of a flake configuration" -msgstr "" +msgstr "Nem lehet a flake konfiguráció beállításait megtekinteni." #: home-manager/home-manager:296 home-manager/home-manager:319 #: home-manager/home-manager:1051 @@ -121,6 +141,13 @@ msgid "" "to configure Home Manager. Run 'man home-configuration.nix' to\n" "see all available options." msgstr "" +"Elkészült! A home-manager eszköz most már installálva van és a \n" +"\n" +" %s\n" +"\n" +"fájl szerkesztésével konfigurálhatja a Home Manager-t. \n" +"Futtassa a 'man home-configuration.nix' parancsot az összes opció " +"áttekintéséhez." #. translators: The "%s" specifier will be replaced by a URL. #: home-manager/home-manager:485 @@ -131,6 +158,11 @@ msgid "" "\n" "if the error seems to be the fault of Home Manager." msgstr "" +"Uh oh, az installáció nem sikerült! Kérem készítsen egy jelentést erről a \n" +"\n" +" %s\n" +"\n" +"helyen amennyiben a hiba a Home Manager miatt lépett fel." #. translators: Here "flake" is a noun that refers to the Nix Flakes feature. #: home-manager/home-manager:496 @@ -145,16 +177,20 @@ msgid_plural "" "There are %d unread and relevant news items.\n" "Read them by running the command \"%s news\"." msgstr[0] "" +"%d olvasatlan és releváns hírt kapott.\n" +"Olvassa el a \"%s news\" futattásával." msgstr[1] "" +"%d olvasatlan és releváns hírt kapott.\n" +"Olvassa el őket a \"%s news\" futattásával." #: home-manager/home-manager:586 msgid "Unknown \"news.display\" setting \"%s\"." -msgstr "" +msgstr "Ismeretlen \"news.display\" opció \"%s\"." #: home-manager/home-manager:594 #, sh-format msgid "Please set the $EDITOR or $VISUAL environment variable" -msgstr "" +msgstr "Kérem állítása be az $EDITOR vagy a $VISUAL környezeti változókat." #: home-manager/home-manager:612 msgid "Cannot run build in read-only directory" @@ -162,11 +198,11 @@ msgstr "Build futtatása nem lehetséges csak-olvasható könyvtárban" #: home-manager/home-manager:693 msgid "No generation with ID %s" -msgstr "" +msgstr "Nem található generáció a következő ID-val: %" #: home-manager/home-manager:695 msgid "Cannot remove the current generation %s" -msgstr "" +msgstr "A jelenlegi generáció %s nem eltávolítható" #: home-manager/home-manager:697 msgid "Removing generation %s" @@ -174,11 +210,11 @@ msgstr "%s generáció eltávolítása" #: home-manager/home-manager:718 msgid "No generations to expire" -msgstr "" +msgstr "Nincs lejárandó generáció" #: home-manager/home-manager:729 msgid "No home-manager packages seem to be installed." -msgstr "" +msgstr "Nem található installált Home Manager csomag" #: home-manager/home-manager:811 msgid "Unknown argument %s" @@ -186,19 +222,19 @@ msgstr "Ismeretlen argumentum %s" #: home-manager/home-manager:835 msgid "This will remove Home Manager from your system." -msgstr "" +msgstr "Ez a művelet eltávolítja a Home Manager-t a rendszeréről." #: home-manager/home-manager:838 msgid "This is a dry run, nothing will actually be uninstalled." -msgstr "" +msgstr "Ez egy üres járat, semmi nem lesz valójában eltávolítva." #: home-manager/home-manager:842 msgid "Really uninstall Home Manager?" -msgstr "" +msgstr "Biztosan eltávolítja a Home Managert-t?" #: home-manager/home-manager:848 msgid "Switching to empty Home Manager configuration..." -msgstr "" +msgstr "Átváltás üres Home Manager konfigurációra..." #: home-manager/home-manager:863 msgid "Yay!" @@ -206,7 +242,7 @@ msgstr "Hurrá!" #: home-manager/home-manager:868 msgid "Home Manager is uninstalled but your home.nix is left untouched." -msgstr "" +msgstr "Home Manager eltávolítva, de a home.nix fájl érintetlenül maradt." #: home-manager/home-manager:1091 msgid "expire-generations expects one argument, got %d." @@ -219,3 +255,4 @@ msgstr "Ismeretlen parancs: %s" #: home-manager/install.nix:18 msgid "This derivation is not buildable, please run it using nix-shell." msgstr "" +"Ez a származtatás nem építhető fel, kérlek futtasd nix-shell segítségével." diff --git a/home-manager/po/lt.po b/home-manager/po/lt.po index 458ac14a7..c635d93a6 100644 --- a/home-manager/po/lt.po +++ b/home-manager/po/lt.po @@ -8,22 +8,22 @@ msgstr "" "Project-Id-Version: Home Manager\n" "Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" "POT-Creation-Date: 2024-04-17 23:19+0200\n" -"PO-Revision-Date: 2024-02-16 22:01+0000\n" -"Last-Translator: Robert Helgesson \n" +"PO-Revision-Date: 2024-10-17 00:20+0000\n" +"Last-Translator: Julius Marozas \n" "Language-Team: Lithuanian \n" "Language: lt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " -"(n%100<10 || n%100>=20) ? 1 : 2);\n" -"X-Generator: Weblate 5.4\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (" +"n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Weblate 5.8-rc\n" #. translators: For example: "home-manager: missing argument for --cores" #: home-manager/home-manager:16 msgid "%s: missing argument for %s" -msgstr "" +msgstr "%s: trūksta argumento %s" #: home-manager/home-manager:64 msgid "No configuration file found at %s" @@ -55,6 +55,8 @@ msgid "" "The fallback Home Manager path %s has been deprecated and a file/directory " "was found there." msgstr "" +"Atsarginis kelias %s į Home Manager jau nebenaudojamas, tačiau jame buvo " +"rastas failas/katalogas." #. translators: This message will be seen by very few users that likely are familiar with English. So feel free to leave this untranslated. #: home-manager/home-manager:118 @@ -77,6 +79,24 @@ msgid "" "\n" " $ rm -r \"%s\"" msgstr "" +"Norėdami pašalinti šį įspėjimą, atlikite vieną iš šių veiksmų.\n" +"\n" +"1. Aiškiai nurodykite kelią į Home Manager, pavyzdžiui, pridėdami\n" +"\n" +" { programs.home-manager.path = \"%s\"; }\n" +"\n" +" prie jūsų konfigūracijos.\n" +"\n" +" Jei importuojate Home Manager tiesiogiai, galite naudoti parametrą `path`." +"\n" +"\n" +" pkgs.callPackage /path/to/home-manager-package { path = \"%s\"; }\n" +"\n" +" kviečiant į Home Manager paketą.\n" +"\n" +"2. Pašalinkite nebenaudojamą kelią.\n" +"\n" +" $ rm -r \"%s\"" #: home-manager/home-manager:146 msgid "Sanity checking Nix" @@ -175,10 +195,9 @@ msgstr "Nežinomas \"news.display\" nustatymas \"%s\"." #: home-manager/home-manager:594 #, sh-format msgid "Please set the $EDITOR or $VISUAL environment variable" -msgstr "" +msgstr "Nustatykite $EDITOR arba $VISUAL aplinkos kintamuosius" #: home-manager/home-manager:612 -#, fuzzy msgid "Cannot run build in read-only directory" msgstr "Negalima vykdyti kompiliavimo read-only kataloge" diff --git a/home-manager/po/ro.po b/home-manager/po/ro.po index bd48a4a83..b4be27ce4 100644 --- a/home-manager/po/ro.po +++ b/home-manager/po/ro.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: Home Manager\n" "Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" "POT-Creation-Date: 2024-04-17 23:19+0200\n" -"PO-Revision-Date: 2024-03-31 22:01+0000\n" -"Last-Translator: SMFloris \n" +"PO-Revision-Date: 2024-09-09 10:09+0000\n" +"Last-Translator: Felix Puscasu \n" "Language-Team: Romanian \n" "Language: ro\n" @@ -18,12 +18,12 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < " "20)) ? 1 : 2;\n" -"X-Generator: Weblate 5.5-dev\n" +"X-Generator: Weblate 5.8-dev\n" #. translators: For example: "home-manager: missing argument for --cores" #: home-manager/home-manager:16 msgid "%s: missing argument for %s" -msgstr "" +msgstr "%s: Argument lipsă pentru %s" #: home-manager/home-manager:64 msgid "No configuration file found at %s" diff --git a/home-manager/po/ru.po b/home-manager/po/ru.po index 5a3f811a3..c8afd5a2f 100644 --- a/home-manager/po/ru.po +++ b/home-manager/po/ru.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: Home Manager\n" "Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" "POT-Creation-Date: 2024-04-17 23:19+0200\n" -"PO-Revision-Date: 2024-03-31 22:01+0000\n" -"Last-Translator: Petr Portnov | PROgrm_JARvis \n" +"PO-Revision-Date: 2024-09-12 02:12+0000\n" +"Last-Translator: NikSne \n" "Language-Team: Russian \n" "Language: ru\n" @@ -18,12 +18,12 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -"X-Generator: Weblate 5.5-dev\n" +"X-Generator: Weblate 5.8-dev\n" #. translators: For example: "home-manager: missing argument for --cores" #: home-manager/home-manager:16 msgid "%s: missing argument for %s" -msgstr "" +msgstr "%s: отсутствует параметр для %s" #: home-manager/home-manager:64 msgid "No configuration file found at %s" diff --git a/modules/accounts/calendar.nix b/modules/accounts/calendar.nix index bfbc3e124..86f1b38c5 100644 --- a/modules/accounts/calendar.nix +++ b/modules/accounts/calendar.nix @@ -12,7 +12,8 @@ let path = mkOption { type = types.str; default = "${cfg.basePath}/${name}"; - defaultText = "‹accounts.calendar.basePath›/‹name›"; + defaultText = + lib.literalExpression "‹accounts.calendar.basePath›/‹name›"; description = "The path of the storage."; }; diff --git a/modules/accounts/contacts.nix b/modules/accounts/contacts.nix index 272594b18..d00f5d071 100644 --- a/modules/accounts/contacts.nix +++ b/modules/accounts/contacts.nix @@ -12,7 +12,8 @@ let path = mkOption { type = types.str; default = "${cfg.basePath}/${name}"; - defaultText = "‹accounts.contact.basePath›/‹name›"; + defaultText = + lib.literalExpression "‹accounts.contact.basePath›/‹name›"; description = "The path of the storage."; }; diff --git a/modules/lib/default.nix b/modules/lib/default.nix index 5d732a83f..8014c625e 100644 --- a/modules/lib/default.nix +++ b/modules/lib/default.nix @@ -14,4 +14,5 @@ rec { shell = import ./shell.nix { inherit lib; }; zsh = import ./zsh.nix { inherit lib; }; + nushell = import ./nushell.nix { inherit lib; }; } diff --git a/modules/lib/maintainers.nix b/modules/lib/maintainers.nix index 920080366..6deea15f7 100644 --- a/modules/lib/maintainers.nix +++ b/modules/lib/maintainers.nix @@ -7,6 +7,12 @@ # [1] https://github.com/NixOS/nixpkgs/blob/fca0d6e093c82b31103dc0dacc48da2a9b06e24b/maintainers/maintainer-list.nix#LC1 { + aabccd021 = { + name = "Muhamad Abdurahman"; + email = "aabccd021@gmail.com"; + github = "aabccd021"; + githubId = 33031950; + }; abayomi185 = { name = "Yomi"; email = "yomi+nix@yomitosh.com"; @@ -276,6 +282,12 @@ github = "nilp0inter"; githubId = 1224006; }; + NitroSniper = { + name = "Nitro Sniper"; + email = "nitro@ortin.dev"; + github = "NitroSniper"; + githubId = 44097331; + }; seylerius = { email = "sable@seyleri.us"; name = "Sable Seyler"; @@ -337,6 +349,11 @@ githubId = 12465195; name = "Bruno BELANYI"; }; + libewa = { + email = "libewa-git@icloud.com"; + github = "libewa"; + githubId = 67926131; + }; malvo = { email = "malte@malvo.org"; github = "malte-v"; @@ -415,12 +432,6 @@ github = "nurelin"; githubId = 5276274; }; - omernaveedxyz = { - name = "Omer Naveed"; - email = "omer@omernaveed.dev"; - github = "omernaveedxyz"; - githubId = 112912585; - }; otavio = { email = "otavio.salvador@ossystems.com.br"; github = "otavio"; @@ -593,4 +604,18 @@ github = "michaelvanstraten"; githubId = 50352631; }; + joygnu = { + name = "joygnu"; + email = "contact@joygnu.org"; + github = "joygnu"; + githubId = 152063003; + }; + callumio = { + name = "Callum Leslie"; + email = "git+nix@cleslie.uk"; + github = "callumio"; + githubId = 16057677; + keys = + [{ fingerprint = "BC82 4BB5 1656 D144 285E A0EC D382 C4AF EECE AA90"; }]; + }; } diff --git a/modules/lib/nushell.nix b/modules/lib/nushell.nix new file mode 100644 index 000000000..e831380cd --- /dev/null +++ b/modules/lib/nushell.nix @@ -0,0 +1,65 @@ +{ lib }: rec { + mkNushellInline = expr: lib.setType "nushell-inline" { inherit expr; }; + + toNushell = { indent ? "", multiline ? true, asBindings ? false }@args: + v: + let + innerIndent = "${indent} "; + introSpace = if multiline then '' + + ${innerIndent}'' else + " "; + outroSpace = if multiline then '' + + ${indent}'' else + " "; + innerArgs = args // { + indent = if asBindings then indent else innerIndent; + asBindings = false; + }; + concatItems = lib.concatStringsSep introSpace; + isNushellInline = lib.isType "nushell-inline"; + + generatedBindings = assert lib.assertMsg (badVarNames == [ ]) + "Bad Nushell variable names: ${ + lib.generators.toPretty { } badVarNames + }"; + lib.concatStrings (lib.mapAttrsToList (key: value: '' + ${indent}let ${key} = ${toNushell innerArgs value} + '') v); + + isBadVarName = name: + # Extracted from https://github.com/nushell/nushell/blob/ebc7b80c23f777f70c5053cca428226b3fe00d30/crates/nu-parser/src/parser.rs#L33 + # Variables with numeric or even empty names are allowed. The only requisite is not containing any of the following characters + let invalidVariableCharacters = ".[({+-*^/=!<>&|"; + in lib.match "^[$]?[^${lib.escapeRegex invalidVariableCharacters}]+$" + name == null; + badVarNames = lib.filter isBadVarName (builtins.attrNames v); + in if asBindings then + generatedBindings + else if v == null then + "null" + else if lib.isInt v || lib.isFloat v || lib.isString v || lib.isBool v then + lib.strings.toJSON v + else if lib.isList v then + (if v == [ ] then + "[]" + else + "[${introSpace}${ + concatItems (map (value: "${toNushell innerArgs value}") v) + }${outroSpace}]") + else if lib.isAttrs v then + (if isNushellInline v then + "(${v.expr})" + else if v == { } then + "{}" + else if lib.isDerivation v then + toString v + else + "{${introSpace}${ + concatItems (lib.mapAttrsToList (key: value: + "${lib.strings.toJSON key}: ${toNushell innerArgs value}") v) + }${outroSpace}}") + else + abort "nushell.toNushell: type ${lib.typeOf v} is unsupported"; +} diff --git a/modules/lib/types.nix b/modules/lib/types.nix index 056d3165b..14d1c2192 100644 --- a/modules/lib/types.nix +++ b/modules/lib/types.nix @@ -107,4 +107,27 @@ in rec { mergeDefaultOption loc defs; }; + nushellValue = let + valueType = types.nullOr (types.oneOf [ + (lib.mkOptionType { + name = "nushell"; + description = "Nushell inline value"; + descriptionClass = "name"; + check = lib.isType "nushell-inline"; + }) + types.bool + types.int + types.float + types.str + types.path + (types.attrsOf valueType // { + description = "attribute set of Nushell values"; + descriptionClass = "name"; + }) + (types.listOf valueType // { + description = "list of Nushell values"; + descriptionClass = "name"; + }) + ]); + in valueType; } diff --git a/modules/misc/news.nix b/modules/misc/news.nix index 60b495859..0f06de38d 100644 --- a/modules/misc/news.nix +++ b/modules/misc/news.nix @@ -1,9 +1,6 @@ { config, lib, options, pkgs, ... }: - with lib; - let - cfg = config.news; hostPlatform = pkgs.stdenv.hostPlatform; @@ -44,7 +41,6 @@ let config = { id = mkDefault (builtins.hashString "sha256" config.message); }; }); - in { meta.maintainers = [ maintainers.rycee ]; @@ -1712,6 +1708,119 @@ in { Sesh is a CLI that helps you create and manage tmux sessions quickly and easily using zoxide. See https://github.com/joshmedeski/sesh for more. + } + + { + time = "2024-09-13T08:58:17+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.trayscale'. + + An unofficial GUI wrapper around the Tailscale CLI client. + ''; + } + + { + time = "2024-09-13T09:50:49+00:00"; + message = '' + A new module is available: 'programs.neovide'. + + Neovide is a simple, no-nonsense, cross-platform graphical user + interface for Neovim (an aggressively refactored and updated Vim + editor). + ''; + } + + { + time = "2024-09-20T07:00:11+00:00"; + condition = config.programs.kitty.theme != null; + message = '' + The option 'programs.kitty.theme' has been deprecated, please use + 'programs.kitty.themeFile' instead. + + The 'programs.kitty.themeFile' option expects the file name of a + theme from `kitty-themes`, without the `.conf` suffix. See + for a + list of themes. + ''; + } + + { + time = "2024-09-20T07:48:08+00:00"; + condition = hostPlatform.isLinux && config.services.swayidle.enable; + message = '' + The swayidle module behavior has changed. Specifically, swayidle was + previously always called with a `-w` flag. This flag is now moved to + the default `services.swayidle.extraArgs` value to make it optional. + + Your configuration may break if you already set this option and also + rely on the flag being automatically added. To resolve this, please + add `-w` to your assignment of `services.swayidle.extraArgs`. + ''; + } + + { + time = "2024-10-09T06:16:23+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.snixembed'. + + snixembed proxies StatusNotifierItems as XEmbedded systemtray-spec + icons. This is useful for some tools in some environments, e.g., Safe + Eyes in i3, lxde or mate. + ''; + } + + { + time = "2024-10-11T08:23:19+00:00"; + message = '' + A new module is available: 'programs.vifm'. + + Vifm is a curses based Vim-like file manager extended with some useful + ideas from mutt. + ''; + } + + { + time = "2024-10-17T13:07:55+00:00"; + message = '' + A new module is available: 'programs.zed-editor'. + + Zed is a fast text editor for macOS and Linux. + See https://zed.dev for more. + ''; + } + + { + time = "2024-10-18T14:01:07+00:00"; + message = '' + A new module is available: 'programs.cmus'. + + cmus is a small, fast and powerful console music player. + ''; + } + + { + time = "2024-10-20T07:53:54+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'programs.nh'. + + nh is yet another Nix CLI helper. Adding functionality on top of the + existing solutions, like nixos-rebuild, home-manager cli or nix + itself. + ''; + } + + { + time = "2024-10-25T08:18:30+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'nixGL'. + + NixGL solve the "OpenGL" problem with nix. The 'nixGL' module provides + integration of NixGL into Home Manager. See the "GPU on non-NixOS + systems" section in the Home Manager mantual for more. ''; } ]; diff --git a/modules/misc/nixgl.nix b/modules/misc/nixgl.nix new file mode 100644 index 000000000..2c7fcaffc --- /dev/null +++ b/modules/misc/nixgl.nix @@ -0,0 +1,296 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.nixGL; + wrapperListMarkdown = with builtins; + foldl' (list: name: + list + '' + - ${name} + '') "" (attrNames config.lib.nixGL.wrappers); +in { + meta.maintainers = [ lib.maintainers.smona ]; + + options.nixGL = { + packages = lib.mkOption { + type = with lib.types; nullOr attrs; + default = null; + example = lib.literalExpression "inputs.nixGL.packages"; + description = '' + The nixGL package set containing GPU library wrappers. This can be used + to provide OpenGL and Vulkan access to applications on non-NixOS systems + by using `(config.lib.nixGL.wrap )` for the default wrapper, or + `(config.lib.nixGL.wrappers. )` for any available + wrapper. + + The wrapper functions are always available. If this option is empty (the + default), they are a no-op. This is useful on NixOS where the wrappers + are unnecessary. + + Note that using any Nvidia wrapper requires building the configuration + with the `--impure` option. + ''; + }; + + defaultWrapper = lib.mkOption { + type = lib.types.enum (builtins.attrNames config.lib.nixGL.wrappers); + default = "mesa"; + description = '' + The package wrapper function available for use as `(config.lib.nixGL.wrap + )`. Intended to start programs on the main GPU. + + Wrapper functions can be found under `config.lib.nixGL.wrappers`. They + can be used directly, however, setting this option provides a convenient + shorthand. + + The following wrappers are available: + ${wrapperListMarkdown} + ''; + }; + + offloadWrapper = lib.mkOption { + type = lib.types.enum (builtins.attrNames config.lib.nixGL.wrappers); + default = "mesaPrime"; + description = '' + The package wrapper function available for use as + `(config.lib.nixGL.wrapOffload )`. Intended to start programs + on the secondary GPU. + + Wrapper functions can be found under `config.lib.nixGL.wrappers`. They + can be used directly, however, setting this option provides a convenient + shorthand. + + The following wrappers are available: + ${wrapperListMarkdown} + ''; + }; + + prime.card = lib.mkOption { + type = lib.types.str; + default = "1"; + example = "pci-0000_06_00_0"; + description = '' + Selects the non-default graphics card used for PRIME render offloading. + The value can be: + + - a number, selecting the n-th non-default GPU; + - a PCI bus id in the form `pci-XXX_YY_ZZ_U`; + - a PCI id in the form `vendor_id:device_id` + + For more information, consult the Mesa documentation on the `DRI_PRIME` + environment variable. + ''; + }; + + prime.nvidiaProvider = lib.mkOption { + type = with lib.types; nullOr str; + default = null; + example = "NVIDIA-G0"; + description = '' + If this option is set, it overrides the offload provider for Nvidia + PRIME offloading. Consult the proprietary Nvidia driver documentation + on the `__NV_PRIME_RENDER_OFFLOAD_PROVIDER` environment variable. + ''; + }; + + prime.installScript = lib.mkOption { + type = with lib.types; nullOr (enum [ "mesa" "nvidia" ]); + default = null; + example = "mesa"; + description = '' + If this option is set, the wrapper script `prime-offload` is installed + into the environment. It allows starting programs on the secondary GPU + selected by the `nixGL.prime.card` option. This makes sense when the + program is not already using one of nixGL PRIME wrappers, or for + programs not installed from Nixpkgs. + + This option can be set to either "mesa" or "nvidia", making the script + use one or the other graphics library. + ''; + }; + + installScripts = lib.mkOption { + type = with lib.types; + nullOr (listOf (enum (builtins.attrNames config.lib.nixGL.wrappers))); + default = null; + example = [ "mesa" "mesaPrime" ]; + description = '' + For each wrapper `wrp` named in the provided list, a wrapper script + named `nixGLWrp` is installed into the environment. These scripts are + useful for running programs not installed via Home Manager. + + The following wrappers are available: + ${wrapperListMarkdown} + ''; + }; + + vulkan.enable = lib.mkOption { + type = lib.types.bool; + default = false; + example = true; + description = '' + Whether to enable Vulkan in nixGL wrappers. + + This is disabled by default bacause Vulkan brings in several libraries + that can cause symbol version conflicts in wrapped programs. Your + mileage may vary. + ''; + }; + }; + + config = let + findWrapperPackage = packageAttr: + # NixGL has wrapper packages in different places depending on how you + # access it. We want HM configuration to be the same, regardless of how + # NixGL is imported. + # + # First, let's see if we have a flake. + if builtins.hasAttr pkgs.system cfg.packages then + cfg.packages.${pkgs.system}.${packageAttr} + else + # Next, let's see if we have a channel. + if builtins.hasAttr packageAttr cfg.packages then + cfg.packages.${packageAttr} + else + # Lastly, with channels, some wrappers are grouped under "auto". + if builtins.hasAttr "auto" cfg.packages then + cfg.packages.auto.${packageAttr} + else + throw "Incompatible NixGL package layout"; + + getWrapperExe = vendor: + let + glPackage = findWrapperPackage "nixGL${vendor}"; + glExe = lib.getExe glPackage; + vulkanPackage = findWrapperPackage "nixVulkan${vendor}"; + vulkanExe = if cfg.vulkan.enable then lib.getExe vulkanPackage else ""; + in "${glExe} ${vulkanExe}"; + + mesaOffloadEnv = { "DRI_PRIME" = "${cfg.prime.card}"; }; + + nvOffloadEnv = { + "DRI_PRIME" = "${cfg.prime.card}"; + "__NV_PRIME_RENDER_OFFLOAD" = "1"; + "__GLX_VENDOR_LIBRARY_NAME" = "nvidia"; + "__VK_LAYER_NV_optimus" = "NVIDIA_only"; + } // (let provider = cfg.prime.nvidiaProvider; + in if !isNull provider then { + "__NV_PRIME_RENDER_OFFLOAD_PROVIDER" = "${provider}"; + } else + { }); + + makePackageWrapper = vendor: environment: pkg: + if builtins.isNull cfg.packages then + pkg + else + # Wrap the package's binaries with nixGL, while preserving the rest of + # the outputs and derivation attributes. + (pkg.overrideAttrs (old: { + name = "nixGL-${pkg.name}"; + + # Make sure this is false for the wrapper derivation, so nix doesn't expect + # a new debug output to be produced. We won't be producing any debug info + # for the original package. + separateDebugInfo = false; + nativeBuildInputs = old.nativeBuildInputs or [ ] + ++ [ pkgs.makeWrapper ]; + buildCommand = let + # We need an intermediate wrapper package because makeWrapper + # requires a single executable as the wrapper. + combinedWrapperPkg = + pkgs.writeShellScriptBin "nixGLCombinedWrapper-${vendor}" '' + exec ${getWrapperExe vendor} "$@" + ''; + in '' + set -eo pipefail + + ${ # Heavily inspired by https://stackoverflow.com/a/68523368/6259505 + lib.concatStringsSep "\n" (map (outputName: '' + echo "Copying output ${outputName}" + set -x + cp -rs --no-preserve=mode "${ + pkg.${outputName} + }" "''$${outputName}" + set +x + '') (old.outputs or [ "out" ]))} + + rm -rf $out/bin/* + shopt -s nullglob # Prevent loop from running if no files + for file in ${pkg.out}/bin/*; do + local prog="$(basename "$file")" + makeWrapper \ + "${lib.getExe combinedWrapperPkg}" \ + "$out/bin/$prog" \ + --argv0 "$prog" \ + --add-flags "$file" \ + ${ + lib.concatStringsSep " " (lib.attrsets.mapAttrsToList + (var: val: "--set '${var}' '${val}'") environment) + } + done + + # If .desktop files refer to the old package, replace the references + for dsk in "$out/share/applications"/*.desktop ; do + if ! grep -q "${pkg.out}" "$dsk"; then + continue + fi + src="$(readlink "$dsk")" + rm "$dsk" + sed "s|${pkg.out}|$out|g" "$src" > "$dsk" + done + + shopt -u nullglob # Revert nullglob back to its normal default state + ''; + })); + + wrappers = { + mesa = makePackageWrapper "Intel" { }; + mesaPrime = makePackageWrapper "Intel" mesaOffloadEnv; + nvidia = makePackageWrapper "Nvidia" { }; + nvidiaPrime = makePackageWrapper "Nvidia" nvOffloadEnv; + }; + in { + lib.nixGL.wrap = wrappers.${cfg.defaultWrapper}; + lib.nixGL.wrapOffload = wrappers.${cfg.offloadWrapper}; + lib.nixGL.wrappers = wrappers; + + home.packages = let + wantsPrimeWrapper = (!isNull cfg.prime.installScript); + wantsWrapper = wrapper: + (!isNull cfg.packages) && (!isNull cfg.installScripts) + && (builtins.elem wrapper cfg.installScripts); + envVarsAsScript = environment: + lib.concatStringsSep "\n" + (lib.attrsets.mapAttrsToList (var: val: "export ${var}=${val}") + environment); + in [ + (lib.mkIf wantsPrimeWrapper (pkgs.writeShellScriptBin "prime-offload" '' + ${if cfg.prime.installScript == "mesa" then + (envVarsAsScript mesaOffloadEnv) + else + (envVarsAsScript nvOffloadEnv)} + exec "$@" + '')) + + (lib.mkIf (wantsWrapper "mesa") (pkgs.writeShellScriptBin "nixGLMesa" '' + exec ${getWrapperExe "Intel"} "$@" + '')) + + (lib.mkIf (wantsWrapper "mesaPrime") + (pkgs.writeShellScriptBin "nixGLMesaPrime" '' + ${envVarsAsScript mesaOffloadEnv} + exec ${getWrapperExe "Intel"} "$@" + '')) + + (lib.mkIf (wantsWrapper "nvidia") + (pkgs.writeShellScriptBin "nixGLNvidia" '' + exec ${getWrapperExe "Nvidia"} "$@" + '')) + + (lib.mkIf (wantsWrapper "nvidia") + (pkgs.writeShellScriptBin "nixGLNvidiaPrime" '' + ${envVarsAsScript nvOffloadEnv} + exec ${getWrapperExe "Nvidia"} "$@" + '')) + ]; + }; +} diff --git a/modules/misc/xdg-mime.nix b/modules/misc/xdg-mime.nix index 09f62aaff..78b569fa5 100644 --- a/modules/misc/xdg-mime.nix +++ b/modules/misc/xdg-mime.nix @@ -5,33 +5,50 @@ with lib; let cfg = config.xdg.mime; + inherit (lib) getExe getExe'; in { options = { - xdg.mime.enable = mkOption { - type = types.bool; - default = pkgs.stdenv.hostPlatform.isLinux; - defaultText = - literalExpression "true if host platform is Linux, false otherwise"; - description = '' - Whether to install programs and files to support the - XDG Shared MIME-info specification and XDG MIME Applications - specification at - - and - , - respectively. - ''; + xdg.mime = { + enable = mkOption { + type = types.bool; + default = pkgs.stdenv.hostPlatform.isLinux; + defaultText = + literalExpression "true if host platform is Linux, false otherwise"; + description = '' + Whether to install programs and files to support the + XDG Shared MIME-info specification and XDG MIME Applications + specification at + + and + , + respectively. + ''; + }; + + sharedMimeInfoPackage = mkOption { + type = types.package; + default = pkgs.shared-mime-info; + defaultText = literalExpression "pkgs.shared-mime-info"; + description = "The package to use when running update-mime-database."; + }; + + desktopFileUtilsPackage = mkOption { + type = types.package; + default = pkgs.desktop-file-utils; + defaultText = literalExpression "pkgs.desktop-file-utils"; + description = + "The package to use when running update-desktop-database."; + }; }; }; - - config = mkIf config.xdg.mime.enable { + config = mkIf cfg.enable { assertions = [ (hm.assertions.assertPlatform "xdg.mime" pkgs platforms.linux) ]; home.packages = [ # Explicitly install package to provide basic mime types. - pkgs.shared-mime-info + cfg.sharedMimeInfoPackage # Make sure the target directories will be real directories. (pkgs.runCommandLocal "dummy-xdg-mime-dirs1" { } '' @@ -46,12 +63,12 @@ in { if [[ -w $out/share/mime && -w $out/share/mime/packages && -d $out/share/mime/packages ]]; then XDG_DATA_DIRS=$out/share \ PKGSYSTEM_ENABLE_FSYNC=0 \ - ${pkgs.buildPackages.shared-mime-info}/bin/update-mime-database \ + ${getExe cfg.sharedMimeInfoPackage} \ -V $out/share/mime > /dev/null fi if [[ -w $out/share/applications ]]; then - ${pkgs.buildPackages.desktop-file-utils}/bin/update-desktop-database \ + ${getExe' cfg.desktopFileUtilsPackage "update-desktop-database"} \ $out/share/applications fi ''; diff --git a/modules/misc/xdg.nix b/modules/misc/xdg.nix index 23cbe72a2..b916e88fb 100644 --- a/modules/misc/xdg.nix +++ b/modules/misc/xdg.nix @@ -30,6 +30,8 @@ in { apply = toString; description = '' Absolute path to directory holding application caches. + + Sets `XDG_CACHE_HOME` for the user if `xdg.enable` is set `true`. ''; }; @@ -48,6 +50,8 @@ in { apply = toString; description = '' Absolute path to directory holding application configurations. + + Sets `XDG_CONFIG_HOME` for the user if `xdg.enable` is set `true`. ''; }; @@ -67,6 +71,18 @@ in { apply = toString; description = '' Absolute path to directory holding application data. + + Sets `XDG_DATA_HOME` for the user if `xdg.enable` is set `true`. + ''; + }; + + stateFile = mkOption { + type = fileType "xdg.stateFile" "xdg.stateHome" + cfg.stateHome; + default = { }; + description = '' + Attribute set of files to link into the user's XDG + state home. ''; }; @@ -76,6 +92,8 @@ in { apply = toString; description = '' Absolute path to directory holding application states. + + Sets `XDG_STATE_HOME` for the user if `xdg.enable` is set `true`. ''; }; }; @@ -122,6 +140,8 @@ in { cfg.configFile) (mapAttrs' (name: file: nameValuePair "${cfg.dataHome}/${name}" file) cfg.dataFile) + (mapAttrs' (name: file: nameValuePair "${cfg.stateHome}/${name}" file) + cfg.stateFile) { "${cfg.cacheHome}/.keep".text = ""; } ]; } diff --git a/modules/modules.nix b/modules/modules.nix index 8c1f03385..ae7549cc2 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -31,6 +31,7 @@ let ./misc/gtk.nix ./misc/lib.nix ./misc/news.nix + ./misc/nixgl.nix ./misc/numlock.nix ./misc/pam.nix ./misc/qt.nix @@ -77,6 +78,7 @@ let ./programs/carapace.nix ./programs/cava.nix ./programs/chromium.nix + ./programs/cmus.nix ./programs/command-not-found/command-not-found.nix ./programs/comodoro.nix ./programs/darcs.nix @@ -92,6 +94,7 @@ let ./programs/feh.nix ./programs/firefox.nix ./programs/fish.nix + ./programs/floorp.nix ./programs/foot.nix ./programs/freetube.nix ./programs/fuzzel.nix @@ -167,8 +170,10 @@ let ./programs/ncspot.nix ./programs/ne.nix ./programs/neomutt.nix + ./programs/neovide.nix ./programs/neovim.nix ./programs/newsboat.nix + ./programs/nh.nix ./programs/nheko.nix ./programs/nix-index.nix ./programs/nnn.nix @@ -241,8 +246,9 @@ let ./programs/translate-shell.nix ./programs/urxvt.nix ./programs/vdirsyncer.nix - ./programs/vim.nix + ./programs/vifm.nix ./programs/vim-vint.nix + ./programs/vim.nix ./programs/vscode.nix ./programs/vscode/haskell.nix ./programs/pywal.nix @@ -260,6 +266,7 @@ let ./programs/yt-dlp.nix ./programs/z-lua.nix ./programs/zathura.nix + ./programs/zed-editor.nix ./programs/zellij.nix ./programs/zk.nix ./programs/zoxide.nix @@ -361,6 +368,7 @@ let ./services/screen-locker.nix ./services/sctd.nix ./services/signaturepdf.nix + ./services/snixembed.nix ./services/spotifyd.nix ./services/ssh-agent.nix ./services/stalonetray.nix @@ -375,6 +383,7 @@ let ./services/tahoe-lafs.nix ./services/taskwarrior-sync.nix ./services/trayer.nix + ./services/trayscale.nix ./services/twmn.nix ./services/udiskie.nix ./services/unclutter.nix diff --git a/modules/po/de.po b/modules/po/de.po index 5783cd7d7..d9cdbc944 100644 --- a/modules/po/de.po +++ b/modules/po/de.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: Home Manager Modules\n" "Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" "POT-Creation-Date: 2024-04-17 23:19+0200\n" -"PO-Revision-Date: 2023-12-29 02:09+0000\n" -"Last-Translator: Peter Pfeufer \n" +"PO-Revision-Date: 2024-10-15 21:37+0000\n" +"Last-Translator: Viktor Illmer \n" "Language-Team: German \n" "Language: de\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.4-dev\n" +"X-Generator: Weblate 5.8-rc\n" #: modules/files.nix:191 msgid "Creating home file links in %s" @@ -120,7 +120,7 @@ msgstr "Fehler: HOME ist auf \"%s\" gesetzt, aber wir erwarten \"%s\"" #: modules/lib-bash/activation-init.sh:153 msgid "Starting Home Manager activation" -msgstr "Starte Home Manager Aktivierung" +msgstr "Starte Home-Manager-Aktivierung" #: modules/lib-bash/activation-init.sh:157 msgid "Sanity checking Nix" diff --git a/modules/po/hi.po b/modules/po/hi.po new file mode 100644 index 000000000..80781aba5 --- /dev/null +++ b/modules/po/hi.po @@ -0,0 +1,116 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager Modules package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager Modules\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2024-04-17 23:19+0200\n" +"PO-Revision-Date: 2024-10-09 14:31+0000\n" +"Last-Translator: Utkarsh Sharma \n" +"Language-Team: Hindi \n" +"Language: hi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 5.8-dev\n" + +#: modules/files.nix:191 +msgid "Creating home file links in %s" +msgstr "" + +#: modules/files.nix:204 +msgid "Cleaning up orphan links from %s" +msgstr "%s से ऑर्फे़न लिंक्स मिटाई जा रही है" + +#: modules/files.nix:220 +msgid "Creating profile generation %s" +msgstr "" + +#: modules/files.nix:237 +msgid "No change so reusing latest profile generation %s" +msgstr "" + +#: modules/home-environment.nix:634 +msgid "" +"Oops, Nix failed to install your new Home Manager profile!\n" +"\n" +"Perhaps there is a conflict with a package that was installed using\n" +"\"%s\"? Try running\n" +"\n" +" %s\n" +"\n" +"and if there is a conflicting package you can remove it with\n" +"\n" +" %s\n" +"\n" +"Then try activating your Home Manager configuration again." +msgstr "" + +#: modules/home-environment.nix:667 +msgid "Activating %s" +msgstr "" + +#: modules/lib-bash/activation-init.sh:22 +msgid "Migrating profile from %s to %s" +msgstr "" + +#: modules/lib-bash/activation-init.sh:54 +msgid "Could not find suitable profile directory, tried %s and %s" +msgstr "" + +#: modules/lib-bash/activation-init.sh:83 +msgid "Sanity checking oldGenNum and oldGenPath" +msgstr "" + +#: modules/lib-bash/activation-init.sh:86 +msgid "" +"The previous generation number and path are in conflict! These\n" +"must be either both empty or both set but are now set to\n" +"\n" +" '%s' and '%s'\n" +"\n" +"If you don't mind losing previous profile generations then\n" +"the easiest solution is probably to run\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"and trying home-manager switch again. Good luck!" +msgstr "" + +#: modules/lib-bash/activation-init.sh:127 +msgid "Error: USER is set to \"%s\" but we expect \"%s\"" +msgstr "" + +#: modules/lib-bash/activation-init.sh:136 +msgid "Error: HOME is set to \"%s\" but we expect \"%s\"" +msgstr "" + +#: modules/lib-bash/activation-init.sh:153 +msgid "Starting Home Manager activation" +msgstr "" + +#: modules/lib-bash/activation-init.sh:157 +msgid "Sanity checking Nix" +msgstr "" + +#: modules/lib-bash/activation-init.sh:170 +msgid "This is a dry run" +msgstr "" + +#: modules/lib-bash/activation-init.sh:174 +msgid "This is a live run" +msgstr "" + +#: modules/lib-bash/activation-init.sh:180 +msgid "Using Nix version: %s" +msgstr "" + +#: modules/lib-bash/activation-init.sh:183 +msgid "Activation variables:" +msgstr "" diff --git a/modules/po/hu.po b/modules/po/hu.po index 99d3e0373..2b013ccc1 100644 --- a/modules/po/hu.po +++ b/modules/po/hu.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: Home Manager Modules\n" "Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" "POT-Creation-Date: 2024-04-17 23:19+0200\n" -"PO-Revision-Date: 2024-08-23 14:09+0000\n" -"Last-Translator: Szabin Hamrik \n" +"PO-Revision-Date: 2024-09-02 17:09+0000\n" +"Last-Translator: Ferenci Ákos \n" "Language-Team: Hungarian \n" "Language: hu\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.7.1-dev\n" +"X-Generator: Weblate 5.8-dev\n" #: modules/files.nix:191 msgid "Creating home file links in %s" @@ -62,6 +62,7 @@ msgstr "" #: modules/lib-bash/activation-init.sh:54 msgid "Could not find suitable profile directory, tried %s and %s" msgstr "" +"Nem található megfelelő profil mappa, %s és %s útvonalak lettek kipróbálva." #: modules/lib-bash/activation-init.sh:83 msgid "Sanity checking oldGenNum and oldGenPath" @@ -97,7 +98,7 @@ msgstr "" #: modules/lib-bash/activation-init.sh:157 msgid "Sanity checking Nix" -msgstr "" +msgstr "Nix épségének ellenőrzése" #: modules/lib-bash/activation-init.sh:170 msgid "This is a dry run" diff --git a/modules/po/ro.po b/modules/po/ro.po index d817496a7..71e9243c9 100644 --- a/modules/po/ro.po +++ b/modules/po/ro.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: Home Manager Modules\n" "Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" "POT-Creation-Date: 2024-04-17 23:19+0200\n" -"PO-Revision-Date: 2023-08-11 19:51+0000\n" -"Last-Translator: HeartBlin913861820c094e37 \n" +"PO-Revision-Date: 2024-10-13 22:15+0000\n" +"Last-Translator: AtomicDude \n" "Language-Team: Romanian \n" "Language: ro\n" @@ -18,7 +18,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < " "20)) ? 1 : 2;\n" -"X-Generator: Weblate 5.0-dev\n" +"X-Generator: Weblate 5.8-dev\n" #: modules/files.nix:191 msgid "Creating home file links in %s" @@ -26,7 +26,7 @@ msgstr "Se creează legături ale fișierelor personale în %s" #: modules/files.nix:204 msgid "Cleaning up orphan links from %s" -msgstr "Se curăță legăturiile orfane din %s" +msgstr "Se curăță legăturile orfane din %s" #: modules/files.nix:220 msgid "Creating profile generation %s" diff --git a/modules/programs/alacritty.nix b/modules/programs/alacritty.nix index e799e2696..6fa7fb6e8 100644 --- a/modules/programs/alacritty.nix +++ b/modules/programs/alacritty.nix @@ -56,7 +56,7 @@ in { buildCommand = lib.concatStringsSep "\n" [ prevAttrs.buildCommand # TODO: why is this needed? Is there a better way to retain escape sequences? - "substituteInPlace $out --replace '\\\\' '\\'" + "substituteInPlace $out --replace-quiet '\\\\' '\\'" ]; }); }; diff --git a/modules/programs/autorandr.nix b/modules/programs/autorandr.nix index edbe83de6..ab59d8d9d 100644 --- a/modules/programs/autorandr.nix +++ b/modules/programs/autorandr.nix @@ -177,6 +177,18 @@ let default = null; example = "nearest"; }; + + extraConfig = mkOption { + type = types.lines; + description = "Extra lines to append to this profile's config."; + default = ""; + example = literalExpression '' + ''' + x-prop-non_desktop 0 + some-key some-value + ''' + ''; + }; }; }; @@ -267,7 +279,8 @@ let + concatMapStringsSep "," toString (flatten config.transform)) ++ optional (config.scale != null) ((if config.scale.method == "factor" then "scale" else "scale-from") - + " ${toString config.scale.x}x${toString config.scale.y}")) + + " ${toString config.scale.x}x${toString config.scale.y}") + ++ optional (config.extraConfig != "") config.extraConfig) else '' output ${name} off diff --git a/modules/programs/bemenu.nix b/modules/programs/bemenu.nix index 58d24dcc2..f90067216 100644 --- a/modules/programs/bemenu.nix +++ b/modules/programs/bemenu.nix @@ -7,7 +7,7 @@ let cfg = config.programs.bemenu; in { - meta.maintainers = [ hm.maintainers.omernaveedxyz ]; + meta.maintainers = [ ]; options.programs.bemenu = { enable = mkEnableOption "bemenu"; diff --git a/modules/programs/borgmatic.nix b/modules/programs/borgmatic.nix index ecc6f5cf3..97a1d54ce 100644 --- a/modules/programs/borgmatic.nix +++ b/modules/programs/borgmatic.nix @@ -272,10 +272,7 @@ in { }; config = mkIf cfg.enable { - assertions = [ - (lib.hm.assertions.assertPlatform "programs.borgmatic" pkgs - lib.platforms.linux) - ] ++ (mapAttrsToList (backup: opts: { + assertions = (mapAttrsToList (backup: opts: { assertion = opts.location.sourceDirectories == null || opts.location.patterns == null; message = '' diff --git a/modules/programs/broot.nix b/modules/programs/broot.nix index 6a1680e07..c1ce94776 100644 --- a/modules/programs/broot.nix +++ b/modules/programs/broot.nix @@ -15,7 +15,7 @@ let modal = mkEnableOption "modal (vim) mode"; verbs = mkOption { - type = with types; listOf (attrsOf (either bool str)); + type = with types; listOf (attrsOf (oneOf [ bool str (listOf str) ])); default = [ ]; example = literalExpression '' [ @@ -46,6 +46,9 @@ let `key` (optional) : a keyboard key triggering execution + `keys` (optional) + : multiple keyboard keys each triggering execution + `shortcut` (optional) : an alternate way to call the verb (without the arguments part) @@ -54,7 +57,7 @@ let : whether to quit broot on execution (default: `true`) - `from_shell` (optional) + `from_shell` (optional) : whether the verb must be executed from the parent shell (default: `false`) ''; diff --git a/modules/programs/cmus.nix b/modules/programs/cmus.nix new file mode 100644 index 000000000..ac3e46ee1 --- /dev/null +++ b/modules/programs/cmus.nix @@ -0,0 +1,44 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.cmus; + +in { + meta.maintainers = [ hm.maintainers.joygnu ]; + + options.programs.cmus = { + enable = mkEnableOption "Enable cmus, the music player."; + + theme = mkOption { + type = types.lines; + default = ""; + example = "gruvbox"; + description = '' + Select color theme. A list of available color themes can be found + here: . + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = '' + set audio_backend = "mpd" + set status_display = "default" + ''; + description = "Extra configuration to add to cmus {file}`rc`."; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.cmus ]; + + home.file.".config/cmus/rc".text = '' + ${optionalString (cfg.theme != "") "colorscheme ${cfg.theme}"} + ${cfg.extraConfig} + ''; + }; +} diff --git a/modules/programs/direnv.nix b/modules/programs/direnv.nix index 4a7636705..37899c4a2 100644 --- a/modules/programs/direnv.nix +++ b/modules/programs/direnv.nix @@ -19,7 +19,7 @@ in { "Flake support is now always enabled.") ]; - meta.maintainers = [ lib.maintainers.rycee ]; + meta.maintainers = [ lib.maintainers.rycee lib.maintainers.shikanime ]; options.programs.direnv = { enable = mkEnableOption "direnv, the environment switcher"; @@ -95,6 +95,14 @@ in { package = mkPackageOption pkgs "nix-direnv" { }; }; + mise = { + enable = mkEnableOption '' + [mise](https://mise.jdx.dev/direnv.html), + integration of use_mise for direnv''; + + package = mkPackageOption pkgs "mise" { }; + }; + silent = mkEnableOption "silent mode, that is, disabling direnv logging"; }; @@ -112,6 +120,12 @@ in { xdg.configFile."direnv/direnvrc" = lib.mkIf (cfg.stdlib != "") { text = cfg.stdlib; }; + xdg.configFile."direnv/lib/hm-mise.sh" = mkIf cfg.mise.enable { + text = '' + eval "$(${getExe cfg.mise.package} direnv activate)" + ''; + }; + programs.bash.initExtra = mkIf cfg.enableBashIntegration ( # Using mkAfter to make it more likely to appear after other # manipulations of the prompt. @@ -130,40 +144,33 @@ in { ${getExe cfg.package} hook fish | source ''); - programs.nushell.extraConfig = mkIf cfg.enableNushellIntegration ( - # Using mkAfter to make it more likely to appear after other - # manipulations of the prompt. - mkAfter '' - $env.config = ($env.config? | default {}) - $env.config.hooks = ($env.config.hooks? | default {}) - $env.config.hooks.pre_prompt = ( - $env.config.hooks.pre_prompt? - | default [] - | append {|| - let direnv = (${getExe cfg.package} export json - | from json - | default {}) - if ($direnv | is-empty) { - return - } - $direnv - | items {|key, value| - { - key: $key - value: (do ( - $env.ENV_CONVERSIONS? - | default {} - | get -i $key - | get -i from_string - | default {|x| $x} - ) $value) - } - } - | transpose -ird - | load-env - } - ) - ''); + # Using mkAfter to make it more likely to appear after other + # manipulations of the prompt. + programs.nushell.extraConfig = mkIf cfg.enableNushellIntegration (mkAfter '' + $env.config = ($env.config? | default {}) + $env.config.hooks = ($env.config.hooks? | default {}) + $env.config.hooks.pre_prompt = ( + $env.config.hooks.pre_prompt? + | default [] + | append {|| + ${getExe cfg.package} export json + | from json --strict + | default {} + | items {|key, value| + let value = do ( + $env.ENV_CONVERSIONS? + | default {} + | get -i $key + | get -i from_string + | default {|x| $x} + ) $value + return [ $key $value ] + } + | into record + | load-env + } + ) + ''); home.sessionVariables = lib.mkIf cfg.silent { DIRENV_LOG_FORMAT = ""; }; }; diff --git a/modules/programs/eza.nix b/modules/programs/eza.nix index 7e002a12e..f35912b8c 100644 --- a/modules/programs/eza.nix +++ b/modules/programs/eza.nix @@ -49,10 +49,21 @@ with lib; }; icons = mkOption { - type = types.bool; - default = false; + type = types.enum [ null true false "auto" "always" "never" ]; + default = null; description = '' Display icons next to file names ({option}`--icons` argument). + + Note, the support for Boolean values is deprecated. + Setting this option to `true` corresponds to `--icons=auto`. + ''; + }; + + colors = mkOption { + type = types.enum [ null "auto" "always" "never" ]; + default = null; + description = '' + Use terminal colors in output ({option}`--color` argument). ''; }; @@ -70,7 +81,15 @@ with lib; config = let cfg = config.programs.eza; - args = escapeShellArgs (optional cfg.icons "--icons" + iconsOption = let + v = if isBool cfg.icons then + (if cfg.icons then "auto" else null) + else + cfg.icons; + in optionals (v != null) [ "--icons" v ]; + + args = escapeShellArgs (iconsOption + ++ optionals (cfg.colors != null) [ "--color" cfg.colors ] ++ optional cfg.git "--git" ++ cfg.extraOptions); optionsAlias = optionalAttrs (args != "") { eza = "eza ${args}"; }; @@ -83,6 +102,12 @@ with lib; lla = "eza -la"; }; in mkIf cfg.enable { + warnings = optional (isBool cfg.icons) '' + Setting programs.eza.icons to a Boolean is deprecated. + Please update your configuration so that + + programs.eza.icons = ${if cfg.icons then ''"auto"'' else "null"}''; + home.packages = [ cfg.package ]; programs.bash.shellAliases = optionsAlias @@ -91,8 +116,17 @@ with lib; programs.zsh.shellAliases = optionsAlias // optionalAttrs cfg.enableZshIntegration aliases; - programs.fish.shellAliases = optionsAlias - // optionalAttrs cfg.enableFishIntegration aliases; + programs.fish = mkMerge [ + (mkIf (!config.programs.fish.preferAbbrs) { + shellAliases = optionsAlias + // optionalAttrs cfg.enableFishIntegration aliases; + }) + + (mkIf config.programs.fish.preferAbbrs { + shellAliases = optionsAlias; + shellAbbrs = optionalAttrs cfg.enableFishIntegration aliases; + }) + ]; programs.ion.shellAliases = optionsAlias // optionalAttrs cfg.enableIonIntegration aliases; diff --git a/modules/programs/firefox.nix b/modules/programs/firefox.nix index ac85990ff..2a2667c35 100644 --- a/modules/programs/firefox.nix +++ b/modules/programs/firefox.nix @@ -11,8 +11,7 @@ let mkFirefoxModule = import ./firefox/mkFirefoxModule.nix; in { - meta.maintainers = - [ maintainers.rycee maintainers.kira-bruneau hm.maintainers.bricked ]; + meta.maintainers = [ maintainers.rycee hm.maintainers.bricked ]; imports = [ (mkFirefoxModule { diff --git a/modules/programs/firefox/mkFirefoxModule.nix b/modules/programs/firefox/mkFirefoxModule.nix index f22af019b..8ef3f12d3 100644 --- a/modules/programs/firefox/mkFirefoxModule.nix +++ b/modules/programs/firefox/mkFirefoxModule.nix @@ -61,7 +61,8 @@ let }) // { General = { StartWithLastProfile = 1; - Version = 2; + } // lib.optionalAttrs (cfg.profileVersion != null) { + Version = cfg.profileVersion; }; }; @@ -100,9 +101,10 @@ let }; in '' ${builtins.toJSON { - version = 4; + version = 5; lastUserContextId = - elemAt (mapAttrsToList (_: container: container.id) containers) 0; + foldlAttrs (acc: _: value: if value.id > acc then value.id else acc) 0 + containers; identities = mapAttrsToList containerToIdentity containers ++ [ { userContextId = 4294967294; # 2^32 - 2 @@ -329,7 +331,7 @@ in { description = "Resulting ${cfg.name} package."; }; - policies = optionalAttrs (unwrappedPackageName != null) (mkOption { + policies = optionalAttrs (wrappedPackageName != null) (mkOption { inherit visible; type = types.attrsOf jsonFormat.type; default = { }; @@ -341,6 +343,13 @@ in { }; }); + profileVersion = mkOption { + internal = true; + type = types.nullOr types.ints.unsigned; + default = if isDarwin then null else 2; + description = "profile version, set null for nix-darwin"; + }; + profiles = mkOption { inherit visible; type = types.attrsOf (types.submodule ({ config, name, ... }: { @@ -538,93 +547,17 @@ in { description = "Whether this is a default profile."; }; - search = { - force = mkOption { - type = with types; bool; - default = false; - description = '' - Whether to force replace the existing search - configuration. This is recommended since ${name} will - replace the symlink for the search configuration on every - launch, but note that you'll lose any existing - configuration by enabling this. - ''; - }; - - default = mkOption { - type = with types; nullOr str; - default = null; - example = "DuckDuckGo"; - description = '' - The default search engine used in the address bar and search bar. - ''; - }; - - privateDefault = mkOption { - type = with types; nullOr str; - default = null; - example = "DuckDuckGo"; - description = '' - The default search engine used in the Private Browsing. - ''; - }; - - order = mkOption { - type = with types; uniq (listOf str); - default = [ ]; - example = [ "DuckDuckGo" "Google" ]; - description = '' - The order the search engines are listed in. Any engines - that aren't included in this list will be listed after - these in an unspecified order. - ''; - }; - - engines = mkOption { - type = with types; attrsOf (attrsOf jsonFormat.type); - default = { }; - example = literalExpression '' - { - "Nix Packages" = { - urls = [{ - template = "https://search.nixos.org/packages"; - params = [ - { name = "type"; value = "packages"; } - { name = "query"; value = "{searchTerms}"; } - ]; - }]; - - icon = "''${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; - definedAliases = [ "@np" ]; - }; - - "NixOS Wiki" = { - urls = [{ template = "https://wiki.nixos.org/index.php?search={searchTerms}"; }]; - iconUpdateURL = "https://wiki.nixos.org/favicon.png"; - updateInterval = 24 * 60 * 60 * 1000; # every day - definedAliases = [ "@nw" ]; - }; - - "Bing".metaData.hidden = true; - "Google".metaData.alias = "@g"; # builtin engines only support specifying one additional alias - } - ''; - description = '' - Attribute set of search engine configurations. Engines - that only have {var}`metaData` specified will - be treated as builtin to ${name}. - - See [SearchEngine.jsm](https://searchfox.org/mozilla-central/rev/669329e284f8e8e2bb28090617192ca9b4ef3380/toolkit/components/search/SearchEngine.jsm#1138-1177) - in Firefox's source for available options. We maintain a - mapping to let you specify all options in the referenced - link without underscores, but it may fall out of date with - future options. - - Note, {var}`icon` is also a special option - added by Home Manager to make it convenient to specify - absolute icon paths. - ''; - }; + search = mkOption { + type = types.submodule (args: + import ./profiles/search.nix { + inherit (args) config; + inherit lib pkgs; + appName = cfg.name; + modulePath = modulePath ++ [ "profiles" name "search" ]; + profilePath = config.path; + }); + default = { }; + description = "Declarative search engine configuration."; }; containersForce = mkOption { @@ -812,15 +745,6 @@ in { its example for how to do this. ''; - programs.firefox.policies = { - ExtensionSettings = listToAttrs (map (lang: - nameValuePair "langpack-${lang}@firefox.mozilla.org" { - installation_mode = "normal_installed"; - install_url = - "https://releases.mozilla.org/pub/firefox/releases/${cfg.package.version}/linux-x86_64/xpi/${lang}.xpi"; - }) cfg.languagePacks); - }; - home.packages = lib.optional (cfg.finalPackage != null) cfg.finalPackage; home.file = mkMerge ([{ @@ -853,152 +777,12 @@ in { force = profile.containersForce; }; - "${profilesPath}/${profile.path}/search.json.mozlz4" = mkIf - (profile.search.default != null || profile.search.privateDefault != null - || profile.search.order != [ ] || profile.search.engines != { }) { - force = profile.search.force; - source = let - settings = { - version = 6; - engines = let - # Map of nice field names to internal field names. - # This is intended to be exhaustive and should be - # updated at every version bump. - internalFieldNames = (genAttrs [ - "name" - "isAppProvided" - "loadPath" - "hasPreferredIcon" - "updateInterval" - "updateURL" - "iconUpdateURL" - "iconURL" - "iconMapObj" - "metaData" - "orderHint" - "definedAliases" - "urls" - ] (name: "_${name}")) // { - searchForm = "__searchForm"; - }; - - processCustomEngineInput = input: - (removeAttrs input [ "icon" ]) - // optionalAttrs (input ? icon) { - # Convenience to specify absolute path to icon - iconURL = "file://${input.icon}"; - } // (optionalAttrs (input ? iconUpdateURL) { - # Convenience to default iconURL to iconUpdateURL so - # the icon is immediately downloaded from the URL - iconURL = input.iconURL or input.iconUpdateURL; - } // { - # Required for custom engine configurations, loadPaths - # are unique identifiers that are generally formatted - # like: [source]/path/to/engine.xml - loadPath = '' - [home-manager]/${moduleName}.profiles.${profile.name}.search.engines."${ - replaceStrings [ "\\" ] [ "\\\\" ] input.name - }"''; - }); - - processEngineInput = name: input: - let - requiredInput = { - inherit name; - isAppProvided = input.isAppProvided or removeAttrs input - [ "metaData" ] == { }; - metaData = input.metaData or { }; - }; - in if requiredInput.isAppProvided then - requiredInput - else - processCustomEngineInput (input // requiredInput); - - buildEngineConfig = name: input: - mapAttrs' (name: value: { - name = internalFieldNames.${name} or name; - inherit value; - }) (processEngineInput name input); - - sortEngineConfigs = configs: - let - buildEngineConfigWithOrder = order: name: - let - config = configs.${name} or { - _name = name; - _isAppProvided = true; - _metaData = { }; - }; - in config // { - _metaData = config._metaData // { inherit order; }; - }; - - engineConfigsWithoutOrder = - attrValues (removeAttrs configs profile.search.order); - - sortedEngineConfigs = - (imap buildEngineConfigWithOrder profile.search.order) - ++ engineConfigsWithoutOrder; - in sortedEngineConfigs; - - engineInput = profile.search.engines // { - # Infer profile.search.default as an app provided - # engine if it's not in profile.search.engines - ${profile.search.default} = - profile.search.engines.${profile.search.default} or { }; - } // { - ${profile.search.privateDefault} = - profile.search.engines.${profile.search.privateDefault} or { }; - }; - in sortEngineConfigs (mapAttrs buildEngineConfig engineInput); - - metaData = optionalAttrs (profile.search.default != null) { - current = profile.search.default; - hash = "@hash@"; - } // optionalAttrs (profile.search.privateDefault != null) { - private = profile.search.privateDefault; - privateHash = "@privateHash@"; - } // { - useSavedOrder = profile.search.order != [ ]; - }; - }; - - # Home Manager doesn't circumvent user consent and isn't acting - # maliciously. We're modifying the search outside of the browser, but - # a claim by Mozilla to remove this would be very anti-user, and - # is unlikely to be an issue for our use case. - disclaimer = appName: - "By modifying this file, I agree that I am doing so " - + "only within ${appName} itself, using official, user-driven search " - + "engine selection processes, and in a way which does not circumvent " - + "user consent. I acknowledge that any attempt to change this file " - + "from outside of ${appName} is a malicious act, and will be responded " - + "to accordingly."; - - salt = if profile.search.default != null then - profile.path + profile.search.default + disclaimer cfg.name - else - null; - - privateSalt = if profile.search.privateDefault != null then - profile.path + profile.search.privateDefault - + disclaimer cfg.name - else - null; - in pkgs.runCommand "search.json.mozlz4" { - nativeBuildInputs = with pkgs; [ mozlz4a openssl ]; - json = builtins.toJSON settings; - inherit salt privateSalt; - } '' - if [[ -n $salt ]]; then - export hash=$(echo -n "$salt" | openssl dgst -sha256 -binary | base64) - export privateHash=$(echo -n "$privateSalt" | openssl dgst -sha256 -binary | base64) - mozlz4a <(substituteStream json search.json.in --subst-var hash --subst-var privateHash) "$out" - else - mozlz4a <(echo "$json") "$out" - fi - ''; - }; + "${profilesPath}/${profile.path}/search.json.mozlz4" = + mkIf (profile.search.enable) { + enable = profile.search.enable; + force = profile.search.force; + source = profile.search.file; + }; "${profilesPath}/${profile.path}/extensions" = mkIf (profile.extensions != [ ]) { @@ -1012,6 +796,16 @@ in { force = true; }; })); - } // setAttrByPath modulePath { finalPackage = wrapPackage cfg.package; }); -} + } // setAttrByPath modulePath { + finalPackage = wrapPackage cfg.package; + policies = { + ExtensionSettings = listToAttrs (map (lang: + nameValuePair "langpack-${lang}@firefox.mozilla.org" { + installation_mode = "normal_installed"; + install_url = + "https://releases.mozilla.org/pub/firefox/releases/${cfg.package.version}/linux-x86_64/xpi/${lang}.xpi"; + }) cfg.languagePacks); + }; + }); +} diff --git a/modules/programs/firefox/profiles/search.nix b/modules/programs/firefox/profiles/search.nix new file mode 100644 index 000000000..69b771aa4 --- /dev/null +++ b/modules/programs/firefox/profiles/search.nix @@ -0,0 +1,251 @@ +{ config, lib, pkgs, appName, modulePath, profilePath }: + +with lib; + +let + jsonFormat = pkgs.formats.json { }; + + # Map of nice field names to internal field names. + # This is intended to be exhaustive and should be + # updated at every version bump. + internalFieldNames = (genAttrs [ + "name" + "isAppProvided" + "loadPath" + "hasPreferredIcon" + "updateInterval" + "updateURL" + "iconUpdateURL" + "iconURL" + "iconMapObj" + "metaData" + "orderHint" + "definedAliases" + "urls" + ] (name: "_${name}")) // { + searchForm = "__searchForm"; + }; + + processCustomEngineInput = input: + (removeAttrs input [ "icon" ]) // optionalAttrs (input ? icon) { + # Convenience to specify absolute path to icon + iconURL = "file://${input.icon}"; + } // (optionalAttrs (input ? iconUpdateURL) { + # Convenience to default iconURL to iconUpdateURL so + # the icon is immediately downloaded from the URL + iconURL = input.iconURL or input.iconUpdateURL; + } // { + # Required for custom engine configurations, loadPaths + # are unique identifiers that are generally formatted + # like: [source]/path/to/engine.xml + loadPath = "[home-manager]/${ + concatStringsSep "." (map strings.escapeNixIdentifier + (modulePath ++ [ "engines" input.name ])) + }"; + }); + + processEngineInput = name: input: + let + requiredInput = { + inherit name; + isAppProvided = input.isAppProvided or removeAttrs input [ "metaData" ] + == { }; + metaData = input.metaData or { }; + }; + in if requiredInput.isAppProvided then + requiredInput + else + processCustomEngineInput (input // requiredInput); + + buildEngineConfig = name: input: + mapAttrs' (name: value: { + name = internalFieldNames.${name} or name; + inherit value; + }) (processEngineInput name input); + + sortEngineConfigs = configs: + let + buildEngineConfigWithOrder = order: name: + let + config = configs.${name} or { + _name = name; + _isAppProvided = true; + _metaData = { }; + }; + in config // { _metaData = config._metaData // { inherit order; }; }; + + engineConfigsWithoutOrder = attrValues (removeAttrs configs config.order); + + sortedEngineConfigs = (imap buildEngineConfigWithOrder config.order) + ++ engineConfigsWithoutOrder; + in sortedEngineConfigs; + + engineInput = config.engines // { + # Infer config.default as an app provided + # engine if it's not in config.engines + ${config.default} = config.engines.${config.default} or { }; + } // { + ${config.privateDefault} = config.engines.${config.privateDefault} or { }; + }; + + settings = { + version = 6; + engines = sortEngineConfigs (mapAttrs buildEngineConfig engineInput); + + metaData = optionalAttrs (config.default != null) { + current = config.default; + hash = "@hash@"; + } // optionalAttrs (config.privateDefault != null) { + private = config.privateDefault; + privateHash = "@privateHash@"; + } // { + useSavedOrder = config.order != [ ]; + }; + }; + + # Home Manager doesn't circumvent user consent and isn't acting + # maliciously. We're modifying the search outside of the browser, but + # a claim by Mozilla to remove this would be very anti-user, and + # is unlikely to be an issue for our use case. + disclaimer = "By modifying this file, I agree that I am doing so " + + "only within ${appName} itself, using official, user-driven search " + + "engine selection processes, and in a way which does not circumvent " + + "user consent. I acknowledge that any attempt to change this file " + + "from outside of ${appName} is a malicious act, and will be responded " + + "to accordingly."; + + salt = if config.default != null then + profilePath + config.default + disclaimer + else + null; + + privateSalt = if config.privateDefault != null then + profilePath + config.privateDefault + disclaimer + else + null; + + file = pkgs.runCommand "search.json.mozlz4" { + nativeBuildInputs = with pkgs; [ mozlz4a openssl ]; + json = builtins.toJSON settings; + inherit salt privateSalt; + } '' + if [[ -n $salt ]]; then + export hash=$(echo -n "$salt" | openssl dgst -sha256 -binary | base64) + export privateHash=$(echo -n "$privateSalt" | openssl dgst -sha256 -binary | base64) + mozlz4a <(substituteStream json search.json.in --subst-var hash --subst-var privateHash) "$out" + else + mozlz4a <(echo "$json") "$out" + fi + ''; +in { + imports = [ (pkgs.path + "/nixos/modules/misc/meta.nix") ]; + + meta.maintainers = with maintainers; [ kira-bruneau ]; + + options = { + enable = mkOption { + type = with types; bool; + default = config.default != null || config.privateDefault != null + || config.order != [ ] || config.engines != { }; + internal = true; + }; + + force = mkOption { + type = with types; bool; + default = false; + description = '' + Whether to force replace the existing search + configuration. This is recommended since ${appName} will + replace the symlink for the search configuration on every + launch, but note that you'll lose any existing configuration + by enabling this. + ''; + }; + + default = mkOption { + type = with types; nullOr str; + default = null; + example = "DuckDuckGo"; + description = '' + The default search engine used in the address bar and search + bar. + ''; + }; + + privateDefault = mkOption { + type = with types; nullOr str; + default = null; + example = "DuckDuckGo"; + description = '' + The default search engine used in the Private Browsing. + ''; + }; + + order = mkOption { + type = with types; uniq (listOf str); + default = [ ]; + example = [ "DuckDuckGo" "Google" ]; + description = '' + The order the search engines are listed in. Any engines that + aren't included in this list will be listed after these in an + unspecified order. + ''; + }; + + engines = mkOption { + type = with types; attrsOf (attrsOf jsonFormat.type); + default = { }; + example = literalExpression '' + { + "Nix Packages" = { + urls = [{ + template = "https://search.nixos.org/packages"; + params = [ + { name = "type"; value = "packages"; } + { name = "query"; value = "{searchTerms}"; } + ]; + }]; + + icon = "''${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; + definedAliases = [ "@np" ]; + }; + + "NixOS Wiki" = { + urls = [{ template = "https://wiki.nixos.org/index.php?search={searchTerms}"; }]; + iconUpdateURL = "https://wiki.nixos.org/favicon.png"; + updateInterval = 24 * 60 * 60 * 1000; # every day + definedAliases = [ "@nw" ]; + }; + + "Bing".metaData.hidden = true; + "Google".metaData.alias = "@g"; # builtin engines only support specifying one additional alias + } + ''; + + description = '' + Attribute set of search engine configurations. Engines that + only have {var}`metaData` specified will be treated as builtin + to ${appName}. + + See [SearchEngine.jsm](https://searchfox.org/mozilla-central/rev/669329e284f8e8e2bb28090617192ca9b4ef3380/toolkit/components/search/SearchEngine.jsm#1138-1177) + in ${appName}'s source for available options. We maintain a + mapping to let you specify all options in the referenced link + without underscores, but it may fall out of date with future + options. + + Note, {var}`icon` is also a special option added by Home + Manager to make it convenient to specify absolute icon paths. + ''; + }; + + file = mkOption { + type = with types; path; + default = file; + internal = true; + readOnly = true; + description = '' + Resulting search.json.mozlz4 file. + ''; + }; + }; +} diff --git a/modules/programs/fish.nix b/modules/programs/fish.nix index fc11e5124..02141042d 100644 --- a/modules/programs/fish.nix +++ b/modules/programs/fish.nix @@ -253,6 +253,12 @@ in { ''; }; + generateCompletions = mkEnableOption + "the automatic generation of completions based upon installed man pages" + // { + default = true; + }; + shellAliases = mkOption { type = with types; attrsOf str; default = { }; @@ -288,6 +294,16 @@ in { ''; }; + preferAbbrs = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + If enabled, abbreviations will be preferred over aliases when + other modules define aliases for fish. + ''; + }; + shellInit = mkOption { type = types.lines; default = ""; @@ -380,9 +396,9 @@ in { }; config = mkIf cfg.enable (mkMerge [ - { - home.packages = [ cfg.package ]; + { home.packages = [ cfg.package ]; } + (mkIf cfg.generateCompletions { # Support completion for `man` by building a cache for `apropos`. programs.man.generateCaches = mkDefault true; @@ -446,7 +462,9 @@ in { set fish_complete_path $prev "${config.xdg.dataHome}/fish/home-manager_generated_completions" $post end ''; + }) + { xdg.configFile."fish/config.fish".source = fishIndent "config.fish" '' # ~/.config/fish/config.fish: DO NOT EDIT -- this file has been generated # automatically by home-manager. diff --git a/modules/programs/floorp.nix b/modules/programs/floorp.nix new file mode 100644 index 000000000..0f231bdf4 --- /dev/null +++ b/modules/programs/floorp.nix @@ -0,0 +1,29 @@ +{ lib, ... }: + +with lib; + +let + + modulePath = [ "programs" "floorp" ]; + + mkFirefoxModule = import ./firefox/mkFirefoxModule.nix; + +in { + meta.maintainers = [ hm.maintainers.bricked ]; + + imports = [ + (mkFirefoxModule { + inherit modulePath; + name = "Floorp"; + wrappedPackageName = "floorp"; + unwrappedPackageName = "floorp-unwrapped"; + visible = true; + + platforms.linux = { + configPath = ".floorp"; + vendorPath = ".floorp"; + }; + platforms.darwin = { configPath = "Library/Application Support/Floorp"; }; + }) + ]; +} diff --git a/modules/programs/git-credential-oauth.nix b/modules/programs/git-credential-oauth.nix index 4833e8068..499c7c4c1 100644 --- a/modules/programs/git-credential-oauth.nix +++ b/modules/programs/git-credential-oauth.nix @@ -12,13 +12,27 @@ in { enable = lib.mkEnableOption "Git authentication handler for OAuth"; package = lib.mkPackageOption pkgs "git-credential-oauth" { }; + + extraFlags = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + example = lib.literalExpression ''[ "-device" ]''; + description = '' + Extra command-line arguments passed to git-credential-oauth. + + For valid arguments, see {manpage}`git-credential-oauth(1)`. + ''; + }; }; }; config = lib.mkIf cfg.enable { home.packages = [ cfg.package ]; - programs.git.extraConfig.credential.helper = - [ "${cfg.package}/bin/git-credential-oauth" ]; + programs.git.extraConfig.credential.helper = lib.mkAfter [ + ("${cfg.package}/bin/git-credential-oauth" + + lib.optionalString (cfg.extraFlags != [ ]) + " ${lib.strings.concatStringsSep " " cfg.extraFlags}") + ]; }; } diff --git a/modules/programs/git.nix b/modules/programs/git.nix index 3061feff7..dfdac2d4b 100644 --- a/modules/programs/git.nix +++ b/modules/programs/git.nix @@ -214,6 +214,59 @@ in { }; }; + maintenance = { + enable = mkEnableOption "" // { + description = '' + Enable the automatic {command}`git maintenance`. + + See . + ''; + }; + + repositories = mkOption { + type = with types; listOf str; + default = [ ]; + description = '' + Repositories on which {command}`git maintenance` should run. + + Should be a list of absolute paths. + ''; + }; + + timers = mkOption { + type = types.attrsOf types.str; + default = { + hourly = "*-*-* 1..23:53:00"; + daily = "Tue..Sun *-*-* 0:53:00"; + weekly = "Mon 0:53:00"; + }; + description = '' + Systemd timers to create for scheduled {command}`git maintenance`. + + Key is passed to `--schedule` argument in {command}`git maintenance run` + and value is passed to `Timer.OnCalendar` in `systemd.user.timers`. + ''; + }; + }; + + diff-highlight = { + enable = mkEnableOption "" // { + description = '' + Enable the contrib {command}`diff-highlight` syntax highlighter. + See , + ''; + }; + + pagerOpts = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "--tabs=4" "-RFX" ]; + description = '' + Arguments to be passed to {command}`less`. + ''; + }; + }; + difftastic = { enable = mkEnableOption "" // { description = '' @@ -222,6 +275,8 @@ in { ''; }; + package = mkPackageOption pkgs "difftastic" { }; + background = mkOption { type = types.enum [ "light" "dark" ]; default = "light"; @@ -358,11 +413,15 @@ in { home.packages = [ cfg.package ]; assertions = [{ assertion = let - enabled = - [ cfg.delta.enable cfg.diff-so-fancy.enable cfg.difftastic.enable ]; + enabled = [ + cfg.delta.enable + cfg.diff-so-fancy.enable + cfg.difftastic.enable + cfg.diff-highlight.enable + ]; in count id enabled <= 1; message = - "Only one of 'programs.git.delta.enable' or 'programs.git.difftastic.enable' or 'programs.git.diff-so-fancy.enable' can be set to true at the same time."; + "Only one of 'programs.git.delta.enable' or 'programs.git.difftastic.enable' or 'programs.git.diff-so-fancy.enable' or 'programs.git.diff-highlight' can be set to true at the same time."; }]; programs.git.iniContent.user = { @@ -477,12 +536,66 @@ in { }; }) + (mkIf cfg.maintenance.enable { + programs.git.iniContent.maintenance.repo = cfg.maintenance.repositories; + + systemd.user.services."git-maintenance@" = { + Unit = { + Description = "Optimize Git repositories data"; + Documentation = [ "man:git-maintenance(1)" ]; + }; + + Service = { + Type = "oneshot"; + ExecStart = let exe = lib.getExe cfg.package; + in '' + "${exe}" --exec-path="${exe}" for-each-repo --config=maintenance.repo maintenance run --schedule=%i + ''; + LockPersonality = "yes"; + MemoryDenyWriteExecute = "yes"; + NoNewPrivileges = "yes"; + RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_VSOCK"; + RestrictNamespaces = "yes"; + RestrictRealtime = "yes"; + RestrictSUIDSGID = "yes"; + SystemCallArchitectures = "native"; + SystemCallFilter = "@system-service"; + }; + }; + + systemd.user.timers = let + toSystemdTimer = name: time: + lib.attrsets.nameValuePair "git-maintenance@${name}" { + Unit.Description = "Optimize Git repositories data"; + + Timer = { + OnCalendar = time; + Persistent = true; + }; + + Install.WantedBy = [ "timers.target" ]; + }; + in lib.attrsets.mapAttrs' toSystemdTimer cfg.maintenance.timers; + }) + + (mkIf cfg.diff-highlight.enable { + programs.git.iniContent = let + dhCommand = + "${cfg.package}/share/git/contrib/diff-highlight/diff-highlight"; + in { + core.pager = "${dhCommand} | ${getExe pkgs.less} ${ + escapeShellArgs cfg.diff-highlight.pagerOpts + }"; + interactive.diffFilter = dhCommand; + }; + }) + (mkIf cfg.difftastic.enable { - home.packages = [ pkgs.difftastic ]; + home.packages = [ cfg.difftastic.package ]; programs.git.iniContent = let difftCommand = concatStringsSep " " [ - "${pkgs.difftastic}/bin/difft" + "${getExe cfg.difftastic.package}" "--color ${cfg.difftastic.color}" "--background ${cfg.difftastic.background}" "--display ${cfg.difftastic.display}" diff --git a/modules/programs/granted.nix b/modules/programs/granted.nix index a09169250..93cdb97df 100644 --- a/modules/programs/granted.nix +++ b/modules/programs/granted.nix @@ -28,7 +28,7 @@ in { programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' function assume() { export GRANTED_ALIAS_CONFIGURED="true" - source ${package}/bin/.assume-wrapped "$@" + source ${package}/bin/assume "$@" unset GRANTED_ALIAS_CONFIGURED } ''; diff --git a/modules/programs/helix.nix b/modules/programs/helix.nix index 96c5bdbf1..01af7b14e 100644 --- a/modules/programs/helix.nix +++ b/modules/programs/helix.nix @@ -15,6 +15,7 @@ in { type = types.package; default = pkgs.helix; defaultText = literalExpression "pkgs.helix"; + example = literalExpression "pkgs.evil-helix"; description = "The package to use for helix."; }; @@ -75,7 +76,6 @@ in { default = { }; example = literalExpression '' { - # the language-server option currently requires helix from the master branch at https://github.com/helix-editor/helix/ language-server.typescript-language-server = with pkgs.nodePackages; { command = "''${typescript-language-server}/bin/typescript-language-server"; args = [ "--stdio" "--tsserver-path=''${typescript}/lib/node_modules/typescript/lib" ]; diff --git a/modules/programs/htop.nix b/modules/programs/htop.nix index 1c569c404..b4004942c 100644 --- a/modules/programs/htop.nix +++ b/modules/programs/htop.nix @@ -113,7 +113,8 @@ in { enable = mkEnableOption "htop"; settings = mkOption { - type = types.attrs; + type = with types; + attrsOf (oneOf [ bool int str (listOf (oneOf [ int str ])) ]); default = { }; example = literalExpression '' { diff --git a/modules/programs/k9s.nix b/modules/programs/k9s.nix index 6ef53291a..0dd107883 100644 --- a/modules/programs/k9s.nix +++ b/modules/programs/k9s.nix @@ -9,11 +9,7 @@ let inherit (pkgs.stdenv.hostPlatform) isDarwin; in { - meta.maintainers = with maintainers; [ - katexochen - liyangau - hm.maintainers.LucasWagler - ]; + meta.maintainers = with maintainers; [ liyangau hm.maintainers.LucasWagler ]; imports = [ (mkRenamedOptionModule [ "programs" "k9s" "skin" ] [ @@ -46,7 +42,7 @@ in { }; skins = mkOption { - type = types.attrsOf yamlFormat.type; + type = with types; attrsOf (either yamlFormat.type path); default = { }; description = '' Skin files written to {file}`$XDG_CONFIG_HOME/k9s/skins/` (linux) @@ -54,13 +50,16 @@ in { for supported values. ''; example = literalExpression '' - my_blue_skin = { - k9s = { - body = { - fgColor = "dodgerblue"; + { + my_blue_skin = { + k9s = { + body = { + fgColor = "dodgerblue"; + }; }; }; - }; + my_red_skin = ./red_skin.yaml; + } ''; }; @@ -174,7 +173,10 @@ in { "k9s/skins/${name}.yaml" else "Library/Application Support/k9s/skins/${name}.yaml") { - source = yamlFormat.generate "k9s-skin-${name}.yaml" value; + source = if lib.types.path.check value then + value + else + yamlFormat.generate "k9s-skin-${name}.yaml" value; }) cfg.skins; enableXdgConfig = !isDarwin || config.xdg.enable; diff --git a/modules/programs/kitty.nix b/modules/programs/kitty.nix index 48ec13da4..9854fe69c 100644 --- a/modules/programs/kitty.nix +++ b/modules/programs/kitty.nix @@ -3,10 +3,9 @@ with lib; let - cfg = config.programs.kitty; - eitherStrBoolInt = with types; either str (either bool int); + settingsValueType = with types; oneOf [ str bool int float ]; optionalPackage = opt: optional (opt != null && opt.package != null) opt.package; @@ -57,6 +56,26 @@ let ''; }; in { + imports = [ + (mkChangedOptionModule [ "programs" "kitty" "theme" ] [ + "programs" + "kitty" + "themeFile" + ] (config: + let value = getAttrFromPath [ "programs" "kitty" "theme" ] config; + in if value != null then + (let + matching = filter (x: x.name == value) (builtins.fromJSON + (builtins.readFile + "${pkgs.kitty-themes}/share/kitty-themes/themes.json")); + in throwIf (length matching == 0) + "kitty-themes does not contain a theme named ${value}" + strings.removeSuffix ".conf" + (strings.removePrefix "themes/" (head matching).file)) + else + null)) + ]; + options.programs.kitty = { enable = mkEnableOption "Kitty terminal emulator"; @@ -83,7 +102,7 @@ in { }; settings = mkOption { - type = types.attrsOf eitherStrBoolInt; + type = types.attrsOf settingsValueType; default = { }; example = literalExpression '' { @@ -100,16 +119,16 @@ in { ''; }; - theme = mkOption { + themeFile = mkOption { type = types.nullOr types.str; default = null; description = '' - Apply a Kitty color theme. This option takes the friendly name of - any theme given by the command {command}`kitty +kitten themes`. - See - for more details. + Apply a Kitty color theme. This option takes the file name of a theme + in `kitty-themes`, without the `.conf` suffix. See + for a + list of themes. ''; - example = "Space Gray Eighties"; + example = "SpaceGray_Eighties"; }; font = mkOption { @@ -146,11 +165,11 @@ in { type = types.str; default = "no-rc"; example = "no-cursor"; - apply = (o: + apply = o: let modes = splitString " " o; filtered = filter (m: m != "no-rc") modes; - in concatStringsSep " " (concatLists [ [ "no-rc" ] filtered ])); + in concatStringsSep " " (concatLists [ [ "no-rc" ] filtered ]); description = '' Set the mode of the shell integration. This accepts the same options as the `shell_integration` option of Kitty. Note that @@ -184,24 +203,15 @@ in { text = '' # Generated by Home Manager. # See https://sw.kovidgoyal.net/kitty/conf.html - '' + concatStringsSep "\n" ([ - + '' + concatStringsSep "\n" [ (optionalString (cfg.font != null) '' font_family ${cfg.font.name} ${optionalString (cfg.font.size != null) "font_size ${toString cfg.font.size}"} '') - (optionalString (cfg.theme != null) '' - include ${pkgs.kitty-themes}/share/kitty-themes/${ - let - matching = filter (x: x.name == cfg.theme) (builtins.fromJSON - (builtins.readFile - "${pkgs.kitty-themes}/share/kitty-themes/themes.json")); - in throwIf (length matching == 0) - "kitty-themes does not contain a theme named ${cfg.theme}" - (head matching).file - } + (optionalString (cfg.themeFile != null) '' + include ${pkgs.kitty-themes}/share/kitty-themes/themes/${cfg.themeFile}.conf '') '' # Shell integration is sourced and configured manually @@ -211,13 +221,23 @@ in { (toKittyKeybindings cfg.keybindings) (toKittyEnv cfg.environment) cfg.extraConfig - ]); + ]; } // optionalAttrs pkgs.stdenv.hostPlatform.isLinux { onChange = '' ${pkgs.procps}/bin/pkill -USR1 -u $USER kitty || true ''; }; + home.activation.checkKittyTheme = mkIf (cfg.themeFile != null) (let + themePath = + "${pkgs.kitty-themes}/share/kitty-themes/themes/${cfg.themeFile}.conf"; + in hm.dag.entryBefore [ "writeBoundary" ] '' + if [[ ! -f "${themePath}" ]]; then + errorEcho "kitty-themes does not contain the theme file ${themePath}!" + exit 1 + fi + ''); + xdg.configFile."kitty/macos-launch-services-cmdline" = mkIf (cfg.darwinLaunchOptions != null && pkgs.stdenv.hostPlatform.isDarwin) { text = concatStringsSep " " cfg.darwinLaunchOptions; diff --git a/modules/programs/lsd.nix b/modules/programs/lsd.nix index c333918a8..0053a494f 100644 --- a/modules/programs/lsd.nix +++ b/modules/programs/lsd.nix @@ -74,7 +74,15 @@ in { programs.zsh.shellAliases = mkIf cfg.enableAliases aliases; - programs.fish.shellAliases = mkIf cfg.enableAliases aliases; + programs.fish = mkMerge [ + (mkIf (!config.programs.fish.preferAbbrs) { + shellAliases = mkIf cfg.enableAliases aliases; + }) + + (mkIf config.programs.fish.preferAbbrs { + shellAbbrs = mkIf cfg.enableAliases aliases; + }) + ]; programs.lsd = mkIf (cfg.colors != { }) { settings.color.theme = "custom"; }; diff --git a/modules/programs/neovide.nix b/modules/programs/neovide.nix new file mode 100644 index 000000000..3b40fb3eb --- /dev/null +++ b/modules/programs/neovide.nix @@ -0,0 +1,52 @@ +{ config, lib, pkgs, ... }: + +let + + cfg = config.programs.neovide; + settingsFormat = pkgs.formats.toml { }; + +in { + meta.maintainers = [ lib.hm.maintainers.NitroSniper ]; + + options.programs.neovide = { + enable = lib.mkEnableOption "Neovide, No Nonsense Neovim Client in Rust"; + + package = lib.mkPackageOption pkgs "neovide" { }; + + settings = lib.mkOption { + type = settingsFormat.type; + example = lib.literalExpression '' + { + fork = false; + frame = "full"; + idle = true; + maximized = false; + neovim-bin = "/usr/bin/nvim"; + no-multigrid = false; + srgb = false; + tabs = true; + theme = "auto"; + title-hidden = true; + vsync = true; + wsl = false; + + font = { + normal = []; + size = 14.0; + }; + } + ''; + description = '' + Neovide configuration. + For available settings see . + For any option not found will need to be done in your neovim's config instead. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + home.packages = [ cfg.package ]; + xdg.configFile."neovide/config.toml".source = + settingsFormat.generate "config.toml" cfg.settings; + }; +} diff --git a/modules/programs/neovim.nix b/modules/programs/neovim.nix index fad05c1c4..e8be25f92 100644 --- a/modules/programs/neovim.nix +++ b/modules/programs/neovim.nix @@ -398,6 +398,13 @@ in { customRC = cfg.extraConfig; }; + wrappedNeovim' = pkgs.wrapNeovimUnstable cfg.package (neovimConfig // { + wrapperArgs = + (lib.escapeShellArgs (neovimConfig.wrapperArgs ++ cfg.extraWrapperArgs)) + + " " + extraMakeWrapperArgs + " " + extraMakeWrapperLuaCArgs + " " + + extraMakeWrapperLuaArgs; + wrapRc = false; + }); in mkIf cfg.enable { programs.neovim.generatedConfigViml = neovimConfig.neovimRcContent; @@ -414,17 +421,18 @@ in { home.sessionVariables = mkIf cfg.defaultEditor { EDITOR = "nvim"; }; + home.shellAliases = mkIf cfg.vimdiffAlias { vimdiff = "nvim -d"; }; + xdg.configFile = let hasLuaConfig = hasAttr "lua" config.programs.neovim.generatedConfigs; in mkMerge ( # writes runtime (map (x: x.runtime) pluginsNormalized) ++ [{ "nvim/init.lua" = let - luaRcContent = - lib.optionalString (neovimConfig.neovimRcContent != "") + luaRcContent = lib.optionalString (wrappedNeovim'.initRc != "") "vim.cmd [[source ${ pkgs.writeText "nvim-init-home-manager.vim" - neovimConfig.neovimRcContent + wrappedNeovim'.initRc }]]" + config.programs.neovim.extraLuaConfig + lib.optionalString hasLuaConfig config.programs.neovim.generatedConfigs.lua; @@ -435,17 +443,6 @@ in { }; }]); - programs.neovim.finalPackage = pkgs.wrapNeovimUnstable cfg.package - (neovimConfig // { - wrapperArgs = (lib.escapeShellArgs - (neovimConfig.wrapperArgs ++ cfg.extraWrapperArgs)) + " " - + extraMakeWrapperArgs + " " + extraMakeWrapperLuaCArgs + " " - + extraMakeWrapperLuaArgs; - wrapRc = false; - }); - - programs.bash.shellAliases = mkIf cfg.vimdiffAlias { vimdiff = "nvim -d"; }; - programs.fish.shellAliases = mkIf cfg.vimdiffAlias { vimdiff = "nvim -d"; }; - programs.zsh.shellAliases = mkIf cfg.vimdiffAlias { vimdiff = "nvim -d"; }; + programs.neovim.finalPackage = wrappedNeovim'; }; } diff --git a/modules/programs/nh.nix b/modules/programs/nh.nix new file mode 100644 index 000000000..a5e8dcfaf --- /dev/null +++ b/modules/programs/nh.nix @@ -0,0 +1,94 @@ +{ config, osConfig, lib, pkgs, ... }: + +let + + cfg = config.programs.nh; + +in { + meta.maintainers = with lib.maintainers; [ johnrtitor ]; + + options.programs.nh = { + enable = lib.mkEnableOption "nh, yet another Nix CLI helper"; + + package = lib.mkPackageOption pkgs "nh" { }; + + flake = lib.mkOption { + type = lib.types.nullOr lib.types.path; + default = null; + description = '' + The path that will be used for the {env}`FLAKE` environment variable. + + {env}`FLAKE` is used by nh as the default flake for performing actions, + like {command}`nh os switch`. + ''; + }; + + clean = { + enable = lib.mkEnableOption '' + periodic garbage collection for user profile and nix store with nh clean + user''; + + dates = lib.mkOption { + type = lib.types.singleLineStr; + default = "weekly"; + description = '' + How often cleanup is performed. + + The format is described in {manpage}`systemd.time(7)`. + ''; + }; + + extraArgs = lib.mkOption { + type = lib.types.singleLineStr; + default = ""; + example = "--keep 5 --keep-since 3d"; + description = '' + Options given to nh clean when the service is run automatically. + + See `nh clean all --help` for more information. + ''; + }; + }; + }; + + config = { + warnings = lib.optionals (!(cfg.clean.enable -> !osConfig.nix.gc.automatic)) + [ + "programs.nh.clean.enable and nix.gc.automatic (system-wide in configuration.nix) are both enabled. Please use one or the other to avoid conflict." + ]; + + assertions = [{ + assertion = (cfg.flake != null) -> !(lib.hasSuffix ".nix" cfg.flake); + message = "nh.flake must be a directory, not a nix file"; + }]; + + home = lib.mkIf cfg.enable { + packages = [ cfg.package ]; + sessionVariables = lib.mkIf (cfg.flake != null) { FLAKE = cfg.flake; }; + }; + + systemd.user = lib.mkIf cfg.clean.enable { + services.nh-clean = { + Unit.Description = "Nh clean (user)"; + + Service = { + Type = "oneshot"; + ExecStart = + "exec ${lib.getExe cfg.package} clean user ${cfg.clean.extraArgs}"; + Environment = "PATH=$PATH:${config.nix.package}"; + }; + }; + + timers.nh-clean = { + Unit.Description = "Run nh clean"; + + Timer = { + OnCalendar = cfg.clean.dates; + Persistent = true; + }; + + Install.WantedBy = [ "timers.target" ]; + }; + }; + }; +} diff --git a/modules/programs/nushell.nix b/modules/programs/nushell.nix index 2ebd9554c..6586d1e1a 100644 --- a/modules/programs/nushell.nix +++ b/modules/programs/nushell.nix @@ -39,7 +39,7 @@ let }; }); in { - meta.maintainers = [ maintainers.Philipp-M ]; + meta.maintainers = [ maintainers.Philipp-M maintainers.joaquintrinanes ]; imports = [ (mkRemovedOptionModule [ "programs" "nushell" "settings" ] '' @@ -145,11 +145,24 @@ in { }; environmentVariables = mkOption { - type = types.attrsOf types.str; + type = types.attrsOf hm.types.nushellValue; default = { }; - example = { FOO = "BAR"; }; + example = literalExpression '' + { + FOO = "BAR"; + LIST_VALUE = [ "foo" "bar" ]; + NU_LIB_DIRS = lib.concatStringsSep ":" [ ./scripts ]; + PROMPT_COMMAND = lib.hm.nushell.mkNushellInline '''{|| "> "}'''; + ENV_CONVERSIONS.PATH = { + from_string = lib.hm.nushell.mkNushellInline "{|s| $s | split row (char esep) }"; + to_string = lib.hm.nushell.mkNushellInline "{|v| $v | str join (char esep) }"; + }; + } + ''; description = '' - An attribute set that maps an environment variable to a shell interpreted string. + Environment variables to be set. + + Inline values can be set with `lib.hm.nushell.mkNushellInline`. ''; }; }; @@ -173,9 +186,11 @@ in { }) (let - envVarsStr = concatStringsSep "\n" - (mapAttrsToList (k: v: "$env.${k} = ${v}") cfg.environmentVariables); - in mkIf (cfg.envFile != null || cfg.extraEnv != "" || envVarsStr != "") { + hasEnvVars = cfg.environmentVariables != { }; + envVarsStr = '' + load-env ${hm.nushell.toNushell { } cfg.environmentVariables} + ''; + in mkIf (cfg.envFile != null || cfg.extraEnv != "" || hasEnvVars) { "${configDir}/env.nu".text = mkMerge [ (mkIf (cfg.envFile != null) cfg.envFile.text) cfg.extraEnv diff --git a/modules/programs/pls.nix b/modules/programs/pls.nix index c56c4b01f..8abb82618 100644 --- a/modules/programs/pls.nix +++ b/modules/programs/pls.nix @@ -9,7 +9,7 @@ let aliases = { ls = "${cfg.package}/bin/pls"; ll = - "${cfg.package}/bin/pls -d perms -d user -d group -d size -d mtime -d git"; + "${cfg.package}/bin/pls -d perm -d user -d group -d size -d mtime -d git"; }; in { @@ -28,7 +28,15 @@ in { programs.bash.shellAliases = mkIf cfg.enableAliases aliases; - programs.fish.shellAliases = mkIf cfg.enableAliases aliases; + programs.fish = mkMerge [ + (mkIf (!config.programs.fish.preferAbbrs) { + shellAliases = mkIf cfg.enableAliases aliases; + }) + + (mkIf config.programs.fish.preferAbbrs { + shellAbbrs = mkIf cfg.enableAliases aliases; + }) + ]; programs.zsh.shellAliases = mkIf cfg.enableAliases aliases; }; diff --git a/modules/programs/pqiv.nix b/modules/programs/pqiv.nix index ed1a0b280..a99b28de8 100644 --- a/modules/programs/pqiv.nix +++ b/modules/programs/pqiv.nix @@ -23,14 +23,13 @@ in { default = { }; description = '' Configuration written to {file}`$XDG_CONFIG_HOME/pqivrc`. See - {manpage}`pqiv(1)` for a list of available options. To set a - boolean flag, set the value to 1. + {manpage}`pqiv(1)` for a list of available options. ''; example = literalExpression '' { options = { - lazy-load = 1; - hide-info-box = 1; + lazy-load = true; + hide-info-box = true; background-pattern = "black"; thumbnail-size = "256x256"; command-1 = "thunar"; @@ -68,7 +67,15 @@ in { xdg.configFile."pqivrc" = mkIf (cfg.settings != { } && cfg.extraConfig != "") { text = lib.concatLines [ - (generators.toINI { } cfg.settings) + (generators.toINI { + mkKeyValue = key: value: + let + value' = if isBool value then + (if value then "1" else "0") + else + toString value; + in "${key} = ${value'}"; + } cfg.settings) cfg.extraConfig ]; }; diff --git a/modules/programs/spotify-player.nix b/modules/programs/spotify-player.nix index 83eefe12d..35d3933bc 100644 --- a/modules/programs/spotify-player.nix +++ b/modules/programs/spotify-player.nix @@ -1,12 +1,12 @@ { config, lib, pkgs, ... }: let - inherit (lib) - mkEnableOption mkPackageOption mkOption types literalExpression mkIf; + inherit (lib) mkEnableOption mkPackageOption mkOption literalExpression mkIf; + inherit (lib.types) listOf; cfg = config.programs.spotify-player; tomlFormat = pkgs.formats.toml { }; - + tomlType = tomlFormat.type; in { meta.maintainers = with lib.hm.maintainers; [ diniamo ]; @@ -16,7 +16,7 @@ in { package = mkPackageOption pkgs "spotify-player" { }; settings = mkOption { - type = tomlFormat.type; + type = tomlType; default = { }; example = literalExpression '' { @@ -43,7 +43,7 @@ in { }; themes = mkOption { - type = types.listOf tomlFormat.type; + type = listOf tomlType; default = [ ]; example = literalExpression '' [ @@ -94,7 +94,7 @@ in { }; keymaps = mkOption { - type = types.listOf tomlFormat.type; + type = listOf tomlType; default = [ ]; example = literalExpression '' [ @@ -129,6 +129,36 @@ in { for the full list of options. ''; }; + + actions = mkOption { + type = listOf tomlType; + default = [ ]; + example = literalExpression '' + [ + { + action = "GoToArtist"; + key_sequence = "g A"; + } + { + action = "GoToAlbum"; + key_sequence = "g B"; + target = "PlayingTrack"; + } + { + action = "ToggleLiked"; + key_sequence = "C-l"; + } + ] + ''; + description = '' + Configuration written to the `actions` field of + {file}`$XDG_CONFIG_HOME/spotify-player/keymap.toml`. + + See + + for the full list of options. + ''; + }; }; config = mkIf cfg.enable { @@ -146,7 +176,7 @@ in { "spotify-player/keymap.toml" = mkIf (cfg.keymaps != [ ]) { source = tomlFormat.generate "spotify-player-keymap" { - inherit (cfg) keymaps; + inherit (cfg) keymaps actions; }; }; }; diff --git a/modules/programs/taskwarrior.nix b/modules/programs/taskwarrior.nix index e90b1eb23..9b5af43ee 100644 --- a/modules/programs/taskwarrior.nix +++ b/modules/programs/taskwarrior.nix @@ -85,7 +85,8 @@ in { ''; }; - package = mkPackageOption pkgs "taskwarrior" { }; + package = + mkPackageOption pkgs "taskwarrior" { example = "pkgs.taskwarrior3"; }; }; }; diff --git a/modules/programs/thunderbird.nix b/modules/programs/thunderbird.nix index c15a946ec..ad7a1360f 100644 --- a/modules/programs/thunderbird.nix +++ b/modules/programs/thunderbird.nix @@ -7,6 +7,11 @@ let cfg = config.programs.thunderbird; + thunderbirdJson = types.attrsOf (pkgs.formats.json { }).type // { + description = + "Thunderbird preference (int, bool, string, and also attrs, list, float as a JSON string)"; + }; + enabledAccounts = attrValues (filterAttrs (_: a: a.thunderbird.enable) config.accounts.email.accounts); @@ -161,11 +166,21 @@ in { }; settings = mkOption { - type = with types; attrsOf (oneOf [ bool int str ]); + type = thunderbirdJson; default = { }; example = literalExpression '' { "mail.spellcheck.inline" = false; + "mailnews.database.global.views.global.columns" = { + selectCol = { + visible = false; + ordinal = 1; + }; + threadCol = { + visible = true; + ordinal = 2; + }; + }; } ''; description = '' @@ -210,13 +225,27 @@ in { Extra preferences to add to {file}`user.js`. ''; }; + + search = mkOption { + type = types.submodule (args: + import ./firefox/profiles/search.nix { + inherit (args) config; + inherit lib pkgs; + appName = "Thunderbird"; + modulePath = + [ "programs" "thunderbird" "profiles" name "search" ]; + profilePath = name; + }); + default = { }; + description = "Declarative search engine configuration."; + }; }; })); description = "Attribute set of Thunderbird profiles."; }; settings = mkOption { - type = with types; attrsOf (oneOf [ bool int str ]); + type = thunderbirdJson; default = { }; example = literalExpression '' { @@ -378,6 +407,13 @@ in { ] ++ (map (a: toThunderbirdAccount a profile) accounts))) profile.extraConfig; }; + + "${thunderbirdProfilesPath}/${name}/search.json.mozlz4" = + mkIf (profile.search.enable) { + enable = profile.search.enable; + force = profile.search.force; + source = profile.search.file; + }; })); }; } diff --git a/modules/programs/vifm.nix b/modules/programs/vifm.nix new file mode 100644 index 000000000..2bf31d52d --- /dev/null +++ b/modules/programs/vifm.nix @@ -0,0 +1,33 @@ +{ config, lib, pkgs, ... }: + +let + + inherit (lib) mkIf mkOption types; + + cfg = config.programs.vifm; + +in { + meta.maintainers = [ lib.hm.maintainers.aabccd021 ]; + + options.programs.vifm = { + enable = lib.mkEnableOption "vifm, a Vim-like file manager"; + + package = lib.mkPackageOption pkgs "vifm" { }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = "mark h ~/"; + description = '' + Extra lines added to the {file}`$XDG_CONFIG_HOME/vifm/vifmrc` file. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."vifm/vifmrc" = + mkIf (cfg.extraConfig != "") { text = cfg.extraConfig; }; + }; +} diff --git a/modules/programs/wezterm.nix b/modules/programs/wezterm.nix index b02099a6c..bd3be4686 100644 --- a/modules/programs/wezterm.nix +++ b/modules/programs/wezterm.nix @@ -100,7 +100,7 @@ in { -- Generated by Home Manager. -- See https://wezfurlong.org/wezterm/ - local wezterm = require 'wezterm'; + local wezterm = require 'wezterm' ${cfg.extraConfig} ''; diff --git a/modules/programs/yazi.nix b/modules/programs/yazi.nix index d7b880200..0f5117dbd 100644 --- a/modules/programs/yazi.nix +++ b/modules/programs/yazi.nix @@ -56,13 +56,21 @@ in { ''; }; - enableBashIntegration = mkEnableOption "Bash integration"; + enableBashIntegration = mkEnableOption "Bash integration" // { + default = true; + }; - enableZshIntegration = mkEnableOption "Zsh integration"; + enableZshIntegration = mkEnableOption "Zsh integration" // { + default = true; + }; - enableFishIntegration = mkEnableOption "Fish integration"; + enableFishIntegration = mkEnableOption "Fish integration" // { + default = true; + }; - enableNushellIntegration = mkEnableOption "Nushell integration"; + enableNushellIntegration = mkEnableOption "Nushell integration" // { + default = true; + }; keymap = mkOption { type = tomlFormat.type; diff --git a/modules/programs/z-lua.nix b/modules/programs/z-lua.nix index 37a8479ee..74dee31dc 100644 --- a/modules/programs/z-lua.nix +++ b/modules/programs/z-lua.nix @@ -77,16 +77,26 @@ in { })" ''; - programs.fish.shellInit = mkIf cfg.enableFishIntegration '' - source (${pkgs.z-lua}/bin/z --init fish ${ - concatStringsSep " " cfg.options - } | psub) - ''; - programs.bash.shellAliases = mkIf cfg.enableAliases aliases; programs.zsh.shellAliases = mkIf cfg.enableAliases aliases; - programs.fish.shellAliases = mkIf cfg.enableAliases aliases; + programs.fish = mkMerge [ + { + shellInit = mkIf cfg.enableFishIntegration '' + source (${pkgs.z-lua}/bin/z --init fish ${ + concatStringsSep " " cfg.options + } | psub) + ''; + } + + (mkIf (!config.programs.fish.preferAbbrs) { + shellAliases = mkIf cfg.enableAliases aliases; + }) + + (mkIf config.programs.fish.preferAbbrs { + shellAbbrs = mkIf cfg.enableAliases aliases; + }) + ]; }; } diff --git a/modules/programs/zathura.nix b/modules/programs/zathura.nix index ba34af590..3e41256d3 100644 --- a/modules/programs/zathura.nix +++ b/modules/programs/zathura.nix @@ -31,7 +31,7 @@ in { options = mkOption { default = { }; - type = with types; attrsOf (either str (either bool int)); + type = with types; attrsOf (oneOf [ str bool int float ]); description = '' Add {option}`:set` command options to zathura and make them permanent. See diff --git a/modules/programs/zed-editor.nix b/modules/programs/zed-editor.nix new file mode 100644 index 000000000..250d891bb --- /dev/null +++ b/modules/programs/zed-editor.nix @@ -0,0 +1,89 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.zed-editor; + jsonFormat = pkgs.formats.json { }; + + mergedSettings = cfg.userSettings // { + # this part by @cmacrae + auto_install_extensions = lib.genAttrs cfg.extensions (_: true); + }; +in { + meta.maintainers = [ hm.maintainers.libewa ]; + + options = { + # TODO: add vscode option parity (installing extensions, configuring + # keybinds with nix etc.) + programs.zed-editor = { + enable = mkEnableOption + "Zed, the high performance, multiplayer code editor from the creators of Atom and Tree-sitter"; + + package = mkPackageOption pkgs "zed-editor" { }; + + userSettings = mkOption { + type = jsonFormat.type; + default = { }; + example = literalExpression '' + { + features = { + copilot = false; + }; + telemetry = { + metrics = false; + }; + vim_mode = false; + ui_font_size = 16; + buffer_font_size = 16; + } + ''; + description = '' + Configuration written to Zed's {file}`settings.json`. + ''; + }; + + userKeymaps = mkOption { + type = jsonFormat.type; + default = { }; + example = literalExpression '' + [ + { + context = "Workspace"; + bindings = { + ctrl-shift-t = "workspace::NewTerminal"; + }; + }; + ] + ''; + description = '' + Configuration written to Zed's {file}`keymap.json`. + ''; + }; + + extensions = mkOption { + type = types.listOf types.str; + default = [ ]; + example = literalExpression '' + [ "swift" "nix" "xy-zed" ] + ''; + description = '' + A list of the extensions Zed should install on startup. + Use the name of a repository in the [extension list](https://github.com/zed-industries/extensions/tree/main/extensions). + ''; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."zed/settings.json" = (mkIf (mergedSettings != { }) { + source = jsonFormat.generate "zed-user-settings" mergedSettings; + }); + + xdg.configFile."zed/keymap.json" = (mkIf (cfg.userKeymaps != { }) { + source = jsonFormat.generate "zed-user-keymaps" cfg.userKeymaps; + }); + }; +} diff --git a/modules/programs/zoxide.nix b/modules/programs/zoxide.nix index 3dcbbd67b..f5e258af9 100644 --- a/modules/programs/zoxide.nix +++ b/modules/programs/zoxide.nix @@ -26,9 +26,9 @@ in { options = mkOption { type = types.listOf types.str; default = [ ]; - example = [ "--no-aliases" ]; + example = [ "--no-cmd" ]; description = '' - List of options to pass to zoxide. + List of options to pass to zoxide init. ''; }; @@ -68,9 +68,9 @@ in { config = mkIf cfg.enable { home.packages = [ cfg.package ]; - programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + programs.bash.initExtra = mkIf cfg.enableBashIntegration (mkOrder 150 '' eval "$(${cfg.package}/bin/zoxide init bash ${cfgOptions})" - ''; + ''); programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' eval "$(${cfg.package}/bin/zoxide init zsh ${cfgOptions})" diff --git a/modules/services/borgmatic.nix b/modules/services/borgmatic.nix index 1e1813946..ad9ace87b 100644 --- a/modules/services/borgmatic.nix +++ b/modules/services/borgmatic.nix @@ -46,7 +46,6 @@ in { # Lower CPU and I/O priority: Nice = 19; - CPUSchedulingPolicy = "batch"; IOSchedulingClass = "best-effort"; IOSchedulingPriority = 7; IOWeight = 100; diff --git a/modules/services/espanso.nix b/modules/services/espanso.nix index f6e27e796..dbfa05875 100644 --- a/modules/services/espanso.nix +++ b/modules/services/espanso.nix @@ -121,9 +121,9 @@ in { systemd.user.services.espanso = { Unit = { Description = "Espanso: cross platform text expander in Rust"; }; Service = { - Type = "exec"; - ExecStart = "${cfg.package}/bin/espanso daemon"; + ExecStart = "${cfg.package}/bin/espanso launcher"; Restart = "on-failure"; + RestartSec = 3; }; Install = { WantedBy = [ "default.target" ]; }; }; diff --git a/modules/services/flameshot.nix b/modules/services/flameshot.nix index 0c2435aeb..ebdfd0067 100644 --- a/modules/services/flameshot.nix +++ b/modules/services/flameshot.nix @@ -24,7 +24,7 @@ in { }; settings = mkOption { - type = iniFormat.type; + inherit (iniFormat) type; default = { }; example = { General = { @@ -64,7 +64,7 @@ in { Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { - Environment = "PATH=${config.home.profileDirectory}/bin"; + Environment = [ "PATH=${config.home.profileDirectory}/bin" ]; ExecStart = "${cfg.package}/bin/flameshot"; Restart = "on-abort"; diff --git a/modules/services/gpg-agent.nix b/modules/services/gpg-agent.nix index cce5ac191..8bfe68aae 100644 --- a/modules/services/gpg-agent.nix +++ b/modules/services/gpg-agent.nix @@ -18,6 +18,10 @@ let export GPG_TTY '' + optionalString cfg.enableSshSupport gpgSshSupportStr; + gpgZshInitStr = '' + export GPG_TTY=$TTY + '' + optionalString cfg.enableSshSupport gpgSshSupportStr; + gpgFishInitStr = '' set -gx GPG_TTY (tty) '' + optionalString cfg.enableSshSupport gpgSshSupportStr; @@ -30,7 +34,7 @@ let $env.SSH_AUTH_SOCK = ($env.SSH_AUTH_SOCK? | default (${gpgPkg}/bin/gpgconf --list-dirs agent-ssh-socket)) ''; - # mimic `gpgconf` output for use in `systemd` unit definitions. + # mimic `gpgconf` output for use in the service definitions. # we cannot use `gpgconf` directly because it heavily depends on system # state, but we need the values at build time. original: # https://github.com/gpg/gnupg/blob/c6702d77d936b3e9d91b34d8fdee9599ab94ee1b/common/homedir.c#L672-L681 @@ -38,10 +42,14 @@ let let hash = substring 0 24 (hexStringToBase32 (builtins.hashString "sha1" homedir)); - in if homedir == options.programs.gpg.homedir.default then - "%t/gnupg/${dir}" + subdir = if homedir == options.programs.gpg.homedir.default then + "${dir}" + else + "d.${hash}/${dir}"; + in if pkgs.stdenv.isDarwin then + "/private/var/run/org.nix-community.home.gpg-agent/${subdir}" else - "%t/gnupg/d.${hash}/${dir}"; + "%t/gnupg/${subdir}"; # Act like `xxd -r -p | base32` but with z-base-32 alphabet and no trailing padding. # Written in Nix for purity. @@ -77,6 +85,32 @@ let }; in hexString: (foldl' go initState (stringToCharacters hexString)).ret; + # Systemd socket unit generator. + mkSocket = { desc, docs, stream, fdName }: { + Unit = { + Description = desc; + Documentation = docs; + }; + + Socket = { + ListenStream = gpgconf "${stream}"; + FileDescriptorName = "${fdName}"; + Service = "gpg-agent.service"; + SocketMode = "0600"; + DirectoryMode = "0700"; + }; + + Install = { WantedBy = [ "sockets.target" ]; }; + }; + + # Launchd agent socket generator. + mkAgentSock = name: { + SockType = "stream"; + SockPathName = gpgconf name; + SockPathMode = + 384; # Property lists don't support octal literals (0600 = 384). + }; + in { meta.maintainers = [ maintainers.rycee ]; @@ -257,7 +291,7 @@ in { ''; programs.bash.initExtra = mkIf cfg.enableBashIntegration gpgInitStr; - programs.zsh.initExtra = mkIf cfg.enableZshIntegration gpgInitStr; + programs.zsh.initExtra = mkIf cfg.enableZshIntegration gpgZshInitStr; programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration gpgFishInitStr; @@ -272,90 +306,74 @@ in { '') cfg.sshKeys; }) - # The systemd units below are direct translations of the - # descriptions in the - # - # ${gpgPkg}/share/doc/gnupg/examples/systemd-user - # - # directory. - { - assertions = [ - (hm.assertions.assertPlatform "services.gpg-agent" pkgs platforms.linux) - ]; + (mkMerge [ + (mkIf pkgs.stdenv.isLinux { + systemd.user.services.gpg-agent = { + Unit = { + Description = "GnuPG cryptographic agent and passphrase cache"; + Documentation = "man:gpg-agent(1)"; + Requires = "gpg-agent.socket"; + After = "gpg-agent.socket"; + # This is a socket-activated service: + RefuseManualStart = true; + }; - systemd.user.services.gpg-agent = { - Unit = { - Description = "GnuPG cryptographic agent and passphrase cache"; - Documentation = "man:gpg-agent(1)"; - Requires = "gpg-agent.socket"; - After = "gpg-agent.socket"; - # This is a socket-activated service: - RefuseManualStart = true; + Service = { + ExecStart = "${gpgPkg}/bin/gpg-agent --supervised" + + optionalString cfg.verbose " --verbose"; + ExecReload = "${gpgPkg}/bin/gpgconf --reload gpg-agent"; + Environment = [ "GNUPGHOME=${homedir}" ]; + }; }; - Service = { - ExecStart = "${gpgPkg}/bin/gpg-agent --supervised" - + optionalString cfg.verbose " --verbose"; - ExecReload = "${gpgPkg}/bin/gpgconf --reload gpg-agent"; - Environment = [ "GNUPGHOME=${homedir}" ]; - }; - }; - - systemd.user.sockets.gpg-agent = { - Unit = { - Description = "GnuPG cryptographic agent and passphrase cache"; - Documentation = "man:gpg-agent(1)"; + systemd.user.sockets.gpg-agent = mkSocket { + desc = "GnuPG cryptographic agent and passphrase cache"; + docs = "man:gpg-agent(1)"; + stream = "S.gpg-agent"; + fdName = "std"; }; - Socket = { - ListenStream = gpgconf "S.gpg-agent"; - FileDescriptorName = "std"; - SocketMode = "0600"; - DirectoryMode = "0700"; + systemd.user.sockets.gpg-agent-ssh = mkIf cfg.enableSshSupport + (mkSocket ({ + desc = "GnuPG cryptographic agent (ssh-agent emulation)"; + docs = + "man:gpg-agent(1) man:ssh-add(1) man:ssh-agent(1) man:ssh(1)"; + stream = "S.gpg-agent.ssh"; + fdName = "ssh"; + })); + + systemd.user.sockets.gpg-agent-extra = mkIf cfg.enableExtraSocket + (mkSocket { + desc = + "GnuPG cryptographic agent and passphrase cache (restricted)"; + docs = "man:gpg-agent(1) man:ssh(1)"; + stream = "S.gpg-agent.extra"; + fdName = "extra"; + }); + }) + + (mkIf pkgs.stdenv.isDarwin { + launchd.agents.gpg-agent = { + enable = true; + config = { + ProgramArguments = [ "${gpgPkg}/bin/gpg-agent" "--supervised" ] + ++ optional cfg.verbose "--verbose"; + EnvironmentVariables = { GNUPGHOME = homedir; }; + KeepAlive = { + Crashed = true; + SuccessfulExit = false; + }; + ProcessType = "Background"; + RunAtLoad = cfg.enableSshSupport; + Sockets = { + Agent = mkAgentSock "S.gpg-agent"; + Ssh = mkIf cfg.enableSshSupport (mkAgentSock "S.gpg-agent.ssh"); + Extra = + mkIf cfg.enableExtraSocket (mkAgentSock "S.gpg-agent.extra"); + }; + }; }; - - Install = { WantedBy = [ "sockets.target" ]; }; - }; - } - - (mkIf cfg.enableSshSupport { - systemd.user.sockets.gpg-agent-ssh = { - Unit = { - Description = "GnuPG cryptographic agent (ssh-agent emulation)"; - Documentation = - "man:gpg-agent(1) man:ssh-add(1) man:ssh-agent(1) man:ssh(1)"; - }; - - Socket = { - ListenStream = gpgconf "S.gpg-agent.ssh"; - FileDescriptorName = "ssh"; - Service = "gpg-agent.service"; - SocketMode = "0600"; - DirectoryMode = "0700"; - }; - - Install = { WantedBy = [ "sockets.target" ]; }; - }; - }) - - (mkIf cfg.enableExtraSocket { - systemd.user.sockets.gpg-agent-extra = { - Unit = { - Description = - "GnuPG cryptographic agent and passphrase cache (restricted)"; - Documentation = "man:gpg-agent(1) man:ssh(1)"; - }; - - Socket = { - ListenStream = gpgconf "S.gpg-agent.extra"; - FileDescriptorName = "extra"; - Service = "gpg-agent.service"; - SocketMode = "0600"; - DirectoryMode = "0700"; - }; - - Install = { WantedBy = [ "sockets.target" ]; }; - }; - }) + }) + ]) ]); } diff --git a/modules/services/grobi.nix b/modules/services/grobi.nix index e656a763f..9031089c9 100644 --- a/modules/services/grobi.nix +++ b/modules/services/grobi.nix @@ -88,7 +88,7 @@ in { ExecStart = "${pkgs.grobi}/bin/grobi watch -v"; Restart = "always"; RestartSec = "2s"; - Environment = "PATH=${pkgs.xorg.xrandr}/bin:${pkgs.bash}/bin"; + Environment = [ "PATH=${pkgs.xorg.xrandr}/bin:${pkgs.bash}/bin" ]; }; Install = { WantedBy = [ "graphical-session.target" ]; }; diff --git a/modules/services/hound.nix b/modules/services/hound.nix index ff18a381a..3aaf93200 100644 --- a/modules/services/hound.nix +++ b/modules/services/hound.nix @@ -72,7 +72,7 @@ in { Install = { WantedBy = [ "default.target" ]; }; Service = { - Environment = "PATH=${makeBinPath [ pkgs.mercurial pkgs.git ]}"; + Environment = [ "PATH=${makeBinPath [ pkgs.mercurial pkgs.git ]}" ]; ExecStart = "${pkgs.hound}/bin/houndd ${concatStringsSep " " houndOptions}"; }; diff --git a/modules/services/kanshi.nix b/modules/services/kanshi.nix index b503ffc7f..3b1bdf2cf 100644 --- a/modules/services/kanshi.nix +++ b/modules/services/kanshi.nix @@ -123,6 +123,15 @@ let ''; }; + alias = mkOption { + type = types.nullOr types.str; + default = null; + example = "laptopMonitor"; + description = '' + Defines an alias for the output + ''; + }; + adaptiveSync = mkOption { type = types.nullOr types.bool; default = null; @@ -135,15 +144,16 @@ let }; }; - outputStr = - { criteria, status, mode, position, scale, transform, adaptiveSync, ... }: + outputStr = { criteria, status, mode, position, scale, transform, adaptiveSync + , alias, ... }: ''output "${criteria}"'' + optionalString (status != null) " ${status}" + optionalString (mode != null) " mode ${mode}" + optionalString (position != null) " position ${position}" + optionalString (scale != null) " scale ${toString scale}" + optionalString (transform != null) " transform ${transform}" + optionalString (adaptiveSync != null) - " adaptive_sync ${if adaptiveSync then "on" else "off"}"; + " adaptive_sync ${if adaptiveSync then "on" else "off"}" + + optionalString (alias != null) " alias \$${alias}"; profileModule = types.submodule { options = { @@ -296,6 +306,14 @@ in { message = "Cannot mix kanshi.settings with kanshi.profiles or kanshi.extraConfig"; } + { + assertion = let profiles = filter (x: x ? profile) cfg.settings; + in length + (filter (x: any (a: a ? alias && a.alias != null) x.profile.outputs) + profiles) == 0; + message = + "Output kanshi.*.output.alias can only be defined on global scope"; + } ]; } diff --git a/modules/services/kbfs.nix b/modules/services/kbfs.nix index 9cfe02752..21e962968 100644 --- a/modules/services/kbfs.nix +++ b/modules/services/kbfs.nix @@ -46,7 +46,7 @@ in { Service = let mountPoint = ''"%h/${cfg.mountPoint}"''; in { - Environment = "PATH=/run/wrappers/bin KEYBASE_SYSTEMD=1"; + Environment = [ "PATH=/run/wrappers/bin" "KEYBASE_SYSTEMD=1" ]; ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p ${mountPoint}"; ExecStart = "${pkgs.kbfs}/bin/kbfsfuse ${toString cfg.extraFlags} ${mountPoint}"; diff --git a/modules/services/kdeconnect.nix b/modules/services/kdeconnect.nix index 656a8c9a6..f0b1da5be 100644 --- a/modules/services/kdeconnect.nix +++ b/modules/services/kdeconnect.nix @@ -47,7 +47,7 @@ in { Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { - Environment = "PATH=${config.home.profileDirectory}/bin"; + Environment = [ "PATH=${config.home.profileDirectory}/bin" ]; ExecStart = if strings.versionAtLeast (versions.majorMinor cfg.package.version) "24.05" then @@ -81,7 +81,7 @@ in { Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { - Environment = "PATH=${config.home.profileDirectory}/bin"; + Environment = [ "PATH=${config.home.profileDirectory}/bin" ]; ExecStart = "${cfg.package}/bin/kdeconnect-indicator"; Restart = "on-abort"; }; diff --git a/modules/services/megasync.nix b/modules/services/megasync.nix index c519ba51f..03eab490a 100644 --- a/modules/services/megasync.nix +++ b/modules/services/megasync.nix @@ -28,7 +28,7 @@ in { systemd.user.services.megasync = { Unit = { Description = "megasync"; - After = [ "graphical-session-pre.target" ]; + After = [ "graphical-session.target" ]; PartOf = [ "graphical-session.target" ]; }; diff --git a/modules/services/mpd.nix b/modules/services/mpd.nix index 3d8d03be7..8787ad667 100644 --- a/modules/services/mpd.nix +++ b/modules/services/mpd.nix @@ -188,7 +188,7 @@ in { }; Service = { - Environment = "PATH=${config.home.profileDirectory}/bin"; + Environment = [ "PATH=${config.home.profileDirectory}/bin" ]; ExecStart = "${cfg.package}/bin/mpd --no-daemon ${mpdConf} ${ escapeShellArgs cfg.extraArgs }"; diff --git a/modules/services/nextcloud-client.nix b/modules/services/nextcloud-client.nix index b436488d1..24b3c99dd 100644 --- a/modules/services/nextcloud-client.nix +++ b/modules/services/nextcloud-client.nix @@ -41,7 +41,7 @@ in { }; Service = { - Environment = "PATH=${config.home.profileDirectory}/bin"; + Environment = [ "PATH=${config.home.profileDirectory}/bin" ]; ExecStart = "${cfg.package}/bin/nextcloud" + (optionalString cfg.startInBackground " --background"); }; diff --git a/modules/services/nix-gc.nix b/modules/services/nix-gc.nix index 50e8b6351..7789aeffb 100644 --- a/modules/services/nix-gc.nix +++ b/modules/services/nix-gc.nix @@ -81,6 +81,18 @@ in { ''; }; + randomizedDelaySec = lib.mkOption { + default = "0"; + type = lib.types.singleLineStr; + example = "45min"; + description = '' + Add a randomized delay before each garbage collection. + The delay will be chosen between zero and this value. + This value must be a time span in the format specified by + {manpage}`systemd.time(7)` + ''; + }; + options = mkOption { type = types.nullOr types.str; default = null; @@ -121,6 +133,7 @@ in { Unit = { Description = "Nix Garbage Collector"; }; Timer = { OnCalendar = "${cfg.frequency}"; + RandomizedDelaySec = cfg.randomizedDelaySec; Persistent = cfg.persistent; Unit = "nix-gc.service"; }; diff --git a/modules/services/opensnitch-ui.nix b/modules/services/opensnitch-ui.nix index a086554ca..f45ee9cdb 100644 --- a/modules/services/opensnitch-ui.nix +++ b/modules/services/opensnitch-ui.nix @@ -28,7 +28,7 @@ in { }; Service = { - Environment = "PATH=${config.home.profileDirectory}/bin"; + Environment = [ "PATH=${config.home.profileDirectory}/bin" ]; ExecStart = "${pkgs.opensnitch-ui}/bin/opensnitch-ui"; }; diff --git a/modules/services/owncloud-client.nix b/modules/services/owncloud-client.nix index 2884affe4..3235dac9c 100644 --- a/modules/services/owncloud-client.nix +++ b/modules/services/owncloud-client.nix @@ -29,7 +29,7 @@ in { }; Service = { - Environment = "PATH=${config.home.profileDirectory}/bin"; + Environment = [ "PATH=${config.home.profileDirectory}/bin" ]; ExecStart = "${cfg.package}/bin/owncloud"; }; diff --git a/modules/services/pass-secret-service.nix b/modules/services/pass-secret-service.nix index db494337e..c6ea59918 100644 --- a/modules/services/pass-secret-service.nix +++ b/modules/services/pass-secret-service.nix @@ -58,6 +58,7 @@ in { optionalString (cfg.storePath != null) "--path ${cfg.storePath}" }"; BusName = busName; + Environment = [ "GNUPGHOME=${config.programs.gpg.homedir}" ]; }; Install.WantedBy = [ "default.target" ]; diff --git a/modules/services/polybar.nix b/modules/services/polybar.nix index fbcecc5af..e41646b2f 100644 --- a/modules/services/polybar.nix +++ b/modules/services/polybar.nix @@ -220,7 +220,7 @@ in { Service = { Type = "forking"; - Environment = "PATH=${cfg.package}/bin:/run/wrappers/bin"; + Environment = [ "PATH=${cfg.package}/bin:/run/wrappers/bin" ]; ExecStart = let scriptPkg = pkgs.writeShellScriptBin "polybar-start" cfg.script; in "${scriptPkg}/bin/polybar-start"; diff --git a/modules/services/poweralertd.nix b/modules/services/poweralertd.nix index bc02dead3..9c59ad3f0 100644 --- a/modules/services/poweralertd.nix +++ b/modules/services/poweralertd.nix @@ -2,13 +2,37 @@ with lib; -let cfg = config.services.poweralertd; - +let + inherit (lib.strings) toJSON; + cfg = config.services.poweralertd; + escapeSystemdExecArg = arg: + let + s = if isPath arg then + "${arg}" + else if isString arg then + arg + else if isInt arg || isFloat arg || isDerivation arg then + toString arg + else + throw + "escapeSystemdExecArg only allows strings, paths, numbers and derivations"; + in replaceStrings [ "%" "$" ] [ "%%" "$$" ] (toJSON s); + escapeSystemdExecArgs = concatMapStringsSep " " escapeSystemdExecArg; in { meta.maintainers = [ maintainers.thibautmarty ]; - options.services.poweralertd.enable = - mkEnableOption "the Upower-powered power alertd"; + options.services.poweralertd = { + enable = mkEnableOption "the Upower-powered power alertd"; + + extraArgs = mkOption { + type = with types; listOf str; + default = [ ]; + example = [ "-s" "-S" ]; + description = '' + Extra command line arguments to pass to poweralertd. + ''; + }; + }; config = mkIf cfg.enable { assertions = [ @@ -28,7 +52,9 @@ in { Service = { Type = "simple"; - ExecStart = "${pkgs.poweralertd}/bin/poweralertd"; + ExecStart = "${pkgs.poweralertd}/bin/poweralertd ${ + escapeSystemdExecArgs cfg.extraArgs + }"; Restart = "always"; }; }; diff --git a/modules/services/rsibreak.nix b/modules/services/rsibreak.nix index 351632a02..d587c2daf 100644 --- a/modules/services/rsibreak.nix +++ b/modules/services/rsibreak.nix @@ -30,7 +30,7 @@ in { Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { - Environment = "PATH=${config.home.profileDirectory}/bin"; + Environment = [ "PATH=${config.home.profileDirectory}/bin" ]; ExecStart = "${pkgs.rsibreak}/bin/rsibreak"; }; }; diff --git a/modules/services/snixembed.nix b/modules/services/snixembed.nix new file mode 100644 index 000000000..a470836b0 --- /dev/null +++ b/modules/services/snixembed.nix @@ -0,0 +1,50 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let cfg = config.services.snixembed; +in { + meta.maintainers = [ maintainers.DamienCassou ]; + + options = { + services.snixembed = { + enable = mkEnableOption + "snixembed: proxy StatusNotifierItems as XEmbedded systemtray-spec icons"; + + package = mkPackageOption pkgs "snixembed" { }; + + beforeUnits = mkOption { + type = with types; listOf str; + default = [ ]; + example = [ "safeeyes.service" ]; + description = '' + List of other units that should be started after snixembed. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (hm.assertions.assertPlatform "services.snixembed" pkgs platforms.linux) + ]; + + systemd.user.services.snixembed = { + Install.WantedBy = [ "graphical-session.target" ]; + + Unit = { + Description = "snixembed"; + PartOf = [ "graphical-session.target" ]; + StartLimitIntervalSec = 100; + StartLimitBurst = 10; + Before = cfg.beforeUnits; + }; + + Service = { + ExecStart = getExe pkgs.snixembed; + Restart = "on-failure"; + RestartSec = 3; + }; + }; + }; +} diff --git a/modules/services/ssh-agent.nix b/modules/services/ssh-agent.nix index 88ecf38b8..d2c170c21 100644 --- a/modules/services/ssh-agent.nix +++ b/modules/services/ssh-agent.nix @@ -20,7 +20,7 @@ in { ]; home.sessionVariablesExtra = '' - if [[ -z "$SSH_AUTH_SOCK" ]]; then + if [ -z "$SSH_AUTH_SOCK" ]; then export SSH_AUTH_SOCK=$XDG_RUNTIME_DIR/ssh-agent fi ''; diff --git a/modules/services/swayidle.nix b/modules/services/swayidle.nix index 80317e42a..7f3376a1c 100644 --- a/modules/services/swayidle.nix +++ b/modules/services/swayidle.nix @@ -6,18 +6,6 @@ let cfg = config.services.swayidle; - mkTimeout = t: - [ "timeout" (toString t.timeout) (escapeShellArg t.command) ] - ++ optionals (t.resumeCommand != null) [ - "resume" - (escapeShellArg t.resumeCommand) - ]; - - mkEvent = e: [ e.event (escapeShellArg e.command) ]; - - args = cfg.extraArgs ++ (concatMap mkTimeout cfg.timeouts) - ++ (concatMap mkEvent cfg.events); - in { meta.maintainers = [ maintainers.c0deaddict ]; @@ -94,7 +82,7 @@ in { extraArgs = mkOption { type = with types; listOf str; - default = [ ]; + default = [ "-w" ]; description = "Extra arguments to pass to swayidle."; }; @@ -127,8 +115,16 @@ in { Restart = "always"; # swayidle executes commands using "sh -c", so the PATH needs to contain a shell. Environment = [ "PATH=${makeBinPath [ pkgs.bash ]}" ]; - ExecStart = - "${cfg.package}/bin/swayidle -w ${concatStringsSep " " args}"; + ExecStart = let + mkTimeout = t: + [ "timeout" (toString t.timeout) t.command ] + ++ optionals (t.resumeCommand != null) [ "resume" t.resumeCommand ]; + + mkEvent = e: [ e.event e.command ]; + + args = cfg.extraArgs ++ (concatMap mkTimeout cfg.timeouts) + ++ (concatMap mkEvent cfg.events); + in "${getExe cfg.package} ${escapeShellArgs args}"; }; Install = { WantedBy = [ cfg.systemdTarget ]; }; diff --git a/modules/services/swaync.nix b/modules/services/swaync.nix index 60bcc913b..5f813af30 100644 --- a/modules/services/swaync.nix +++ b/modules/services/swaync.nix @@ -63,7 +63,7 @@ in { notification-inline-replies = false; notification-icon-size = 64; notification-body-image-height = 100; - notification-body-image-width = 200 + notification-body-image-width = 200; }; ''; description = '' diff --git a/modules/services/taskwarrior-sync.nix b/modules/services/taskwarrior-sync.nix index 9c01f414b..3bad924cf 100644 --- a/modules/services/taskwarrior-sync.nix +++ b/modules/services/taskwarrior-sync.nix @@ -12,6 +12,9 @@ in { options.services.taskwarrior-sync = { enable = mkEnableOption "Taskwarrior periodic sync"; + package = + mkPackageOption pkgs "taskwarrior" { example = "pkgs.taskwarrior3"; }; + frequency = mkOption { type = types.str; default = "*:0/5"; @@ -36,7 +39,7 @@ in { Service = { CPUSchedulingPolicy = "idle"; IOSchedulingClass = "idle"; - ExecStart = "${pkgs.taskwarrior}/bin/task synchronize"; + ExecStart = "${cfg.package}/bin/task synchronize"; }; }; diff --git a/modules/services/trayscale.nix b/modules/services/trayscale.nix new file mode 100644 index 000000000..d9853d7aa --- /dev/null +++ b/modules/services/trayscale.nix @@ -0,0 +1,39 @@ +{ config, lib, pkgs, ... }: + +let cfg = config.services.trayscale; +in { + meta.maintainers = [ lib.hm.maintainers.callumio ]; + + options.services.trayscale = { + enable = lib.mkEnableOption + "An unofficial GUI wrapper around the Tailscale CLI client."; + + package = lib.mkPackageOption pkgs "trayscale" { }; + + hideWindow = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Whether to hide the trayscale window on startup."; + }; + }; + + config = lib.mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.trayscale" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.trayscale = { + Unit = { + Description = + "An unofficial GUI wrapper around the Tailscale CLI client"; + Requires = [ "tray.target" ]; + After = [ "graphical-session-pre.target" "tray.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + Install = { WantedBy = [ "graphical-session.target" ]; }; + Service.ExecStart = toString ([ "${cfg.package}/bin/trayscale" ] + ++ lib.optional cfg.hideWindow "--hide-window"); + }; + }; +} diff --git a/modules/services/window-managers/i3-sway/lib/options.nix b/modules/services/window-managers/i3-sway/lib/options.nix index 1f6820f5d..2869c2bf8 100644 --- a/modules/services/window-managers/i3-sway/lib/options.nix +++ b/modules/services/window-managers/i3-sway/lib/options.nix @@ -31,7 +31,7 @@ let }; size = mkOption { - type = types.float; + type = types.either types.float types.str; default = 8.0; description = '' The font size to use for window titles. diff --git a/modules/services/window-managers/i3-sway/sway.nix b/modules/services/window-managers/i3-sway/sway.nix index f4e437218..4148fcf1d 100644 --- a/modules/services/window-managers/i3-sway/sway.nix +++ b/modules/services/window-managers/i3-sway/sway.nix @@ -249,7 +249,7 @@ let moduleStr = moduleType: name: attrs: '' ${moduleType} "${name}" { ${concatStringsSep "\n" - (mapAttrsToList (name: value: "${name} ${value}") attrs)} + (mapAttrsToList (name: value: " ${name} ${value}") attrs)} } ''; inputStr = moduleStr "input"; @@ -258,7 +258,6 @@ let variables = concatStringsSep " " cfg.systemd.variables; extraCommands = concatStringsSep " && " cfg.systemd.extraCommands; - swayPackage = if cfg.package == null then pkgs.sway else cfg.package; systemdActivation = '' exec "${pkgs.dbus}/bin/dbus-update-activation-environment --systemd ${variables}; ${extraCommands}"''; @@ -269,7 +268,7 @@ let checkPhase = lib.optionalString cfg.checkConfig '' export DBUS_SESSION_BUS_ADDRESS=/dev/null export XDG_RUNTIME_DIR=$(mktemp -d) - ${pkgs.xvfb-run}/bin/xvfb-run ${swayPackage}/bin/sway --config "$target" --validate --unsupported-gpu + ${pkgs.xvfb-run}/bin/xvfb-run ${cfg.package}/bin/sway --config "$target" --validate --unsupported-gpu ''; text = concatStringsSep "\n" @@ -331,13 +330,6 @@ let ++ [ cfg.extraConfig ]); }; - defaultSwayPackage = pkgs.sway.override { - extraSessionCommands = cfg.extraSessionCommands; - extraOptions = cfg.extraOptions; - withBaseWrapper = cfg.wrapperFeatures.base; - withGtkWrapper = cfg.wrapperFeatures.gtk; - }; - in { meta.maintainers = with maintainers; [ Scrumplex @@ -357,14 +349,20 @@ in { package = mkOption { type = with types; nullOr package; - default = defaultSwayPackage; + default = pkgs.sway.override { + extraSessionCommands = cfg.extraSessionCommands; + extraOptions = cfg.extraOptions; + withBaseWrapper = cfg.wrapperFeatures.base; + withGtkWrapper = cfg.wrapperFeatures.gtk; + }; defaultText = literalExpression "${pkgs.sway}"; description = '' Sway package to use. Will override the options 'wrapperFeatures', 'extraSessionCommands', and 'extraOptions'. Set to `null` to not add any Sway package to your path. This should be done if you want to use the NixOS Sway - module to install Sway. + module to install Sway. Beware setting to `null` will also disable + reloading Sway when new config is activated. ''; }; @@ -485,9 +483,10 @@ in { checkConfig = mkOption { type = types.bool; - default = true; - description = - "If enabled (the default), validates the generated config file."; + default = cfg.package != null; + defaultText = + literalExpression "wayland.windowManager.sway.package != null"; + description = "If enabled, validates the generated config file."; }; extraConfig = mkOption { @@ -522,6 +521,11 @@ in { assertions = [ (hm.assertions.assertPlatform "wayland.windowManager.sway" pkgs platforms.linux) + { + assertion = cfg.checkConfig -> cfg.package != null; + message = + "programs.sway.checkConfig requires non-null programs.sway.package"; + } ]; home.packages = optional (cfg.package != null) cfg.package @@ -529,10 +533,10 @@ in { xdg.configFile."sway/config" = { source = configFile; - onChange = '' + onChange = lib.optionalString (cfg.package != null) '' swaySocket="''${XDG_RUNTIME_DIR:-/run/user/$UID}/sway-ipc.$UID.$(${pkgs.procps}/bin/pgrep --uid $UID -x sway || true).sock" if [ -S "$swaySocket" ]; then - ${swayPackage}/bin/swaymsg -s $swaySocket reload + ${cfg.package}/bin/swaymsg -s $swaySocket reload fi ''; }; diff --git a/modules/services/xembed-sni-proxy.nix b/modules/services/xembed-sni-proxy.nix index e0b1f8464..4273e81a3 100644 --- a/modules/services/xembed-sni-proxy.nix +++ b/modules/services/xembed-sni-proxy.nix @@ -41,7 +41,7 @@ in { Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { - Environment = "PATH=${config.home.profileDirectory}/bin"; + Environment = [ "PATH=${config.home.profileDirectory}/bin" ]; ExecStart = "${cfg.package}/bin/xembedsniproxy"; Restart = "on-abort"; }; diff --git a/modules/services/xscreensaver.nix b/modules/services/xscreensaver.nix index 6205e3ee8..c5d6126be 100644 --- a/modules/services/xscreensaver.nix +++ b/modules/services/xscreensaver.nix @@ -60,7 +60,7 @@ in { Service = { ExecStart = "${cfg.package}/bin/xscreensaver -no-splash"; - Environment = "PATH=${makeBinPath [ cfg.package ]}"; + Environment = [ "PATH=${makeBinPath [ cfg.package ]}" ]; }; Install = { WantedBy = [ "graphical-session.target" ]; }; diff --git a/modules/services/xsettingsd.nix b/modules/services/xsettingsd.nix index c949676fa..c71e9ad82 100644 --- a/modules/services/xsettingsd.nix +++ b/modules/services/xsettingsd.nix @@ -82,7 +82,7 @@ in { Install.WantedBy = [ "graphical-session.target" ]; Service = { - Environment = "PATH=${config.home.profileDirectory}/bin"; + Environment = [ "PATH=${config.home.profileDirectory}/bin" ]; ExecStart = "${cfg.package}/bin/xsettingsd" + optionalString (cfg.configFile != null) " -c ${escapeShellArg cfg.configFile}"; diff --git a/modules/systemd.nix b/modules/systemd.nix index 707bb3294..9d3777c65 100644 --- a/modules/systemd.nix +++ b/modules/systemd.nix @@ -325,11 +325,9 @@ in { home.activation.reloadSystemd = hm.dag.entryAfter [ "linkGeneration" ] (let cmd = { suggest = '' - PATH=${dirOf cfg.systemctlPath}:$PATH \ bash ${./systemd-activate.sh} "''${oldGenPath=}" "$newGenPath" ''; legacy = '' - PATH=${dirOf cfg.systemctlPath}:$PATH \ ${pkgs.ruby}/bin/ruby ${./systemd-activate.rb} \ "''${oldGenPath=}" "$newGenPath" "${servicesStartTimeoutMs}" ''; @@ -339,17 +337,21 @@ in { else ""; in '' - ${pkgs.sd-switch}/bin/sd-switch \ + ${lib.getExe pkgs.sd-switch} \ ''${DRY_RUN:+--dry-run} $VERBOSE_ARG ${timeoutArg} \ ''${oldUnitsDir:+--old-units $oldUnitsDir} \ --new-units "$newUnitsDir" ''; }; - ensureRuntimeDir = - "XDG_RUNTIME_DIR=\${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"; + # Make sure that we have an environment where we are likely to + # successfully talk with systemd. + ensureSystemd = '' + env XDG_RUNTIME_DIR="''${XDG_RUNTIME_DIR:-/run/user/$(id -u)}" \ + PATH="${dirOf cfg.systemctlPath}:$PATH" \ + ''; - systemctl = "${ensureRuntimeDir} ${cfg.systemctlPath}"; + systemctl = "${ensureSystemd} systemctl"; in '' systemdStatus=$(${systemctl} --user is-system-running 2>&1 || true) @@ -372,8 +374,7 @@ in { newUnitsDir=${pkgs.emptyDirectory} fi - ${ensureRuntimeDir} \ - ${getAttr cfg.startServices cmd} + ${ensureSystemd} ${getAttr cfg.startServices cmd} unset newUnitsDir oldUnitsDir else diff --git a/tests/default.nix b/tests/default.nix index bdfd11676..3efb89198 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -60,12 +60,14 @@ in import nmtSrc { ./modules/programs/bacon ./modules/programs/bash ./modules/programs/bat + ./modules/programs/borgmatic ./modules/programs/bottom ./modules/programs/broot ./modules/programs/browserpass ./modules/programs/btop ./modules/programs/carapace ./modules/programs/cava + ./modules/programs/cmus ./modules/programs/comodoro ./modules/programs/darcs ./modules/programs/dircolors @@ -79,6 +81,7 @@ in import nmtSrc { ./modules/programs/gh-dash ./modules/programs/git ./modules/programs/git-cliff + ./modules/programs/git-credential-oauth ./modules/programs/gpg ./modules/programs/gradle ./modules/programs/granted @@ -110,6 +113,7 @@ in import nmtSrc { ./modules/programs/ncmpcpp ./modules/programs/ne ./modules/programs/neomutt + ./modules/programs/neovide ./modules/programs/neovim ./modules/programs/newsboat ./modules/programs/nheko @@ -154,15 +158,18 @@ in import nmtSrc { ./modules/programs/tmux ./modules/programs/topgrade ./modules/programs/translate-shell + ./modules/programs/vifm ./modules/programs/vim-vint ./modules/programs/vscode ./modules/programs/watson ./modules/programs/wezterm ./modules/programs/yazi + ./modules/programs/zed-editor ./modules/programs/zellij ./modules/programs/zk ./modules/programs/zplug ./modules/programs/zsh + ./modules/services/gpg-agent ./modules/services/syncthing/common ./modules/xresources ] ++ lib.optionals isDarwin [ @@ -188,9 +195,9 @@ in import nmtSrc { ./modules/programs/awscli ./modules/programs/beets # One test relies on services.mpd ./modules/programs/bemenu - ./modules/programs/borgmatic ./modules/programs/boxxy ./modules/programs/firefox/firefox.nix + ./modules/programs/firefox/floorp.nix ./modules/programs/foot ./modules/programs/freetube ./modules/programs/fuzzel @@ -243,7 +250,6 @@ in import nmtSrc { ./modules/services/fusuma ./modules/services/git-sync ./modules/services/glance - ./modules/services/gpg-agent ./modules/services/gromit-mpx ./modules/services/home-manager-auto-upgrade ./modules/services/hypridle @@ -270,12 +276,14 @@ in import nmtSrc { ./modules/services/remmina ./modules/services/screen-locker ./modules/services/signaturepdf + ./modules/services/snixembed ./modules/services/swayidle ./modules/services/swaync ./modules/services/swayosd ./modules/services/sxhkd ./modules/services/syncthing/linux ./modules/services/trayer + ./modules/services/trayscale ./modules/services/twmn ./modules/services/udiskie ./modules/services/window-managers/bspwm diff --git a/tests/integration/default.nix b/tests/integration/default.nix index c31030172..262f28faf 100644 --- a/tests/integration/default.nix +++ b/tests/integration/default.nix @@ -10,6 +10,7 @@ let }; tests = { + kitty = runTest ./standalone/kitty.nix; nixos-basics = runTest ./nixos/basics.nix; standalone-flake-basics = runTest ./standalone/flake-basics.nix; standalone-standard-basics = runTest ./standalone/standard-basics.nix; diff --git a/tests/integration/standalone/kitty-theme-bad-home.nix b/tests/integration/standalone/kitty-theme-bad-home.nix new file mode 100644 index 000000000..e4851701b --- /dev/null +++ b/tests/integration/standalone/kitty-theme-bad-home.nix @@ -0,0 +1,13 @@ +{ ... }: { + home.username = "alice"; + home.homeDirectory = "/home/alice"; + home.stateVersion = "24.05"; + + # Let Home Manager install and manage itself. + programs.home-manager.enable = true; + + programs.kitty = { + enable = true; + themeFile = "No Such Theme"; + }; +} diff --git a/tests/integration/standalone/kitty-theme-good-home.nix b/tests/integration/standalone/kitty-theme-good-home.nix new file mode 100644 index 000000000..f6085b1e1 --- /dev/null +++ b/tests/integration/standalone/kitty-theme-good-home.nix @@ -0,0 +1,14 @@ +{ ... }: { + home.username = "alice"; + home.homeDirectory = "/home/alice"; + + home.stateVersion = "24.05"; # Please read the comment before changing. + + # Let Home Manager install and manage itself. + programs.home-manager.enable = true; + + programs.kitty = { + enable = true; + themeFile = "SpaceGray_Eighties"; + }; +} diff --git a/tests/integration/standalone/kitty.nix b/tests/integration/standalone/kitty.nix new file mode 100644 index 000000000..8f89330cf --- /dev/null +++ b/tests/integration/standalone/kitty.nix @@ -0,0 +1,73 @@ +{ pkgs, ... }: { + name = "kitty-theme-path"; + meta.maintainers = [ pkgs.lib.maintainers.rycee ]; + + nodes.machine = { ... }: { + imports = [ "${pkgs.path}/nixos/modules/installer/cd-dvd/channel.nix" ]; + virtualisation.memorySize = 2048; + users.users.alice = { + isNormalUser = true; + description = "Alice Foobar"; + password = "foobar"; + uid = 1000; + }; + }; + + testScript = '' + start_all() + machine.wait_for_unit("network.target") + machine.wait_for_unit("multi-user.target") + + home_manager = "${../../..}" + + def login_as_alice(): + machine.wait_until_tty_matches("1", "login: ") + machine.send_chars("alice\n") + machine.wait_until_tty_matches("1", "Password: ") + machine.send_chars("foobar\n") + machine.wait_until_tty_matches("1", "alice\\@machine") + + def logout_alice(): + machine.send_chars("exit\n") + + def alice_cmd(cmd): + return f"su -l alice --shell /bin/sh -c $'export XDG_RUNTIME_DIR=/run/user/$UID ; {cmd}'" + + def succeed_as_alice(cmd): + return machine.succeed(alice_cmd(cmd)) + + def fail_as_alice(cmd): + return machine.fail(alice_cmd(cmd)) + + # Create a persistent login so that Alice has a systemd session. + login_as_alice() + + # Set up a home-manager channel. + succeed_as_alice(" ; ".join([ + "mkdir -p /home/alice/.nix-defexpr/channels", + f"ln -s {home_manager} /home/alice/.nix-defexpr/channels/home-manager" + ])) + + succeed_as_alice("nix-shell \"\" -A install") + + with subtest("Switch to Bad Kitty"): + succeed_as_alice("cp ${ + ./kitty-theme-bad-home.nix + } /home/alice/.config/home-manager/home.nix") + + actual = fail_as_alice("home-manager switch") + expected = "kitty-themes does not contain the theme file" + assert expected in actual, \ + f"expected home-manager switch to contain {expected}, but got {actual}" + + with subtest("Switch to Good Kitty"): + succeed_as_alice("cp ${ + ./kitty-theme-good-home.nix + } /home/alice/.config/home-manager/home.nix") + + actual = succeed_as_alice("home-manager switch") + expected = "Activating checkKittyTheme" + assert expected in actual, \ + f"expected home-manager switch to contain {expected}, but got {actual}" + ''; +} diff --git a/tests/modules/misc/xdg/default.nix b/tests/modules/misc/xdg/default.nix index bc2f9a9df..87f74e22f 100644 --- a/tests/modules/misc/xdg/default.nix +++ b/tests/modules/misc/xdg/default.nix @@ -6,4 +6,7 @@ xdg-default-locations = ./default-locations.nix; xdg-user-dirs-null = ./user-dirs-null.nix; xdg-portal = ./portal.nix; + xdg-mime = ./mime.nix; + xdg-mime-disabled = ./mime-disabled.nix; + xdg-mime-package = ./mime-packages.nix; } diff --git a/tests/modules/misc/xdg/file-gen.nix b/tests/modules/misc/xdg/file-gen.nix index 47a3102c2..7514f414f 100644 --- a/tests/modules/misc/xdg/file-gen.nix +++ b/tests/modules/misc/xdg/file-gen.nix @@ -11,8 +11,8 @@ with lib; xdg.configFile.test.text = "config"; xdg.dataFile.test.text = "data"; + xdg.stateFile.test.text = "state"; home.file."${config.xdg.cacheHome}/test".text = "cache"; - home.file."${config.xdg.stateHome}/test".text = "state"; nmt.script = '' assertFileExists home-files/.dummy-config/test diff --git a/tests/modules/misc/xdg/mime-disabled.nix b/tests/modules/misc/xdg/mime-disabled.nix new file mode 100644 index 000000000..a3df63091 --- /dev/null +++ b/tests/modules/misc/xdg/mime-disabled.nix @@ -0,0 +1,10 @@ +{ ... }: { + config = { + xdg.mime.enable = false; + nmt.script = '' + # assert that neither application is run + assertPathNotExists home-path/share/applications/mimeinfo.cache + assertPathNotExists home-path/share/applications/mime + ''; + }; +} diff --git a/tests/modules/misc/xdg/mime-expected.cache b/tests/modules/misc/xdg/mime-expected.cache new file mode 100644 index 000000000..6907f8f88 --- /dev/null +++ b/tests/modules/misc/xdg/mime-expected.cache @@ -0,0 +1,3 @@ +[MIME Cache] +text/html=mime-test.desktop; +text/xml=mime-test.desktop; diff --git a/tests/modules/misc/xdg/mime-packages.nix b/tests/modules/misc/xdg/mime-packages.nix new file mode 100644 index 000000000..0eaaddcec --- /dev/null +++ b/tests/modules/misc/xdg/mime-packages.nix @@ -0,0 +1,38 @@ +{ config, ... }: +let inherit (config.lib.test) mkStubPackage; +in { + config = { + xdg.mime.enable = true; + xdg.mime.sharedMimeInfoPackage = mkStubPackage { + name = "update-mime-database"; + buildScript = '' + mkdir -p $out/bin + echo '#!/bin/sh' > $out/bin/update-mime-database + echo 'mkdir -p $out/share/mime && touch $out/share/mime/mime.cache' >> $out/bin/update-mime-database + chmod +x $out/bin/update-mime-database + ''; + }; + xdg.mime.desktopFileUtilsPackage = mkStubPackage { + name = "desktop-file-utils"; + buildScript = '' + mkdir -p $out/bin + echo '#!/bin/sh' > $out/bin/update-desktop-database + echo 'mkdir -p $out/share/applications/ && ln -s ${ + ./mime-expected.cache + } $out/share/applications/mimeinfo.cache' >> $out/bin/update-desktop-database + chmod +x $out/bin/update-desktop-database + ''; + }; + nmt.script = '' + assertFileExists home-path/share/applications/mimeinfo.cache # Check that update-desktop-database created file + # Check that update-desktop-database file matches expected + assertFileContent \ + home-path/share/applications/mimeinfo.cache \ + ${./mime-expected.cache} + + assertDirectoryExists home-path/share/mime # Check that update-mime-database created directory + assertFileExists home-path/share/mime/mime.cache # Check that update-mime-database created file + + ''; + }; +} diff --git a/tests/modules/misc/xdg/mime.nix b/tests/modules/misc/xdg/mime.nix new file mode 100644 index 000000000..90d21d567 --- /dev/null +++ b/tests/modules/misc/xdg/mime.nix @@ -0,0 +1,24 @@ +{ ... }: { + config = { + xdg.mime.enable = true; + xdg.desktopEntries = { + mime-test = { # mime info test + name = "mime-test"; + mimeType = [ "text/html" "text/xml" ]; + }; + + }; + + nmt.script = '' + assertFileExists home-path/share/applications/mimeinfo.cache # Check that update-desktop-database created file + # Check that update-desktop-database file matches expected + assertFileContent \ + home-path/share/applications/mimeinfo.cache \ + ${./mime-expected.cache} + + assertDirectoryExists home-path/share/mime # Check that update-mime-database created directory + assertDirectoryNotEmpty home-path/share/mime # Check that update-mime-database created files + + ''; + }; +} diff --git a/tests/modules/misc/xsession/basic-xprofile-expected.txt b/tests/modules/misc/xsession/basic-xprofile-expected.txt index b3d591c22..282f8f5c5 100644 --- a/tests/modules/misc/xsession/basic-xprofile-expected.txt +++ b/tests/modules/misc/xsession/basic-xprofile-expected.txt @@ -9,7 +9,7 @@ fi # script starts up graphical-session.target. systemctl --user stop graphical-session.target graphical-session-pre.target -systemctl --user import-environment 'DBUS_SESSION_BUS_ADDRESS' 'DISPLAY' 'SSH_AUTH_SOCK' 'XAUTHORITY' 'XDG_DATA_DIRS' 'XDG_RUNTIME_DIR' 'XDG_SESSION_ID' 'EXTRA_IMPORTED_VARIABLE' +systemctl --user import-environment DBUS_SESSION_BUS_ADDRESS DISPLAY SSH_AUTH_SOCK XAUTHORITY XDG_DATA_DIRS XDG_RUNTIME_DIR XDG_SESSION_ID EXTRA_IMPORTED_VARIABLE profile extra commands diff --git a/tests/modules/misc/xsession/basic-xsession-expected.txt b/tests/modules/misc/xsession/basic-xsession-expected.txt index a95bb35ab..243c57622 100644 --- a/tests/modules/misc/xsession/basic-xsession-expected.txt +++ b/tests/modules/misc/xsession/basic-xsession-expected.txt @@ -17,4 +17,4 @@ while [ -n "$(systemctl --user --no-legend --state=deactivating list-units)" ]; sleep 0.5 done -systemctl --user unset-environment 'DBUS_SESSION_BUS_ADDRESS' 'DISPLAY' 'SSH_AUTH_SOCK' 'XAUTHORITY' 'XDG_DATA_DIRS' 'XDG_RUNTIME_DIR' 'XDG_SESSION_ID' 'EXTRA_IMPORTED_VARIABLE' +systemctl --user unset-environment DBUS_SESSION_BUS_ADDRESS DISPLAY SSH_AUTH_SOCK XAUTHORITY XDG_DATA_DIRS XDG_RUNTIME_DIR XDG_SESSION_ID EXTRA_IMPORTED_VARIABLE diff --git a/tests/modules/programs/atuin/set-flags.nix b/tests/modules/programs/atuin/set-flags.nix index b6e8330d1..ebc68a5d1 100644 --- a/tests/modules/programs/atuin/set-flags.nix +++ b/tests/modules/programs/atuin/set-flags.nix @@ -25,12 +25,12 @@ assertFileExists home-files/.bashrc assertFileContains \ home-files/.bashrc \ - "eval \"\$(@atuin@/bin/atuin init bash '--disable-ctrl-r' '--disable-up-arrow')\"" + "eval \"\$(@atuin@/bin/atuin init bash --disable-ctrl-r --disable-up-arrow)\"" assertFileExists home-files/.zshrc assertFileContains \ home-files/.zshrc \ - "eval \"\$(@atuin@/bin/atuin init zsh '--disable-ctrl-r' '--disable-up-arrow')\"" + "eval \"\$(@atuin@/bin/atuin init zsh --disable-ctrl-r --disable-up-arrow)\"" assertFileExists home-files/.config/fish/config.fish assertFileContains \ home-files/.config/fish/config.fish \ diff --git a/tests/modules/programs/autorandr/basic-configuration.nix b/tests/modules/programs/autorandr/basic-configuration.nix index e650f6005..d0f14ec86 100644 --- a/tests/modules/programs/autorandr/basic-configuration.nix +++ b/tests/modules/programs/autorandr/basic-configuration.nix @@ -23,6 +23,10 @@ [ 0.0 0.6 0.0 ] # d e f [ 0.0 0.0 1.0 ] # g h i ]; + extraConfig = '' + key1 value1 + key2 value2 + ''; }; }; }; @@ -52,7 +56,10 @@ primary mode 1920x1080 filter nearest - transform 0.600000,0.000000,0.000000,0.000000,0.600000,0.000000,0.000000,0.000000,1.000000'' + transform 0.600000,0.000000,0.000000,0.000000,0.600000,0.000000,0.000000,0.000000,1.000000 + key1 value1 + key2 value2 + '' } ''; }; diff --git a/tests/modules/programs/bat/bat.nix b/tests/modules/programs/bat/bat.nix index cd169ffb7..578310486 100644 --- a/tests/modules/programs/bat/bat.nix +++ b/tests/modules/programs/bat/bat.nix @@ -35,7 +35,7 @@ with lib; --map-syntax='*.jenkinsfile:Groovy' --map-syntax='*.props:Java Properties' --pager='less -FR' - --theme='TwoDark' + --theme=TwoDark --show-all '' } diff --git a/tests/modules/programs/bat/deprecated-options.nix b/tests/modules/programs/bat/deprecated-options.nix index 31a10413a..096815cbe 100644 --- a/tests/modules/programs/bat/deprecated-options.nix +++ b/tests/modules/programs/bat/deprecated-options.nix @@ -45,7 +45,7 @@ with lib; --map-syntax='*.jenkinsfile:Groovy' --map-syntax='*.props:Java Properties' --pager='less -FR' - --theme='TwoDark' + --theme=TwoDark '' } diff --git a/tests/modules/programs/bemenu/basic-configuration.nix b/tests/modules/programs/bemenu/basic-configuration.nix index b8d84469c..01708d202 100644 --- a/tests/modules/programs/bemenu/basic-configuration.nix +++ b/tests/modules/programs/bemenu/basic-configuration.nix @@ -24,6 +24,6 @@ nmt.script = '' assertFileExists home-path/etc/profile.d/hm-session-vars.sh assertFileContains home-path/etc/profile.d/hm-session-vars.sh \ - "export BEMENU_OPTS=\"'--ab' '#1e1e2e' '--af' '#cdd6f4' '--fb' '#1e1e2e' '--ff' '#cdd6f4' '--hb' '#1e1e2e' '--hf' '#f9e2af' '--ignorecase' '--line-height' '28' '--nb' '#1e1e2e' '--nf' '#cdd6f4' '--prompt' 'open' '--tb' '#1e1e2e' '--tf' '#f38ba8' '--width-factor' '0.300000'\"" + "export BEMENU_OPTS=\"--ab '#1e1e2e' --af '#cdd6f4' --fb '#1e1e2e' --ff '#cdd6f4' --hb '#1e1e2e' --hf '#f9e2af' --ignorecase --line-height 28 --nb '#1e1e2e' --nf '#cdd6f4' --prompt open --tb '#1e1e2e' --tf '#f38ba8' --width-factor 0.300000\"" ''; } diff --git a/tests/modules/programs/cmus/cmus.nix b/tests/modules/programs/cmus/cmus.nix new file mode 100644 index 000000000..8d1bbbd3a --- /dev/null +++ b/tests/modules/programs/cmus/cmus.nix @@ -0,0 +1,20 @@ +{ ... }: + +{ + programs.cmus = { + enable = true; + theme = "gruvbox"; + extraConfig = "test"; + }; + + nmt.script = '' + assertFileContent \ + home-files/.config/cmus/rc \ + ${ + builtins.toFile "cmus-expected-rc" '' + colorscheme gruvbox + test + '' + } + ''; +} diff --git a/tests/modules/programs/cmus/default.nix b/tests/modules/programs/cmus/default.nix new file mode 100644 index 000000000..1b606bab3 --- /dev/null +++ b/tests/modules/programs/cmus/default.nix @@ -0,0 +1 @@ +{ cmus = ./cmus.nix; } diff --git a/tests/modules/programs/direnv/default.nix b/tests/modules/programs/direnv/default.nix index a0e618481..b61fb1e33 100644 --- a/tests/modules/programs/direnv/default.nix +++ b/tests/modules/programs/direnv/default.nix @@ -1,5 +1,6 @@ { direnv-bash = ./bash.nix; + direnv-mise = ./mise.nix; direnv-nix-direnv = ./nix-direnv.nix; direnv-nushell = ./nushell.nix; direnv-stdlib = ./stdlib.nix; diff --git a/tests/modules/programs/direnv/mise.nix b/tests/modules/programs/direnv/mise.nix new file mode 100644 index 000000000..b205df627 --- /dev/null +++ b/tests/modules/programs/direnv/mise.nix @@ -0,0 +1,17 @@ +{ config, ... }: + +{ + programs.bash.enable = true; + programs.direnv = { + enable = true; + mise = { + enable = true; + package = config.lib.test.mkStubPackage { name = "mise"; }; + }; + }; + + nmt.script = '' + assertFileExists home-files/.bashrc + assertFileExists home-files/.config/direnv/lib/hm-mise.sh + ''; +} diff --git a/tests/modules/programs/direnv/nushell.nix b/tests/modules/programs/direnv/nushell.nix index 6655f01a8..502b325d5 100644 --- a/tests/modules/programs/direnv/nushell.nix +++ b/tests/modules/programs/direnv/nushell.nix @@ -13,7 +13,6 @@ "home-files/.config/nushell/config.nu"; in '' assertFileExists "${configFile}" - assertFileRegex "${configFile}" \ - '^\s*let direnv = (/nix/store/.*direnv.*/bin/direnv export json$' + assertFileRegex "${configFile}" '/nix/store/.*direnv.*/bin/direnv export json' ''; } diff --git a/tests/modules/programs/firefox/common.nix b/tests/modules/programs/firefox/common.nix new file mode 100644 index 000000000..a3af6d4ab --- /dev/null +++ b/tests/modules/programs/firefox/common.nix @@ -0,0 +1,16 @@ +name: +builtins.mapAttrs (test: module: import module [ "programs" name ]) { + "${name}-deprecated-native-messenger" = ./deprecated-native-messenger.nix; + "${name}-policies" = ./policies.nix; + "${name}-profiles-bookmarks" = ./profiles/bookmarks; + "${name}-profiles-containers" = ./profiles/containers; + "${name}-profiles-containers-duplicate-ids" = + ./profiles/containers/duplicate-ids.nix; + "${name}-profiles-containers-id-out-of-range" = + ./profiles/containers/id-out-of-range.nix; + "${name}-profiles-duplicate-ids" = ./profiles/duplicate-ids.nix; + "${name}-profiles-search" = ./profiles/search; + "${name}-profiles-settings" = ./profiles/settings; + "${name}-state-version-19_09" = ./state-version-19_09.nix; + "${name}-profiles-shared-path" = ./profiles/shared-path.nix; +} diff --git a/tests/modules/programs/firefox/firefox.nix b/tests/modules/programs/firefox/firefox.nix index 6598d6ec2..dd126e260 100644 --- a/tests/modules/programs/firefox/firefox.nix +++ b/tests/modules/programs/firefox/firefox.nix @@ -1,11 +1 @@ -let name = "firefox"; - -in builtins.mapAttrs (test: module: import module [ "programs" name ]) { - "${name}-profile-settings" = ./profile-settings.nix; - "${name}-state-version-19_09" = ./state-version-19_09.nix; - "${name}-deprecated-native-messenger" = ./deprecated-native-messenger.nix; - "${name}-duplicate-profile-ids" = ./duplicate-profile-ids.nix; - "${name}-duplicate-container-ids" = ./duplicate-container-ids.nix; - "${name}-container-id-out-of-range" = ./container-id-out-of-range.nix; - "${name}-policies" = ./policies.nix; -} +import ./common.nix "firefox" diff --git a/tests/modules/programs/firefox/floorp.nix b/tests/modules/programs/firefox/floorp.nix new file mode 100644 index 000000000..67a13659c --- /dev/null +++ b/tests/modules/programs/firefox/floorp.nix @@ -0,0 +1 @@ +import ./common.nix "floorp" diff --git a/tests/modules/programs/firefox/policies.nix b/tests/modules/programs/firefox/policies.nix index 5e02a1916..5cda1406a 100644 --- a/tests/modules/programs/firefox/policies.nix +++ b/tests/modules/programs/firefox/policies.nix @@ -20,7 +20,7 @@ in { package = pkgs.${cfg.wrappedPackageName}.override { extraPolicies = { DownloadDirectory = "/foo"; }; }; - }) // { + } // { nmt.script = '' jq=${lib.getExe pkgs.jq} config_file="${cfg.finalPackage}/lib/${cfg.wrappedPackageName}/distribution/policies.json" @@ -39,5 +39,5 @@ in { fail "Expected '$config_file' to set 'policies.DownloadDirectory' to \"/foo\"" fi ''; - }; + }); } diff --git a/tests/modules/programs/firefox/profile-settings.nix b/tests/modules/programs/firefox/profile-settings.nix index d7776eb4f..897067625 100644 --- a/tests/modules/programs/firefox/profile-settings.nix +++ b/tests/modules/programs/firefox/profile-settings.nix @@ -9,6 +9,12 @@ let firefoxMockOverlay = import ./setup-firefox-mock-overlay.nix modulePath; + withName = path: + pkgs.substituteAll { + src = path; + name = cfg.wrappedPackageName; + }; + in { imports = [ firefoxMockOverlay ]; @@ -162,7 +168,27 @@ in { }; } // { - nmt.script = '' + nmt.script = let + + noHashQuery = '' + 'def walk(f): + . as $in + | if type == "object" then + reduce keys[] as $key + ( {}; . + { ($key): ($in[$key] | walk(f)) } | f ) + elif type == "array" then + map( walk(f) ) + else + f + end; + walk(if type == "object" then + if has("hash") then .hash = null else . end | + if has("privateHash") then .privateHash = null else . end + else + . + end)' ''; + + in '' assertFileRegex \ home-path/bin/${cfg.wrappedPackageName} \ MOZ_APP_LAUNCHER @@ -171,18 +197,18 @@ in { assertFileContent \ home-files/${cfg.configPath}/test/user.js \ - ${./profile-settings-expected-user.js} + ${withName ./profile-settings-expected-user.js} assertFileContent \ home-files/${cfg.configPath}/containers/containers.json \ - ${./profile-settings-expected-containers.json} + ${withName ./profile-settings-expected-containers.json} bookmarksUserJs=$(normalizeStorePaths \ home-files/${cfg.configPath}/bookmarks/user.js) assertFileContent \ $bookmarksUserJs \ - ${./profile-settings-expected-bookmarks-user.js} + ${withName ./profile-settings-expected-bookmarks-user.js} bookmarksFile="$(sed -n \ '/browser.bookmarks.file/ {s|^.*\(/nix/store[^"]*\).*|\1|;p}' \ @@ -190,13 +216,13 @@ in { assertFileContent \ $bookmarksFile \ - ${./profile-settings-expected-bookmarks.html} + ${withName ./profile-settings-expected-bookmarks.html} function assertFirefoxSearchContent() { compressedSearch=$(normalizeStorePaths "$1") decompressedSearch=$(dirname $compressedSearch)/search.json - ${pkgs.mozlz4a}/bin/mozlz4a -d "$compressedSearch" >(${pkgs.jq}/bin/jq . > "$decompressedSearch") + ${pkgs.mozlz4a}/bin/mozlz4a -d "$compressedSearch" >(${pkgs.jq}/bin/jq ${noHashQuery} > "$decompressedSearch") assertFileContent \ $decompressedSearch \ @@ -205,11 +231,11 @@ in { assertFirefoxSearchContent \ home-files/${cfg.configPath}/search/search.json.mozlz4 \ - ${./profile-settings-expected-search.json} + ${withName ./profile-settings-expected-search.json} assertFirefoxSearchContent \ home-files/${cfg.configPath}/searchWithoutDefault/search.json.mozlz4 \ - ${./profile-settings-expected-search-without-default.json} + ${withName ./profile-settings-expected-search-without-default.json} ''; }); } diff --git a/tests/modules/programs/firefox/profiles/bookmarks/default.nix b/tests/modules/programs/firefox/profiles/bookmarks/default.nix new file mode 100644 index 000000000..dfbcfbd92 --- /dev/null +++ b/tests/modules/programs/firefox/profiles/bookmarks/default.nix @@ -0,0 +1,90 @@ +modulePath: +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = getAttrFromPath modulePath config; + + firefoxMockOverlay = import ../../setup-firefox-mock-overlay.nix modulePath; + + withName = path: + pkgs.substituteAll { + src = path; + name = cfg.wrappedPackageName; + }; + +in { + imports = [ firefoxMockOverlay ]; + + config = mkIf config.test.enableBig (setAttrByPath modulePath { + enable = true; + profiles.bookmarks = { + settings = { "general.smoothScroll" = false; }; + bookmarks = [ + { + toolbar = true; + bookmarks = [{ + name = "Home Manager"; + url = "https://wiki.nixos.org/wiki/Home_Manager"; + }]; + } + { + name = "wikipedia"; + tags = [ "wiki" ]; + keyword = "wiki"; + url = "https://en.wikipedia.org/wiki/Special:Search?search=%s&go=Go"; + } + { + name = "kernel.org"; + url = "https://www.kernel.org"; + } + { + name = "Nix sites"; + bookmarks = [ + { + name = "homepage"; + url = "https://nixos.org/"; + } + { + name = "wiki"; + tags = [ "wiki" "nix" ]; + url = "https://wiki.nixos.org/"; + } + { + name = "Nix sites"; + bookmarks = [ + { + name = "homepage"; + url = "https://nixos.org/"; + } + { + name = "wiki"; + url = "https://wiki.nixos.org/"; + } + ]; + } + ]; + } + ]; + }; + } // { + nmt.script = '' + bookmarksUserJs=$(normalizeStorePaths \ + home-files/${cfg.configPath}/bookmarks/user.js) + + assertFileContent \ + $bookmarksUserJs \ + ${withName ./expected-bookmarks-user.js} + + bookmarksFile="$(sed -n \ + '/browser.bookmarks.file/ {s|^.*\(/nix/store[^"]*\).*|\1|;p}' \ + $TESTED/home-files/${cfg.configPath}/bookmarks/user.js)" + + assertFileContent \ + $bookmarksFile \ + ${./expected-bookmarks.html} + ''; + }); +} diff --git a/tests/modules/programs/firefox/profile-settings-expected-bookmarks-user.js b/tests/modules/programs/firefox/profiles/bookmarks/expected-bookmarks-user.js similarity index 81% rename from tests/modules/programs/firefox/profile-settings-expected-bookmarks-user.js rename to tests/modules/programs/firefox/profiles/bookmarks/expected-bookmarks-user.js index 922d3651e..47448a6e4 100644 --- a/tests/modules/programs/firefox/profile-settings-expected-bookmarks-user.js +++ b/tests/modules/programs/firefox/profiles/bookmarks/expected-bookmarks-user.js @@ -1,6 +1,6 @@ // Generated by Home Manager. -user_pref("browser.bookmarks.file", "/nix/store/00000000000000000000000000000000-firefox-bookmarks.html"); +user_pref("browser.bookmarks.file", "/nix/store/00000000000000000000000000000000-@name@-bookmarks.html"); user_pref("browser.places.importBookmarksHTML", true); user_pref("general.smoothScroll", false); diff --git a/tests/modules/programs/firefox/profile-settings-expected-bookmarks.html b/tests/modules/programs/firefox/profiles/bookmarks/expected-bookmarks.html similarity index 100% rename from tests/modules/programs/firefox/profile-settings-expected-bookmarks.html rename to tests/modules/programs/firefox/profiles/bookmarks/expected-bookmarks.html diff --git a/tests/modules/programs/firefox/profiles/containers/default.nix b/tests/modules/programs/firefox/profiles/containers/default.nix new file mode 100644 index 000000000..6a0d9e93f --- /dev/null +++ b/tests/modules/programs/firefox/profiles/containers/default.nix @@ -0,0 +1,32 @@ +modulePath: +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = getAttrFromPath modulePath config; + + firefoxMockOverlay = import ../../setup-firefox-mock-overlay.nix modulePath; + +in { + imports = [ firefoxMockOverlay ]; + + config = mkIf config.test.enableBig (setAttrByPath modulePath { + enable = true; + profiles.containers = { + containers = { + "shopping" = { + icon = "circle"; + color = "yellow"; + }; + }; + }; + } // { + nmt.script = '' + assertFileContent \ + home-files/${cfg.configPath}/containers/containers.json \ + ${./expected-containers.json} + ''; + }); +} diff --git a/tests/modules/programs/firefox/duplicate-container-ids.nix b/tests/modules/programs/firefox/profiles/containers/duplicate-ids.nix similarity index 90% rename from tests/modules/programs/firefox/duplicate-container-ids.nix rename to tests/modules/programs/firefox/profiles/containers/duplicate-ids.nix index 2ad99b4b7..a60522165 100644 --- a/tests/modules/programs/firefox/duplicate-container-ids.nix +++ b/tests/modules/programs/firefox/profiles/containers/duplicate-ids.nix @@ -7,7 +7,7 @@ let cfg = getAttrFromPath modulePath config; - firefoxMockOverlay = import ./setup-firefox-mock-overlay.nix modulePath; + firefoxMockOverlay = import ../../setup-firefox-mock-overlay.nix modulePath; in { imports = [ firefoxMockOverlay ]; diff --git a/tests/modules/programs/firefox/profile-settings-expected-containers.json b/tests/modules/programs/firefox/profiles/containers/expected-containers.json similarity index 66% rename from tests/modules/programs/firefox/profile-settings-expected-containers.json rename to tests/modules/programs/firefox/profiles/containers/expected-containers.json index 8eea55558..28d8143d0 100644 --- a/tests/modules/programs/firefox/profile-settings-expected-containers.json +++ b/tests/modules/programs/firefox/profiles/containers/expected-containers.json @@ -1 +1 @@ -{"identities":[{"color":"yellow","icon":"circle","name":"shopping","public":true,"userContextId":6},{"accessKey":"","color":"","icon":"","name":"userContextIdInternal.thumbnail","public":false,"userContextId":4294967294},{"accessKey":"","color":"","icon":"","name":"userContextIdInternal.webextStorageLocal","public":false,"userContextId":4294967295}],"lastUserContextId":6,"version":4} +{"identities":[{"color":"yellow","icon":"circle","name":"shopping","public":true,"userContextId":0},{"accessKey":"","color":"","icon":"","name":"userContextIdInternal.thumbnail","public":false,"userContextId":4294967294},{"accessKey":"","color":"","icon":"","name":"userContextIdInternal.webextStorageLocal","public":false,"userContextId":4294967295}],"lastUserContextId":0,"version":5} diff --git a/tests/modules/programs/firefox/container-id-out-of-range.nix b/tests/modules/programs/firefox/profiles/containers/id-out-of-range.nix similarity index 86% rename from tests/modules/programs/firefox/container-id-out-of-range.nix rename to tests/modules/programs/firefox/profiles/containers/id-out-of-range.nix index 2ea08e880..f39666723 100644 --- a/tests/modules/programs/firefox/container-id-out-of-range.nix +++ b/tests/modules/programs/firefox/profiles/containers/id-out-of-range.nix @@ -5,7 +5,7 @@ with lib; let - firefoxMockOverlay = import ./setup-firefox-mock-overlay.nix modulePath; + firefoxMockOverlay = import ../../setup-firefox-mock-overlay.nix modulePath; in { imports = [ firefoxMockOverlay ]; diff --git a/tests/modules/programs/firefox/duplicate-profile-ids.nix b/tests/modules/programs/firefox/profiles/duplicate-ids.nix similarity index 87% rename from tests/modules/programs/firefox/duplicate-profile-ids.nix rename to tests/modules/programs/firefox/profiles/duplicate-ids.nix index ad946af10..dc5557b47 100644 --- a/tests/modules/programs/firefox/duplicate-profile-ids.nix +++ b/tests/modules/programs/firefox/profiles/duplicate-ids.nix @@ -7,7 +7,7 @@ let cfg = getAttrFromPath modulePath config; - firefoxMockOverlay = import ./setup-firefox-mock-overlay.nix modulePath; + firefoxMockOverlay = import ../setup-firefox-mock-overlay.nix modulePath; in { imports = [ firefoxMockOverlay ]; diff --git a/tests/modules/programs/firefox/profiles/search/default.nix b/tests/modules/programs/firefox/profiles/search/default.nix new file mode 100644 index 000000000..76acfcd3a --- /dev/null +++ b/tests/modules/programs/firefox/profiles/search/default.nix @@ -0,0 +1,138 @@ +modulePath: +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = getAttrFromPath modulePath config; + + firefoxMockOverlay = import ../../setup-firefox-mock-overlay.nix modulePath; + + withName = path: + pkgs.substituteAll { + src = path; + name = cfg.wrappedPackageName; + }; + +in { + imports = [ firefoxMockOverlay ]; + + config = mkIf config.test.enableBig (setAttrByPath modulePath { + enable = true; + profiles = { + search = { + id = 0; + search = { + force = true; + default = "Google"; + privateDefault = "DuckDuckGo"; + order = [ "Nix Packages" "NixOS Wiki" ]; + engines = { + "Nix Packages" = { + urls = [{ + template = "https://search.nixos.org/packages"; + params = [ + { + name = "type"; + value = "packages"; + } + { + name = "query"; + value = "{searchTerms}"; + } + ]; + }]; + + icon = + "/run/current-system/sw/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; + + definedAliases = [ "@np" ]; + }; + + "NixOS Wiki" = { + urls = [{ + template = + "https://wiki.nixos.org/index.php?search={searchTerms}"; + }]; + iconUpdateURL = "https://wiki.nixos.org/favicon.png"; + updateInterval = 24 * 60 * 60 * 1000; + definedAliases = [ "@nw" ]; + }; + + "Bing".metaData.hidden = true; + "Google".metaData.alias = "@g"; + }; + }; + }; + + searchWithoutDefault = { + id = 1; + search = { + force = true; + order = [ "Google" "Nix Packages" ]; + engines = { + "Nix Packages" = { + urls = [{ + template = "https://search.nixos.org/packages"; + params = [ + { + name = "type"; + value = "packages"; + } + { + name = "query"; + value = "{searchTerms}"; + } + ]; + }]; + + definedAliases = [ "@np" ]; + }; + }; + }; + }; + }; + } // { + nmt.script = let + + noHashQuery = '' + 'def walk(f): + . as $in + | if type == "object" then + reduce keys[] as $key + ( {}; . + { ($key): ($in[$key] | walk(f)) } | f ) + elif type == "array" then + map( walk(f) ) + else + f + end; + walk(if type == "object" then + if has("hash") then .hash = null else . end | + if has("privateHash") then .privateHash = null else . end + else + . + end)' ''; + + in '' + function assertFirefoxSearchContent() { + compressedSearch=$(normalizeStorePaths "$1") + + decompressedSearch=$(dirname $compressedSearch)/search.json + ${pkgs.mozlz4a}/bin/mozlz4a -d "$compressedSearch" >(${pkgs.jq}/bin/jq ${noHashQuery} > "$decompressedSearch") + + assertFileContent \ + $decompressedSearch \ + "$2" + } + + assertFirefoxSearchContent \ + home-files/${cfg.configPath}/search/search.json.mozlz4 \ + ${withName ./expected-search.json} + + assertFirefoxSearchContent \ + home-files/${cfg.configPath}/searchWithoutDefault/search.json.mozlz4 \ + ${withName ./expected-search-without-default.json} + ''; + }); +} diff --git a/tests/modules/programs/firefox/profile-settings-expected-search-without-default.json b/tests/modules/programs/firefox/profiles/search/expected-search-without-default.json similarity index 85% rename from tests/modules/programs/firefox/profile-settings-expected-search-without-default.json rename to tests/modules/programs/firefox/profiles/search/expected-search-without-default.json index b845dad42..ec1ce14c8 100644 --- a/tests/modules/programs/firefox/profile-settings-expected-search-without-default.json +++ b/tests/modules/programs/firefox/profiles/search/expected-search-without-default.json @@ -12,7 +12,7 @@ "@np" ], "_isAppProvided": false, - "_loadPath": "[home-manager]/programs.firefox.profiles.searchWithoutDefault.search.engines.\"Nix Packages\"", + "_loadPath": "[home-manager]/programs.@name@.profiles.searchWithoutDefault.search.engines.\"Nix Packages\"", "_metaData": { "order": 2 }, diff --git a/tests/modules/programs/firefox/profile-settings-expected-search.json b/tests/modules/programs/firefox/profiles/search/expected-search.json similarity index 82% rename from tests/modules/programs/firefox/profile-settings-expected-search.json rename to tests/modules/programs/firefox/profiles/search/expected-search.json index 832b6c09c..a661cf3fe 100644 --- a/tests/modules/programs/firefox/profile-settings-expected-search.json +++ b/tests/modules/programs/firefox/profiles/search/expected-search.json @@ -6,7 +6,7 @@ ], "_iconURL": "file:///run/current-system/sw/share/icons/hicolor/scalable/apps/nix-snowflake.svg", "_isAppProvided": false, - "_loadPath": "[home-manager]/programs.firefox.profiles.search.search.engines.\"Nix Packages\"", + "_loadPath": "[home-manager]/programs.@name@.profiles.search.search.engines.\"Nix Packages\"", "_metaData": { "order": 1 }, @@ -34,7 +34,7 @@ "_iconURL": "https://wiki.nixos.org/favicon.png", "_iconUpdateURL": "https://wiki.nixos.org/favicon.png", "_isAppProvided": false, - "_loadPath": "[home-manager]/programs.firefox.profiles.search.search.engines.\"NixOS Wiki\"", + "_loadPath": "[home-manager]/programs.@name@.profiles.search.search.engines.\"NixOS Wiki\"", "_metaData": { "order": 2 }, @@ -68,9 +68,9 @@ ], "metaData": { "current": "Google", - "hash": "IRmKVSQlAYnvLO8kdZyNUR/g5hzVn4++T0PLPGm+kZk=", + "hash": null, "private": "DuckDuckGo", - "privateHash": "BWvqUiaCuMJ20lbymFf2dqzWyl1cgm1LZhhdWNEp0Cc=", + "privateHash": null, "useSavedOrder": true }, "version": 6 diff --git a/tests/modules/programs/firefox/profiles/settings/default.nix b/tests/modules/programs/firefox/profiles/settings/default.nix new file mode 100644 index 000000000..39d329ece --- /dev/null +++ b/tests/modules/programs/firefox/profiles/settings/default.nix @@ -0,0 +1,43 @@ +modulePath: +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = getAttrFromPath modulePath config; + + firefoxMockOverlay = import ../../setup-firefox-mock-overlay.nix modulePath; + +in { + imports = [ firefoxMockOverlay ]; + + config = mkIf config.test.enableBig (setAttrByPath modulePath { + enable = true; + profiles = { + basic.isDefault = true; + test = { + id = 1; + settings = { + "general.smoothScroll" = false; + "browser.newtabpage.pinned" = [{ + title = "NixOS"; + url = "https://nixos.org"; + }]; + }; + }; + }; + } // { + nmt.script = '' + assertFileRegex \ + home-path/bin/${cfg.wrappedPackageName} \ + MOZ_APP_LAUNCHER + + assertDirectoryExists home-files/${cfg.configPath}/basic + + assertFileContent \ + home-files/${cfg.configPath}/test/user.js \ + ${./expected-user.js} + ''; + }); +} diff --git a/tests/modules/programs/firefox/profile-settings-expected-user.js b/tests/modules/programs/firefox/profiles/settings/expected-user.js similarity index 100% rename from tests/modules/programs/firefox/profile-settings-expected-user.js rename to tests/modules/programs/firefox/profiles/settings/expected-user.js diff --git a/tests/modules/programs/firefox/profiles/shared-path.nix b/tests/modules/programs/firefox/profiles/shared-path.nix new file mode 100644 index 000000000..e6d4a06d4 --- /dev/null +++ b/tests/modules/programs/firefox/profiles/shared-path.nix @@ -0,0 +1,53 @@ +modulePath: +{ config, lib, ... }: + +with lib; + +let firefoxMockOverlay = import ../setup-firefox-mock-overlay.nix modulePath; +in { + imports = [ firefoxMockOverlay ]; + + config = mkIf config.test.enableBig (setAttrByPath modulePath { + enable = true; + + profiles = { + main = { + isDefault = true; + id = 1; + bookmarks = [{ + toolbar = true; + bookmarks = [{ + name = "Home Manager"; + url = "https://wiki.nixos.org/wiki/Home_Manager"; + }]; + }]; + containers = { + "shopping" = { + icon = "circle"; + color = "yellow"; + }; + }; + search = { + force = true; + default = "Google"; + privateDefault = "DuckDuckGo"; + engines = { + "Bing".metaData.hidden = true; + "Google".metaData.alias = "@g"; + }; + }; + settings = { + "general.smoothScroll" = false; + "browser.newtabpage.pinned" = [{ + title = "NixOS"; + url = "https://nixos.org"; + }]; + }; + }; + "dev-edition-default" = { + id = 2; + path = "main"; + }; + }; + }); +} diff --git a/tests/modules/programs/git-credential-oauth/basic.nix b/tests/modules/programs/git-credential-oauth/basic.nix new file mode 100644 index 000000000..741adfbfb --- /dev/null +++ b/tests/modules/programs/git-credential-oauth/basic.nix @@ -0,0 +1,16 @@ +{ config, pkgs, ... }: + +{ + programs.git-credential-oauth = { enable = true; }; + + programs.git = { enable = true; }; + + test.stubs.git-credential-oauth = { }; + + nmt.script = '' + assertFileExists home-files/.config/git/config + assertFileContains \ + home-files/.config/git/config \ + "${config.programs.git-credential-oauth.package}/bin/git-credential-oauth" + ''; +} diff --git a/tests/modules/programs/git-credential-oauth/default.nix b/tests/modules/programs/git-credential-oauth/default.nix new file mode 100644 index 000000000..63ecb183a --- /dev/null +++ b/tests/modules/programs/git-credential-oauth/default.nix @@ -0,0 +1,4 @@ +{ + git-credential-oauth-basic = ./basic.nix; + git-credential-oauth-extra-flags = ./extra-flags.nix; +} diff --git a/tests/modules/programs/git-credential-oauth/extra-flags.nix b/tests/modules/programs/git-credential-oauth/extra-flags.nix new file mode 100644 index 000000000..7a586ede6 --- /dev/null +++ b/tests/modules/programs/git-credential-oauth/extra-flags.nix @@ -0,0 +1,19 @@ +{ config, pkgs, ... }: + +{ + programs.git-credential-oauth = { + enable = true; + extraFlags = [ "-device" ]; + }; + + programs.git = { enable = true; }; + + test.stubs.git-credential-oauth = { }; + + nmt.script = '' + assertFileExists home-files/.config/git/config + assertFileContains \ + home-files/.config/git/config \ + "${config.programs.git-credential-oauth.package}/bin/git-credential-oauth -device" + ''; +} diff --git a/tests/modules/programs/gpg/immutable-keyfiles.nix b/tests/modules/programs/gpg/immutable-keyfiles.nix index 15dd2b9e7..37889a11e 100644 --- a/tests/modules/programs/gpg/immutable-keyfiles.nix +++ b/tests/modules/programs/gpg/immutable-keyfiles.nix @@ -27,7 +27,7 @@ }; nmt.script = '' - assertFileNotRegex activate "^export GNUPGHOME='/home/hm-user/.gnupg'$" + assertFileNotRegex activate "^export GNUPGHOME=/home/hm-user/.gnupg$" assertFileRegex activate \ '^install -m 0700 /nix/store/[0-9a-z]*-gpg-pubring/trustdb.gpg "/home/hm-user/.gnupg/trustdb.gpg"$' diff --git a/tests/modules/programs/gpg/mutable-keyfiles.nix b/tests/modules/programs/gpg/mutable-keyfiles.nix index ea87a3e0a..6ffcb7053 100644 --- a/tests/modules/programs/gpg/mutable-keyfiles.nix +++ b/tests/modules/programs/gpg/mutable-keyfiles.nix @@ -17,7 +17,7 @@ test.stubs.systemd = { }; # depends on gnupg.override nmt.script = '' - assertFileContains activate "export GNUPGHOME='/home/hm-user/.gnupg'" + assertFileContains activate "export GNUPGHOME=/home/hm-user/.gnupg" assertFileContains activate "unset GNUPGHOME QUIET_ARG keyId importTrust" diff --git a/tests/modules/programs/granted/integration-disabled.nix b/tests/modules/programs/granted/integration-disabled.nix index 6e43b4777..90f8d494a 100644 --- a/tests/modules/programs/granted/integration-disabled.nix +++ b/tests/modules/programs/granted/integration-disabled.nix @@ -19,7 +19,7 @@ 'export GRANTED_ALIAS_CONFIGURED="true"' assertFileNotRegex \ home-files/.zshrc \ - 'source @granted@/bin/.assume-wrapped "$@"' + 'source @granted@/bin/assume "$@"' assertFileNotRegex \ home-files/.zshrc \ 'unset GRANTED_ALIAS_CONFIGURED' diff --git a/tests/modules/programs/granted/integration-enabled.nix b/tests/modules/programs/granted/integration-enabled.nix index daf843676..5bb903aae 100644 --- a/tests/modules/programs/granted/integration-enabled.nix +++ b/tests/modules/programs/granted/integration-enabled.nix @@ -18,7 +18,7 @@ 'export GRANTED_ALIAS_CONFIGURED="true"' assertFileContains \ home-files/.zshrc \ - 'source @granted@/bin/.assume-wrapped "$@"' + 'source @granted@/bin/assume "$@"' assertFileContains \ home-files/.zshrc \ 'unset GRANTED_ALIAS_CONFIGURED' diff --git a/tests/modules/programs/k9s/example-settings.nix b/tests/modules/programs/k9s/example-settings.nix index 23a42120b..0000d81da 100644 --- a/tests/modules/programs/k9s/example-settings.nix +++ b/tests/modules/programs/k9s/example-settings.nix @@ -39,6 +39,7 @@ }; }; }; + "default2" = ./example-skin-expected.yaml; "alt-skin" = { k9s = { body = { @@ -92,6 +93,10 @@ assertFileContent \ "home-files/${configDir}/skins/default.yaml" \ ${./example-skin-expected.yaml} + assertFileExists "home-files/${configDir}/skins/default2.yaml" + assertFileContent \ + "home-files/${configDir}/skins/default2.yaml" \ + ${./example-skin-expected.yaml} assertFileExists "home-files/${configDir}/skins/alt-skin.yaml" assertFileContent \ "home-files/${configDir}/skins/alt-skin.yaml" \ diff --git a/tests/modules/programs/kitty/default.nix b/tests/modules/programs/kitty/default.nix index 694c43cd8..76016d516 100644 --- a/tests/modules/programs/kitty/default.nix +++ b/tests/modules/programs/kitty/default.nix @@ -1 +1,4 @@ -{ kitty-example-settings = ./example-settings.nix; } +{ + kitty-example-settings = ./example-settings.nix; + kitty-theme-to-themeFile = ./theme-to-themeFile.nix; +} diff --git a/tests/modules/programs/kitty/example-settings-expected.conf b/tests/modules/programs/kitty/example-settings-expected.conf index aca1b0c18..41a9cb772 100644 --- a/tests/modules/programs/kitty/example-settings-expected.conf +++ b/tests/modules/programs/kitty/example-settings-expected.conf @@ -7,6 +7,7 @@ font_size 8 # Shell integration is sourced and configured manually shell_integration no-rc +background_opacity 0.500000 enable_audio_bell no scrollback_lines 10000 update_check_interval 0 diff --git a/tests/modules/programs/kitty/example-settings.nix b/tests/modules/programs/kitty/example-settings.nix index 8d609a5ab..8f2e0b894 100644 --- a/tests/modules/programs/kitty/example-settings.nix +++ b/tests/modules/programs/kitty/example-settings.nix @@ -17,6 +17,7 @@ with lib; scrollback_lines = 10000; enable_audio_bell = false; update_check_interval = 0; + background_opacity = 0.5; }; font.name = "DejaVu Sans"; diff --git a/tests/modules/programs/kitty/theme-to-themeFile.nix b/tests/modules/programs/kitty/theme-to-themeFile.nix new file mode 100644 index 000000000..84596bba9 --- /dev/null +++ b/tests/modules/programs/kitty/theme-to-themeFile.nix @@ -0,0 +1,24 @@ +{ config, lib, pkgs, options, ... }: { + config = { + programs.kitty = { + enable = true; + theme = "Space Gray Eighties"; + }; + + test.stubs.kitty = { }; + + test.asserts.warnings.enable = true; + test.asserts.warnings.expected = [ + ("The option `programs.kitty.theme' defined in ${ + lib.showFiles options.programs.kitty.theme.files + } has been changed to `programs.kitty.themeFile' that has a different" + + " type. Please read `programs.kitty.themeFile' documentation and" + + " update your configuration accordingly.") + ]; + + nmt.script = '' + assertFileExists home-files/.config/kitty/kitty.conf + assertFileRegex home-files/.config/kitty/kitty.conf "^include .*themes/SpaceGray_Eighties\.conf$" + ''; + }; +} diff --git a/tests/modules/programs/mujmap/mujmap-defaults-expected.toml b/tests/modules/programs/mujmap/mujmap-defaults-expected.toml index 87b5bf402..7d94afa64 100644 --- a/tests/modules/programs/mujmap/mujmap-defaults-expected.toml +++ b/tests/modules/programs/mujmap/mujmap-defaults-expected.toml @@ -1,6 +1,6 @@ auto_create_new_mailboxes = true fqdn = "example.com" -password_command = "'password-command'" +password_command = "password-command" username = "home.manager" [tags] diff --git a/tests/modules/programs/neovide/default.nix b/tests/modules/programs/neovide/default.nix new file mode 100644 index 000000000..f11bc33bc --- /dev/null +++ b/tests/modules/programs/neovide/default.nix @@ -0,0 +1 @@ +{ neovide-program = ./neovide.nix; } diff --git a/tests/modules/programs/neovide/expected.toml b/tests/modules/programs/neovide/expected.toml new file mode 100644 index 000000000..0c3f0b20b --- /dev/null +++ b/tests/modules/programs/neovide/expected.toml @@ -0,0 +1,15 @@ +fork = false +frame = "full" +idle = true +maximized = false +neovim-bin = "/usr/bin/nvim" +no-multigrid = false +srgb = false +tabs = true +theme = "auto" +title-hidden = true +vsync = true +wsl = false +[font] +normal = [] +size = 14.0 diff --git a/tests/modules/programs/neovide/neovide.nix b/tests/modules/programs/neovide/neovide.nix new file mode 100644 index 000000000..774964f01 --- /dev/null +++ b/tests/modules/programs/neovide/neovide.nix @@ -0,0 +1,34 @@ +{ ... }: + +{ + programs.neovide = { + enable = true; + + settings = { + fork = false; + frame = "full"; + idle = true; + maximized = false; + neovim-bin = "/usr/bin/nvim"; + no-multigrid = false; + srgb = false; + tabs = true; + theme = "auto"; + title-hidden = true; + vsync = true; + wsl = false; + + font = { + normal = [ ]; + size = 14.0; + }; + }; + }; + + test.stubs.neovide = { }; + + nmt.script = '' + assertFileExists home-files/.config/neovide/config.toml + assertFileContent home-files/.config/neovide/config.toml ${./expected.toml} + ''; +} diff --git a/tests/modules/programs/nushell/env-expected.nu b/tests/modules/programs/nushell/env-expected.nu index 07105fc54..50f6f767b 100644 --- a/tests/modules/programs/nushell/env-expected.nu +++ b/tests/modules/programs/nushell/env-expected.nu @@ -1,4 +1,17 @@ $env.FOO = 'BAR' -$env.BAR = $'(echo BAZ)' \ No newline at end of file +load-env { + "ENV_CONVERSIONS": { + "PATH": { + "from_string": ({|s| $s | split row (char esep) }) + "to_string": ({|v| $v | str join (char esep) }) + } + } + "FOO": "BAR" + "LIST_VALUE": [ + "foo" + "bar" + ] + "PROMPT_COMMAND": ({|| "> "}) +} diff --git a/tests/modules/programs/nushell/example-settings.nix b/tests/modules/programs/nushell/example-settings.nix index d870eb9db..4fc1402a4 100644 --- a/tests/modules/programs/nushell/example-settings.nix +++ b/tests/modules/programs/nushell/example-settings.nix @@ -1,4 +1,4 @@ -{ pkgs, config, ... }: +{ pkgs, config, lib, ... }: { programs.nushell = { @@ -28,7 +28,17 @@ "ll" = "ls -a"; }; - environmentVariables = { BAR = "$'(echo BAZ)'"; }; + environmentVariables = { + FOO = "BAR"; + LIST_VALUE = [ "foo" "bar" ]; + PROMPT_COMMAND = lib.hm.nushell.mkNushellInline ''{|| "> "}''; + ENV_CONVERSIONS.PATH = { + from_string = + lib.hm.nushell.mkNushellInline "{|s| $s | split row (char esep) }"; + to_string = + lib.hm.nushell.mkNushellInline "{|v| $v | str join (char esep) }"; + }; + }; }; test.stubs.nushell = { }; diff --git a/tests/modules/programs/pls/bash.nix b/tests/modules/programs/pls/bash.nix index d6fff5f4e..dc1743997 100644 --- a/tests/modules/programs/pls/bash.nix +++ b/tests/modules/programs/pls/bash.nix @@ -20,10 +20,10 @@ with lib; assertFileExists home-files/.bashrc assertFileContains \ home-files/.bashrc \ - "alias ls='@pls@/bin/pls'" + "alias ls=@pls@/bin/pls" assertFileContains \ home-files/.bashrc \ - "alias ll='@pls@/bin/pls -d perms -d user -d group -d size -d mtime -d git'" + "alias ll='@pls@/bin/pls -d perm -d user -d group -d size -d mtime -d git'" ''; }; } diff --git a/tests/modules/programs/pls/fish.nix b/tests/modules/programs/pls/fish.nix index d555a11c1..c745cd768 100644 --- a/tests/modules/programs/pls/fish.nix +++ b/tests/modules/programs/pls/fish.nix @@ -24,10 +24,10 @@ with lib; assertFileExists home-files/.config/fish/config.fish assertFileContains \ home-files/.config/fish/config.fish \ - "alias ls '@pls@/bin/pls'" + "alias ls @pls@/bin/pls" assertFileContains \ home-files/.config/fish/config.fish \ - "alias ll '@pls@/bin/pls -d perms -d user -d group -d size -d mtime -d git'" + "alias ll '@pls@/bin/pls -d perm -d user -d group -d size -d mtime -d git'" ''; }; } diff --git a/tests/modules/programs/pls/zsh.nix b/tests/modules/programs/pls/zsh.nix index 3a27c4d3e..bbe68abb5 100644 --- a/tests/modules/programs/pls/zsh.nix +++ b/tests/modules/programs/pls/zsh.nix @@ -23,10 +23,10 @@ with lib; assertFileExists home-files/.zshrc assertFileContains \ home-files/.zshrc \ - "alias -- 'ls'='@pls@/bin/pls'" + "alias -- ls=@pls@/bin/pls" assertFileContains \ home-files/.zshrc \ - "alias -- 'll'='@pls@/bin/pls -d perms -d user -d group -d size -d mtime -d git'" + "alias -- ll='@pls@/bin/pls -d perm -d user -d group -d size -d mtime -d git'" ''; }; } diff --git a/tests/modules/programs/pqiv/settings.nix b/tests/modules/programs/pqiv/settings.nix index 277203da5..117fa6f04 100644 --- a/tests/modules/programs/pqiv/settings.nix +++ b/tests/modules/programs/pqiv/settings.nix @@ -6,7 +6,7 @@ package = config.lib.test.mkStubPackage { name = "pqiv"; }; settings = { options = { - hide-info-box = 1; + hide-info-box = true; thumbnail-size = "256x256"; }; }; @@ -21,8 +21,8 @@ assertFileContent home-files/.config/pqivrc ${ builtins.toFile "pqiv.expected" '' [options] - hide-info-box=1 - thumbnail-size=256x256 + hide-info-box = 1 + thumbnail-size = 256x256 [keybindings] t { montage_mode_enter() } diff --git a/tests/modules/programs/spotify-player/keymap.toml b/tests/modules/programs/spotify-player/keymap.toml index d11c86e41..29cac4781 100644 --- a/tests/modules/programs/spotify-player/keymap.toml +++ b/tests/modules/programs/spotify-player/keymap.toml @@ -1,3 +1,16 @@ +[[actions]] +action = "GoToArtist" +key_sequence = "g A" + +[[actions]] +action = "GoToAlbum" +key_sequence = "g B" +target = "PlayingTrack" + +[[actions]] +action = "ToggleLiked" +key_sequence = "C-l" + [[keymaps]] command = "NextTrack" key_sequence = "g n" diff --git a/tests/modules/programs/spotify-player/settings.nix b/tests/modules/programs/spotify-player/settings.nix index dc7fe8c6a..e0442360b 100644 --- a/tests/modules/programs/spotify-player/settings.nix +++ b/tests/modules/programs/spotify-player/settings.nix @@ -87,6 +87,22 @@ key_sequence = "q"; } ]; + + actions = [ + { + action = "GoToArtist"; + key_sequence = "g A"; + } + { + action = "GoToAlbum"; + key_sequence = "g B"; + target = "PlayingTrack"; + } + { + action = "ToggleLiked"; + key_sequence = "C-l"; + } + ]; }; test.stubs.spotify-player = { }; diff --git a/tests/modules/programs/taskwarrior/taskwarrior.nix b/tests/modules/programs/taskwarrior/taskwarrior.nix index f21198f57..163135a03 100644 --- a/tests/modules/programs/taskwarrior/taskwarrior.nix +++ b/tests/modules/programs/taskwarrior/taskwarrior.nix @@ -6,6 +6,7 @@ with lib; config = { programs.taskwarrior = { enable = true; + package = pkgs.taskwarrior3; colorTheme = "dark-violets-256"; dataLocation = "/some/data/location"; config = { @@ -18,7 +19,7 @@ with lib; ''; }; - test.stubs.taskwarrior = { }; + test.stubs.taskwarrior3 = { }; nmt.script = '' assertFileExists home-files/.config/task/home-manager-taskrc diff --git a/tests/modules/programs/thefuck/integration-enabled-instant.nix b/tests/modules/programs/thefuck/integration-enabled-instant.nix index 18584acbd..7b89276af 100644 --- a/tests/modules/programs/thefuck/integration-enabled-instant.nix +++ b/tests/modules/programs/thefuck/integration-enabled-instant.nix @@ -16,11 +16,11 @@ assertFileExists home-files/.bashrc assertFileContains \ home-files/.bashrc \ - 'eval "$(@thefuck@/bin/thefuck '"'"'--alias'"'"' '"'"'--enable-experimental-instant-mode'"'"')"' + 'eval "$(@thefuck@/bin/thefuck --alias --enable-experimental-instant-mode)"' assertFileExists home-files/.zshrc assertFileContains \ home-files/.zshrc \ - 'eval "$(@thefuck@/bin/thefuck '"'"'--alias'"'"' '"'"'--enable-experimental-instant-mode'"'"')"' + 'eval "$(@thefuck@/bin/thefuck --alias --enable-experimental-instant-mode)"' ''; } diff --git a/tests/modules/programs/thefuck/integration-enabled.nix b/tests/modules/programs/thefuck/integration-enabled.nix index 54d6b794e..fb220e6cb 100644 --- a/tests/modules/programs/thefuck/integration-enabled.nix +++ b/tests/modules/programs/thefuck/integration-enabled.nix @@ -15,7 +15,7 @@ assertFileExists home-files/.bashrc assertFileContains \ home-files/.bashrc \ - 'eval "$(@thefuck@/bin/thefuck '"'"'--alias'"'"')"' + 'eval "$(@thefuck@/bin/thefuck --alias)"' assertFileExists home-files/.config/fish/functions/fuck.fish assertFileContains \ @@ -33,7 +33,7 @@ assertFileExists home-files/.zshrc assertFileContains \ home-files/.zshrc \ - 'eval "$(@thefuck@/bin/thefuck '"'"'--alias'"'"')"' + 'eval "$(@thefuck@/bin/thefuck --alias)"' assertFileExists home-files/.config/nushell/config.nu assertFileContains \ diff --git a/tests/modules/programs/thunderbird/thunderbird-expected-second.js b/tests/modules/programs/thunderbird/thunderbird-expected-second.js index 085182cbe..e4e9296a8 100644 --- a/tests/modules/programs/thunderbird/thunderbird-expected-second.js +++ b/tests/modules/programs/thunderbird/thunderbird-expected-second.js @@ -28,6 +28,7 @@ user_pref("mail.smtpserver.smtp_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da user_pref("mail.smtpserver.smtp_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.username", "home.manager.jr"); user_pref("mail.smtpservers", "smtp_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc"); user_pref("privacy.donottrackheader.enabled", true); +user_pref("second", {"nested":{"evenFurtherNested":[1,2,3]}}); user_pref("second.setting", "some-test-setting"); diff --git a/tests/modules/programs/thunderbird/thunderbird.nix b/tests/modules/programs/thunderbird/thunderbird.nix index f65f80bdf..127083977 100644 --- a/tests/modules/programs/thunderbird/thunderbird.nix +++ b/tests/modules/programs/thunderbird/thunderbird.nix @@ -53,7 +53,10 @@ ''; }; - second.settings = { "second.setting" = "some-test-setting"; }; + second.settings = { + "second.setting" = "some-test-setting"; + second.nested.evenFurtherNested = [ 1 2 3 ]; + }; }; settings = { diff --git a/tests/modules/programs/vifm/default.nix b/tests/modules/programs/vifm/default.nix new file mode 100644 index 000000000..5a75a54aa --- /dev/null +++ b/tests/modules/programs/vifm/default.nix @@ -0,0 +1,4 @@ +{ + vifm-example-settings = ./example-settings.nix; + vifm-empty-settings = ./empty-settings.nix; +} diff --git a/tests/modules/programs/vifm/empty-settings.nix b/tests/modules/programs/vifm/empty-settings.nix new file mode 100644 index 000000000..4e1df9c18 --- /dev/null +++ b/tests/modules/programs/vifm/empty-settings.nix @@ -0,0 +1,11 @@ +{ ... }: + +{ + programs.vifm.enable = true; + + test.stubs.vifm = { }; + + nmt.script = '' + assertPathNotExists home-files/.config/vifm + ''; +} diff --git a/tests/modules/programs/vifm/example-settings.nix b/tests/modules/programs/vifm/example-settings.nix new file mode 100644 index 000000000..8f562aa62 --- /dev/null +++ b/tests/modules/programs/vifm/example-settings.nix @@ -0,0 +1,21 @@ +{ config, ... }: + +{ + programs.vifm = { + enable = true; + package = config.lib.test.mkStubPackage { }; + extraConfig = '' + mark h ~/ + ''; + }; + + nmt.script = '' + assertFileContent \ + home-files/.config/vifm/vifmrc \ + ${ + builtins.toFile "vifm-expected.conf" '' + mark h ~/ + '' + } + ''; +} diff --git a/tests/modules/programs/wezterm/empty-setting.nix b/tests/modules/programs/wezterm/empty-setting.nix index 8e72b3b0e..2f2ffa084 100644 --- a/tests/modules/programs/wezterm/empty-setting.nix +++ b/tests/modules/programs/wezterm/empty-setting.nix @@ -10,7 +10,7 @@ -- Generated by Home Manager. -- See https://wezfurlong.org/wezterm/ - local wezterm = require 'wezterm'; + local wezterm = require 'wezterm' return {} diff --git a/tests/modules/programs/wezterm/example-setting.nix b/tests/modules/programs/wezterm/example-setting.nix index 60b81fa20..2ed566a7e 100644 --- a/tests/modules/programs/wezterm/example-setting.nix +++ b/tests/modules/programs/wezterm/example-setting.nix @@ -53,7 +53,7 @@ -- Generated by Home Manager. -- See https://wezfurlong.org/wezterm/ - local wezterm = require 'wezterm'; + local wezterm = require 'wezterm' return { font = wezterm.font("JetBrains Mono"), diff --git a/tests/modules/programs/zed-editor/default.nix b/tests/modules/programs/zed-editor/default.nix new file mode 100644 index 000000000..3c5c894fe --- /dev/null +++ b/tests/modules/programs/zed-editor/default.nix @@ -0,0 +1,5 @@ +{ + zed-extensions = ./extensions.nix; + zed-keymap = ./keymap.nix; + zed-settings = ./settings.nix; +} diff --git a/tests/modules/programs/zed-editor/extensions.nix b/tests/modules/programs/zed-editor/extensions.nix new file mode 100644 index 000000000..82b79aed8 --- /dev/null +++ b/tests/modules/programs/zed-editor/extensions.nix @@ -0,0 +1,24 @@ +{ config, ... }: + +{ + programs.zed-editor = { + enable = true; + package = config.lib.test.mkStubPackage { }; + extensions = [ "swift" "html" "xy-zed" ]; + }; + + nmt.script = let + expectedContent = builtins.toFile "expected.json" '' + { + "auto_install_extensions": { + "html": true, + "swift": true, + "xy-zed": true + } + } + ''; + in '' + assertFileExists "home-files/.config/zed/settings.json" + assertFileContent "home-files/.config/zed/settings.json" "${expectedContent}" + ''; +} diff --git a/tests/modules/programs/zed-editor/keymap.nix b/tests/modules/programs/zed-editor/keymap.nix new file mode 100644 index 000000000..df6abebdf --- /dev/null +++ b/tests/modules/programs/zed-editor/keymap.nix @@ -0,0 +1,39 @@ +# Test custom keymap functionality +{ config, ... }: + +{ + programs.zed-editor = { + enable = true; + package = config.lib.test.mkStubPackage { }; + userKeymaps = [ + { bindings = { up = "menu::SelectPrev"; }; } + { + context = "Editor"; + bindings = { escape = "editor::Cancel"; }; + } + ]; + }; + + nmt.script = let + expectedContent = builtins.toFile "expected.json" '' + [ + { + "bindings": { + "up": "menu::SelectPrev" + } + }, + { + "bindings": { + "escape": "editor::Cancel" + }, + "context": "Editor" + } + ] + ''; + + keymapPath = ".config/zed/keymap.json"; + in '' + assertFileExists "home-files/${keymapPath}" + assertFileContent "home-files/${keymapPath}" "${expectedContent}" + ''; +} diff --git a/tests/modules/programs/zed-editor/settings.nix b/tests/modules/programs/zed-editor/settings.nix new file mode 100644 index 000000000..701caab13 --- /dev/null +++ b/tests/modules/programs/zed-editor/settings.nix @@ -0,0 +1,36 @@ +# Test custom keymap functionality +{ config, ... }: + +{ + programs.zed-editor = { + enable = true; + package = config.lib.test.mkStubPackage { }; + userSettings = { + theme = "XY-Zed"; + features = { copilot = false; }; + vim_mode = false; + ui_font_size = 16; + buffer_font_size = 16; + }; + }; + + nmt.script = let + expectedContent = builtins.toFile "expected.json" '' + { + "auto_install_extensions": {}, + "buffer_font_size": 16, + "features": { + "copilot": false + }, + "theme": "XY-Zed", + "ui_font_size": 16, + "vim_mode": false + } + ''; + + settingsPath = ".config/zed/settings.json"; + in '' + assertFileExists "home-files/${settingsPath}" + assertFileContent "home-files/${settingsPath}" "${expectedContent}" + ''; +} diff --git a/tests/modules/programs/zsh/syntax-highlighting.nix b/tests/modules/programs/zsh/syntax-highlighting.nix index 981cefb63..052b228bd 100644 --- a/tests/modules/programs/zsh/syntax-highlighting.nix +++ b/tests/modules/programs/zsh/syntax-highlighting.nix @@ -19,8 +19,8 @@ with lib; nmt.script = '' assertFileContains home-files/.zshrc "source ${pkgs.hello}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh" - assertFileContains home-files/.zshrc "ZSH_HIGHLIGHT_HIGHLIGHTERS+=('brackets' 'pattern' 'cursor')" - assertFileContains home-files/.zshrc "ZSH_HIGHLIGHT_STYLES+=('comment' 'fg=#6c6c6c')" + assertFileContains home-files/.zshrc "ZSH_HIGHLIGHT_HIGHLIGHTERS+=(brackets pattern cursor)" + assertFileContains home-files/.zshrc "ZSH_HIGHLIGHT_STYLES+=(comment 'fg=#6c6c6c')" ''; }; } diff --git a/tests/modules/programs/zsh/zsh-abbr.nix b/tests/modules/programs/zsh/zsh-abbr.nix index 0e016fafe..7e8370d00 100644 --- a/tests/modules/programs/zsh/zsh-abbr.nix +++ b/tests/modules/programs/zsh/zsh-abbr.nix @@ -12,6 +12,6 @@ abbreviations=home-files/.config/zsh-abbr/user-abbreviations assertFileExists $abbreviations - assertFileContains $abbreviations "abbr 'ga'='git add'" + assertFileContains $abbreviations "abbr ga='git add'" ''; } diff --git a/tests/modules/services/activitywatch/basic-setup.nix b/tests/modules/services/activitywatch/basic-setup.nix index d3a14ae87..a8ba1cb49 100644 --- a/tests/modules/services/activitywatch/basic-setup.nix +++ b/tests/modules/services/activitywatch/basic-setup.nix @@ -5,6 +5,7 @@ let stubPackage = config.lib.test.mkStubPackage { }; in { services.activitywatch = { enable = true; + package = stubPackage; settings = { port = 3012; custom_static = { custom-watcher = stubPackage; }; diff --git a/tests/modules/services/borgmatic/basic-configuration.service b/tests/modules/services/borgmatic/basic-configuration.service index 80713fd90..8b760293a 100644 --- a/tests/modules/services/borgmatic/basic-configuration.service +++ b/tests/modules/services/borgmatic/basic-configuration.service @@ -1,5 +1,4 @@ [Service] -CPUSchedulingPolicy=batch ExecStart=/nix/store/00000000000000000000000000000000-systemd/bin/systemd-inhibit \ --who="borgmatic" \ --what="sleep:shutdown" \ diff --git a/tests/modules/services/cachix-agent/basic-setup.nix b/tests/modules/services/cachix-agent/basic-setup.nix index 0f84ae35c..22c088900 100644 --- a/tests/modules/services/cachix-agent/basic-setup.nix +++ b/tests/modules/services/cachix-agent/basic-setup.nix @@ -20,7 +20,7 @@ [Service] Environment=PATH=@nix@/bin EnvironmentFile=/home/hm-user/.config/cachix-agent.token - ExecStart='@cachix-agent@/bin/cachix' 'deploy' 'agent' 'test-agent' 'home-manager' + ExecStart=@cachix-agent@/bin/cachix deploy agent test-agent home-manager KillMode=process Restart=on-failure diff --git a/tests/modules/services/cliphist/cliphist-extra-options.nix b/tests/modules/services/cliphist/cliphist-extra-options.nix index 65d4fdca1..dcf097c6c 100644 --- a/tests/modules/services/cliphist/cliphist-extra-options.nix +++ b/tests/modules/services/cliphist/cliphist-extra-options.nix @@ -16,9 +16,9 @@ assertFileExists $servicePath/cliphist.service assertFileExists $servicePath/cliphist-images.service - assertFileRegex $servicePath/cliphist.service " '-max-dedupe-search' '10' " - assertFileRegex $servicePath/cliphist.service " '-max-items' '500' " - assertFileRegex $servicePath/cliphist-images.service " '-max-dedupe-search' '10' " - assertFileRegex $servicePath/cliphist-images.service " '-max-items' '500' " + assertFileRegex $servicePath/cliphist.service " -max-dedupe-search 10 " + assertFileRegex $servicePath/cliphist.service " -max-items 500 " + assertFileRegex $servicePath/cliphist-images.service " -max-dedupe-search 10 " + assertFileRegex $servicePath/cliphist-images.service " -max-items 500 " ''; } diff --git a/tests/modules/services/emacs/emacs-service-emacs-after-graphical-session-target.service b/tests/modules/services/emacs/emacs-service-emacs-after-graphical-session-target.service index 193327621..9349f9cc1 100644 --- a/tests/modules/services/emacs/emacs-service-emacs-after-graphical-session-target.service +++ b/tests/modules/services/emacs/emacs-service-emacs-after-graphical-session-target.service @@ -2,7 +2,7 @@ WantedBy=graphical-session.target [Service] -ExecStart=@runtimeShell@ -l -c "@emacs@/bin/emacs --fg-daemon '-f' 'exwm-enable'" +ExecStart=@runtimeShell@ -l -c "@emacs@/bin/emacs --fg-daemon -f exwm-enable" Restart=on-failure SuccessExitStatus=15 Type=notify diff --git a/tests/modules/services/emacs/emacs-service-emacs.service b/tests/modules/services/emacs/emacs-service-emacs.service index 64120f4c0..142bc208c 100644 --- a/tests/modules/services/emacs/emacs-service-emacs.service +++ b/tests/modules/services/emacs/emacs-service-emacs.service @@ -2,7 +2,7 @@ WantedBy=default.target [Service] -ExecStart=@runtimeShell@ -l -c "@emacs@/bin/emacs --fg-daemon '-f' 'exwm-enable'" +ExecStart=@runtimeShell@ -l -c "@emacs@/bin/emacs --fg-daemon -f exwm-enable" Restart=on-failure SuccessExitStatus=15 Type=notify diff --git a/tests/modules/services/emacs/emacs-socket-27-emacs.service b/tests/modules/services/emacs/emacs-socket-27-emacs.service index b44694d39..fe85103c0 100644 --- a/tests/modules/services/emacs/emacs-socket-27-emacs.service +++ b/tests/modules/services/emacs/emacs-socket-27-emacs.service @@ -1,5 +1,5 @@ [Service] -ExecStart=@runtimeShell@ -l -c "@emacs@/bin/emacs --fg-daemon='%t/emacs/server' '-f' 'exwm-enable'" +ExecStart=@runtimeShell@ -l -c "@emacs@/bin/emacs --fg-daemon=%t/emacs/server -f exwm-enable" ExecStartPost=@coreutils@/bin/chmod --changes -w %t/emacs ExecStopPost=@coreutils@/bin/chmod --changes +w %t/emacs Restart=on-failure diff --git a/tests/modules/services/emacs/emacs-socket-28-emacs.service b/tests/modules/services/emacs/emacs-socket-28-emacs.service index 153f5d8fe..ab711bc84 100644 --- a/tests/modules/services/emacs/emacs-socket-28-emacs.service +++ b/tests/modules/services/emacs/emacs-socket-28-emacs.service @@ -1,5 +1,5 @@ [Service] -ExecStart=@runtimeShell@ -l -c "@emacs@/bin/emacs --fg-daemon='%t/emacs/server' '-f' 'exwm-enable'" +ExecStart=@runtimeShell@ -l -c "@emacs@/bin/emacs --fg-daemon=%t/emacs/server -f exwm-enable" Restart=on-failure SuccessExitStatus=15 Type=notify diff --git a/tests/modules/services/espanso/basic-configuration.service b/tests/modules/services/espanso/basic-configuration.service index 593196e59..2c07465a0 100644 --- a/tests/modules/services/espanso/basic-configuration.service +++ b/tests/modules/services/espanso/basic-configuration.service @@ -2,9 +2,9 @@ WantedBy=default.target [Service] -ExecStart=@espanso@/bin/espanso daemon +ExecStart=@espanso@/bin/espanso launcher Restart=on-failure -Type=exec +RestartSec=3 [Unit] Description=Espanso: cross platform text expander in Rust diff --git a/tests/modules/services/fnott/systemd-user-service-expected.service b/tests/modules/services/fnott/systemd-user-service-expected.service index 1d09bfad5..c39a7b19b 100644 --- a/tests/modules/services/fnott/systemd-user-service-expected.service +++ b/tests/modules/services/fnott/systemd-user-service-expected.service @@ -1,6 +1,6 @@ [Service] BusName=org.freedesktop.Notifications -ExecStart=@fnott@/bin/fnott -c '/home/hm-user/.config/fnott/fnott.ini' +ExecStart=@fnott@/bin/fnott -c /home/hm-user/.config/fnott/fnott.ini Type=dbus [Unit] diff --git a/tests/modules/services/gpg-agent/default-homedir.nix b/tests/modules/services/gpg-agent/default-homedir.nix index e23de764d..9c13520ae 100644 --- a/tests/modules/services/gpg-agent/default-homedir.nix +++ b/tests/modules/services/gpg-agent/default-homedir.nix @@ -2,7 +2,7 @@ with lib; -{ +mkIf pkgs.stdenv.isLinux { config = { services.gpg-agent.enable = true; services.gpg-agent.pinentryPackage = pkgs.pinentry-gnome3; diff --git a/tests/modules/services/gpg-agent/expected-agent.plist b/tests/modules/services/gpg-agent/expected-agent.plist new file mode 100644 index 000000000..5843ff449 --- /dev/null +++ b/tests/modules/services/gpg-agent/expected-agent.plist @@ -0,0 +1,41 @@ + + + + + EnvironmentVariables + + GNUPGHOME + /path/to/hash + + KeepAlive + + Crashed + + SuccessfulExit + + + Label + org.nix-community.home.gpg-agent + ProcessType + Background + ProgramArguments + + @gpg@/bin/gpg-agent + --supervised + + RunAtLoad + + Sockets + + Agent + + SockPathMode + 384 + SockPathName + /private/var/run/org.nix-community.home.gpg-agent/d.wp4h7ks5zxy4dodqadgpbbpz/S.gpg-agent + SockType + stream + + + + \ No newline at end of file diff --git a/tests/modules/services/gpg-agent/override-homedir.nix b/tests/modules/services/gpg-agent/override-homedir.nix index c50786739..82dec0f95 100644 --- a/tests/modules/services/gpg-agent/override-homedir.nix +++ b/tests/modules/services/gpg-agent/override-homedir.nix @@ -2,19 +2,25 @@ with lib; -{ +let inherit (pkgs.stdenv) isDarwin; +in { config = { services.gpg-agent.enable = true; services.gpg-agent.pinentryPackage = null; # Don't build pinentry package. programs.gpg = { enable = true; homedir = "/path/to/hash"; + package = config.lib.test.mkStubPackage { outPath = "@gpg@"; }; }; test.stubs.gnupg = { }; test.stubs.systemd = { }; # depends on gnupg.override - nmt.script = '' + nmt.script = if isDarwin then '' + serviceFile=LaunchAgents/org.nix-community.home.gpg-agent.plist + assertFileExists "$serviceFile" + assertFileContent "$serviceFile" ${./expected-agent.plist} + '' else '' in="${config.systemd.user.sockets.gpg-agent.Socket.ListenStream}" if [[ $in != "%t/gnupg/d.wp4h7ks5zxy4dodqadgpbbpz/S.gpg-agent" ]] then diff --git a/tests/modules/services/imapnotify/imapnotify-config.json b/tests/modules/services/imapnotify/imapnotify-config.json index 21276857d..646fa2212 100644 --- a/tests/modules/services/imapnotify/imapnotify-config.json +++ b/tests/modules/services/imapnotify/imapnotify-config.json @@ -1 +1 @@ -{"boxes":["Inbox"],"host":"imap.example.com","onNewMail":"@notmuch@/bin/notmuch new\n","passwordCmd":"'password-command'","port":993,"tls":true,"tlsOptions":{"starttls":false},"username":"home.manager"} \ No newline at end of file +{"boxes":["Inbox"],"host":"imap.example.com","onNewMail":"@notmuch@/bin/notmuch new\n","passwordCmd":"password-command","port":993,"tls":true,"tlsOptions":{"starttls":false},"username":"home.manager"} \ No newline at end of file diff --git a/tests/modules/services/kanshi/alias-assertion.nix b/tests/modules/services/kanshi/alias-assertion.nix new file mode 100644 index 000000000..0dc6d7e64 --- /dev/null +++ b/tests/modules/services/kanshi/alias-assertion.nix @@ -0,0 +1,18 @@ +{ config, pkgs, ... }: { + config = { + services.kanshi = { + enable = true; + package = config.lib.test.mkStubPackage { }; + settings = [{ + profile.name = "nomad"; + profile.outputs = [{ + criteria = "eDP-1"; + alias = "test"; + }]; + }]; + }; + + test.asserts.assertions.expected = + [ "Output kanshi.*.output.alias can only be defined on global scope" ]; + }; +} diff --git a/tests/modules/services/kanshi/default.nix b/tests/modules/services/kanshi/default.nix index b7704b112..05e224aaa 100644 --- a/tests/modules/services/kanshi/default.nix +++ b/tests/modules/services/kanshi/default.nix @@ -1,4 +1,5 @@ { kanshi-basic-configuration = ./basic-configuration.nix; kanshi-new-configuration = ./new-configuration.nix; + kanshi-alias-assertion = ./alias-assertion.nix; } diff --git a/tests/modules/services/kanshi/new-configuration.conf b/tests/modules/services/kanshi/new-configuration.conf index c0858a048..817f66329 100644 --- a/tests/modules/services/kanshi/new-configuration.conf +++ b/tests/modules/services/kanshi/new-configuration.conf @@ -1,12 +1,12 @@ include "path/to/included/file" -output "*" enable +output "Iiyama North America PLE2483H-DP" alias $iiyama profile nomad { output "eDP-1" enable } profile desktop { output "eDP-1" disable - output "Iiyama North America PLE2483H-DP" enable position 0,0 + output "$iiyama" enable position 0,0 output "Iiyama North America PLE2483H-DP 1158765348486" enable mode 1920x1080 position 1920,0 scale 2.100000 transform flipped-270 exec echo "1 two 3" exec echo "4 five 6" diff --git a/tests/modules/services/kanshi/new-configuration.nix b/tests/modules/services/kanshi/new-configuration.nix index 9b3a36478..2c92c730d 100644 --- a/tests/modules/services/kanshi/new-configuration.nix +++ b/tests/modules/services/kanshi/new-configuration.nix @@ -7,8 +7,8 @@ { include = "path/to/included/file"; } { output = { - criteria = "*"; - status = "enable"; + criteria = "Iiyama North America PLE2483H-DP"; + alias = "iiyama"; }; } { @@ -27,7 +27,7 @@ status = "disable"; } { - criteria = "Iiyama North America PLE2483H-DP"; + criteria = "$iiyama"; status = "enable"; position = "0,0"; } diff --git a/tests/modules/services/mopidy/mopidy-scan.nix b/tests/modules/services/mopidy/mopidy-scan.nix index 58a035a6a..16b04292a 100644 --- a/tests/modules/services/mopidy/mopidy-scan.nix +++ b/tests/modules/services/mopidy/mopidy-scan.nix @@ -6,6 +6,20 @@ extensionPackages = [ pkgs.mopidy-local ]; }; + test.stubs = { + mopidy = { + version = "0"; + outPath = null; + buildScript = '' + mkdir -p $out/bin + touch $out/bin/mopidy + chmod +x $out/bin/mopidy + ''; + }; + + mopidy-local = { }; + }; + nmt.script = '' assertFileExists home-files/.config/systemd/user/mopidy.service assertFileExists home-files/.config/systemd/user/mopidy-scan.service diff --git a/tests/modules/services/mpd-mpris/configuration-with-password.service b/tests/modules/services/mpd-mpris/configuration-with-password.service index 868d55539..8c8290875 100644 --- a/tests/modules/services/mpd-mpris/configuration-with-password.service +++ b/tests/modules/services/mpd-mpris/configuration-with-password.service @@ -2,7 +2,7 @@ WantedBy=default.target [Service] -ExecStart=@mpd-mpris@/bin/mpd-mpris -host 'example.com' -network 'tcp' -no-instance -port 1234 -pwd 'my_password' +ExecStart=@mpd-mpris@/bin/mpd-mpris -host example.com -network tcp -no-instance -port 1234 -pwd my_password Restart=on-failure RestartSec=5s Type=simple diff --git a/tests/modules/services/mpd/basic-configuration.service b/tests/modules/services/mpd/basic-configuration.service index 678d16d70..feb155ac4 100644 --- a/tests/modules/services/mpd/basic-configuration.service +++ b/tests/modules/services/mpd/basic-configuration.service @@ -3,7 +3,7 @@ WantedBy=default.target [Service] Environment=PATH=/home/hm-user/.nix-profile/bin -ExecStart=@mpd@/bin/mpd --no-daemon /nix/store/00000000000000000000000000000000-mpd.conf '--verbose' +ExecStart=@mpd@/bin/mpd --no-daemon /nix/store/00000000000000000000000000000000-mpd.conf --verbose ExecStartPre=/nix/store/00000000000000000000000000000000-bash/bin/bash -c "/nix/store/00000000000000000000000000000000-coreutils/bin/mkdir -p '/home/hm-user/.local/share/mpd' '/home/hm-user/.local/share/mpd/playlists'" Type=notify diff --git a/tests/modules/services/mpd/start-when-needed.service b/tests/modules/services/mpd/start-when-needed.service index 87eb4b79a..ac98a3f97 100644 --- a/tests/modules/services/mpd/start-when-needed.service +++ b/tests/modules/services/mpd/start-when-needed.service @@ -1,6 +1,6 @@ [Service] Environment=PATH=/home/hm-user/.nix-profile/bin -ExecStart=@mpd@/bin/mpd --no-daemon /nix/store/00000000000000000000000000000000-mpd.conf '--verbose' +ExecStart=@mpd@/bin/mpd --no-daemon /nix/store/00000000000000000000000000000000-mpd.conf --verbose ExecStartPre=/nix/store/00000000000000000000000000000000-bash/bin/bash -c "/nix/store/00000000000000000000000000000000-coreutils/bin/mkdir -p '/home/hm-user/.local/share/mpd' '/home/hm-user/.local/share/mpd/playlists'" Type=notify diff --git a/tests/modules/services/nix-gc/basic.nix b/tests/modules/services/nix-gc/basic.nix index a06b67238..1fc019da7 100644 --- a/tests/modules/services/nix-gc/basic.nix +++ b/tests/modules/services/nix-gc/basic.nix @@ -4,6 +4,7 @@ nix.gc = { automatic = true; frequency = "monthly"; + randomizedDelaySec = "42min"; options = "--delete-older-than 30d --max-freed $((64 * 1024**3))"; }; diff --git a/tests/modules/services/nix-gc/expected.timer b/tests/modules/services/nix-gc/expected.timer index ef30df435..70232bb47 100644 --- a/tests/modules/services/nix-gc/expected.timer +++ b/tests/modules/services/nix-gc/expected.timer @@ -4,6 +4,7 @@ WantedBy=timers.target [Timer] OnCalendar=monthly Persistent=true +RandomizedDelaySec=42min Unit=nix-gc.service [Unit] diff --git a/tests/modules/services/parcellite/parcellite-expected.service b/tests/modules/services/parcellite/parcellite-expected.service index 02d8243a6..f1e7e2333 100644 --- a/tests/modules/services/parcellite/parcellite-expected.service +++ b/tests/modules/services/parcellite/parcellite-expected.service @@ -2,7 +2,7 @@ WantedBy=graphical-session.target [Service] -ExecStart=@parcellite@/bin/parcellite '--no-icon' +ExecStart=@parcellite@/bin/parcellite --no-icon Restart=on-abort [Unit] diff --git a/tests/modules/services/pasystray/expected.service b/tests/modules/services/pasystray/expected.service index b2c23c518..7bea7f215 100644 --- a/tests/modules/services/pasystray/expected.service +++ b/tests/modules/services/pasystray/expected.service @@ -3,7 +3,7 @@ WantedBy=graphical-session.target [Service] Environment=PATH=@paprefs@/bin:@pavucontrol@/bin -ExecStart='@pasystray@/bin/pasystray' '-g' +ExecStart=@pasystray@/bin/pasystray -g [Unit] After=graphical-session-pre.target diff --git a/tests/modules/services/redshift-gammastep/gammastep-basic-configuration-expected.service b/tests/modules/services/redshift-gammastep/gammastep-basic-configuration-expected.service index d172e3a86..35eaf519f 100644 --- a/tests/modules/services/redshift-gammastep/gammastep-basic-configuration-expected.service +++ b/tests/modules/services/redshift-gammastep/gammastep-basic-configuration-expected.service @@ -2,7 +2,7 @@ WantedBy=graphical-session.target [Service] -ExecStart=@gammastep@/bin/gammastep '-c' '/home/hm-user/.config/gammastep/config.ini' +ExecStart=@gammastep@/bin/gammastep -c /home/hm-user/.config/gammastep/config.ini Restart=on-failure RestartSec=3 diff --git a/tests/modules/services/redshift-gammastep/redshift-basic-configuration-expected.service b/tests/modules/services/redshift-gammastep/redshift-basic-configuration-expected.service index 6ee4cdda2..5dce5dc19 100644 --- a/tests/modules/services/redshift-gammastep/redshift-basic-configuration-expected.service +++ b/tests/modules/services/redshift-gammastep/redshift-basic-configuration-expected.service @@ -2,7 +2,7 @@ WantedBy=graphical-session.target [Service] -ExecStart=@redshift@/bin/redshift '-c' '/home/hm-user/.config/redshift/redshift.conf' +ExecStart=@redshift@/bin/redshift -c /home/hm-user/.config/redshift/redshift.conf Restart=on-failure RestartSec=3 diff --git a/tests/modules/services/remmina/basic-config.nix b/tests/modules/services/remmina/basic-config.nix index 2741353ae..de8d0e08b 100644 --- a/tests/modules/services/remmina/basic-config.nix +++ b/tests/modules/services/remmina/basic-config.nix @@ -17,7 +17,7 @@ assertFileExists $serviceFile assertFileRegex $serviceFile 'ExecStart=.*/bin/dummy' - assertFileRegex $serviceFile "dummy '--icon' '--enable-extra-hardening'" + assertFileRegex $serviceFile "dummy --icon --enable-extra-hardening" mimetypeFile='./home-files/.local/share/mime/packages/application-x-rdp.xml' diff --git a/tests/modules/services/signaturepdf/basic-configuration.service b/tests/modules/services/signaturepdf/basic-configuration.service index 0775fff65..e73b586c6 100644 --- a/tests/modules/services/signaturepdf/basic-configuration.service +++ b/tests/modules/services/signaturepdf/basic-configuration.service @@ -2,7 +2,7 @@ WantedBy=default.target [Service] -ExecStart=/signaturepdf/bin/signaturepdf 9494 '-d' 'upload_max_filesize=24M' +ExecStart=/signaturepdf/bin/signaturepdf 9494 -d 'upload_max_filesize=24M' [Unit] Description=signaturepdf; signing, organizing, editing metadatas or compressing PDFs diff --git a/tests/modules/services/snixembed/basic-configuration.desktop b/tests/modules/services/snixembed/basic-configuration.desktop new file mode 100644 index 000000000..a606d8f2f --- /dev/null +++ b/tests/modules/services/snixembed/basic-configuration.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Exec=@xdg-utils@/bin/xdg-open http://localhost:9494 +Icon=/snixembed/share/snixembed/public/favicon.ico +Name=Snixembed +Terminal=false +Type=Application +Version=1.4 diff --git a/tests/modules/services/snixembed/basic-configuration.nix b/tests/modules/services/snixembed/basic-configuration.nix new file mode 100644 index 000000000..fd8ec4701 --- /dev/null +++ b/tests/modules/services/snixembed/basic-configuration.nix @@ -0,0 +1,16 @@ +{ ... }: + +{ + services.snixembed = { + enable = true; + beforeUnits = [ "safeeyes.service" ]; + }; + + test.stubs = { snixembed = { outPath = "/snixembed"; }; }; + + nmt.script = '' + assertFileContent \ + home-files/.config/systemd/user/snixembed.service \ + ${./basic-configuration.service} + ''; +} diff --git a/tests/modules/services/snixembed/basic-configuration.service b/tests/modules/services/snixembed/basic-configuration.service new file mode 100644 index 000000000..97e87664b --- /dev/null +++ b/tests/modules/services/snixembed/basic-configuration.service @@ -0,0 +1,14 @@ +[Install] +WantedBy=graphical-session.target + +[Service] +ExecStart=/snixembed/bin/dummy +Restart=on-failure +RestartSec=3 + +[Unit] +Before=safeeyes.service +Description=snixembed +PartOf=graphical-session.target +StartLimitBurst=10 +StartLimitIntervalSec=100 diff --git a/tests/modules/services/snixembed/default.nix b/tests/modules/services/snixembed/default.nix new file mode 100644 index 000000000..b49917197 --- /dev/null +++ b/tests/modules/services/snixembed/default.nix @@ -0,0 +1 @@ +{ snixembed-basic-configuration = ./basic-configuration.nix; } diff --git a/tests/modules/services/swayidle/basic-configuration.nix b/tests/modules/services/swayidle/basic-configuration.nix index 96d983209..c38f4d67d 100644 --- a/tests/modules/services/swayidle/basic-configuration.nix +++ b/tests/modules/services/swayidle/basic-configuration.nix @@ -3,7 +3,7 @@ { services.swayidle = { enable = true; - package = config.lib.test.mkStubPackage { }; + package = config.lib.test.mkStubPackage { outPath = "@swayidle@"; }; timeouts = [ { timeout = 50; @@ -31,24 +31,30 @@ ]; }; - nmt.script = let - escapeForRegex = builtins.replaceStrings [ "'" "*" ] [ "'\\''" "\\*" ]; - expectedArgs = escapeForRegex (lib.concatStringsSep " " [ - "-w" - "timeout 50 'notify-send -t 10000 -- \"Screen lock in 10 seconds\"'" - "timeout 60 'swaylock -fF'" - "timeout 300 'swaymsg \"output * dpms off\"' resume 'swaymsg \"output * dpms on\"'" - "before-sleep 'swaylock -fF'" - "lock 'swaylock -fF'" - ]); - in '' + nmt.script = '' serviceFile=home-files/.config/systemd/user/swayidle.service - assertFileExists $serviceFile - assertFileRegex $serviceFile 'ExecStart=.*/bin/swayidle ${expectedArgs}' - assertFileRegex $serviceFile 'Restart=always' - assertFileRegex $serviceFile 'Environment=.*PATH=${ - lib.makeBinPath [ pkgs.bash ] - }' + assertFileExists "$serviceFile" + + serviceFileNormalized="$(normalizeStorePaths "$serviceFile")" + + assertFileContent "$serviceFileNormalized" ${ + builtins.toFile "expected.service" '' + [Install] + WantedBy=graphical-session.target + + [Service] + Environment=PATH=/nix/store/00000000000000000000000000000000-bash/bin + ExecStart=@swayidle@/bin/dummy -w timeout 50 'notify-send -t 10000 -- "Screen lock in 10 seconds"' timeout 60 'swaylock -fF' timeout 300 'swaymsg "output * dpms off"' resume 'swaymsg "output * dpms on"' before-sleep 'swaylock -fF' lock 'swaylock -fF' + Restart=always + Type=simple + + [Unit] + ConditionEnvironment=WAYLAND_DISPLAY + Description=Idle manager for Wayland + Documentation=man:swayidle(1) + PartOf=graphical-session.target + '' + } ''; } diff --git a/tests/modules/services/swayosd/swayosd.nix b/tests/modules/services/swayosd/swayosd.nix index 1bc7d5354..7b9b2a806 100644 --- a/tests/modules/services/swayosd/swayosd.nix +++ b/tests/modules/services/swayosd/swayosd.nix @@ -21,7 +21,7 @@ WantedBy=graphical-session.target [Service] - ExecStart=@swayosd@/bin/swayosd-server --display DISPLAY --style '/etc/xdg/swayosd/style.css' --top-margin 0.100000 + ExecStart=@swayosd@/bin/swayosd-server --display DISPLAY --style /etc/xdg/swayosd/style.css --top-margin 0.100000 Restart=always RestartSec=2s Type=simple diff --git a/tests/modules/services/syncthing/common/extra-options.nix b/tests/modules/services/syncthing/common/extra-options.nix index 016850cc3..df968636f 100644 --- a/tests/modules/services/syncthing/common/extra-options.nix +++ b/tests/modules/services/syncthing/common/extra-options.nix @@ -13,7 +13,7 @@ lib.mkMerge [ nmt.script = '' assertFileExists home-files/.config/systemd/user/syncthing.service assertFileContains home-files/.config/systemd/user/syncthing.service \ - "ExecStart='@syncthing@/bin/syncthing' '-no-browser' '-no-restart' '-logflags=0' '-foo' '-bar \"baz\"'" + "ExecStart=@syncthing@/bin/syncthing -no-browser -no-restart '-logflags=0' -foo '-bar \"baz\"'" ''; }) (lib.mkIf pkgs.stdenv.isDarwin { diff --git a/tests/modules/services/trayscale/default.nix b/tests/modules/services/trayscale/default.nix new file mode 100644 index 000000000..9702b1c7c --- /dev/null +++ b/tests/modules/services/trayscale/default.nix @@ -0,0 +1,4 @@ +{ + trayscale-show-window = ./show-window.nix; + trayscale-hide-window = ./hide-window.nix; +} diff --git a/tests/modules/services/trayscale/hide-window.nix b/tests/modules/services/trayscale/hide-window.nix new file mode 100644 index 000000000..72181e898 --- /dev/null +++ b/tests/modules/services/trayscale/hide-window.nix @@ -0,0 +1,15 @@ +{ ... }: { + services.trayscale = { + enable = true; + hideWindow = true; + }; + + test.stubs = { trayscale = { }; }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/trayscale.service + assertFileExists $serviceFile + assertFileRegex $serviceFile \ + '^ExecStart=@trayscale@/bin/trayscale --hide-window$' + ''; +} diff --git a/tests/modules/services/trayscale/show-window.nix b/tests/modules/services/trayscale/show-window.nix new file mode 100644 index 000000000..62157ab54 --- /dev/null +++ b/tests/modules/services/trayscale/show-window.nix @@ -0,0 +1,15 @@ +{ ... }: { + services.trayscale = { + enable = true; + hideWindow = false; + }; + + test.stubs = { trayscale = { }; }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/trayscale.service + assertFileExists $serviceFile + assertFileRegex $serviceFile \ + '^ExecStart=@trayscale@/bin/trayscale$' + ''; +} diff --git a/tests/modules/services/window-managers/bspwm/bspwmrc b/tests/modules/services/window-managers/bspwm/bspwmrc index ccc070088..70f32ff2c 100755 --- a/tests/modules/services/window-managers/bspwm/bspwmrc +++ b/tests/modules/services/window-managers/bspwm/bspwmrc @@ -1,14 +1,14 @@ extra config early -if [[ $(bspc query --desktops --names --monitor 'focused') == Desktop ]]; then - bspc monitor 'focused' -d 'desktop 1' 'd'\''esk top' +if [[ $(bspc query --desktops --names --monitor focused) == Desktop ]]; then + bspc monitor focused -d 'desktop 1' 'd'\''esk top' fi -bspc config 'border_width' '2' -bspc config 'external_rules_command' '/path/to/external rules command' -bspc config 'gapless_monocle' 'on' -bspc config 'ignore_ewmh_fullscreen' 'enter,exit' -bspc config 'split_ratio' '0.520000' +bspc config border_width 2 +bspc config external_rules_command '/path/to/external rules command' +bspc config gapless_monocle on +bspc config ignore_ewmh_fullscreen enter,exit +bspc config split_ratio 0.520000 bspc rule -r '*' bspc rule -a '*' 'center=off' 'desktop=d'\''esk top#next' 'split_dir=north' 'sticky=on' 'unknown_rule=42' diff --git a/tests/modules/services/window-managers/herbstluftwm/herbstluftwm-simple-config-autostart b/tests/modules/services/window-managers/herbstluftwm/herbstluftwm-simple-config-autostart index 78d4d7d56..85ef45b12 100644 --- a/tests/modules/services/window-managers/herbstluftwm/herbstluftwm-simple-config-autostart +++ b/tests/modules/services/window-managers/herbstluftwm/herbstluftwm-simple-config-autostart @@ -15,18 +15,18 @@ herbstclient mouseunbind --all herbstclient unrule --all herbstclient set always_show_frame true -herbstclient set default_frame_layout 'max' +herbstclient set default_frame_layout max herbstclient set frame_bg_active_color '#000000' -herbstclient set frame_gap '12' -herbstclient set frame_padding '-12' +herbstclient set frame_gap 12 +herbstclient set frame_padding -12 -for tag in '1' 'with space' 'wə1rd#ch@rs'\'''; do +for tag in 1 'with space' 'wə1rd#ch@rs'\'''; do herbstclient add "$tag" done if @herbstluftwm@/bin/herbstclient object_tree tags.by-name.default &>/dev/null; then - herbstclient use '1' - herbstclient merge_tag default '1' + herbstclient use 1 + herbstclient merge_tag default 1 fi diff --git a/tests/modules/services/window-managers/i3/i3-fonts-deprecated.nix b/tests/modules/services/window-managers/i3/i3-fonts-deprecated.nix index 0216681f3..fefff9904 100644 --- a/tests/modules/services/window-managers/i3/i3-fonts-deprecated.nix +++ b/tests/modules/services/window-managers/i3/i3-fonts-deprecated.nix @@ -7,7 +7,10 @@ enable = true; config = { - bars = [{ fonts = [ "FontAwesome" "Iosevka 11.500000" ]; }]; + bars = [ + { fonts = [ "FontAwesome" "Iosevka 11.500000" ]; } + { fonts = [ "FontAwesome" "Iosevka Bold Semi-Condensed 14px" ]; } + ]; fonts = [ "DejaVuSansMono" "Terminus Bold Semi-Condensed 13.500000" ]; }; }; @@ -21,5 +24,6 @@ test.asserts.warnings.expected = [ "Specifying i3.config.fonts as a list is deprecated. Use the attrset version instead." "Specifying i3.config.bars[].fonts as a list is deprecated. Use the attrset version instead." + "Specifying i3.config.bars[].fonts as a list is deprecated. Use the attrset version instead." ]; } diff --git a/tests/modules/services/window-managers/i3/i3-fonts-expected.conf b/tests/modules/services/window-managers/i3/i3-fonts-expected.conf index e2606b320..9ce876874 100644 --- a/tests/modules/services/window-managers/i3/i3-fonts-expected.conf +++ b/tests/modules/services/window-managers/i3/i3-fonts-expected.conf @@ -94,3 +94,25 @@ bar { } } +bar { + font pango:FontAwesome, Iosevka Bold Semi-Condensed 14px + mode dock + hidden_state hide + position bottom + status_command @i3status@/bin/i3status + i3bar_command @i3@/bin/i3bar + workspace_buttons yes + strip_workspace_numbers no + tray_output primary + colors { + background #000000 + statusline #ffffff + separator #666666 + focused_workspace #4c7899 #285577 #ffffff + active_workspace #333333 #5f676a #ffffff + inactive_workspace #333333 #222222 #888888 + urgent_workspace #2f343a #900000 #ffffff + binding_mode #2f343a #900000 #ffffff + } +} + diff --git a/tests/modules/services/window-managers/i3/i3-fonts.nix b/tests/modules/services/window-managers/i3/i3-fonts.nix index decd9fcca..061f7a0bd 100644 --- a/tests/modules/services/window-managers/i3/i3-fonts.nix +++ b/tests/modules/services/window-managers/i3/i3-fonts.nix @@ -7,12 +7,21 @@ enable = true; config = { - bars = [{ - fonts = { - names = [ "FontAwesome" "Iosevka" ]; - size = 11.5; - }; - }]; + bars = [ + { + fonts = { + names = [ "FontAwesome" "Iosevka" ]; + size = 11.5; + }; + } + { + fonts = { + names = [ "FontAwesome" "Iosevka" ]; + style = "Bold Semi-Condensed"; + size = "14px"; + }; + } + ]; fonts = { names = [ "DejaVuSansMono" "Terminus" ]; style = "Bold Semi-Condensed"; diff --git a/tests/modules/services/window-managers/river/configuration.nix b/tests/modules/services/window-managers/river/configuration.nix index 9a0199215..9532006fc 100644 --- a/tests/modules/services/window-managers/river/configuration.nix +++ b/tests/modules/services/window-managers/river/configuration.nix @@ -79,7 +79,6 @@ }; test.stubs = { - dbus = { }; river = { }; xwayland = { }; }; diff --git a/tests/modules/services/window-managers/river/init b/tests/modules/services/window-managers/river/init index c266ca9e9..8662dc910 100755 --- a/tests/modules/services/window-managers/river/init +++ b/tests/modules/services/window-managers/river/init @@ -62,6 +62,6 @@ extra config ### SYSTEMD INTEGRATION ### -@dbus@/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY XDG_CURRENT_DESKTOP NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE && systemctl --user stop river-session.target && systemctl --user start river-session.target +/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY XDG_CURRENT_DESKTOP NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE && systemctl --user stop river-session.target && systemctl --user start river-session.target diff --git a/tests/modules/services/window-managers/sway/sway-modules.conf b/tests/modules/services/window-managers/sway/sway-modules.conf index d0302d07a..d36a164ee 100644 --- a/tests/modules/services/window-managers/sway/sway-modules.conf +++ b/tests/modules/services/window-managers/sway/sway-modules.conf @@ -71,15 +71,15 @@ bindsym Mod1+v splitv bindsym Mod1+w layout tabbed input "*" { -xkb_variant dvorak + xkb_variant dvorak } output "HDMI-A-2" { -bg ~/path/to/background.png fill + bg ~/path/to/background.png fill } seat "*" { -hide_cursor when-typing enable + hide_cursor when-typing enable } mode "resize" { diff --git a/tests/modules/services/wlsunset/wlsunset-service-expected.service b/tests/modules/services/wlsunset/wlsunset-service-expected.service index f311d900e..fecd05b9f 100644 --- a/tests/modules/services/wlsunset/wlsunset-service-expected.service +++ b/tests/modules/services/wlsunset/wlsunset-service-expected.service @@ -2,7 +2,7 @@ WantedBy=test.target [Service] -ExecStart=@wlsunset@/bin/wlsunset '-L' '128.8' '-T' '6000' '-g' '0.6' '-l' '12.3' '-t' '3500' +ExecStart=@wlsunset@/bin/wlsunset -L 128.8 -T 6000 -g 0.6 -l 12.3 -t 3500 [Unit] Description=Day/night gamma adjustments for Wayland compositors. diff --git a/tests/modules/systemd/user-config.nix b/tests/modules/systemd/user-config.nix index f977d2f19..3e6a9fcbe 100644 --- a/tests/modules/systemd/user-config.nix +++ b/tests/modules/systemd/user-config.nix @@ -17,7 +17,7 @@ pkgs.writeText "expected" '' [Manager] DefaultCPUAccounting=true - DefaultEnvironment=PATH='/bin:/sbin:/some where' TEST='abc' + DefaultEnvironment=PATH='/bin:/sbin:/some where' TEST=abc LogLevel=debug '' }