diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index 9df8060df..8ba9264d3 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -14,7 +14,7 @@ jobs: - name: Install Nix uses: cachix/install-nix-action@v27 - name: Update flake.lock - uses: DeterminateSystems/update-flake-lock@v22 + uses: DeterminateSystems/update-flake-lock@v23 with: token: ${{ secrets.GH_TOKEN_FOR_UPDATES }} pr-labels: dependencies diff --git a/docs/home-manager-manual.nix b/docs/home-manager-manual.nix index 34196d423..23b2d1e65 100644 --- a/docs/home-manager-manual.nix +++ b/docs/home-manager-manual.nix @@ -32,6 +32,8 @@ in stdenv.mkDerivation { OPTIONS_JSON \ ${home-manager-options.nix-darwin}/share/doc/nixos/options.json + cp ${./options.html} out/options.html + cp ${./static/style.css} out/style.css cp -r ${./release-notes} release-notes diff --git a/docs/manual/introduction.md b/docs/manual/introduction.md new file mode 100644 index 000000000..ebdac5bd6 --- /dev/null +++ b/docs/manual/introduction.md @@ -0,0 +1,32 @@ +# Introduction to Home Manager {#ch-introduction} + +Home Manager is a [Nix](https://nix.dev/)-powered tool for reproducible management of the contents of users' home directories. +This includes programs, configuration files, environment variables and, well… arbitrary files. +The following example snippet of Nix code: + +```nix +programs.git = { + enable = true; + userEmail = "joe@example.org"; + userName = "joe"; +}; +``` + +would make available to a user the `git` executable and man pages and a configuration file `~/.config/git/config`: + +```ini +[user] + email = "joe@example.org" + name = "joe" +``` + +Since Home Manager is implemented in Nix, it provides several benefits: + +- Contents are reproducible — a home will be the exact same every time it is built, unless of course, an intentional change is made. + This also means you can have the exact same home on different hosts. +- Significantly faster and more powerful than various backup strategies. +- Unlike "dotfiles" repositories, Home Manager supports specifying programs, as well as their configurations. +- Supported by , so that you don't have to build from source. +- If you do want to build some programs from source, there is hardly a tool more useful than Nix for that, and the build instructions can be neatly integrated in your Home Manager usage. +- Infinitely composable, so that values in different configuration files and build instructions can share a source of truth. +- Connects you with the [most extensive](https://repology.org/repositories/statistics/total) and [most up-to-date](https://repology.org/repositories/statistics/newest) software package repository on earth, [Nixpkgs](https://github.com/NixOS/nixpkgs). diff --git a/docs/manual/manual.md b/docs/manual/manual.md index a1cfb1a0c..0f81642f7 100644 --- a/docs/manual/manual.md +++ b/docs/manual/manual.md @@ -8,6 +8,7 @@ preface.md ``` ```{=include=} parts +introduction.md installation.md usage.md nix-flakes.md diff --git a/docs/options.html b/docs/options.html new file mode 100644 index 000000000..66c803fc9 --- /dev/null +++ b/docs/options.html @@ -0,0 +1,15 @@ + + + + Redirecting… + + + + + +

Redirecting…

+ + + diff --git a/flake.lock b/flake.lock index 865072042..7282c6b45 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1716948383, - "narHash": "sha256-SzDKxseEcHR5KzPXLwsemyTR/kaM9whxeiJohbL04rs=", + "lastModified": 1725103162, + "narHash": "sha256-Ym04C5+qovuQDYL/rKWSR+WESseQBbNAe5DsXNx5trY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ad57eef4ef0659193044870c731987a6df5cf56b", + "rev": "12228ff1752d7b7624a54e9c1af4b222b3c1073b", "type": "github" }, "original": { diff --git a/home-manager/home-manager b/home-manager/home-manager index 5bf796b47..ab4de5387 100644 --- a/home-manager/home-manager +++ b/home-manager/home-manager @@ -198,9 +198,19 @@ 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. - for n in "$USER@$(hostname -f)" "$USER@$(hostname)" "$USER@$(hostname -s)"; do + hostnameArray+=( "$USER@$(hostname)" "$USER@$(hostname -s)" ) + + for n in "${hostnameArray[@]}"; do if [[ "$(nix eval "$flake#homeConfigurations" --apply "x: x ? \"$n\"")" == "true" ]]; then name="$n" if [[ -v VERBOSE ]]; then diff --git a/home-manager/po/ar.po b/home-manager/po/ar.po new file mode 100644 index 000000000..ea67fd5ae --- /dev/null +++ b/home-manager/po/ar.po @@ -0,0 +1,217 @@ +# 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: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ar\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n" + +#. translators: For example: "home-manager: missing argument for --cores" +#: home-manager/home-manager:16 +msgid "%s: missing argument for %s" +msgstr "" + +#: home-manager/home-manager:64 +msgid "No configuration file found at %s" +msgstr "" + +#. 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/home-manager:92 +msgid "No configuration file found. Please create one at %s" +msgstr "" + +#: home-manager/home-manager:107 +msgid "Home Manager not found at %s." +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: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/ca.po b/home-manager/po/ca.po index 4159c95fc..12992995a 100644 --- a/home-manager/po/ca.po +++ b/home-manager/po/ca.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-04-05 11:01+0000\n" -"Last-Translator: Leix b \n" +"PO-Revision-Date: 2024-08-07 17:09+0000\n" +"Last-Translator: Tomi Ockier \n" "Language-Team: Catalan \n" "Language: ca\n" @@ -17,12 +17,12 @@ 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.5-dev\n" +"X-Generator: Weblate 5.7-dev\n" #. translators: For example: "home-manager: missing argument for --cores" #: home-manager/home-manager:16 msgid "%s: missing argument for %s" -msgstr "" +msgstr "%: falta un argument per %s" #: home-manager/home-manager:64 msgid "No configuration file found at %s" diff --git a/home-manager/po/hu.po b/home-manager/po/hu.po new file mode 100644 index 000000000..3cfab2551 --- /dev/null +++ b/home-manager/po/hu.po @@ -0,0 +1,258 @@ +# 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-09-02 17:09+0000\n" +"Last-Translator: Ferenci Ákos \n" +"Language-Team: Hungarian \n" +"Language: hu\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: hiányzó érték erre: %s" + +#: home-manager/home-manager:64 +msgid "No configuration file found at %s" +msgstr "Nincs konfigurációs fájl itt: %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 "" +"A Home Manager %s %s elérési úton való tárolása elavult. Kérem helyezze át a " +"%s elérési úthoz" + +#: home-manager/home-manager:92 +msgid "No configuration file found. Please create one at %s" +msgstr "" +"Nem található konfigurációs fájl. Kérem hozza létre a fájlt a %s elérési úton" + +#: home-manager/home-manager:107 +msgid "Home Manager not found at %s." +msgstr "Home Manager nem található a %s elérési úton." + +#. 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 "" +"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 +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 "" +"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 "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 "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 +msgid "%s: unknown option '%s'" +msgstr "%s: ismeretlen opció '%s'" + +#: home-manager/home-manager:301 home-manager/home-manager:1052 +msgid "Run '%s --help' for usage help" +msgstr "Futtasa a '%s --help' parancsot a használattal kapcsolatos segítségért" + +#: home-manager/home-manager:327 home-manager/home-manager:431 +msgid "The file %s already exists, leaving it unchanged..." +msgstr "A fájl %s már létezik és változatlan marad..." + +#: home-manager/home-manager:329 home-manager/home-manager:433 +msgid "Creating %s..." +msgstr "%s létrehozása..." + +#: home-manager/home-manager:475 +msgid "Creating initial Home Manager generation..." +msgstr "Kezdeti Home Manager generáció létrehozása..." + +#. 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 "" +"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 +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 "" +"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 +msgid "Can't instantiate a flake configuration" +msgstr "Flake konfiguráció nem példányosítható" + +#: 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] "" +"%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 "Ismeretlen \"news.display\" opció \"%s\"." + +#: home-manager/home-manager:594 +#, sh-format +msgid "Please set the $EDITOR or $VISUAL environment variable" +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" +msgstr "Build futtatása nem lehetséges csak-olvasható könyvtárban" + +#: home-manager/home-manager:693 +msgid "No generation with ID %s" +msgstr "Nem található generáció a következő ID-val: %" + +#: home-manager/home-manager:695 +msgid "Cannot remove the current generation %s" +msgstr "A jelenlegi generáció %s nem eltávolítható" + +#: home-manager/home-manager:697 +msgid "Removing generation %s" +msgstr "%s generáció eltávolítása" + +#: home-manager/home-manager:718 +msgid "No generations to expire" +msgstr "Nincs lejárandó generáció" + +#: home-manager/home-manager:729 +msgid "No home-manager packages seem to be installed." +msgstr "Nem található installált Home Manager csomag" + +#: home-manager/home-manager:811 +msgid "Unknown argument %s" +msgstr "Ismeretlen argumentum %s" + +#: home-manager/home-manager:835 +msgid "This will remove Home Manager from your system." +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 "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 "Biztosan eltávolítja a Home Managert-t?" + +#: home-manager/home-manager:848 +msgid "Switching to empty Home Manager configuration..." +msgstr "Átváltás üres Home Manager konfigurációra..." + +#: home-manager/home-manager:863 +msgid "Yay!" +msgstr "Hurrá!" + +#: home-manager/home-manager:868 +msgid "Home Manager is uninstalled but your home.nix is left untouched." +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." +msgstr "" + +#: home-manager/home-manager:1113 +msgid "Unknown command: %s" +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/pl.po b/home-manager/po/pl.po index c8fa742f0..63eeed3f0 100644 --- a/home-manager/po/pl.po +++ b/home-manager/po/pl.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-02-16 22:01+0000\n" -"Last-Translator: Robert Helgesson \n" +"PO-Revision-Date: 2024-06-17 09:46+0000\n" +"Last-Translator: Mateusz P \n" "Language-Team: Polish \n" "Language: pl\n" @@ -18,12 +18,12 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2);\n" -"X-Generator: Weblate 5.4\n" +"X-Generator: Weblate 5.6-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: brakuje wartości dla %s" #: home-manager/home-manager:64 msgid "No configuration file found at %s" @@ -194,7 +194,7 @@ msgstr "Nieznane ustawienie „%s” „news.display”." #: home-manager/home-manager:594 #, sh-format msgid "Please set the $EDITOR or $VISUAL environment variable" -msgstr "" +msgstr "Proszę ustawić zmienną środowiskową $EDITOR lub $VISUAL" #: home-manager/home-manager:612 msgid "Cannot run build in read-only directory" diff --git a/home-manager/po/vi.po b/home-manager/po/vi.po index 85baac38b..749de0218 100644 --- a/home-manager/po/vi.po +++ b/home-manager/po/vi.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-06-02 08:12+0000\n" +"PO-Revision-Date: 2024-08-01 04:09+0000\n" "Last-Translator: goatastronaut0212 \n" "Language-Team: Vietnamese \n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 5.6-dev\n" +"X-Generator: Weblate 5.7-dev\n" #. translators: For example: "home-manager: missing argument for --cores" #: home-manager/home-manager:16 @@ -97,7 +97,7 @@ msgstr "" #: home-manager/home-manager:146 msgid "Sanity checking Nix" -msgstr "Kiểm tra độ hợp lệ của Nix" +msgstr "Kiểm tra hợp lệ của Nix" #: home-manager/home-manager:166 msgid "Could not find suitable profile directory, tried %s and %s" @@ -175,11 +175,12 @@ msgid_plural "" "There are %d unread and relevant news items.\n" "Read them by running the command \"%s news\"." msgstr[0] "" -msgstr[1] "" +"Có %d tin tức liên quan và chưa được đọc.\n" +"Để đọc nó hãy chạy lệnh \"%s news\"." #: home-manager/home-manager:586 msgid "Unknown \"news.display\" setting \"%s\"." -msgstr "" +msgstr "Không tồn tại \"news.display\" cấu hình \"%s\"." #: home-manager/home-manager:594 #, sh-format @@ -192,19 +193,19 @@ msgstr "Không thể chạy lệnh xây dựng trong thư mục chỉ cho phép #: home-manager/home-manager:693 msgid "No generation with ID %s" -msgstr "" +msgstr "Không có thế hệ với ID %s" #: home-manager/home-manager:695 msgid "Cannot remove the current generation %s" -msgstr "" +msgstr "Không thể xóa thể hệ hiện tại %s" #: home-manager/home-manager:697 msgid "Removing generation %s" -msgstr "" +msgstr "Đang xóa thế hệ %s" #: home-manager/home-manager:718 msgid "No generations to expire" -msgstr "" +msgstr "Không có bất kỳ thế hệ nào hết hạn" #: home-manager/home-manager:729 msgid "No home-manager packages seem to be installed." @@ -237,10 +238,12 @@ msgstr "Tuyệt vời!" #: home-manager/home-manager:868 msgid "Home Manager is uninstalled but your home.nix is left untouched." msgstr "" +"Home Manager đã được gỡ cài đặt nhưng home.nix của bạn sẽ được giữ nguyên " +"vẹn." #: home-manager/home-manager:1091 msgid "expire-generations expects one argument, got %d." -msgstr "" +msgstr "expire-generations kỳ vọng 1 đối số, có %d." #: home-manager/home-manager:1113 msgid "Unknown command: %s" diff --git a/modules/config/home-cursor.nix b/modules/config/home-cursor.nix index c696908d5..cb9a2ab28 100644 --- a/modules/config/home-cursor.nix +++ b/modules/config/home-cursor.nix @@ -67,7 +67,7 @@ let }; in { - meta.maintainers = [ maintainers.polykernel maintainers.league ]; + meta.maintainers = [ maintainers.league ]; imports = [ (mkAliasOptionModule [ "xsession" "pointerCursor" "package" ] [ diff --git a/modules/lib/maintainers.nix b/modules/lib/maintainers.nix index b5175a875..9793d5c3f 100644 --- a/modules/lib/maintainers.nix +++ b/modules/lib/maintainers.nix @@ -49,6 +49,12 @@ github = "bertof"; githubId = 9915675; }; + bricked = { + name = "Bricked"; + email = "hello@bricked.dev"; + github = "brckd"; + githubId = 92804487; + }; CarlosLoboxyz = { name = "Carlos Lobo"; email = "86011416+CarlosLoboxyz@users.noreply.github.com"; @@ -113,6 +119,13 @@ github = "jack5079"; githubId = 29169102; }; + janik = { + name = "Janik"; + email = "janik@aq0.de"; + matrix = "@janik0:matrix.org"; + github = "Janik-Haag"; + githubId = 80165193; + }; jkarlson = { email = "jekarlson@gmail.com"; github = "jkarlson"; @@ -173,6 +186,13 @@ github = "iosmanthus"; githubId = 16307070; }; + jonringer = { + email = "jonringer117@gmail.com"; + matrix = "@jonringer:matrix.org"; + github = "jonringer"; + githubId = 7673602; + name = "Jonathan Ringer"; + }; kalhauge = { name = "Christian Gram Kalhauge"; email = "kalhauge@users.noreply.github.com"; @@ -201,6 +221,19 @@ github = "kubukoz"; githubId = 894884; }; + lheckemann = { + name = "Linus Heckemann"; + email = "git@sphalerite.org"; + github = "lheckemann"; + githubId = 341954; + }; + lilyinstarlight = { + email = "lily@lily.flowers"; + matrix = "@lily:lily.flowers"; + github = "lilyinstarlight"; + githubId = 298109; + name = "Lily Foster"; + }; loicreynier = { name = "Loïc Reynier"; email = "loic@loireynier.fr"; diff --git a/modules/misc/gtk.nix b/modules/misc/gtk.nix index 6454eb2ae..e1ae250fd 100644 --- a/modules/misc/gtk.nix +++ b/modules/misc/gtk.nix @@ -221,10 +221,9 @@ in { config = mkIf cfg.enable (let gtkIni = optionalAttrs (cfg.font != null) { - gtk-font-name = let - fontSize = - optionalString (cfg.font.size != null) " ${toString cfg.font.size}"; - in "${cfg.font.name}" + fontSize; + gtk-font-name = + let fontSize = if cfg.font.size != null then cfg.font.size else 10; + in "${cfg.font.name} ${toString fontSize}"; } // optionalAttrs (cfg.theme != null) { gtk-theme-name = cfg.theme.name; } // optionalAttrs (cfg.iconTheme != null) { gtk-icon-theme-name = cfg.iconTheme.name; @@ -245,10 +244,9 @@ in { '' + cfg4.extraCss; dconfIni = optionalAttrs (cfg.font != null) { - font-name = let - fontSize = - optionalString (cfg.font.size != null) " ${toString cfg.font.size}"; - in "${cfg.font.name}" + fontSize; + font-name = + let fontSize = if cfg.font.size != null then cfg.font.size else 10; + in "${cfg.font.name} ${toString fontSize}"; } // optionalAttrs (cfg.theme != null) { gtk-theme = cfg.theme.name; } // optionalAttrs (cfg.iconTheme != null) { icon-theme = cfg.iconTheme.name; diff --git a/modules/misc/news.nix b/modules/misc/news.nix index c125db1c8..a71557885 100644 --- a/modules/misc/news.nix +++ b/modules/misc/news.nix @@ -1673,6 +1673,53 @@ in { Please migrate to the new option to suppress the generated warning. ''; } + + { + time = "2024-05-25T14:36:03+00:00"; + message = '' + Multiple new options are available: + + - 'nix.nixPath' + - 'nix.keepOldNixPath' + - 'nix.channels' + ''; + } + + { + time = "2024-06-22T05:49:48+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.blanket'. + + Blanket is a program you can use to improve your focus and increase + your productivity by listening to different sounds. See + https://github.com/rafaelmardojai/blanket for more. + ''; + } + + { + time = "2024-06-26T07:07:17+00:00"; + condition = with config.programs.yazi; + enable && (enableBashIntegration || enableZshIntegration + || enableFishIntegration || enableNushellIntegration); + message = '' + Yazi's shell integration wrappers have been renamed from 'ya' to 'yy'. + + A new option `programs.yazi.shellWrapperName` is also available that + allows you to override this name. + ''; + } + + { + time = "2024-06-28T14:18:16+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.glance'. + + Glance is a self-hosted dashboard that puts all your feeds in + one place. See https://github.com/glanceapp/glance for more. + ''; + } ]; }; } diff --git a/modules/misc/nix.nix b/modules/misc/nix.nix index a4456946e..652d3eb89 100644 --- a/modules/misc/nix.nix +++ b/modules/misc/nix.nix @@ -1,15 +1,40 @@ { config, lib, pkgs, ... }: -with lib; - let + inherit (lib) + boolToString concatStringsSep escape floatToString getVersion isBool + isConvertibleWithToString isDerivation isFloat isInt isList isString + literalExpression maintainers mapAttrsToList mkDefault mkEnableOption mkIf + mkMerge mkOption optionalString toPretty types versionAtLeast; + cfg = config.nix; nixPackage = cfg.package; isNixAtLeast = versionAtLeast (getVersion nixPackage); + nixPath = concatStringsSep ":" cfg.nixPath; + + useXdg = config.nix.enable + && (config.nix.settings.use-xdg-base-directories or false); + defexprDir = if useXdg then + "${config.xdg.stateHome}/nix/defexpr" + else + "${config.home.homeDirectory}/.nix-defexpr"; + + # The deploy path for declarative channels. The directory name is prefixed + # with a number to make it easier for files in defexprDir to control the order + # they'll be read relative to each other. + channelPath = "${defexprDir}/50-home-manager"; + + channelsDrv = let + mkEntry = name: drv: { + inherit name; + path = toString drv; + }; + in pkgs.linkFarm "channels" (lib.mapAttrsToList mkEntry cfg.channels); + nixConf = assert isNixAtLeast "2.2"; let @@ -102,6 +127,47 @@ in { ''; }; + nixPath = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ + "$HOME/.nix-defexpr/channels" + "darwin-config=$HOME/.config/nixpkgs/darwin-configuration.nix" + ]; + description = '' + Adds new directories to the Nix expression search path. + + Used by Nix when looking up paths in angular brackets + (e.g. ``). + ''; + }; + + keepOldNixPath = mkOption { + type = types.bool; + default = true; + example = false; + description = '' + Whether {option}`nix.nixPath` should keep the previously set values in + {env}`NIX_PATH`. + ''; + }; + + channels = lib.mkOption { + type = with lib.types; attrsOf package; + default = { }; + example = lib.literalExpression "{ inherit nixpkgs; }"; + description = '' + A declarative alternative to Nix channels. Whereas with stock channels, + you would register URLs and fetch them into the Nix store with + {manpage}`nix-channel(1)`, this option allows you to register the store + path directly. One particularly useful example is registering flake + inputs as channels. + + This option can coexist with stock Nix channels. If the same channel is + defined in both, this option takes precedence. + ''; + }; + registry = mkOption { type = types.attrsOf (types.submodule (let inputAttrs = types.attrsOf @@ -210,6 +276,19 @@ in { }; config = mkIf cfg.enable (mkMerge [ + (mkIf (cfg.nixPath != [ ] && !cfg.keepOldNixPath) { + home.sessionVariables.NIX_PATH = "${nixPath}"; + }) + + (mkIf (cfg.nixPath != [ ] && cfg.keepOldNixPath) { + home.sessionVariables.NIX_PATH = "${nixPath}\${NIX_PATH:+:$NIX_PATH}"; + }) + + (lib.mkIf (cfg.channels != { }) { + nix.nixPath = [ channelPath ]; + home.file."${channelPath}".source = channelsDrv; + }) + (mkIf (cfg.registry != { }) { xdg.configFile."nix/registry.json".source = jsonFormat.generate "registry.json" { @@ -232,5 +311,5 @@ in { }) ]); - meta.maintainers = [ maintainers.polykernel ]; + meta.maintainers = [ ]; } diff --git a/modules/misc/submodule-support.nix b/modules/misc/submodule-support.nix index 400e234cb..82fbc0a30 100644 --- a/modules/misc/submodule-support.nix +++ b/modules/misc/submodule-support.nix @@ -29,4 +29,19 @@ with lib; ''; }; }; + + config = { + # To make it easier for the end user to override the values in the + # configuration depending on the installation method, we set default values + # for the arguments that are defined in the NixOS/nix-darwin modules. + # + # Without these defaults, these attributes would simply not exist, and the + # module system can not inform modules about their non-existence; see + # https://github.com/NixOS/nixpkgs/issues/311709#issuecomment-2110861842 + _module.args = { + osConfig = mkDefault null; + nixosConfig = mkDefault null; + darwinConfig = mkDefault null; + }; + }; } diff --git a/modules/misc/xdg-desktop-entries.nix b/modules/misc/xdg-desktop-entries.nix index 7ec7fa568..1aab6ffe7 100644 --- a/modules/misc/xdg-desktop-entries.nix +++ b/modules/misc/xdg-desktop-entries.nix @@ -51,7 +51,7 @@ let terminal = mkOption { description = "Whether the program runs in a terminal window."; - type = types.bool; + type = types.nullOr types.bool; default = false; }; diff --git a/modules/misc/xdg.nix b/modules/misc/xdg.nix index 23cbe72a2..a47a33f56 100644 --- a/modules/misc/xdg.nix +++ b/modules/misc/xdg.nix @@ -70,6 +70,16 @@ in { ''; }; + 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. + ''; + }; + stateHome = mkOption { type = types.path; defaultText = "~/.local/state"; @@ -122,6 +132,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 4e1f0e201..dbeebfbf7 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -274,6 +274,7 @@ let ./services/barrier.nix ./services/batsignal.nix ./services/betterlockscreen.nix + ./services/blanket.nix ./services/blueman-applet.nix ./services/borgmatic.nix ./services/cachix-agent.nix @@ -300,6 +301,7 @@ let ./services/fusuma.nix ./services/getmail.nix ./services/git-sync.nix + ./services/glance.nix ./services/gnome-keyring.nix ./services/gpg-agent.nix ./services/grobi.nix diff --git a/modules/po/ar.po b/modules/po/ar.po new file mode 100644 index 000000000..c2469fa54 --- /dev/null +++ b/modules/po/ar.po @@ -0,0 +1,113 @@ +# 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: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ar\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\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 "" + +#: 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 new file mode 100644 index 000000000..2b013ccc1 --- /dev/null +++ b/modules/po/hu.po @@ -0,0 +1,117 @@ +# 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-09-02 17:09+0000\n" +"Last-Translator: Ferenci Ákos \n" +"Language-Team: Hungarian \n" +"Language: hu\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 "Hivatkozások létrehozása itt: %s" + +#: modules/files.nix:204 +msgid "Cleaning up orphan links from %s" +msgstr "Árva hivatkozások kitakarítása innen: %s" + +#: modules/files.nix:220 +msgid "Creating profile generation %s" +msgstr "%s. profil generáció létrehozása" + +#: modules/files.nix:237 +msgid "No change so reusing latest profile generation %s" +msgstr "Nincs változás, legutóbbi %s. generáció lesz használva" + +#: 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 "" +"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" +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 "Nix épségének ellenőrzése" + +#: 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/pl.po b/modules/po/pl.po index 0e88a781a..6ce24f50f 100644 --- a/modules/po/pl.po +++ b/modules/po/pl.po @@ -8,17 +8,17 @@ 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-05-03 19:48+0000\n" -"Last-Translator: Eryk Michalak \n" +"PO-Revision-Date: 2024-06-17 09:46+0000\n" +"Last-Translator: Mateusz P \n" "Language-Team: Polish \n" "Language: pl\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==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " -"|| n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 4.18-dev\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" +"X-Generator: Weblate 5.6-dev\n" #: modules/files.nix:191 msgid "Creating home file links in %s" @@ -112,10 +112,14 @@ msgstr "" #: modules/lib-bash/activation-init.sh:127 msgid "Error: USER is set to \"%s\" but we expect \"%s\"" msgstr "" +"Błąd: Właściwość USER ma wartość \"%s\" podczas gdy spodziewana wartość to \"" +"%s\"" #: modules/lib-bash/activation-init.sh:136 msgid "Error: HOME is set to \"%s\" but we expect \"%s\"" msgstr "" +"Błąd: Właściwość HOME ma wartość \"%s\" podczas gdy spodziewana wartość to \"" +"%s\"" #: modules/lib-bash/activation-init.sh:153 msgid "Starting Home Manager activation" diff --git a/modules/po/vi.po b/modules/po/vi.po index 09b510df8..827e32066 100644 --- a/modules/po/vi.po +++ b/modules/po/vi.po @@ -8,7 +8,7 @@ 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-06-02 08:12+0000\n" +"PO-Revision-Date: 2024-08-01 04:09+0000\n" "Last-Translator: goatastronaut0212 \n" "Language-Team: Vietnamese \n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 5.6-dev\n" +"X-Generator: Weblate 5.7-dev\n" #: modules/files.nix:191 msgid "Creating home file links in %s" @@ -53,11 +53,11 @@ msgstr "" #: modules/home-environment.nix:667 msgid "Activating %s" -msgstr "" +msgstr "Đang khởi động %s" #: modules/lib-bash/activation-init.sh:22 msgid "Migrating profile from %s to %s" -msgstr "" +msgstr "Chuyển đổi hồ sơ từ %s tới %s" #: modules/lib-bash/activation-init.sh:54 msgid "Could not find suitable profile directory, tried %s and %s" @@ -85,11 +85,11 @@ msgstr "" #: modules/lib-bash/activation-init.sh:127 msgid "Error: USER is set to \"%s\" but we expect \"%s\"" -msgstr "" +msgstr "Lỗi: USER được đặt thành \"%s\" nhưng chúng tôi kỳ vọng \"%s\"" #: modules/lib-bash/activation-init.sh:136 msgid "Error: HOME is set to \"%s\" but we expect \"%s\"" -msgstr "" +msgstr "Lỗi: HOME được đặt thành \"%s\" nhưng chúng tôi kỳ vọng \"%s\"" #: modules/lib-bash/activation-init.sh:153 msgid "Starting Home Manager activation" @@ -97,7 +97,7 @@ msgstr "" #: modules/lib-bash/activation-init.sh:157 msgid "Sanity checking Nix" -msgstr "Kiểm tra độ hợp lệ của Nix" +msgstr "Kiểm tra hợp lệ của Nix" #: modules/lib-bash/activation-init.sh:170 msgid "This is a dry run" diff --git a/modules/programs/atuin.nix b/modules/programs/atuin.nix index bd907ac03..a27bcf860 100644 --- a/modules/programs/atuin.nix +++ b/modules/programs/atuin.nix @@ -110,18 +110,18 @@ in { programs.bash.initExtra = mkIf cfg.enableBashIntegration '' if [[ :$SHELLOPTS: =~ :(vi|emacs): ]]; then source "${pkgs.bash-preexec}/share/bash/bash-preexec.sh" - eval "$(${cfg.package}/bin/atuin init bash ${flagsStr})" + eval "$(${lib.getExe cfg.package} init bash ${flagsStr})" fi ''; programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' if [[ $options[zle] = on ]]; then - eval "$(${cfg.package}/bin/atuin init zsh ${flagsStr})" + eval "$(${lib.getExe cfg.package} init zsh ${flagsStr})" fi ''; programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration '' - ${cfg.package}/bin/atuin init fish ${flagsStr} | source + ${lib.getExe cfg.package} init fish ${flagsStr} | source ''; programs.nushell = mkIf cfg.enableNushellIntegration { @@ -130,7 +130,9 @@ in { if not ($atuin_cache | path exists) { mkdir $atuin_cache } - ${cfg.package}/bin/atuin init nu ${flagsStr} | save --force ${config.xdg.cacheHome}/atuin/init.nu + ${ + lib.getExe cfg.package + } init nu ${flagsStr} | save --force ${config.xdg.cacheHome}/atuin/init.nu ''; extraConfig = '' source ${config.xdg.cacheHome}/atuin/init.nu diff --git a/modules/programs/bash.nix b/modules/programs/bash.nix index 5a328ecda..3a367b9e7 100644 --- a/modules/programs/bash.nix +++ b/modules/programs/bash.nix @@ -29,6 +29,8 @@ in { programs.bash = { enable = mkEnableOption "GNU Bourne-Again SHell"; + package = mkPackageOption pkgs "bash" { default = "bashInteractive"; }; + enableCompletion = mkOption { type = types.bool; default = true; @@ -190,7 +192,7 @@ in { HISTIGNORE = escapeShellArg (concatStringsSep ":" cfg.historyIgnore); })); in mkIf cfg.enable { - home.packages = [ pkgs.bashInteractive ]; + home.packages = [ cfg.package ]; home.file.".bash_profile".source = writeBashScript "bash_profile" '' # include .profile if it exists diff --git a/modules/programs/bottom.nix b/modules/programs/bottom.nix index 810307b14..fd18fe0db 100644 --- a/modules/programs/bottom.nix +++ b/modules/programs/bottom.nix @@ -56,5 +56,5 @@ in { }; }; - meta.maintainers = [ maintainers.polykernel ]; + meta.maintainers = [ ]; } diff --git a/modules/programs/direnv.nix b/modules/programs/direnv.nix index add2c8fca..4a7636705 100644 --- a/modules/programs/direnv.nix +++ b/modules/programs/direnv.nix @@ -95,6 +95,7 @@ in { package = mkPackageOption pkgs "nix-direnv" { }; }; + silent = mkEnableOption "silent mode, that is, disabling direnv logging"; }; config = mkIf cfg.enable { @@ -163,5 +164,7 @@ in { } ) ''); + + home.sessionVariables = lib.mkIf cfg.silent { DIRENV_LOG_FORMAT = ""; }; }; } diff --git a/modules/programs/eww.nix b/modules/programs/eww.nix index 3d178f942..75a109226 100644 --- a/modules/programs/eww.nix +++ b/modules/programs/eww.nix @@ -5,6 +5,7 @@ with lib; let cfg = config.programs.eww; + ewwCmd = "${cfg.package}/bin/eww"; in { meta.maintainers = [ hm.maintainers.mainrs ]; @@ -30,10 +31,40 @@ in { {file}`$XDG_CONFIG_HOME/eww`. ''; }; + + enableBashIntegration = mkEnableOption "Bash integration" // { + default = true; + }; + + enableZshIntegration = mkEnableOption "Zsh integration" // { + default = true; + }; + + enableFishIntegration = mkEnableOption "Fish integration" // { + default = true; + }; }; config = mkIf cfg.enable { home.packages = [ cfg.package ]; xdg.configFile."eww".source = cfg.configDir; + + programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + if [[ $TERM != "dumb" ]]; then + eval "$(${ewwCmd} shell-completions --shell bash)" + fi + ''; + + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + if [[ $TERM != "dumb" ]]; then + eval "$(${ewwCmd} shell-completions --shell zsh)" + fi + ''; + + programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration '' + if test "$TERM" != "dumb" + eval "$(${ewwCmd} shell-completions --shell fish)" + end + ''; }; } diff --git a/modules/programs/fastfetch.nix b/modules/programs/fastfetch.nix index 32021611d..55a932f9a 100644 --- a/modules/programs/fastfetch.nix +++ b/modules/programs/fastfetch.nix @@ -26,7 +26,9 @@ in { }; }; display = { - binaryPrefix = "si"; + size = { + binaryPrefix = "si"; + }; color = "blue"; separator = "  "; }; diff --git a/modules/programs/firefox.nix b/modules/programs/firefox.nix index 1370d4c28..ac85990ff 100644 --- a/modules/programs/firefox.nix +++ b/modules/programs/firefox.nix @@ -1,945 +1,51 @@ -{ config, lib, pkgs, ... }: +{ lib, ... }: with lib; let - inherit (pkgs.stdenv.hostPlatform) isDarwin; + modulePath = [ "programs" "firefox" ]; - cfg = config.programs.firefox; + moduleName = concatStringsSep "." modulePath; - jsonFormat = pkgs.formats.json { }; - - mozillaConfigPath = - if isDarwin then "Library/Application Support/Mozilla" else ".mozilla"; - - firefoxConfigPath = if isDarwin then - "Library/Application Support/Firefox" - else - "${mozillaConfigPath}/firefox"; - - profilesPath = - if isDarwin then "${firefoxConfigPath}/Profiles" else firefoxConfigPath; - - nativeMessagingHostsPath = if isDarwin then - "${mozillaConfigPath}/NativeMessagingHosts" - else - "${mozillaConfigPath}/native-messaging-hosts"; - - nativeMessagingHostsJoined = pkgs.symlinkJoin { - name = "ff_native-messaging-hosts"; - paths = [ - # Link a .keep file to keep the directory around - (pkgs.writeTextDir "lib/mozilla/native-messaging-hosts/.keep" "") - # Link package configured native messaging hosts (entire Firefox actually) - cfg.finalPackage - ] - # Link user configured native messaging hosts - ++ cfg.nativeMessagingHosts; - }; - - # The extensions path shared by all profiles; will not be supported - # by future Firefox versions. - extensionPath = "extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"; - - profiles = flip mapAttrs' cfg.profiles (_: profile: - nameValuePair "Profile${toString profile.id}" { - Name = profile.name; - Path = if isDarwin then "Profiles/${profile.path}" else profile.path; - IsRelative = 1; - Default = if profile.isDefault then 1 else 0; - }) // { - General = { StartWithLastProfile = 1; }; - }; - - profilesIni = generators.toINI { } profiles; - - userPrefValue = pref: - builtins.toJSON (if isBool pref || isInt pref || isString pref then - pref - else - builtins.toJSON pref); - - mkUserJs = prefs: extraPrefs: bookmarks: - let - prefs' = lib.optionalAttrs ([ ] != bookmarks) { - "browser.bookmarks.file" = toString (firefoxBookmarksFile bookmarks); - "browser.places.importBookmarksHTML" = true; - } // prefs; - in '' - // Generated by Home Manager. - - ${concatStrings (mapAttrsToList (name: value: '' - user_pref("${name}", ${userPrefValue value}); - '') prefs')} - - ${extraPrefs} - ''; - - mkContainersJson = containers: - let - containerToIdentity = _: container: { - userContextId = container.id; - name = container.name; - icon = container.icon; - color = container.color; - public = true; - }; - in '' - ${builtins.toJSON { - version = 4; - lastUserContextId = - elemAt (mapAttrsToList (_: container: container.id) containers) 0; - identities = mapAttrsToList containerToIdentity containers ++ [ - { - userContextId = 4294967294; # 2^32 - 2 - name = "userContextIdInternal.thumbnail"; - icon = ""; - color = ""; - accessKey = ""; - public = false; - } - { - userContextId = 4294967295; # 2^32 - 1 - name = "userContextIdInternal.webextStorageLocal"; - icon = ""; - color = ""; - accessKey = ""; - public = false; - } - ]; - }} - ''; - - firefoxBookmarksFile = bookmarks: - let - indent = level: - lib.concatStringsSep "" (map (lib.const " ") (lib.range 1 level)); - - bookmarkToHTML = indentLevel: bookmark: - '' - ${indent indentLevel}
${escapeXML bookmark.name}''; - - directoryToHTML = indentLevel: directory: '' - ${indent indentLevel}
${ - if directory.toolbar then - '' -

Bookmarks Toolbar'' - else - ''

${escapeXML directory.name}'' - }

- ${indent indentLevel}

- ${allItemsToHTML (indentLevel + 1) directory.bookmarks} - ${indent indentLevel}

''; - - itemToHTMLOrRecurse = indentLevel: item: - if item ? "url" then - bookmarkToHTML indentLevel item - else - directoryToHTML indentLevel item; - - allItemsToHTML = indentLevel: bookmarks: - lib.concatStringsSep "\n" - (map (itemToHTMLOrRecurse indentLevel) bookmarks); - - bookmarkEntries = allItemsToHTML 1 bookmarks; - in pkgs.writeText "firefox-bookmarks.html" '' - - - - Bookmarks -

Bookmarks Menu

-

- ${bookmarkEntries} -

- ''; - - mkNoDuplicateAssertion = entities: entityKind: - (let - # Return an attribute set with entity IDs as keys and a list of - # entity names with corresponding ID as value. An ID is present in - # the result only if more than one entity has it. The argument - # entities is a list of AttrSet of one id/name pair. - findDuplicateIds = entities: - filterAttrs (_entityId: entityNames: length entityNames != 1) - (zipAttrs entities); - - duplicates = findDuplicateIds (mapAttrsToList - (entityName: entity: { "${toString entity.id}" = entityName; }) - entities); - - mkMsg = entityId: entityNames: - " - ID ${entityId} is used by " + concatStringsSep ", " entityNames; - in { - assertion = duplicates == { }; - message = '' - Must not have a Firefox ${entityKind} with an existing ID but - '' + concatStringsSep "\n" (mapAttrsToList mkMsg duplicates); - }); - - wrapPackage = package: - let - # The configuration expected by the Firefox wrapper. - fcfg = { enableGnomeExtensions = cfg.enableGnomeExtensions; }; - - # A bit of hackery to force a config into the wrapper. - browserName = - package.browserName or (builtins.parseDrvName package.name).name; - - # The configuration expected by the Firefox wrapper builder. - bcfg = setAttrByPath [ browserName ] fcfg; - - in if package == null then - null - else if isDarwin then - package - else if versionAtLeast config.home.stateVersion "19.09" then - package.override (old: { - cfg = old.cfg or { } // fcfg; - extraPolicies = (old.extraPolicies or { }) // cfg.policies; - }) - else - (pkgs.wrapFirefox.override { config = bcfg; }) package { }; + mkFirefoxModule = import ./firefox/mkFirefoxModule.nix; in { - meta.maintainers = [ maintainers.rycee maintainers.kira-bruneau ]; + meta.maintainers = + [ maintainers.rycee maintainers.kira-bruneau hm.maintainers.bricked ]; imports = [ - (mkRemovedOptionModule [ "programs" "firefox" "extensions" ] '' + (mkFirefoxModule { + inherit modulePath; + name = "Firefox"; + wrappedPackageName = "firefox"; + unwrappedPackageName = "firefox-unwrapped"; + visible = true; + + platforms.linux = rec { + vendorPath = ".mozilla"; + configPath = "${vendorPath}/firefox"; + }; + platforms.darwin = { + vendorPath = "Library/Application Support/Mozilla"; + configPath = "Library/Application Support/Firefox"; + }; + }) + + (mkRemovedOptionModule (modulePath ++ [ "extensions" ]) '' Extensions are now managed per-profile. That is, change from - programs.firefox.extensions = [ foo bar ]; + ${moduleName}.extensions = [ foo bar ]; to - programs.firefox.profiles.myprofile.extensions = [ foo bar ];'') - (mkRemovedOptionModule [ "programs" "firefox" "enableAdobeFlash" ] + ${moduleName}.profiles.myprofile.extensions = [ foo bar ];'') + (mkRemovedOptionModule (modulePath ++ [ "enableAdobeFlash" ]) "Support for this option has been removed.") - (mkRemovedOptionModule [ "programs" "firefox" "enableGoogleTalk" ] + (mkRemovedOptionModule (modulePath ++ [ "enableGoogleTalk" ]) "Support for this option has been removed.") - (mkRemovedOptionModule [ "programs" "firefox" "enableIcedTea" ] + (mkRemovedOptionModule (modulePath ++ [ "enableIcedTea" ]) "Support for this option has been removed.") ]; - - options = { - programs.firefox = { - enable = mkEnableOption "Firefox"; - - package = mkOption { - type = with types; nullOr package; - default = if versionAtLeast config.home.stateVersion "19.09" then - pkgs.firefox - else - pkgs.firefox-unwrapped; - defaultText = literalExpression "pkgs.firefox"; - example = literalExpression '' - pkgs.firefox.override { - # See nixpkgs' firefox/wrapper.nix to check which options you can use - nativeMessagingHosts = [ - # Gnome shell native connector - pkgs.gnome-browser-connector - # Tridactyl native connector - pkgs.tridactyl-native - ]; - } - ''; - description = '' - The Firefox package to use. If state version ≥ 19.09 then - this should be a wrapped Firefox package. For earlier state - versions it should be an unwrapped Firefox package. - Set to `null` to disable installing Firefox. - ''; - }; - - nativeMessagingHosts = mkOption { - type = types.listOf types.package; - default = [ ]; - description = '' - Additional packages containing native messaging hosts that should be - made available to Firefox extensions. - ''; - }; - - finalPackage = mkOption { - type = with types; nullOr package; - readOnly = true; - description = "Resulting Firefox package."; - }; - - policies = mkOption { - type = types.attrsOf jsonFormat.type; - default = { }; - description = - "[See list of policies](https://mozilla.github.io/policy-templates/)."; - example = { - DefaultDownloadDirectory = "\${home}/Downloads"; - BlockAboutConfig = true; - }; - }; - - profiles = mkOption { - type = types.attrsOf (types.submodule ({ config, name, ... }: { - options = { - name = mkOption { - type = types.str; - default = name; - description = "Profile name."; - }; - - id = mkOption { - type = types.ints.unsigned; - default = 0; - description = '' - Profile ID. This should be set to a unique number per profile. - ''; - }; - - settings = mkOption { - type = types.attrsOf (jsonFormat.type // { - description = - "Firefox preference (int, bool, string, and also attrs, list, float as a JSON string)"; - }); - default = { }; - example = literalExpression '' - { - "browser.startup.homepage" = "https://nixos.org"; - "browser.search.region" = "GB"; - "browser.search.isUS" = false; - "distribution.searchplugins.defaultLocale" = "en-GB"; - "general.useragent.locale" = "en-GB"; - "browser.bookmarks.showMobileBookmarks" = true; - "browser.newtabpage.pinned" = [{ - title = "NixOS"; - url = "https://nixos.org"; - }]; - } - ''; - description = '' - Attribute set of Firefox preferences. - - Firefox only supports int, bool, and string types for - preferences, but home-manager will automatically - convert all other JSON-compatible values into strings. - ''; - }; - - extraConfig = mkOption { - type = types.lines; - default = ""; - description = '' - Extra preferences to add to {file}`user.js`. - ''; - }; - - userChrome = mkOption { - type = types.lines; - default = ""; - description = "Custom Firefox user chrome CSS."; - example = '' - /* Hide tab bar in FF Quantum */ - @-moz-document url("chrome://browser/content/browser.xul") { - #TabsToolbar { - visibility: collapse !important; - margin-bottom: 21px !important; - } - - #sidebar-box[sidebarcommand="treestyletab_piro_sakura_ne_jp-sidebar-action"] #sidebar-header { - visibility: collapse !important; - } - } - ''; - }; - - userContent = mkOption { - type = types.lines; - default = ""; - description = "Custom Firefox user content CSS."; - example = '' - /* Hide scrollbar in FF Quantum */ - *{scrollbar-width:none !important} - ''; - }; - - bookmarks = mkOption { - type = let - bookmarkSubmodule = types.submodule ({ config, name, ... }: { - options = { - name = mkOption { - type = types.str; - default = name; - description = "Bookmark name."; - }; - - tags = mkOption { - type = types.listOf types.str; - default = [ ]; - description = "Bookmark tags."; - }; - - keyword = mkOption { - type = types.nullOr types.str; - default = null; - description = "Bookmark search keyword."; - }; - - url = mkOption { - type = types.str; - description = "Bookmark url, use %s for search terms."; - }; - }; - }) // { - description = "bookmark submodule"; - }; - - bookmarkType = types.addCheck bookmarkSubmodule (x: x ? "url"); - - directoryType = types.submodule ({ config, name, ... }: { - options = { - name = mkOption { - type = types.str; - default = name; - description = "Directory name."; - }; - - bookmarks = mkOption { - type = types.listOf nodeType; - default = [ ]; - description = "Bookmarks within directory."; - }; - - toolbar = mkOption { - type = types.bool; - default = false; - description = '' - Make this the toolbar directory. Note, this does _not_ - mean that this directory will be added to the toolbar, - this directory _is_ the toolbar. - ''; - }; - }; - }) // { - description = "directory submodule"; - }; - - nodeType = types.either bookmarkType directoryType; - in with types; - coercedTo (attrsOf nodeType) attrValues (listOf nodeType); - default = [ ]; - example = literalExpression '' - [ - { - 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"; - toolbar = true; - bookmarks = [ - { - name = "homepage"; - url = "https://nixos.org/"; - } - { - name = "wiki"; - tags = [ "wiki" "nix" ]; - url = "https://wiki.nixos.org/"; - } - ]; - } - ] - ''; - description = '' - Preloaded bookmarks. Note, this may silently overwrite any - previously existing bookmarks! - ''; - }; - - path = mkOption { - type = types.str; - default = name; - description = "Profile path."; - }; - - isDefault = mkOption { - type = types.bool; - default = config.id == 0; - defaultText = "true if profile ID is 0"; - 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 Firefox 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 Firefox. - - 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. - ''; - }; - }; - - containersForce = mkOption { - type = types.bool; - default = false; - description = '' - Whether to force replace the existing containers - configuration. This is recommended since Firefox will - replace the symlink on every launch, but note that you'll - lose any existing configuration by enabling this. - ''; - }; - - containers = mkOption { - type = types.attrsOf (types.submodule ({ name, ... }: { - options = { - name = mkOption { - type = types.str; - default = name; - description = "Container name, e.g., shopping."; - }; - - id = mkOption { - type = types.ints.unsigned; - default = 0; - description = '' - Container ID. This should be set to a unique number per container in this profile. - ''; - }; - - # List of colors at - # https://searchfox.org/mozilla-central/rev/5ad226c7379b0564c76dc3b54b44985356f94c5a/toolkit/components/extensions/parent/ext-contextualIdentities.js#32 - color = mkOption { - type = types.enum [ - "blue" - "turquoise" - "green" - "yellow" - "orange" - "red" - "pink" - "purple" - "toolbar" - ]; - default = "pink"; - description = "Container color."; - }; - - icon = mkOption { - type = types.enum [ - "briefcase" - "cart" - "circle" - "dollar" - "fence" - "fingerprint" - "gift" - "vacation" - "food" - "fruit" - "pet" - "tree" - "chill" - ]; - default = "fruit"; - description = "Container icon."; - }; - }; - })); - default = { }; - example = { - "shopping" = { - id = 1; - color = "blue"; - icon = "cart"; - }; - "dangerous" = { - id = 2; - color = "red"; - icon = "fruit"; - }; - }; - description = '' - Attribute set of container configurations. See - [Multi-Account - Containers](https://support.mozilla.org/en-US/kb/containers) - for more information. - ''; - }; - - extensions = mkOption { - type = types.listOf types.package; - default = [ ]; - example = literalExpression '' - with pkgs.nur.repos.rycee.firefox-addons; [ - privacy-badger - ] - ''; - description = '' - List of Firefox add-on packages to install for this profile. - Some pre-packaged add-ons are accessible from the - [Nix User Repository](https://github.com/nix-community/NUR). - Once you have NUR installed run - - ```console - $ nix-env -f '' -qaP -A nur.repos.rycee.firefox-addons - ``` - - to list the available Firefox add-ons. - - Note that it is necessary to manually enable these extensions - inside Firefox after the first installation. - - To automatically enable extensions add - `"extensions.autoDisableScopes" = 0;` - to - [{option}`programs.firefox.profiles..settings`](#opt-programs.firefox.profiles._name_.settings) - ''; - }; - - }; - })); - default = { }; - description = "Attribute set of Firefox profiles."; - }; - - enableGnomeExtensions = mkOption { - type = types.bool; - default = false; - description = '' - Whether to enable the GNOME Shell native host connector. Note, you - also need to set the NixOS option - `services.gnome.gnome-browser-connector.enable` to - `true`. - ''; - }; - }; - }; - - config = mkIf cfg.enable { - assertions = [ - (let - defaults = - catAttrs "name" (filter (a: a.isDefault) (attrValues cfg.profiles)); - in { - assertion = cfg.profiles == { } || length defaults == 1; - message = "Must have exactly one default Firefox profile but found " - + toString (length defaults) + optionalString (length defaults > 1) - (", namely " + concatStringsSep ", " defaults); - }) - - (let - getContainers = profiles: - flatten - (mapAttrsToList (_: value: (attrValues value.containers)) profiles); - - findInvalidContainerIds = profiles: - filter (container: container.id >= 4294967294) - (getContainers profiles); - in { - assertion = cfg.profiles == { } - || length (findInvalidContainerIds cfg.profiles) == 0; - message = "Container id must be smaller than 4294967294 (2^32 - 2)"; - }) - - (mkNoDuplicateAssertion cfg.profiles "profile") - ] ++ (mapAttrsToList - (_: profile: mkNoDuplicateAssertion profile.containers "container") - cfg.profiles); - - warnings = optional (cfg.enableGnomeExtensions or false) '' - Using 'programs.firefox.enableGnomeExtensions' has been deprecated and - will be removed in the future. Please change to overriding the package - configuration using 'programs.firefox.package' instead. You can refer to - its example for how to do this. - ''; - - programs.firefox.finalPackage = wrapPackage cfg.package; - - home.packages = lib.optional (cfg.finalPackage != null) cfg.finalPackage; - - home.file = mkMerge ([{ - "${firefoxConfigPath}/profiles.ini" = - mkIf (cfg.profiles != { }) { text = profilesIni; }; - - "${nativeMessagingHostsPath}" = { - source = - "${nativeMessagingHostsJoined}/lib/mozilla/native-messaging-hosts"; - recursive = true; - }; - }] ++ flip mapAttrsToList cfg.profiles (_: profile: { - "${profilesPath}/${profile.path}/.keep".text = ""; - - "${profilesPath}/${profile.path}/chrome/userChrome.css" = - mkIf (profile.userChrome != "") { text = profile.userChrome; }; - - "${profilesPath}/${profile.path}/chrome/userContent.css" = - mkIf (profile.userContent != "") { text = profile.userContent; }; - - "${profilesPath}/${profile.path}/user.js" = mkIf (profile.settings != { } - || profile.extraConfig != "" || profile.bookmarks != [ ]) { - text = - mkUserJs profile.settings profile.extraConfig profile.bookmarks; - }; - - "${profilesPath}/${profile.path}/containers.json" = - mkIf (profile.containers != { }) { - force = profile.containersForce; - text = mkContainersJson profile.containers; - }; - - "${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]/programs.firefox.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 Firefox, 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 "Firefox" - else - null; - - privateSalt = if profile.search.privateDefault != null then - profile.path + profile.search.privateDefault - + disclaimer "Firefox" - 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}/extensions" = - mkIf (profile.extensions != [ ]) { - source = let - extensionsEnvPkg = pkgs.buildEnv { - name = "hm-firefox-extensions"; - paths = profile.extensions; - }; - in "${extensionsEnvPkg}/share/mozilla/${extensionPath}"; - recursive = true; - force = true; - }; - })); - }; } diff --git a/modules/programs/firefox/mkFirefoxModule.nix b/modules/programs/firefox/mkFirefoxModule.nix new file mode 100644 index 000000000..f22af019b --- /dev/null +++ b/modules/programs/firefox/mkFirefoxModule.nix @@ -0,0 +1,1017 @@ +{ modulePath, name, description ? null, wrappedPackageName ? null +, unwrappedPackageName ? null, platforms, visible ? false }: + +{ config, lib, pkgs, ... }: + +with lib; + +let + + inherit (pkgs.stdenv.hostPlatform) isDarwin; + + moduleName = concatStringsSep "." modulePath; + + cfg = getAttrFromPath modulePath config; + + jsonFormat = pkgs.formats.json { }; + + supportedPlatforms = flatten (attrVals (attrNames platforms) lib.platforms); + + isWrapped = versionAtLeast config.home.stateVersion "19.09" + && wrappedPackageName != null; + + defaultPackageName = + if isWrapped then wrappedPackageName else unwrappedPackageName; + + packageName = if wrappedPackageName != null then + wrappedPackageName + else + unwrappedPackageName; + + profilesPath = + if isDarwin then "${cfg.configPath}/Profiles" else cfg.configPath; + + nativeMessagingHostsPath = if isDarwin then + "${cfg.vendorPath}/NativeMessagingHosts" + else + "${cfg.vendorPath}/native-messaging-hosts"; + + nativeMessagingHostsJoined = pkgs.symlinkJoin { + name = "ff_native-messaging-hosts"; + paths = [ + # Link a .keep file to keep the directory around + (pkgs.writeTextDir "lib/mozilla/native-messaging-hosts/.keep" "") + # Link package configured native messaging hosts (entire browser actually) + cfg.finalPackage + ] + # Link user configured native messaging hosts + ++ cfg.nativeMessagingHosts; + }; + + # The extensions path shared by all profiles; will not be supported + # by future browser versions. + extensionPath = "extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"; + + profiles = flip mapAttrs' cfg.profiles (_: profile: + nameValuePair "Profile${toString profile.id}" { + Name = profile.name; + Path = if isDarwin then "Profiles/${profile.path}" else profile.path; + IsRelative = 1; + Default = if profile.isDefault then 1 else 0; + }) // { + General = { + StartWithLastProfile = 1; + Version = 2; + }; + }; + + profilesIni = generators.toINI { } profiles; + + userPrefValue = pref: + builtins.toJSON (if isBool pref || isInt pref || isString pref then + pref + else + builtins.toJSON pref); + + mkUserJs = prefs: extraPrefs: bookmarks: + let + prefs' = lib.optionalAttrs ([ ] != bookmarks) { + "browser.bookmarks.file" = toString (browserBookmarksFile bookmarks); + "browser.places.importBookmarksHTML" = true; + } // prefs; + in '' + // Generated by Home Manager. + + ${concatStrings (mapAttrsToList (name: value: '' + user_pref("${name}", ${userPrefValue value}); + '') prefs')} + + ${extraPrefs} + ''; + + mkContainersJson = containers: + let + containerToIdentity = _: container: { + userContextId = container.id; + name = container.name; + icon = container.icon; + color = container.color; + public = true; + }; + in '' + ${builtins.toJSON { + version = 4; + lastUserContextId = + elemAt (mapAttrsToList (_: container: container.id) containers) 0; + identities = mapAttrsToList containerToIdentity containers ++ [ + { + userContextId = 4294967294; # 2^32 - 2 + name = "userContextIdInternal.thumbnail"; + icon = ""; + color = ""; + accessKey = ""; + public = false; + } + { + userContextId = 4294967295; # 2^32 - 1 + name = "userContextIdInternal.webextStorageLocal"; + icon = ""; + color = ""; + accessKey = ""; + public = false; + } + ]; + }} + ''; + + browserBookmarksFile = bookmarks: + let + indent = level: + lib.concatStringsSep "" (map (lib.const " ") (lib.range 1 level)); + + bookmarkToHTML = indentLevel: bookmark: + '' + ${indent indentLevel}
${escapeXML bookmark.name}''; + + directoryToHTML = indentLevel: directory: '' + ${indent indentLevel}
${ + if directory.toolbar then + '' +

Bookmarks Toolbar'' + else + ''

${escapeXML directory.name}'' + }

+ ${indent indentLevel}

+ ${allItemsToHTML (indentLevel + 1) directory.bookmarks} + ${indent indentLevel}

''; + + itemToHTMLOrRecurse = indentLevel: item: + if item ? "url" then + bookmarkToHTML indentLevel item + else + directoryToHTML indentLevel item; + + allItemsToHTML = indentLevel: bookmarks: + lib.concatStringsSep "\n" + (map (itemToHTMLOrRecurse indentLevel) bookmarks); + + bookmarkEntries = allItemsToHTML 1 bookmarks; + in pkgs.writeText "${packageName}-bookmarks.html" '' + + + + Bookmarks +

Bookmarks Menu

+

+ ${bookmarkEntries} +

+ ''; + + mkNoDuplicateAssertion = entities: entityKind: + (let + # Return an attribute set with entity IDs as keys and a list of + # entity names with corresponding ID as value. An ID is present in + # the result only if more than one entity has it. The argument + # entities is a list of AttrSet of one id/name pair. + findDuplicateIds = entities: + filterAttrs (_entityId: entityNames: length entityNames != 1) + (zipAttrs entities); + + duplicates = findDuplicateIds (mapAttrsToList + (entityName: entity: { "${toString entity.id}" = entityName; }) + entities); + + mkMsg = entityId: entityNames: + " - ID ${entityId} is used by " + concatStringsSep ", " entityNames; + in { + assertion = duplicates == { }; + message = '' + Must not have a ${name} ${entityKind} with an existing ID but + '' + concatStringsSep "\n" (mapAttrsToList mkMsg duplicates); + }); + + wrapPackage = package: + let + # The configuration expected by the Firefox wrapper. + fcfg = { enableGnomeExtensions = cfg.enableGnomeExtensions; }; + + # A bit of hackery to force a config into the wrapper. + browserName = + package.browserName or (builtins.parseDrvName package.name).name; + + # The configuration expected by the Firefox wrapper builder. + bcfg = setAttrByPath [ browserName ] fcfg; + + in if package == null then + null + else if isDarwin then + package + else if isWrapped then + package.override (old: { + cfg = old.cfg or { } // fcfg; + extraPolicies = (old.extraPolicies or { }) // cfg.policies; + }) + else + (pkgs.wrapFirefox.override { config = bcfg; }) package { }; + +in { + options = setAttrByPath modulePath { + enable = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + Whether to enable ${name}.${ + optionalString (description != null) " ${description}" + } + ${optionalString (!visible) + "See `programs.firefox` for more configuration options."} + ''; + }; + + package = mkOption { + inherit visible; + type = with types; nullOr package; + default = pkgs.${defaultPackageName}; + defaultText = literalExpression "pkgs.${packageName}"; + example = literalExpression '' + pkgs.${packageName}.override { + # See nixpkgs' firefox/wrapper.nix to check which options you can use + nativeMessagingHosts = [ + # Gnome shell native connector + pkgs.gnome-browser-connector + # Tridactyl native connector + pkgs.tridactyl-native + ]; + } + ''; + description = '' + The ${name} package to use. If state version ≥ 19.09 then + this should be a wrapped ${name} package. For earlier state + versions it should be an unwrapped ${name} package. + Set to `null` to disable installing ${name}. + ''; + }; + + languagePacks = mkOption { + type = types.listOf types.str; + default = [ ]; + description = '' + The language packs to install. Available language codes can be found + on the releases page: + `https://releases.mozilla.org/pub/firefox/releases/''${version}/linux-x86_64/xpi/`, + replacing `''${version}` with the version of Firefox you have. + ''; + example = [ "en-GB" "de" ]; + }; + + name = mkOption { + internal = true; + type = types.str; + default = name; + example = "Firefox"; + description = "The name of the browser."; + }; + + wrappedPackageName = mkOption { + internal = true; + type = with types; nullOr str; + default = wrappedPackageName; + description = "Name of the wrapped browser package."; + }; + + vendorPath = mkOption { + internal = true; + type = with types; nullOr str; + default = with platforms; + if isDarwin then + darwin.vendorPath or null + else + linux.vendorPath or null; + example = ".mozilla"; + description = + "Directory containing the native messaging hosts directory."; + }; + + configPath = mkOption { + internal = true; + type = types.str; + default = with platforms; + if isDarwin then darwin.configPath else linux.configPath; + example = ".mozilla/firefox"; + description = "Directory containing the ${name} configuration files."; + }; + + nativeMessagingHosts = optionalAttrs (cfg.vendorPath != null) (mkOption { + inherit visible; + type = types.listOf types.package; + default = [ ]; + description = '' + Additional packages containing native messaging hosts that should be + made available to ${name} extensions. + ''; + }); + + finalPackage = mkOption { + inherit visible; + type = with types; nullOr package; + readOnly = true; + description = "Resulting ${cfg.name} package."; + }; + + policies = optionalAttrs (unwrappedPackageName != null) (mkOption { + inherit visible; + type = types.attrsOf jsonFormat.type; + default = { }; + description = + "[See list of policies](https://mozilla.github.io/policy-templates/)."; + example = { + DefaultDownloadDirectory = "\${home}/Downloads"; + BlockAboutConfig = true; + }; + }); + + profiles = mkOption { + inherit visible; + type = types.attrsOf (types.submodule ({ config, name, ... }: { + options = { + name = mkOption { + type = types.str; + default = name; + description = "Profile name."; + }; + + id = mkOption { + type = types.ints.unsigned; + default = 0; + description = '' + Profile ID. This should be set to a unique number per profile. + ''; + }; + + settings = mkOption { + type = types.attrsOf (jsonFormat.type // { + description = + "${name} preference (int, bool, string, and also attrs, list, float as a JSON string)"; + }); + default = { }; + example = literalExpression '' + { + "browser.startup.homepage" = "https://nixos.org"; + "browser.search.region" = "GB"; + "browser.search.isUS" = false; + "distribution.searchplugins.defaultLocale" = "en-GB"; + "general.useragent.locale" = "en-GB"; + "browser.bookmarks.showMobileBookmarks" = true; + "browser.newtabpage.pinned" = [{ + title = "NixOS"; + url = "https://nixos.org"; + }]; + } + ''; + description = '' + Attribute set of ${name} preferences. + + ${name} only supports int, bool, and string types for + preferences, but home-manager will automatically + convert all other JSON-compatible values into strings. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra preferences to add to {file}`user.js`. + ''; + }; + + userChrome = mkOption { + type = types.lines; + default = ""; + description = "Custom ${name} user chrome CSS."; + example = '' + /* Hide tab bar in FF Quantum */ + @-moz-document url(chrome://browser/content/browser.xul), url(chrome://browser/content/browser.xhtml) { + #TabsToolbar { + visibility: collapse !important; + margin-bottom: 21px !important; + } + + #sidebar-box[sidebarcommand="treestyletab_piro_sakura_ne_jp-sidebar-action"] #sidebar-header { + visibility: collapse !important; + } + } + ''; + }; + + userContent = mkOption { + type = types.lines; + default = ""; + description = "Custom ${name} user content CSS."; + example = '' + /* Hide scrollbar in FF Quantum */ + *{scrollbar-width:none !important} + ''; + }; + + bookmarks = mkOption { + type = let + bookmarkSubmodule = types.submodule ({ config, name, ... }: { + options = { + name = mkOption { + type = types.str; + default = name; + description = "Bookmark name."; + }; + + tags = mkOption { + type = types.listOf types.str; + default = [ ]; + description = "Bookmark tags."; + }; + + keyword = mkOption { + type = types.nullOr types.str; + default = null; + description = "Bookmark search keyword."; + }; + + url = mkOption { + type = types.str; + description = "Bookmark url, use %s for search terms."; + }; + }; + }) // { + description = "bookmark submodule"; + }; + + bookmarkType = types.addCheck bookmarkSubmodule (x: x ? "url"); + + directoryType = types.submodule ({ config, name, ... }: { + options = { + name = mkOption { + type = types.str; + default = name; + description = "Directory name."; + }; + + bookmarks = mkOption { + type = types.listOf nodeType; + default = [ ]; + description = "Bookmarks within directory."; + }; + + toolbar = mkOption { + type = types.bool; + default = false; + description = '' + Make this the toolbar directory. Note, this does _not_ + mean that this directory will be added to the toolbar, + this directory _is_ the toolbar. + ''; + }; + }; + }) // { + description = "directory submodule"; + }; + + nodeType = types.either bookmarkType directoryType; + in with types; + coercedTo (attrsOf nodeType) attrValues (listOf nodeType); + default = [ ]; + example = literalExpression '' + [ + { + 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"; + toolbar = true; + bookmarks = [ + { + name = "homepage"; + url = "https://nixos.org/"; + } + { + name = "wiki"; + tags = [ "wiki" "nix" ]; + url = "https://wiki.nixos.org/"; + } + ]; + } + ] + ''; + description = '' + Preloaded bookmarks. Note, this may silently overwrite any + previously existing bookmarks! + ''; + }; + + path = mkOption { + type = types.str; + default = name; + description = "Profile path."; + }; + + isDefault = mkOption { + type = types.bool; + default = config.id == 0; + defaultText = "true if profile ID is 0"; + 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. + ''; + }; + }; + + containersForce = mkOption { + type = types.bool; + default = false; + description = '' + Whether to force replace the existing containers configuration. + This is recommended since Firefox will replace the symlink on + every launch, but note that you'll lose any existing configuration + by enabling this. + ''; + }; + + containers = mkOption { + type = types.attrsOf (types.submodule ({ name, ... }: { + options = { + name = mkOption { + type = types.str; + default = name; + description = "Container name, e.g., shopping."; + }; + + id = mkOption { + type = types.ints.unsigned; + default = 0; + description = '' + Container ID. This should be set to a unique number per container in this profile. + ''; + }; + + # List of colors at + # https://searchfox.org/mozilla-central/rev/5ad226c7379b0564c76dc3b54b44985356f94c5a/toolkit/components/extensions/parent/ext-contextualIdentities.js#32 + color = mkOption { + type = types.enum [ + "blue" + "turquoise" + "green" + "yellow" + "orange" + "red" + "pink" + "purple" + "toolbar" + ]; + default = "pink"; + description = "Container color."; + }; + + icon = mkOption { + type = types.enum [ + "briefcase" + "cart" + "circle" + "dollar" + "fence" + "fingerprint" + "gift" + "vacation" + "food" + "fruit" + "pet" + "tree" + "chill" + ]; + default = "fruit"; + description = "Container icon."; + }; + }; + })); + default = { }; + example = { + "shopping" = { + id = 1; + color = "blue"; + icon = "cart"; + }; + "dangerous" = { + id = 2; + color = "red"; + icon = "fruit"; + }; + }; + description = '' + Attribute set of container configurations. See + [Multi-Account + Containers](https://support.mozilla.org/en-US/kb/containers) + for more information. + ''; + }; + + extensions = mkOption { + type = types.listOf types.package; + default = [ ]; + example = literalExpression '' + with pkgs.nur.repos.rycee.firefox-addons; [ + privacy-badger + ] + ''; + description = '' + List of ${name} add-on packages to install for this profile. + Some pre-packaged add-ons are accessible from the + [Nix User Repository](https://github.com/nix-community/NUR). + Once you have NUR installed run + + ```console + $ nix-env -f '' -qaP -A nur.repos.rycee.firefox-addons + ``` + + to list the available ${name} add-ons. + + Note that it is necessary to manually enable these extensions + inside ${name} after the first installation. + + To automatically enable extensions add + `"extensions.autoDisableScopes" = 0;` + to + [{option}`${moduleName}.profiles..settings`](#opt-${moduleName}.profiles._name_.settings) + ''; + }; + + }; + })); + default = { }; + description = "Attribute set of ${name} profiles."; + }; + + enableGnomeExtensions = mkOption { + inherit visible; + type = types.bool; + default = false; + description = '' + Whether to enable the GNOME Shell native host connector. Note, you + also need to set the NixOS option + `services.gnome.gnome-browser-connector.enable` to + `true`. + ''; + }; + }; + + config = mkIf cfg.enable ({ + assertions = [ + (hm.assertions.assertPlatform moduleName pkgs supportedPlatforms) + + (let + defaults = + catAttrs "name" (filter (a: a.isDefault) (attrValues cfg.profiles)); + in { + assertion = cfg.profiles == { } || length defaults == 1; + message = "Must have exactly one default ${cfg.name} profile but found " + + toString (length defaults) + optionalString (length defaults > 1) + (", namely " + concatStringsSep ", " defaults); + }) + + (let + getContainers = profiles: + flatten + (mapAttrsToList (_: value: (attrValues value.containers)) profiles); + + findInvalidContainerIds = profiles: + filter (container: container.id >= 4294967294) + (getContainers profiles); + in { + assertion = cfg.profiles == { } + || length (findInvalidContainerIds cfg.profiles) == 0; + message = "Container id must be smaller than 4294967294 (2^32 - 2)"; + }) + + { + assertion = cfg.languagePacks == [ ] || cfg.package != null; + message = '' + 'programs.firefox.languagePacks' requires 'programs.firefox.package' + to be set to a non-null value. + ''; + } + + (mkNoDuplicateAssertion cfg.profiles "profile") + ] ++ (mapAttrsToList + (_: profile: mkNoDuplicateAssertion profile.containers "container") + cfg.profiles); + + warnings = optional (cfg.enableGnomeExtensions or false) '' + Using '${moduleName}.enableGnomeExtensions' has been deprecated and + will be removed in the future. Please change to overriding the package + configuration using '${moduleName}.package' instead. You can refer to + 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 ([{ + "${cfg.configPath}/profiles.ini" = + mkIf (cfg.profiles != { }) { text = profilesIni; }; + }] ++ optional (cfg.vendorPath != null) { + "${nativeMessagingHostsPath}" = { + source = + "${nativeMessagingHostsJoined}/lib/mozilla/native-messaging-hosts"; + recursive = true; + }; + } ++ flip mapAttrsToList cfg.profiles (_: profile: { + "${profilesPath}/${profile.path}/.keep".text = ""; + + "${profilesPath}/${profile.path}/chrome/userChrome.css" = + mkIf (profile.userChrome != "") { text = profile.userChrome; }; + + "${profilesPath}/${profile.path}/chrome/userContent.css" = + mkIf (profile.userContent != "") { text = profile.userContent; }; + + "${profilesPath}/${profile.path}/user.js" = mkIf (profile.settings != { } + || profile.extraConfig != "" || profile.bookmarks != [ ]) { + text = + mkUserJs profile.settings profile.extraConfig profile.bookmarks; + }; + + "${profilesPath}/${profile.path}/containers.json" = + mkIf (profile.containers != { }) { + text = mkContainersJson profile.containers; + 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}/extensions" = + mkIf (profile.extensions != [ ]) { + source = let + extensionsEnvPkg = pkgs.buildEnv { + name = "hm-firefox-extensions"; + paths = profile.extensions; + }; + in "${extensionsEnvPkg}/share/mozilla/${extensionPath}"; + recursive = true; + force = true; + }; + })); + } // setAttrByPath modulePath { finalPackage = wrapPackage cfg.package; }); +} + diff --git a/modules/programs/gh-dash.nix b/modules/programs/gh-dash.nix index 69d5482b6..b351bb33a 100644 --- a/modules/programs/gh-dash.nix +++ b/modules/programs/gh-dash.nix @@ -7,7 +7,7 @@ let yamlFormat = pkgs.formats.yaml { }; in { - meta.maintainers = [ lib.maintainers.janik ]; + meta.maintainers = [ lib.hm.maintainers.janik ]; options.programs.gh-dash = { enable = lib.mkEnableOption "GitHub CLI dashboard plugin"; diff --git a/modules/programs/git.nix b/modules/programs/git.nix index 00ac6392a..a16eeb12b 100644 --- a/modules/programs/git.nix +++ b/modules/programs/git.nix @@ -225,6 +225,8 @@ in { ''; }; + package = mkPackageOption pkgs "difftastic" { }; + background = mkOption { type = types.enum [ "light" "dark" ]; default = "light"; @@ -507,11 +509,11 @@ in { }) (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/gnome-terminal.nix b/modules/programs/gnome-terminal.nix index 83cfc0274..dafadb7e9 100644 --- a/modules/programs/gnome-terminal.nix +++ b/modules/programs/gnome-terminal.nix @@ -316,7 +316,7 @@ in { }) ]; - home.packages = [ pkgs.gnome.gnome-terminal ]; + home.packages = [ pkgs.gnome-terminal ]; dconf.settings = let dconfPath = "org/gnome/terminal/legacy"; in { diff --git a/modules/programs/hyfetch.nix b/modules/programs/hyfetch.nix index 726bc94e6..485ceb046 100644 --- a/modules/programs/hyfetch.nix +++ b/modules/programs/hyfetch.nix @@ -7,7 +7,7 @@ let jsonFormat = pkgs.formats.json { }; in { - meta.maintainers = [ maintainers.lilyinstarlight ]; + meta.maintainers = [ hm.maintainers.lilyinstarlight ]; options.programs.hyfetch = { enable = mkEnableOption "hyfetch"; diff --git a/modules/programs/jujutsu.nix b/modules/programs/jujutsu.nix index a21c71087..f0e1b4250 100644 --- a/modules/programs/jujutsu.nix +++ b/modules/programs/jujutsu.nix @@ -7,6 +7,11 @@ let cfg = config.programs.jujutsu; tomlFormat = pkgs.formats.toml { }; + configDir = if pkgs.stdenv.isDarwin then + "Library/Application Support" + else + config.xdg.configHome; + in { meta.maintainers = [ maintainers.shikanime ]; @@ -51,7 +56,7 @@ in { config = mkIf cfg.enable { home.packages = [ cfg.package ]; - xdg.configFile."jj/config.toml" = mkIf (cfg.settings != { }) { + home.file."${configDir}/jj/config.toml" = mkIf (cfg.settings != { }) { source = tomlFormat.generate "jujutsu-config" (cfg.settings // optionalAttrs (cfg.ediff) (let emacsDiffScript = pkgs.writeShellScriptBin "emacs-ediff" '' diff --git a/modules/programs/khard.nix b/modules/programs/khard.nix index a3e73fb07..cbd8c1f07 100644 --- a/modules/programs/khard.nix +++ b/modules/programs/khard.nix @@ -68,6 +68,11 @@ in { type = with lib.types; attrsOf (submodule { options.khard.enable = lib.mkEnableOption "khard access"; + options.khard.defaultCollection = lib.mkOption { + type = types.str; + default = ""; + description = "VCARD collection to be searched by khard."; + }; }); }; }; @@ -75,11 +80,17 @@ in { config = lib.mkIf cfg.enable { home.packages = [ pkgs.khard ]; - xdg.configFile."khard/khard.conf".text = '' + xdg.configFile."khard/khard.conf".text = let + makePath = anAccount: + builtins.toString (/. + lib.concatStringsSep "/" [ + anAccount.local.path + anAccount.khard.defaultCollection + ]); + in '' [addressbooks] ${lib.concatMapStringsSep "\n" (acc: '' [[${acc.name}]] - path = ${acc.local.path} + path = ${makePath acc} '') (lib.attrValues accounts)} ${renderSettings cfg.settings} diff --git a/modules/programs/mcfly.nix b/modules/programs/mcfly.nix index 450a27380..d0dddba21 100644 --- a/modules/programs/mcfly.nix +++ b/modules/programs/mcfly.nix @@ -5,6 +5,8 @@ let cfg = config.programs.mcfly; + tomlFormat = pkgs.formats.toml { }; + bashIntegration = '' eval "$(${getExe pkgs.mcfly} init bash)" '' + optionalString cfg.fzf.enable '' @@ -40,6 +42,37 @@ in { options.programs.mcfly = { enable = mkEnableOption "mcfly"; + settings = mkOption { + type = tomlFormat.type; + default = { }; + example = literalExpression '' + { + colors = { + menubar = { + bg = "black"; + fg = "red"; + }; + darkmode = { + prompt = "cyan"; + timing = "yellow"; + results_selection_fg = "cyan"; + results_selection_bg = "black"; + results_selection_hl = "red"; + }; + }; + } + ''; + description = '' + Settings written to {file}`~/.config/mcfly/config.toml`. + + Note, if your McFly database is currently in {file}`~/.mcfly`, + then this option has no effect. + Move the database to {file}`$XDG_DATA_DIR/mcfly/history.db` and + remove {file}`~/.mcfly` to make the settings take effect. See + . + ''; + }; + keyScheme = mkOption { type = types.enum [ "emacs" "vim" ]; default = "emacs"; @@ -105,6 +138,11 @@ in { { home.packages = [ pkgs.mcfly ] ++ optional cfg.fzf.enable pkgs.mcfly-fzf; + # Oddly enough, McFly expects this in the data path, not in config. + xdg.dataFile."mcfly/config.toml" = mkIf (cfg.settings != { }) { + source = tomlFormat.generate "mcfly-config.toml" cfg.settings; + }; + programs.bash.initExtra = mkIf cfg.enableBashIntegration bashIntegration; programs.zsh.initExtra = mkIf cfg.enableZshIntegration zshIntegration; diff --git a/modules/programs/micro.nix b/modules/programs/micro.nix index 0093e25f0..bf34f8e62 100644 --- a/modules/programs/micro.nix +++ b/modules/programs/micro.nix @@ -15,6 +15,8 @@ in { programs.micro = { enable = mkEnableOption "micro, a terminal-based text editor"; + package = mkPackageOption pkgs "micro" { }; + settings = mkOption { type = jsonFormat.type; default = { }; @@ -35,7 +37,7 @@ in { }; config = mkIf cfg.enable { - home.packages = [ pkgs.micro ]; + home.packages = [ cfg.package ]; xdg.configFile."micro/settings.json".source = jsonFormat.generate "micro-settings" cfg.settings; diff --git a/modules/programs/mpv.nix b/modules/programs/mpv.nix index 26cad1112..f2664e71a 100644 --- a/modules/programs/mpv.nix +++ b/modules/programs/mpv.nix @@ -55,8 +55,10 @@ let mpvPackage = if cfg.scripts == [ ] then cfg.package + else if hasAttr "wrapMpv" pkgs then + pkgs.wrapMpv pkgs.mpv-unwrapped { scripts = cfg.scripts; } else - pkgs.wrapMpv pkgs.mpv-unwrapped { scripts = cfg.scripts; }; + pkgs.mpv.override { scripts = cfg.scripts; }; in { options = { @@ -227,5 +229,5 @@ in { } ]); - meta.maintainers = with maintainers; [ tadeokondrak thiagokokada chuangzhu ]; + meta.maintainers = with maintainers; [ thiagokokada chuangzhu ]; } diff --git a/modules/programs/papis.nix b/modules/programs/papis.nix index b110172d9..837bfc274 100644 --- a/modules/programs/papis.nix +++ b/modules/programs/papis.nix @@ -19,6 +19,8 @@ in { options.programs.papis = { enable = mkEnableOption "papis"; + package = mkPackageOption pkgs "papis" { }; + settings = mkOption { type = with types; attrsOf (oneOf [ bool int str ]); default = { }; @@ -84,7 +86,7 @@ in { (", namely " + concatStringsSep "," defaultLibraries); }]; - home.packages = [ pkgs.papis ]; + home.packages = [ cfg.package ]; xdg.configFile."papis/config" = mkIf (cfg.libraries != { }) { text = generators.toINI { } settingsIni; }; diff --git a/modules/programs/rbw.nix b/modules/programs/rbw.nix index 5dd751d07..b7381c672 100644 --- a/modules/programs/rbw.nix +++ b/modules/programs/rbw.nix @@ -19,7 +19,7 @@ let base_url = mkOption { type = with types; nullOr str; default = null; - example = "bitwarden.example.com"; + example = "https://bitwarden.example.com/"; description = "The base-url for a self-hosted bitwarden installation."; }; @@ -27,7 +27,7 @@ let identity_url = mkOption { type = with types; nullOr str; default = null; - example = "identity.example.com"; + example = "https://identity.example.com/"; description = "The identity url for your bitwarden installation."; }; diff --git a/modules/programs/script-directory.nix b/modules/programs/script-directory.nix index 9f5abf65a..bd6b3b401 100644 --- a/modules/programs/script-directory.nix +++ b/modules/programs/script-directory.nix @@ -1,7 +1,7 @@ { config, pkgs, lib, ... }: let cfg = config.programs.script-directory; in { - meta.maintainers = [ lib.maintainers.janik ]; + meta.maintainers = [ lib.hm.maintainers.janik ]; options.programs.script-directory = { enable = lib.mkEnableOption "script-directory"; diff --git a/modules/programs/sm64ex.nix b/modules/programs/sm64ex.nix index 35d608bab..23b75808f 100644 --- a/modules/programs/sm64ex.nix +++ b/modules/programs/sm64ex.nix @@ -29,7 +29,7 @@ let in "${key} ${generatedValue}"; in { - meta.maintainers = [ maintainers.ivar ]; + meta.maintainers = [ ]; options.programs.sm64ex = { enable = mkEnableOption "sm64ex"; diff --git a/modules/programs/starship.nix b/modules/programs/starship.nix index f253fa7f0..9ccff7fcf 100644 --- a/modules/programs/starship.nix +++ b/modules/programs/starship.nix @@ -24,14 +24,7 @@ in { }; settings = mkOption { - type = with types; - let - prim = either bool (either int str); - primOrPrimAttrs = either prim (attrsOf prim); - entry = either prim (listOf primOrPrimAttrs); - entryOrAttrsOf = t: either entry (attrsOf t); - entries = entryOrAttrsOf (entryOrAttrsOf entry); - in attrsOf entries // { description = "Starship configuration"; }; + type = tomlFormat.type; default = { }; example = literalExpression '' { 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/watson.nix b/modules/programs/watson.nix index b30dec096..c842c519a 100644 --- a/modules/programs/watson.nix +++ b/modules/programs/watson.nix @@ -14,7 +14,7 @@ let config.xdg.configHome; in { - meta.maintainers = [ maintainers.polykernel ]; + meta.maintainers = [ ]; options.programs.watson = { enable = mkEnableOption "watson, a wonderful CLI to track your time"; diff --git a/modules/programs/waybar.nix b/modules/programs/waybar.nix index 9925effc9..72d247323 100644 --- a/modules/programs/waybar.nix +++ b/modules/programs/waybar.nix @@ -69,8 +69,8 @@ let }; modules-left = mkOption { - type = listOf str; - default = [ ]; + type = nullOr (listOf str); + default = null; description = "Modules that will be displayed on the left."; example = literalExpression '' [ "sway/workspaces" "sway/mode" "wlr/taskbar" ] @@ -78,8 +78,8 @@ let }; modules-center = mkOption { - type = listOf str; - default = [ ]; + type = nullOr (listOf str); + default = null; description = "Modules that will be displayed in the center."; example = literalExpression '' [ "sway/window" ] @@ -87,8 +87,8 @@ let }; modules-right = mkOption { - type = listOf str; - default = [ ]; + type = nullOr (listOf str); + default = null; description = "Modules that will be displayed on the right."; example = literalExpression '' [ "mpd" "custom/mymodule#with-css-id" "temperature" ] diff --git a/modules/programs/yazi.nix b/modules/programs/yazi.nix index 11f4e75cf..d7b880200 100644 --- a/modules/programs/yazi.nix +++ b/modules/programs/yazi.nix @@ -7,7 +7,7 @@ let tomlFormat = pkgs.formats.toml { }; bashIntegration = '' - function ya() { + function ${cfg.shellWrapperName}() { local tmp="$(mktemp -t "yazi-cwd.XXXXX")" yazi "$@" --cwd-file="$tmp" if cwd="$(cat -- "$tmp")" && [ -n "$cwd" ] && [ "$cwd" != "$PWD" ]; then @@ -18,7 +18,7 @@ let ''; fishIntegration = '' - function ya + function ${cfg.shellWrapperName} set tmp (mktemp -t "yazi-cwd.XXXXX") yazi $argv --cwd-file="$tmp" if set cwd (cat -- "$tmp"); and [ -n "$cwd" ]; and [ "$cwd" != "$PWD" ] @@ -29,7 +29,7 @@ let ''; nushellIntegration = '' - def --env ya [...args] { + def --env ${cfg.shellWrapperName} [...args] { let tmp = (mktemp -t "yazi-cwd.XXXXX") yazi ...$args --cwd-file $tmp let cwd = (open $tmp) @@ -40,13 +40,22 @@ let } ''; in { - meta.maintainers = with maintainers; [ xyenon ]; + meta.maintainers = with maintainers; [ xyenon eljamm ]; options.programs.yazi = { enable = mkEnableOption "yazi"; package = mkPackageOption pkgs "yazi" { }; + shellWrapperName = mkOption { + type = types.str; + default = "yy"; + example = "y"; + description = '' + Name of the shell wrapper to be called. + ''; + }; + enableBashIntegration = mkEnableOption "Bash integration"; enableZshIntegration = mkEnableOption "Zsh integration"; @@ -132,7 +141,7 @@ in { }; initLua = mkOption { - type = with types; nullOr path; + type = with types; nullOr (either path lines); default = null; description = '' The init.lua for Yazi itself. @@ -145,8 +154,11 @@ in { default = { }; description = '' Lua plugins. + Values should be a package or path containing an `init.lua` file. + Will be linked to {file}`$XDG_CONFIG_HOME/yazi/plugins/.yazi`. - See https://yazi-rs.github.io/docs/plugins/overview/ for documentation. + See + for documentation. ''; example = literalExpression '' { @@ -161,8 +173,10 @@ in { default = { }; description = '' Pre-made themes. + Values should be a package or path containing the required files. + Will be linked to {file}`$XDG_CONFIG_HOME/yazi/flavors/.yazi`. - See https://yazi-rs.github.io/docs/flavors/overview/ for documentation. + See for documentation. ''; example = literalExpression '' { @@ -171,7 +185,6 @@ in { } ''; }; - }; config = mkIf cfg.enable { @@ -197,11 +210,69 @@ in { "yazi/theme.toml" = mkIf (cfg.theme != { }) { source = tomlFormat.generate "yazi-theme" cfg.theme; }; - "yazi/init.lua" = mkIf (cfg.initLua != null) { source = cfg.initLua; }; - } // (mapAttrs' - (name: value: nameValuePair "yazi/plugins/${name}" { source = value; }) - cfg.plugins) // (mapAttrs' - (name: value: nameValuePair "yazi/flavors/${name}" { source = value; }) - cfg.flavors); + "yazi/init.lua" = mkIf (cfg.initLua != null) + (if builtins.isPath cfg.initLua then { + source = cfg.initLua; + } else { + text = cfg.initLua; + }); + } // (mapAttrs' (name: value: + nameValuePair "yazi/flavors/${name}.yazi" { source = value; }) + cfg.flavors) // (mapAttrs' (name: value: + nameValuePair "yazi/plugins/${name}.yazi" { source = value; }) + cfg.plugins); + + warnings = filter (s: s != "") (concatLists [ + (mapAttrsToList (name: value: + optionalString (hasSuffix ".yazi" name) '' + Flavors like `programs.yazi.flavors."${name}"` should no longer have the suffix ".yazi" in their attribute name. + The flavor will be linked to `$XDG_CONFIG_HOME/yazi/flavors/${name}.yazi`. + You probably want to rename it to `programs.yazi.flavors."${ + removeSuffix ".yazi" name + }"`. + '') cfg.flavors) + (mapAttrsToList (name: value: + optionalString (hasSuffix ".yazi" name) '' + Plugins like `programs.yazi.plugins."${name}"` should no longer have the suffix ".yazi" in their attribute name. + The plugin will be linked to `$XDG_CONFIG_HOME/yazi/plugins/${name}.yazi`. + You probably want to rename it to `programs.yazi.plugins."${ + removeSuffix ".yazi" name + }"`. + '') cfg.plugins) + ]); + + assertions = let + mkAsserts = opt: requiredFiles: + mapAttrsToList (name: value: + let + isDir = pathIsDirectory "${value}"; + msgNotDir = optionalString (!isDir) + "The path or package should be a directory, not a single file."; + isFileMissing = file: + !(pathExists "${value}/${file}") + || pathIsDirectory "${value}/${file}"; + missingFiles = filter isFileMissing requiredFiles; + msgFilesMissing = optionalString (missingFiles != [ ]) + "The ${singularOpt} is missing these files: ${ + toString missingFiles + }"; + singularOpt = removeSuffix "s" opt; + in { + assertion = isDir && missingFiles == [ ]; + message = '' + Value at `programs.yazi.${opt}.${name}` is not a valid yazi ${singularOpt}. + ${msgNotDir} + ${msgFilesMissing} + Evaluated value: `${value}` + ''; + }) cfg.${opt}; + in (mkAsserts "flavors" [ + "flavor.toml" + "tmtheme.xml" + "README.md" + "preview.png" + "LICENSE" + "LICENSE-tmtheme" + ]) ++ (mkAsserts "plugins" [ "init.lua" ]); }; } diff --git a/modules/programs/zsh.nix b/modules/programs/zsh.nix index 3ec73f30d..b6e46392c 100644 --- a/modules/programs/zsh.nix +++ b/modules/programs/zsh.nix @@ -34,6 +34,21 @@ let historyModule = types.submodule ({ config, ... }: { options = { + append = mkOption { + type = types.bool; + default = false; + description = '' + If set, zsh sessions will append their history list to the history + file, rather than replace it. Thus, multiple parallel zsh sessions + will all have the new entries from their history lists added to the + history file, in the order that they exit. + + This file will still be periodically re-written to trim it when the + number of lines grows 20% beyond the value specified by + `programs.zsh.history.save`. + ''; + }; + size = mkOption { type = types.int; default = 10000; @@ -398,6 +413,22 @@ in {manpage}`zshzle(1)` for syntax. ''; }; + + strategy = mkOption { + type = types.listOf (types.enum [ "history" "completion" "match_prev_cmd" ]); + default = [ "history" ]; + description = '' + `ZSH_AUTOSUGGEST_STRATEGY` is an array that specifies how suggestions should be generated. + The strategies in the array are tried successively until a suggestion is found. + There are currently three built-in strategies to choose from: + + - `history`: Chooses the most recent match from history. + - `completion`: Chooses a suggestion based on what tab-completion would suggest. (requires `zpty` module) + - `match_prev_cmd`: Like `history`, but chooses the most recent match whose preceding history item matches + the most recently executed command. Note that this strategy won't work as expected with ZSH options that + don't preserve the history order such as `HIST_IGNORE_ALL_DUPS` or `HIST_EXPIRE_DUPS_FIRST`. + ''; + }; }; history = mkOption { @@ -610,6 +641,7 @@ in (optionalString cfg.autosuggestion.enable '' source ${pkgs.zsh-autosuggestions}/share/zsh-autosuggestions/zsh-autosuggestions.zsh + ZSH_AUTOSUGGEST_STRATEGY=(${concatStringsSep " " cfg.autosuggestion.strategy}) '') (optionalString (cfg.autosuggestion.enable && cfg.autosuggestion.highlight != null) '' ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="${cfg.autosuggestion.highlight}" @@ -652,6 +684,7 @@ in mkdir -p "$(dirname "$HISTFILE")" setopt HIST_FCNTL_LOCK + ${if cfg.history.append then "setopt" else "unsetopt"} APPEND_HISTORY ${if cfg.history.ignoreDups then "setopt" else "unsetopt"} HIST_IGNORE_DUPS ${if cfg.history.ignoreAllDups then "setopt" else "unsetopt"} HIST_IGNORE_ALL_DUPS ${if cfg.history.ignoreSpace then "setopt" else "unsetopt"} HIST_IGNORE_SPACE diff --git a/modules/services/blanket.nix b/modules/services/blanket.nix new file mode 100644 index 000000000..5eeb2ab1e --- /dev/null +++ b/modules/services/blanket.nix @@ -0,0 +1,40 @@ +{ pkgs, lib, config, ... }: + +let + cfg = config.services.blanket; + + inherit (lib) mkIf mkEnableOption mkPackageOption hm platforms; +in { + meta.maintainers = [ lib.maintainers.daru-san ]; + + options.services.blanket = { + enable = mkEnableOption "blanket"; + + package = mkPackageOption pkgs "blanket" { }; + }; + + config = mkIf cfg.enable { + assertions = [ + (hm.assertions.assertPlatform "services.blanket" pkgs platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + systemd.user.services.blanket = { + Unit = { + Description = "Blanket daemon"; + Requires = [ "dbus.service" ]; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" "pipewire.service" ]; + }; + + Install.WantedBy = [ "graphical-session.target" ]; + + Service = { + ExecStart = "${cfg.package}/bin/blanket --gapplication-service"; + Restart = "on-failure"; + RestartSec = 5; + }; + }; + }; +} diff --git a/modules/services/cliphist.nix b/modules/services/cliphist.nix index 3599557f0..1877a6de0 100644 --- a/modules/services/cliphist.nix +++ b/modules/services/cliphist.nix @@ -1,7 +1,7 @@ { config, lib, pkgs, ... }: let cfg = config.services.cliphist; in { - meta.maintainers = [ lib.maintainers.janik ]; + meta.maintainers = [ lib.hm.maintainers.janik ]; options.services.cliphist = { enable = diff --git a/modules/services/dunst.nix b/modules/services/dunst.nix index daa800cf0..5bd82a399 100644 --- a/modules/services/dunst.nix +++ b/modules/services/dunst.nix @@ -65,9 +65,8 @@ in { }; configFile = mkOption { - type = with types; either str path; - default = "${config.xdg.configHome}/dunst/dunstrc"; - defaultText = "$XDG_CONFIG_HOME/dunst/dunstrc"; + type = with types; nullOr (either str path); + default = null; description = '' Path to the configuration file read by dunst. @@ -170,9 +169,9 @@ in { "stock" ]; - mkPath = { basePath, theme, category }: + mkPath = { basePath, theme, category, }: "${basePath}/share/icons/${theme.name}/${theme.size}/${category}"; - in concatMapStringsSep ":" mkPath (cartesianProductOfSets { + in concatMapStringsSep ":" mkPath (cartesianProduct { basePath = basePaths; theme = themes; category = categories; @@ -188,7 +187,9 @@ in { Service = { Type = "dbus"; BusName = "org.freedesktop.Notifications"; - ExecStart = "${cfg.package}/bin/dunst -config ${cfg.configFile}"; + ExecStart = escapeShellArgs ([ "${cfg.package}/bin/dunst" ] ++ + # Using `-config` breaks dunst's drop-ins, so only use it when an alternative path is set + optionals (cfg.configFile != null) [ "-config" cfg.configFile ]); Environment = optionalString (cfg.waylandDisplay != "") "WAYLAND_DISPLAY=${cfg.waylandDisplay}"; }; diff --git a/modules/services/fnott.nix b/modules/services/fnott.nix index 3d2d1dd8a..ecbd0fd15 100644 --- a/modules/services/fnott.nix +++ b/modules/services/fnott.nix @@ -9,7 +9,7 @@ let iniFormat = pkgs.formats.ini { }; in { - meta.maintainers = with maintainers; [ polykernel ]; + meta.maintainers = [ ]; options = { services.fnott = { diff --git a/modules/services/glance.nix b/modules/services/glance.nix new file mode 100644 index 000000000..fa4f1a8d7 --- /dev/null +++ b/modules/services/glance.nix @@ -0,0 +1,77 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.services.glance; + + inherit (lib) mkEnableOption mkPackageOption mkOption mkIf getExe; + + settingsFormat = pkgs.formats.yaml { }; + + settingsFile = settingsFormat.generate "glance.yml" cfg.settings; + + configFilePath = "${config.xdg.configHome}/glance/glance.yml"; +in { + meta.maintainers = [ pkgs.lib.maintainers.gepbird ]; + + options.services.glance = { + enable = mkEnableOption "glance"; + + package = mkPackageOption pkgs "glance" { }; + + settings = mkOption { + type = settingsFormat.type; + default = { + pages = [{ + name = "Calendar"; + columns = [{ + size = "full"; + widgets = [{ type = "calendar"; }]; + }]; + }]; + }; + example = { + server.port = 5678; + pages = [{ + name = "Home"; + columns = [{ + size = "full"; + widgets = [ + { type = "calendar"; } + { + type = "weather"; + location = "London, United Kingdom"; + } + ]; + }]; + }]; + }; + description = '' + Configuration written to a yaml file that is read by glance. See + + for more. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.glance" pkgs + lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + xdg.configFile."glance/glance.yml".source = settingsFile; + + systemd.user.services.glance = { + Unit = { + Description = "Glance feed dashboard server"; + PartOf = [ "graphical-session.target" ]; + }; + + Install.WantedBy = [ "graphical-session.target" ]; + + Service.ExecStart = "${getExe cfg.package} --config ${configFilePath}"; + }; + }; +} diff --git a/modules/services/gnome-keyring.nix b/modules/services/gnome-keyring.nix index 460e4abd1..2cfa33d03 100644 --- a/modules/services/gnome-keyring.nix +++ b/modules/services/gnome-keyring.nix @@ -49,7 +49,7 @@ in { args = concatStringsSep " " ([ "--start" "--foreground" ] ++ optional (cfg.components != [ ]) ("--components=" + concatStringsSep "," cfg.components)); - in "${pkgs.gnome.gnome-keyring}/bin/gnome-keyring-daemon ${args}"; + in "${pkgs.gnome-keyring}/bin/gnome-keyring-daemon ${args}"; Restart = "on-abort"; }; diff --git a/modules/services/kbfs.nix b/modules/services/kbfs.nix index a541a32ca..9cfe02752 100644 --- a/modules/services/kbfs.nix +++ b/modules/services/kbfs.nix @@ -52,7 +52,6 @@ in { "${pkgs.kbfs}/bin/kbfsfuse ${toString cfg.extraFlags} ${mountPoint}"; ExecStopPost = "/run/wrappers/bin/fusermount -u ${mountPoint}"; Restart = "on-failure"; - PrivateTmp = true; }; Install.WantedBy = [ "default.target" ]; diff --git a/modules/services/mpd.nix b/modules/services/mpd.nix index a0011b021..3d8d03be7 100644 --- a/modules/services/mpd.nix +++ b/modules/services/mpd.nix @@ -171,10 +171,17 @@ in { ]; systemd.user.services.mpd = { - Unit = { - After = [ "network.target" "sound.target" ]; - Description = "Music Player Daemon"; - }; + Unit = mkMerge [ + { + Description = "Music Player Daemon"; + After = [ "network.target" "sound.target" ]; + } + + (mkIf cfg.network.startWhenNeeded { + Requires = [ "mpd.socket" ]; + After = [ "mpd.socket" ]; + }) + ]; Install = mkIf (!cfg.network.startWhenNeeded) { WantedBy = [ "default.target" ]; diff --git a/modules/services/nix-gc.nix b/modules/services/nix-gc.nix index 652c575ac..50e8b6351 100644 --- a/modules/services/nix-gc.nix +++ b/modules/services/nix-gc.nix @@ -110,9 +110,11 @@ in { systemd.user.services.nix-gc = { Unit = { Description = "Nix Garbage Collector"; }; Service = { - ExecStart = "${nixPackage}/bin/nix-collect-garbage ${ + Type = "oneshot"; + ExecStart = toString (pkgs.writeShellScript "nix-gc" + "exec ${nixPackage}/bin/nix-collect-garbage ${ lib.optionalString (cfg.options != null) cfg.options - }"; + }"); }; }; systemd.user.timers.nix-gc = { diff --git a/modules/services/pbgopy.nix b/modules/services/pbgopy.nix index fecc64ca0..3a3499e52 100644 --- a/modules/services/pbgopy.nix +++ b/modules/services/pbgopy.nix @@ -15,7 +15,7 @@ let "--basic-auth ${escapeShellArg cfg.httpAuth}"); in { - meta.maintainers = [ maintainers.ivar ]; + meta.maintainers = [ ]; options.services.pbgopy = { enable = mkEnableOption "pbgopy"; diff --git a/modules/services/pulseeffects.nix b/modules/services/pulseeffects.nix index 434adf85e..3edc53499 100644 --- a/modules/services/pulseeffects.nix +++ b/modules/services/pulseeffects.nix @@ -9,7 +9,7 @@ let presetOpts = optionalString (cfg.preset != "") "--load-preset ${cfg.preset}"; in { - meta.maintainers = [ maintainers.jonringer ]; + meta.maintainers = [ hm.maintainers.jonringer ]; options.services.pulseeffects = { enable = mkEnableOption '' diff --git a/modules/services/ssh-agent.nix b/modules/services/ssh-agent.nix index 16db3232c..88ecf38b8 100644 --- a/modules/services/ssh-agent.nix +++ b/modules/services/ssh-agent.nix @@ -5,7 +5,7 @@ let cfg = config.services.ssh-agent; in { - meta.maintainers = [ lib.maintainers.lheckemann ]; + meta.maintainers = [ lib.hm.maintainers.lheckemann ]; options = { services.ssh-agent = { diff --git a/modules/services/stalonetray.nix b/modules/services/stalonetray.nix index 172d6dd9d..9d4d7a53e 100644 --- a/modules/services/stalonetray.nix +++ b/modules/services/stalonetray.nix @@ -74,7 +74,7 @@ in { } (mkIf (cfg.config != { }) { - home.file.".stalonetrayrc".text = let + xdg.configFile."stalonetrayrc".text = let valueToString = v: if isBool v then (if v then "true" else "false") @@ -88,7 +88,7 @@ in { }) (mkIf (cfg.extraConfig != "") { - home.file.".stalonetrayrc".text = cfg.extraConfig; + xdg.configFile."stalonetrayrc".text = cfg.extraConfig; }) ]); } diff --git a/modules/services/swayosd.nix b/modules/services/swayosd.nix index 79ca7f5ee..869b48729 100644 --- a/modules/services/swayosd.nix +++ b/modules/services/swayosd.nix @@ -60,6 +60,8 @@ in { After = [ "graphical-session.target" ]; ConditionEnvironment = "WAYLAND_DISPLAY"; Documentation = "man:swayosd(1)"; + StartLimitBurst = 5; + StartLimitIntervalSec = 10; }; Service = { @@ -71,6 +73,7 @@ in { + (optionalString (cfg.topMargin != null) " --top-margin ${toString cfg.topMargin}"); Restart = "always"; + RestartSec = "2s"; }; Install = { WantedBy = [ "graphical-session.target" ]; }; 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/window-managers/hyprland.nix b/modules/services/window-managers/hyprland.nix index 6b79248ba..73602ec61 100644 --- a/modules/services/window-managers/hyprland.nix +++ b/modules/services/window-managers/hyprland.nix @@ -40,7 +40,21 @@ in { ]; options.wayland.windowManager.hyprland = { - enable = lib.mkEnableOption "Hyprland wayland compositor"; + enable = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Whether to enable configuration for Hyprland, a tiling Wayland + compositor that doesn't sacrifice on its looks. + + ::: {.note} + This module configures Hyprland and adds it to your user's {env}`PATH`, + but does not make certain system-level changes. NixOS users should + enable the NixOS module with {option}`programs.hyprland.enable`, which + makes system-level changes such as adding a desktop session entry. + ::: + ''; + }; package = lib.mkPackageOption pkgs "hyprland" { }; @@ -206,7 +220,10 @@ in { "You have enabled hyprland.systemd.enable or listed plugins in hyprland.plugins but do not have any configuration in hyprland.settings or hyprland.extraConfig. This is almost certainly a mistake."; in lib.optional inconsistent warning; - home.packages = lib.optional (cfg.package != null) cfg.finalPackage; + home.packages = lib.concatLists [ + (lib.optional (cfg.package != null) cfg.finalPackage) + (lib.optional (cfg.xwayland.enable) pkgs.xwayland) + ]; xdg.configFile."hypr/hyprland.conf" = let shouldGenerate = cfg.systemd.enable || cfg.extraConfig != "" 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 bc20e9d9b..3acd6b17c 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"; @@ -403,7 +403,7 @@ in { "XCURSOR_THEME" "XCURSOR_SIZE" ]; - example = [ "-all" ]; + example = [ "--all" ]; description = '' Environment variables imported into the systemd and D-Bus user environment. ''; @@ -411,7 +411,12 @@ in { extraCommands = mkOption { type = types.listOf types.str; - default = [ "systemctl --user start sway-session.target" ]; + default = [ + "systemctl --user reset-failed" + "systemctl --user start sway-session.target" + "swaymsg -mt subscribe '[]' || true" + "systemctl --user stop sway-session.target" + ]; description = '' Extra commands to run after D-Bus activation. ''; diff --git a/modules/services/window-managers/i3-sway/swaynag.nix b/modules/services/window-managers/i3-sway/swaynag.nix index fcdedd3d8..924521f77 100644 --- a/modules/services/window-managers/i3-sway/swaynag.nix +++ b/modules/services/window-managers/i3-sway/swaynag.nix @@ -14,7 +14,7 @@ let }; in attrsOf confAtom; in { - meta.maintainers = with maintainers; [ polykernel ]; + meta.maintainers = [ ]; options = { wayland.windowManager.sway.swaynag = { diff --git a/modules/systemd-activate.sh b/modules/systemd-activate.sh index 235f1a241..ca26fea8b 100644 --- a/modules/systemd-activate.sh +++ b/modules/systemd-activate.sh @@ -34,7 +34,7 @@ function systemdPostReload() { touch "$oldServiceFiles" else find "$oldUserServicePath" \ - -maxdepth 1 -name '*.service' -exec basename '{}' ';' \ + -maxdepth 1 -name '*.service' \! -name '*@.service' -exec basename '{}' ';' \ | sort \ > "$oldServiceFiles" fi @@ -43,7 +43,7 @@ function systemdPostReload() { touch "$newServiceFiles" else find "$newUserServicePath" \ - -maxdepth 1 -name '*.service' -exec basename '{}' ';' \ + -maxdepth 1 -name '*.service' \! -name '*@.service' -exec basename '{}' ';' \ | sort \ > "$newServiceFiles" fi diff --git a/modules/systemd.nix b/modules/systemd.nix index f209f65dd..707bb3294 100644 --- a/modules/systemd.nix +++ b/modules/systemd.nix @@ -100,6 +100,8 @@ let settingsFormat.generate "user.conf" cfg.settings; }; + configHome = lib.removePrefix config.home.homeDirectory config.xdg.configHome; + in { meta.maintainers = [ lib.maintainers.rycee ]; @@ -181,7 +183,7 @@ in { default = "suggest"; type = with types; either bool (enum [ "suggest" "legacy" "sd-switch" ]); - apply = p: if isBool p then if p then "legacy" else "suggest" else p; + apply = p: if isBool p then if p then "sd-switch" else "suggest" else p; description = '' Whether new or changed services that are wanted by active targets should be started. Additionally, stop obsolete services from the @@ -194,17 +196,15 @@ in { {command}`systemctl` commands to run. You will have to manually run those commands after the switch. - `legacy` (or `true`) + `legacy` : Use a Ruby script to, in a more robust fashion, determine the necessary changes and automatically run the - {command}`systemctl` commands. + {command}`systemctl` commands. Note, this alternative will soon + be removed. - `sd-switch` - : Use sd-switch, a third party application, to perform the service - updates. This tool offers more features while having a small - closure size. Note, it requires a fully functional user D-Bus - session. Once tested and deemed sufficiently robust, this will - become the default. + `sd-switch` (or `true`) + : Use sd-switch, a tool that determines the necessary changes and + automatically apply them. ''; }; @@ -297,6 +297,12 @@ in { message = "This module is only available on Linux."; }]; + warnings = lib.optional (cfg.startServices == "legacy") '' + Having 'systemd.user.startServices = "legacy"' is deprecated and will soon be removed. + + Please change to 'systemd.user.startServices = true' to use the new systemd unit switcher (sd-switch). + ''; + xdg.configFile = mkMerge [ (lib.listToAttrs ((buildServices "service" cfg.services) ++ (buildServices "slice" cfg.slices) @@ -335,8 +341,8 @@ in { in '' ${pkgs.sd-switch}/bin/sd-switch \ ''${DRY_RUN:+--dry-run} $VERBOSE_ARG ${timeoutArg} \ - ''${oldGenPath:+--old-units $oldGenPath/home-files/.config/systemd/user} \ - --new-units $newGenPath/home-files/.config/systemd/user + ''${oldUnitsDir:+--old-units $oldUnitsDir} \ + --new-units "$newUnitsDir" ''; }; @@ -354,8 +360,22 @@ in { warnEcho "Attempting to reload services anyway..." fi + if [[ -v oldGenPath ]]; then + oldUnitsDir="$oldGenPath/home-files${configHome}/systemd/user" + if [[ ! -e $oldUnitsDir ]]; then + oldUnitsDir= + fi + fi + + newUnitsDir="$newGenPath/home-files${configHome}/systemd/user" + if [[ ! -e $newUnitsDir ]]; then + newUnitsDir=${pkgs.emptyDirectory} + fi + ${ensureRuntimeDir} \ ${getAttr cfg.startServices cmd} + + unset newUnitsDir oldUnitsDir else echo "User systemd daemon not running. Skipping reload." fi diff --git a/tests/default.nix b/tests/default.nix index 4d8d49d45..1c143716f 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -189,7 +189,7 @@ in import nmtSrc { ./modules/programs/bemenu ./modules/programs/borgmatic ./modules/programs/boxxy - ./modules/programs/firefox + ./modules/programs/firefox/firefox.nix ./modules/programs/foot ./modules/programs/freetube ./modules/programs/fuzzel @@ -224,6 +224,7 @@ in import nmtSrc { ./modules/services/activitywatch ./modules/services/avizo ./modules/services/barrier + ./modules/services/blanket ./modules/services/borgmatic ./modules/services/cachix-agent ./modules/services/cliphist @@ -240,6 +241,7 @@ in import nmtSrc { ./modules/services/fnott ./modules/services/fusuma ./modules/services/git-sync + ./modules/services/glance ./modules/services/gpg-agent ./modules/services/gromit-mpx ./modules/services/home-manager-auto-upgrade diff --git a/tests/integration/nixos/basics.nix b/tests/integration/nixos/basics.nix index 001623ca5..e2bff229f 100644 --- a/tests/integration/nixos/basics.nix +++ b/tests/integration/nixos/basics.nix @@ -7,6 +7,8 @@ nodes.machine = { ... }: { imports = [ ../../../nixos ]; # Import the HM NixOS module. + virtualisation.memorySize = 2048; + users.users.alice = { isNormalUser = true; description = "Alice Foobar"; @@ -31,7 +33,7 @@ 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") + machine.wait_until_tty_matches("1", "alice\\@machine") def logout_alice(): machine.send_chars("exit\n") diff --git a/tests/integration/standalone/flake-basics.nix b/tests/integration/standalone/flake-basics.nix index 8f9627d9f..d79974b4b 100644 --- a/tests/integration/standalone/flake-basics.nix +++ b/tests/integration/standalone/flake-basics.nix @@ -6,7 +6,7 @@ nodes.machine = { ... }: { imports = [ "${pkgs.path}/nixos/modules/installer/cd-dvd/channel.nix" ]; - virtualisation.memorySize = 2048; + virtualisation.memorySize = 3072; nix = { registry.home-manager.to = { type = "path"; @@ -32,7 +32,7 @@ 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") + machine.wait_until_tty_matches("1", "alice\\@machine") def logout_alice(): machine.send_chars("exit\n") @@ -88,7 +88,7 @@ } /home/alice/.config/home-manager/home.nix") actual = succeed_as_alice("home-manager switch") - expected = "Started pueued.service - active" + expected = "Starting units: pueued.service" assert expected in actual, \ f"expected home-manager switch to contain {expected}, but got {actual}" diff --git a/tests/integration/standalone/standard-basics.nix b/tests/integration/standalone/standard-basics.nix index d4cac249a..a3efb0411 100644 --- a/tests/integration/standalone/standard-basics.nix +++ b/tests/integration/standalone/standard-basics.nix @@ -27,7 +27,7 @@ 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") + machine.wait_until_tty_matches("1", "alice\\@machine") def logout_alice(): machine.send_chars("exit\n") @@ -85,7 +85,7 @@ } /home/alice/.config/home-manager/home.nix") actual = succeed_as_alice("home-manager switch") - expected = "Started pueued.service - active" + expected = "Starting units: pueued.service" assert expected in actual, \ f"expected home-manager switch to contain {expected}, but got {actual}" diff --git a/tests/modules/i18n/input-method/fcitx5-stubs.nix b/tests/modules/i18n/input-method/fcitx5-stubs.nix index 2390ddde8..9712a7518 100644 --- a/tests/modules/i18n/input-method/fcitx5-stubs.nix +++ b/tests/modules/i18n/input-method/fcitx5-stubs.nix @@ -4,11 +4,15 @@ version = "0"; outPath = null; buildScript = '' - mkdir -p $out/bin $out/share/applications $out/etc/xdg/autostart + mkdir -p $out/bin $out/share/applications $out/share/dbus-1/services $out/etc/xdg/autostart touch $out/bin/fcitx5 \ $out/bin/fcitx5-config-qt \ $out/share/applications/org.fcitx.Fcitx5.desktop \ + $out/share/dbus-1/services/org.fcitx.Fcitx5.service \ $out/etc/xdg/autostart/org.fcitx.Fcitx5.desktop + # The grep usage of fcitx5-with-addons expects one of the files to match with the fcitx5.out + # https://github.com/NixOS/nixpkgs/blob/d2eb4be48705289791428c07aca8ff654c1422ba/pkgs/tools/inputmethods/fcitx5/with-addons.nix#L40-L44 + echo $out >> $out/etc/xdg/autostart/org.fcitx.Fcitx5.desktop chmod +x $out/bin/fcitx5 \ $out/bin/fcitx5-config-qt ''; diff --git a/tests/modules/misc/nix/default.nix b/tests/modules/misc/nix/default.nix index b0370c2e4..4c8822bf2 100644 --- a/tests/modules/misc/nix/default.nix +++ b/tests/modules/misc/nix/default.nix @@ -2,4 +2,7 @@ nix-empty-settings = ./empty-settings.nix; nix-example-settings = ./example-settings.nix; nix-example-registry = ./example-registry.nix; + nix-keep-old-nix-path = ./keep-old-nix-path.nix; + nix-example-channels = ./example-channels.nix; + nix-example-channels-xdg = ./example-channels-xdg.nix; } diff --git a/tests/modules/misc/nix/empty-settings.nix b/tests/modules/misc/nix/empty-settings.nix index 18f1ab430..7e5844742 100644 --- a/tests/modules/misc/nix/empty-settings.nix +++ b/tests/modules/misc/nix/empty-settings.nix @@ -8,6 +8,7 @@ with lib; nmt.script = '' assertPathNotExists home-files/.config/nix + assertPathNotExists home-files/.nix-defexpr/50-home-manager ''; }; } diff --git a/tests/modules/misc/nix/example-channels-xdg.nix b/tests/modules/misc/nix/example-channels-xdg.nix new file mode 100644 index 000000000..8ca1569f3 --- /dev/null +++ b/tests/modules/misc/nix/example-channels-xdg.nix @@ -0,0 +1,29 @@ +{ lib, config, pkgs, ... }: + +let + exampleChannel = pkgs.writeTextDir "default.nix" '' + { pkgs ? import { } }: + + { + example = pkgs.emptyDirectory; + } + ''; +in { + config = { + nix = { + package = config.lib.test.mkStubPackage { + version = lib.getVersion pkgs.nixVersions.stable; + }; + channels.example = exampleChannel; + settings.use-xdg-base-directories = true; + }; + + nmt.script = '' + assertFileContains home-path/etc/profile.d/hm-session-vars.sh \ + 'export NIX_PATH="/home/hm-user/.local/state/nix/defexpr/50-home-manager''${NIX_PATH:+:$NIX_PATH}"' + assertFileContent \ + home-files/.local/state/nix/defexpr/50-home-manager/example/default.nix \ + ${exampleChannel}/default.nix + ''; + }; +} diff --git a/tests/modules/misc/nix/example-channels.nix b/tests/modules/misc/nix/example-channels.nix new file mode 100644 index 000000000..4b98c55d4 --- /dev/null +++ b/tests/modules/misc/nix/example-channels.nix @@ -0,0 +1,26 @@ +{ config, pkgs, ... }: + +let + exampleChannel = pkgs.writeTextDir "default.nix" '' + { pkgs ? import { } }: + + { + example = pkgs.emptyDirectory; + } + ''; +in { + config = { + nix = { + package = config.lib.test.mkStubPackage { }; + channels.example = exampleChannel; + }; + + nmt.script = '' + assertFileContains home-path/etc/profile.d/hm-session-vars.sh \ + 'export NIX_PATH="/home/hm-user/.nix-defexpr/50-home-manager''${NIX_PATH:+:$NIX_PATH}"' + assertFileContent \ + home-files/.nix-defexpr/50-home-manager/example/default.nix \ + ${exampleChannel}/default.nix + ''; + }; +} diff --git a/tests/modules/misc/nix/example-settings.nix b/tests/modules/misc/nix/example-settings.nix index 6cbcd9dfa..df62fe8d1 100644 --- a/tests/modules/misc/nix/example-settings.nix +++ b/tests/modules/misc/nix/example-settings.nix @@ -17,6 +17,8 @@ with lib; ''; }; + nixPath = [ "/a" "/b/c" ]; + settings = { use-sandbox = true; show-trace = true; @@ -28,6 +30,9 @@ with lib; assertFileContent \ home-files/.config/nix/nix.conf \ ${./example-settings-expected.conf} + + assertFileContains home-path/etc/profile.d/hm-session-vars.sh \ + 'export NIX_PATH="/a:/b/c''${NIX_PATH:+:$NIX_PATH}"' ''; }; } diff --git a/tests/modules/misc/nix/keep-old-nix-path.nix b/tests/modules/misc/nix/keep-old-nix-path.nix new file mode 100644 index 000000000..72bd9f164 --- /dev/null +++ b/tests/modules/misc/nix/keep-old-nix-path.nix @@ -0,0 +1,16 @@ +{ config, ... }: + +{ + config = { + nix = { + package = config.lib.test.mkStubPackage { }; + nixPath = [ "/a" "/b/c" ]; + keepOldNixPath = false; + }; + + nmt.script = '' + assertFileContains home-path/etc/profile.d/hm-session-vars.sh \ + 'export NIX_PATH="/a:/b/c"' + ''; + }; +} 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/programs/atuin/bash.nix b/tests/modules/programs/atuin/bash.nix index a84ea99e3..21d306b2f 100644 --- a/tests/modules/programs/atuin/bash.nix +++ b/tests/modules/programs/atuin/bash.nix @@ -10,7 +10,7 @@ }; test.stubs = { - atuin = { }; + atuin = { name = "atuin"; }; bash-preexec = { }; }; diff --git a/tests/modules/programs/atuin/empty-settings.nix b/tests/modules/programs/atuin/empty-settings.nix index 58f126965..be6b55986 100644 --- a/tests/modules/programs/atuin/empty-settings.nix +++ b/tests/modules/programs/atuin/empty-settings.nix @@ -4,7 +4,7 @@ programs.atuin.enable = true; test.stubs = { - atuin = { }; + atuin = { name = "atuin"; }; bash-preexec = { }; }; diff --git a/tests/modules/programs/atuin/example-settings.nix b/tests/modules/programs/atuin/example-settings.nix index f2d3a8876..98aca707d 100644 --- a/tests/modules/programs/atuin/example-settings.nix +++ b/tests/modules/programs/atuin/example-settings.nix @@ -13,7 +13,7 @@ }; test.stubs = { - atuin = { }; + atuin = { name = "atuin"; }; bash-preexec = { }; }; diff --git a/tests/modules/programs/atuin/fish.nix b/tests/modules/programs/atuin/fish.nix index ae3122cf1..49d9a2821 100644 --- a/tests/modules/programs/atuin/fish.nix +++ b/tests/modules/programs/atuin/fish.nix @@ -11,7 +11,7 @@ lib.mkForce (builtins.toFile "empty" ""); test.stubs = { - atuin = { }; + atuin = { name = "atuin"; }; bash-preexec = { }; }; diff --git a/tests/modules/programs/atuin/no-shell.nix b/tests/modules/programs/atuin/no-shell.nix index 381bcc0ca..c6481e427 100644 --- a/tests/modules/programs/atuin/no-shell.nix +++ b/tests/modules/programs/atuin/no-shell.nix @@ -18,7 +18,7 @@ lib.mkForce (builtins.toFile "empty" ""); test.stubs = { - atuin = { }; + atuin = { name = "atuin"; }; bash-preexec = { }; }; diff --git a/tests/modules/programs/atuin/set-flags.nix b/tests/modules/programs/atuin/set-flags.nix index 7e3a7982f..b6e8330d1 100644 --- a/tests/modules/programs/atuin/set-flags.nix +++ b/tests/modules/programs/atuin/set-flags.nix @@ -17,7 +17,7 @@ lib.mkForce (builtins.toFile "empty" ""); test.stubs = { - atuin = { }; + atuin = { name = "atuin"; }; bash-preexec = { }; }; diff --git a/tests/modules/programs/atuin/zsh.nix b/tests/modules/programs/atuin/zsh.nix index 14adddcac..2cb4fefef 100644 --- a/tests/modules/programs/atuin/zsh.nix +++ b/tests/modules/programs/atuin/zsh.nix @@ -7,7 +7,7 @@ }; test.stubs = { - atuin = { }; + atuin = { name = "atuin"; }; bash-preexec = { }; }; diff --git a/tests/modules/programs/firefox/container-id-out-of-range.nix b/tests/modules/programs/firefox/container-id-out-of-range.nix index 5dbeaedda..2ea08e880 100644 --- a/tests/modules/programs/firefox/container-id-out-of-range.nix +++ b/tests/modules/programs/firefox/container-id-out-of-range.nix @@ -1,27 +1,32 @@ +modulePath: { config, lib, ... }: -{ - imports = [ ./setup-firefox-mock-overlay.nix ]; +with lib; - config = lib.mkIf config.test.enableBig { +let + + firefoxMockOverlay = import ./setup-firefox-mock-overlay.nix modulePath; + +in { + imports = [ firefoxMockOverlay ]; + + config = mkIf config.test.enableBig ({ test.asserts.assertions.expected = [ "Container id must be smaller than 4294967294 (2^32 - 2)" ]; + } // setAttrByPath modulePath { + enable = true; - programs.firefox = { - enable = true; + profiles.my-profile = { + isDefault = true; + id = 1; - profiles.my-profile = { - isDefault = true; - id = 1; - - containers = { - "shopping" = { - id = 4294967294; - color = "blue"; - icon = "circle"; - }; + containers = { + "shopping" = { + id = 4294967294; + color = "blue"; + icon = "circle"; }; }; }; - }; + }); } diff --git a/tests/modules/programs/firefox/default.nix b/tests/modules/programs/firefox/default.nix deleted file mode 100644 index 1cd462f2e..000000000 --- a/tests/modules/programs/firefox/default.nix +++ /dev/null @@ -1,9 +0,0 @@ -{ - firefox-profile-settings = ./profile-settings.nix; - firefox-state-version-19_09 = ./state-version-19_09.nix; - firefox-deprecated-native-messenger = ./deprecated-native-messenger.nix; - firefox-duplicate-profile-ids = ./duplicate-profile-ids.nix; - firefox-duplicate-container-ids = ./duplicate-container-ids.nix; - firefox-container-id-out-of-range = ./container-id-out-of-range.nix; - firefox-policies = ./policies.nix; -} diff --git a/tests/modules/programs/firefox/deprecated-native-messenger.nix b/tests/modules/programs/firefox/deprecated-native-messenger.nix index db70d405b..87423aba3 100644 --- a/tests/modules/programs/firefox/deprecated-native-messenger.nix +++ b/tests/modules/programs/firefox/deprecated-native-messenger.nix @@ -1,21 +1,26 @@ -{ config, lib, pkgs, ... }: +modulePath: +{ config, lib, ... }: with lib; -{ - imports = [ ./setup-firefox-mock-overlay.nix ]; +let - config = lib.mkIf config.test.enableBig { - programs.firefox = { - enable = true; - enableGnomeExtensions = true; - }; + moduleName = concatStringsSep "." modulePath; + firefoxMockOverlay = import ./setup-firefox-mock-overlay.nix modulePath; + +in { + imports = [ firefoxMockOverlay ]; + + config = mkIf config.test.enableBig (setAttrByPath modulePath { + enable = true; + enableGnomeExtensions = true; + } // { test.asserts.warnings.expected = ['' - Using 'programs.firefox.enableGnomeExtensions' has been deprecated and + Using '${moduleName}.enableGnomeExtensions' has been deprecated and will be removed in the future. Please change to overriding the package - configuration using 'programs.firefox.package' instead. You can refer to + configuration using '${moduleName}.package' instead. You can refer to its example for how to do this. '']; - }; + }); } diff --git a/tests/modules/programs/firefox/duplicate-container-ids.nix b/tests/modules/programs/firefox/duplicate-container-ids.nix index fce91fa02..2ad99b4b7 100644 --- a/tests/modules/programs/firefox/duplicate-container-ids.nix +++ b/tests/modules/programs/firefox/duplicate-container-ids.nix @@ -1,35 +1,42 @@ +modulePath: { config, lib, ... }: -{ - imports = [ ./setup-firefox-mock-overlay.nix ]; +with lib; - config = lib.mkIf config.test.enableBig { +let + + cfg = getAttrFromPath modulePath config; + + firefoxMockOverlay = import ./setup-firefox-mock-overlay.nix modulePath; + +in { + imports = [ firefoxMockOverlay ]; + + config = mkIf config.test.enableBig ({ test.asserts.assertions.expected = ['' - Must not have a Firefox container with an existing ID but + Must not have a ${cfg.name} container with an existing ID but - ID 9 is used by dangerous, shopping'']; + } // setAttrByPath modulePath { + enable = true; - programs.firefox = { - enable = true; + profiles = { + my-profile = { + isDefault = true; + id = 1; - profiles = { - my-profile = { - isDefault = true; - id = 1; - - containers = { - "shopping" = { - id = 9; - color = "blue"; - icon = "circle"; - }; - "dangerous" = { - id = 9; - color = "red"; - icon = "circle"; - }; + containers = { + "shopping" = { + id = 9; + color = "blue"; + icon = "circle"; + }; + "dangerous" = { + id = 9; + color = "red"; + icon = "circle"; }; }; }; }; - }; + }); } diff --git a/tests/modules/programs/firefox/duplicate-profile-ids.nix b/tests/modules/programs/firefox/duplicate-profile-ids.nix index 9b0b7c060..ad946af10 100644 --- a/tests/modules/programs/firefox/duplicate-profile-ids.nix +++ b/tests/modules/programs/firefox/duplicate-profile-ids.nix @@ -1,23 +1,30 @@ +modulePath: { config, lib, ... }: -{ - imports = [ ./setup-firefox-mock-overlay.nix ]; +with lib; - config = lib.mkIf config.test.enableBig { +let + + cfg = getAttrFromPath modulePath config; + + firefoxMockOverlay = import ./setup-firefox-mock-overlay.nix modulePath; + +in { + imports = [ firefoxMockOverlay ]; + + config = mkIf config.test.enableBig ({ test.asserts.assertions.expected = ['' - Must not have a Firefox profile with an existing ID but + Must not have a ${cfg.name} profile with an existing ID but - ID 1 is used by first, second'']; + } // setAttrByPath modulePath { + enable = true; - programs.firefox = { - enable = true; - - profiles = { - first = { - isDefault = true; - id = 1; - }; - second = { id = 1; }; + profiles = { + first = { + isDefault = true; + id = 1; }; + second = { id = 1; }; }; - }; + }); } diff --git a/tests/modules/programs/firefox/firefox.nix b/tests/modules/programs/firefox/firefox.nix new file mode 100644 index 000000000..6598d6ec2 --- /dev/null +++ b/tests/modules/programs/firefox/firefox.nix @@ -0,0 +1,11 @@ +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; +} diff --git a/tests/modules/programs/firefox/policies.nix b/tests/modules/programs/firefox/policies.nix index 7b503d3d8..5e02a1916 100644 --- a/tests/modules/programs/firefox/policies.nix +++ b/tests/modules/programs/firefox/policies.nix @@ -1,22 +1,29 @@ +modulePath: { config, lib, pkgs, ... }: -{ - imports = [ ./setup-firefox-mock-overlay.nix ]; +with lib; - config = lib.mkIf config.test.enableBig { +let + + cfg = getAttrFromPath modulePath config; + + firefoxMockOverlay = import ./setup-firefox-mock-overlay.nix modulePath; + +in { + imports = [ firefoxMockOverlay ]; + + config = mkIf config.test.enableBig ({ home.stateVersion = "23.05"; - - programs.firefox = { - enable = true; - policies = { BlockAboutConfig = true; }; - package = pkgs.firefox.override { - extraPolicies = { DownloadDirectory = "/foo"; }; - }; + } // setAttrByPath modulePath { + enable = true; + policies = { BlockAboutConfig = true; }; + package = pkgs.${cfg.wrappedPackageName}.override { + extraPolicies = { DownloadDirectory = "/foo"; }; }; - + }) // { nmt.script = '' jq=${lib.getExe pkgs.jq} - config_file="${config.programs.firefox.finalPackage}/lib/firefox/distribution/policies.json" + config_file="${cfg.finalPackage}/lib/${cfg.wrappedPackageName}/distribution/policies.json" assertFileExists "$config_file" diff --git a/tests/modules/programs/firefox/profile-settings.nix b/tests/modules/programs/firefox/profile-settings.nix index 8b781552b..d7776eb4f 100644 --- a/tests/modules/programs/firefox/profile-settings.nix +++ b/tests/modules/programs/firefox/profile-settings.nix @@ -1,177 +1,184 @@ +modulePath: { config, lib, pkgs, ... }: -{ - imports = [ ./setup-firefox-mock-overlay.nix ]; +with lib; - config = lib.mkIf config.test.enableBig { - programs.firefox = { - enable = true; - profiles.basic.isDefault = true; +let - profiles.test = { - id = 1; - settings = { - "general.smoothScroll" = false; - "browser.newtabpage.pinned" = [{ - title = "NixOS"; - url = "https://nixos.org"; + 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; + + profiles.test = { + id = 1; + settings = { + "general.smoothScroll" = false; + "browser.newtabpage.pinned" = [{ + title = "NixOS"; + url = "https://nixos.org"; + }]; + }; + }; + + profiles.bookmarks = { + id = 2; + 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/"; + } + ]; + } + ]; + } + ]; + }; - profiles.bookmarks = { - id = 2; - settings = { "general.smoothScroll" = false; }; - bookmarks = [ - { - toolbar = true; - bookmarks = [{ - name = "Home Manager"; - url = "https://wiki.nixos.org/wiki/Home_Manager"; + profiles.search = { + id = 3; + 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}"; + } + ]; }]; - } - { - 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/"; - } - ]; - } - ]; - } - ]; - }; - profiles.search = { - id = 3; - 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"; - 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"; + 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"; }; }; + }; - profiles.searchWithoutDefault = { - id = 4; - 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}"; - } - ]; - }]; + profiles.searchWithoutDefault = { + id = 4; + 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" ]; - }; - }; - }; - }; - - profiles.containers = { - id = 5; - containers = { - "shopping" = { - id = 6; - icon = "circle"; - color = "yellow"; + definedAliases = [ "@np" ]; }; }; }; }; + profiles.containers = { + id = 5; + containers = { + "shopping" = { + id = 6; + icon = "circle"; + color = "yellow"; + }; + }; + }; + } // { + nmt.script = '' assertFileRegex \ - home-path/bin/firefox \ + home-path/bin/${cfg.wrappedPackageName} \ MOZ_APP_LAUNCHER - assertDirectoryExists home-files/.mozilla/firefox/basic + assertDirectoryExists home-files/${cfg.configPath}/basic assertFileContent \ - home-files/.mozilla/firefox/test/user.js \ + home-files/${cfg.configPath}/test/user.js \ ${./profile-settings-expected-user.js} assertFileContent \ - home-files/.mozilla/firefox/containers/containers.json \ + home-files/${cfg.configPath}/containers/containers.json \ ${./profile-settings-expected-containers.json} bookmarksUserJs=$(normalizeStorePaths \ - home-files/.mozilla/firefox/bookmarks/user.js) + home-files/${cfg.configPath}/bookmarks/user.js) assertFileContent \ $bookmarksUserJs \ @@ -179,7 +186,7 @@ bookmarksFile="$(sed -n \ '/browser.bookmarks.file/ {s|^.*\(/nix/store[^"]*\).*|\1|;p}' \ - $TESTED/home-files/.mozilla/firefox/bookmarks/user.js)" + $TESTED/home-files/${cfg.configPath}/bookmarks/user.js)" assertFileContent \ $bookmarksFile \ @@ -197,12 +204,12 @@ } assertFirefoxSearchContent \ - home-files/.mozilla/firefox/search/search.json.mozlz4 \ + home-files/${cfg.configPath}/search/search.json.mozlz4 \ ${./profile-settings-expected-search.json} assertFirefoxSearchContent \ - home-files/.mozilla/firefox/searchWithoutDefault/search.json.mozlz4 \ + home-files/${cfg.configPath}/searchWithoutDefault/search.json.mozlz4 \ ${./profile-settings-expected-search-without-default.json} ''; - }; + }); } diff --git a/tests/modules/programs/firefox/setup-firefox-mock-overlay.nix b/tests/modules/programs/firefox/setup-firefox-mock-overlay.nix index 0f0d182a4..ecbd492fa 100644 --- a/tests/modules/programs/firefox/setup-firefox-mock-overlay.nix +++ b/tests/modules/programs/firefox/setup-firefox-mock-overlay.nix @@ -1,16 +1,24 @@ -{ pkgs, ... }: +modulePath: +{ config, lib, pkgs, ... }: -{ +with lib; + +let + + cfg = getAttrFromPath modulePath config; + +in { nixpkgs.overlays = [ (self: super: { - firefox-unwrapped = pkgs.runCommandLocal "firefox-0" { - meta.description = "I pretend to be Firefox"; - passthru.gtk3 = null; - } '' - mkdir -p "$out"/{bin,lib} - touch "$out/bin/firefox" - chmod 755 "$out/bin/firefox" - ''; + "${cfg.wrappedPackageName}-unwrapped" = + pkgs.runCommandLocal "${cfg.wrappedPackageName}-0" { + meta.description = "I pretend to be ${cfg.name}"; + passthru.gtk3 = null; + } '' + mkdir -p "$out"/{bin,lib} + touch "$out/bin/${cfg.wrappedPackageName}" + chmod 755 "$out/bin/${cfg.wrappedPackageName}" + ''; chrome-gnome-shell = pkgs.runCommandLocal "dummy-chrome-gnome-shell" { } '' diff --git a/tests/modules/programs/firefox/state-version-19_09.nix b/tests/modules/programs/firefox/state-version-19_09.nix index c4c75970e..475705c31 100644 --- a/tests/modules/programs/firefox/state-version-19_09.nix +++ b/tests/modules/programs/firefox/state-version-19_09.nix @@ -1,19 +1,24 @@ +modulePath: { config, lib, pkgs, ... }: with lib; -{ - imports = [ ./setup-firefox-mock-overlay.nix ]; +let - config = lib.mkIf config.test.enableBig { + cfg = getAttrFromPath modulePath config; + + firefoxMockOverlay = import ./setup-firefox-mock-overlay.nix modulePath; + +in { + imports = [ firefoxMockOverlay ]; + + config = lib.mkIf config.test.enableBig ({ home.stateVersion = "19.09"; - - programs.firefox.enable = true; - + } // setAttrByPath modulePath { enable = true; } // { nmt.script = '' assertFileRegex \ - home-path/bin/firefox \ + home-path/bin/${cfg.wrappedPackageName} \ MOZ_APP_LAUNCHER ''; - }; + }); } diff --git a/tests/modules/programs/gnome-terminal/bad-profile-name.nix b/tests/modules/programs/gnome-terminal/bad-profile-name.nix index ebd854406..308b9306e 100644 --- a/tests/modules/programs/gnome-terminal/bad-profile-name.nix +++ b/tests/modules/programs/gnome-terminal/bad-profile-name.nix @@ -13,9 +13,8 @@ }; }; - nixpkgs.overlays = [ - (self: super: { gnome.gnome-terminal = config.lib.test.mkStubPackage { }; }) - ]; + nixpkgs.overlays = + [ (self: super: { gnome-terminal = config.lib.test.mkStubPackage { }; }) ]; test.stubs.dconf = { }; diff --git a/tests/modules/programs/gnome-terminal/gnome-terminal-1.nix b/tests/modules/programs/gnome-terminal/gnome-terminal-1.nix index bb58983fe..6dab6a2b4 100644 --- a/tests/modules/programs/gnome-terminal/gnome-terminal-1.nix +++ b/tests/modules/programs/gnome-terminal/gnome-terminal-1.nix @@ -49,9 +49,7 @@ with lib; }; nixpkgs.overlays = [ - (self: super: { - gnome.gnome-terminal = config.lib.test.mkStubPackage { }; - }) + (self: super: { gnome-terminal = config.lib.test.mkStubPackage { }; }) ]; test.stubs.dconf = { }; diff --git a/tests/modules/programs/jujutsu/empty-config.nix b/tests/modules/programs/jujutsu/empty-config.nix index 10dd12589..55b5d87e8 100644 --- a/tests/modules/programs/jujutsu/empty-config.nix +++ b/tests/modules/programs/jujutsu/empty-config.nix @@ -1,11 +1,14 @@ -{ ... }: +{ pkgs, ... }: -{ +let + configDir = + if pkgs.stdenv.isDarwin then "Library/Application Support" else ".config"; +in { programs.jujutsu.enable = true; test.stubs.jujutsu = { }; nmt.script = '' - assertPathNotExists home-files/.config/jj/config.toml + assertPathNotExists 'home-files/${configDir}/jj/config.toml' ''; } diff --git a/tests/modules/programs/jujutsu/example-config.nix b/tests/modules/programs/jujutsu/example-config.nix index d83b552b2..029187786 100644 --- a/tests/modules/programs/jujutsu/example-config.nix +++ b/tests/modules/programs/jujutsu/example-config.nix @@ -1,6 +1,9 @@ -{ config, ... }: +{ pkgs, config, ... }: -{ +let + configDir = + if pkgs.stdenv.isDarwin then "Library/Application Support" else ".config"; +in { programs.jujutsu = { enable = true; package = config.lib.test.mkStubPackage { }; @@ -13,9 +16,8 @@ }; nmt.script = '' - assertFileExists home-files/.config/jj/config.toml - assertFileContent \ - home-files/.config/jj/config.toml \ + assertFileExists 'home-files/${configDir}/jj/config.toml' + assertFileContent 'home-files/${configDir}/jj/config.toml' \ ${ builtins.toFile "expected.toml" '' [user] diff --git a/tests/modules/programs/khard/default.nix b/tests/modules/programs/khard/default.nix index 3762dc0f1..58b7a6f74 100644 --- a/tests/modules/programs/khard/default.nix +++ b/tests/modules/programs/khard/default.nix @@ -2,4 +2,5 @@ khard_empty_config = ./empty_config.nix; khard_basic_config = ./basic_config.nix; khard_multiple_accounts = ./multiple_accounts.nix; + khard_dirty_path = ./dirty_path.nix; } diff --git a/tests/modules/programs/khard/dirty_path.nix b/tests/modules/programs/khard/dirty_path.nix new file mode 100644 index 000000000..07396a144 --- /dev/null +++ b/tests/modules/programs/khard/dirty_path.nix @@ -0,0 +1,22 @@ +{ + accounts.contact = { + basePath = "/home/user/who/likes///"; + accounts.forward = { + local.type = "filesystem"; + khard = { + enable = true; + defaultCollection = "////slashes//a/lot"; + }; + }; + }; + + programs.khard.enable = true; + + test.stubs.khard = { }; + + nmt.script = '' + assertFileContent \ + home-files/.config/khard/khard.conf \ + ${./dirty_path_expected} + ''; +} diff --git a/tests/modules/programs/khard/dirty_path_expected b/tests/modules/programs/khard/dirty_path_expected new file mode 100644 index 000000000..8b7bb63eb --- /dev/null +++ b/tests/modules/programs/khard/dirty_path_expected @@ -0,0 +1,8 @@ +[addressbooks] +[[forward]] +path = /home/user/who/likes/forward/slashes/a/lot + + +[general] +default_action=list + 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/waybar/deprecated-modules-option.nix b/tests/modules/programs/waybar/deprecated-modules-option.nix index b4d730afc..09f163b0f 100644 --- a/tests/modules/programs/waybar/deprecated-modules-option.nix +++ b/tests/modules/programs/waybar/deprecated-modules-option.nix @@ -31,8 +31,6 @@ with lib; "modules-center": [ "test" ], - "modules-left": [], - "modules-right": [], "test": {} } ] diff --git a/tests/modules/programs/waybar/settings-complex-expected.json b/tests/modules/programs/waybar/settings-complex-expected.json index 87e4f690d..e7ec8b4a3 100644 --- a/tests/modules/programs/waybar/settings-complex-expected.json +++ b/tests/modules/programs/waybar/settings-complex-expected.json @@ -51,7 +51,6 @@ "modules-left": [ "sway/mode" ], - "modules-right": [], "output": [ "!DP-1" ], diff --git a/tests/modules/programs/yazi/bash-integration-enabled.nix b/tests/modules/programs/yazi/bash-integration-enabled.nix index ac2e49796..474a989f9 100644 --- a/tests/modules/programs/yazi/bash-integration-enabled.nix +++ b/tests/modules/programs/yazi/bash-integration-enabled.nix @@ -2,7 +2,7 @@ let shellIntegration = '' - function ya() { + function yy() { local tmp="$(mktemp -t "yazi-cwd.XXXXX")" yazi "$@" --cwd-file="$tmp" if cwd="$(cat -- "$tmp")" && [ -n "$cwd" ] && [ "$cwd" != "$PWD" ]; then diff --git a/tests/modules/programs/yazi/default.nix b/tests/modules/programs/yazi/default.nix index 09d52ac3d..ec543c84d 100644 --- a/tests/modules/programs/yazi/default.nix +++ b/tests/modules/programs/yazi/default.nix @@ -1,5 +1,6 @@ { yazi-settings = ./settings.nix; + yazi-init-lua-string = ./init-lua-string.nix; yazi-bash-integration-enabled = ./bash-integration-enabled.nix; yazi-zsh-integration-enabled = ./zsh-integration-enabled.nix; yazi-fish-integration-enabled = ./fish-integration-enabled.nix; diff --git a/tests/modules/programs/yazi/empty/.gitkeep b/tests/modules/programs/yazi/empty/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/tests/modules/programs/yazi/fish-integration-enabled.nix b/tests/modules/programs/yazi/fish-integration-enabled.nix index 6d2b9fa31..2231035b9 100644 --- a/tests/modules/programs/yazi/fish-integration-enabled.nix +++ b/tests/modules/programs/yazi/fish-integration-enabled.nix @@ -2,7 +2,7 @@ let shellIntegration = '' - function ya + function yy set tmp (mktemp -t "yazi-cwd.XXXXX") yazi $argv --cwd-file="$tmp" if set cwd (cat -- "$tmp"); and [ -n "$cwd" ]; and [ "$cwd" != "$PWD" ] diff --git a/tests/modules/programs/yazi/flavor/LICENSE b/tests/modules/programs/yazi/flavor/LICENSE new file mode 100644 index 000000000..e69de29bb diff --git a/tests/modules/programs/yazi/flavor/LICENSE-tmtheme b/tests/modules/programs/yazi/flavor/LICENSE-tmtheme new file mode 100644 index 000000000..e69de29bb diff --git a/tests/modules/programs/yazi/flavor/README.md b/tests/modules/programs/yazi/flavor/README.md new file mode 100644 index 000000000..3ba41d0db --- /dev/null +++ b/tests/modules/programs/yazi/flavor/README.md @@ -0,0 +1,50 @@ +
+ Yazi logo +
+ +

+ Example Flavor for Yazi +

+ +## Cooking up a new flavor + +> [!NOTE] +> Please remove this section from your README before publishing. + +1. [x] Fork this repository and rename it to `your-flavor-name.yazi`. +2. [ ] Copy the **parts you need to customize** from the [default theme.toml](https://github.com/sxyazi/yazi/blob/main/yazi-config/preset/theme.toml) as `./flavor.toml`, and change them to meet your preferences. +3. [ ] Find a `.tmTheme` file on GitHub that matches the color of your flavor, copy it and it's license file as `./tmtheme.xml`, and `LICENSE-tmtheme`. +4. [ ] Modify the content and preview image in the README to fit your flavor. + +## 👀 Preview + + + +## 🎨 Installation + + + +```bash +# Linux/macOS +git clone https://github.com/username/example.yazi.git ~/.config/yazi/flavors/example.yazi + +# Windows +git clone https://github.com/username/example.yazi.git %AppData%\yazi\config\flavors\example.yazi +``` + +## ⚙️ Usage + +Add the these lines to your `theme.toml` configuration file to use it: + + + +```toml +[flavor] +use = "example" +``` + +## 📜 License + +The flavor is MIT-licensed, and the included tmTheme is also MIT-licensed. + +Check the [LICENSE](LICENSE) and [LICENSE-tmtheme](LICENSE-tmtheme) file for more details. diff --git a/tests/modules/programs/yazi/flavor/flavor.toml b/tests/modules/programs/yazi/flavor/flavor.toml new file mode 100644 index 000000000..35e1fe770 --- /dev/null +++ b/tests/modules/programs/yazi/flavor/flavor.toml @@ -0,0 +1,2 @@ +# This is a flavor. + diff --git a/tests/modules/programs/yazi/flavor/init.lua b/tests/modules/programs/yazi/flavor/init.lua deleted file mode 100644 index 8d06fa7a9..000000000 --- a/tests/modules/programs/yazi/flavor/init.lua +++ /dev/null @@ -1 +0,0 @@ --- This is a flavor. diff --git a/tests/modules/programs/yazi/flavor/preview.png b/tests/modules/programs/yazi/flavor/preview.png new file mode 100644 index 000000000..e69de29bb diff --git a/tests/modules/programs/yazi/flavor/tmtheme.xml b/tests/modules/programs/yazi/flavor/tmtheme.xml new file mode 100644 index 000000000..e69de29bb diff --git a/tests/modules/programs/yazi/init-lua-string.nix b/tests/modules/programs/yazi/init-lua-string.nix new file mode 100644 index 000000000..999dd6bc6 --- /dev/null +++ b/tests/modules/programs/yazi/init-lua-string.nix @@ -0,0 +1,14 @@ +{ ... }: { + programs.yazi = { + enable = true; + + initLua = builtins.readFile ./init.lua; + }; + + test.stubs.yazi = { }; + + nmt.script = '' + assertFileContent home-files/.config/yazi/init.lua \ + ${./init.lua} + ''; +} diff --git a/tests/modules/programs/yazi/nushell-integration-enabled.nix b/tests/modules/programs/yazi/nushell-integration-enabled.nix index 9adbaa982..a2de2d8b7 100644 --- a/tests/modules/programs/yazi/nushell-integration-enabled.nix +++ b/tests/modules/programs/yazi/nushell-integration-enabled.nix @@ -2,7 +2,7 @@ let shellIntegration = '' - def --env ya [...args] { + def --env yy [...args] { let tmp = (mktemp -t "yazi-cwd.XXXXX") yazi ...$args --cwd-file $tmp let cwd = (open $tmp) diff --git a/tests/modules/programs/yazi/settings.nix b/tests/modules/programs/yazi/settings.nix index 4655ae8b3..2694dadec 100644 --- a/tests/modules/programs/yazi/settings.nix +++ b/tests/modules/programs/yazi/settings.nix @@ -70,8 +70,22 @@ }; }; initLua = ./init.lua; - plugins = { "test.yazi" = ./plugin; }; - flavors = { "test.yazi" = ./flavor; }; + plugins = { + testplugin = ./plugin; + ## Produces warning + #"plugin-with-suffix.yazi" = ./plugin; + ## Fails assertion + #single-file-plugin = ./plugin/init.lua; + #empty-dir-plugin = ./empty; + }; + flavors = { + testflavor = ./flavor; + ## Produces warning + #"flavor-with-suffix.yazi" = ./flavor; + ## Fails assertion + #single-file-flavor = ./flavor/flavor.toml; + #empty-dir-flavor = ./empty; + }; }; test.stubs.yazi = { }; @@ -85,9 +99,9 @@ ${./theme-expected.toml} assertFileContent home-files/.config/yazi/init.lua \ ${./init.lua} - assertFileContent home-files/.config/yazi/plugins/test.yazi/init.lua \ + assertFileContent home-files/.config/yazi/plugins/testplugin.yazi/init.lua \ ${./plugin/init.lua} - assertFileContent home-files/.config/yazi/flavors/test.yazi/init.lua \ - ${./flavor/init.lua} + assertFileContent home-files/.config/yazi/flavors/testflavor.yazi/flavor.toml \ + ${./flavor/flavor.toml} ''; } diff --git a/tests/modules/programs/yazi/zsh-integration-enabled.nix b/tests/modules/programs/yazi/zsh-integration-enabled.nix index d5090a6a8..0c0ec217f 100644 --- a/tests/modules/programs/yazi/zsh-integration-enabled.nix +++ b/tests/modules/programs/yazi/zsh-integration-enabled.nix @@ -2,7 +2,7 @@ let shellIntegration = '' - function ya() { + function yy() { local tmp="$(mktemp -t "yazi-cwd.XXXXX")" yazi "$@" --cwd-file="$tmp" if cwd="$(cat -- "$tmp")" && [ -n "$cwd" ] && [ "$cwd" != "$PWD" ]; then diff --git a/tests/modules/services/blanket/basic-configuration.nix b/tests/modules/services/blanket/basic-configuration.nix new file mode 100644 index 000000000..740c4d08d --- /dev/null +++ b/tests/modules/services/blanket/basic-configuration.nix @@ -0,0 +1,31 @@ +{ ... }: + +{ + services.blanket = { enable = true; }; + + test.stubs.blanket = { }; + + nmt.script = '' + clientServiceFile=home-files/.config/systemd/user/blanket.service + + assertFileExists $clientServiceFile + assertFileContent $clientServiceFile ${ + builtins.toFile "expected.service" '' + [Install] + WantedBy=graphical-session.target + + [Service] + ExecStart=@blanket@/bin/blanket --gapplication-service + Restart=on-failure + RestartSec=5 + + [Unit] + After=graphical-session-pre.target + Description=Blanket daemon + PartOf=graphical-session.target + PartOf=pipewire.service + Requires=dbus.service + '' + } + ''; +} diff --git a/tests/modules/services/blanket/default.nix b/tests/modules/services/blanket/default.nix new file mode 100644 index 000000000..8a439a52a --- /dev/null +++ b/tests/modules/services/blanket/default.nix @@ -0,0 +1 @@ +{ blanket-basic-configuration = ./basic-configuration.nix; } diff --git a/tests/modules/services/glance/default-settings.nix b/tests/modules/services/glance/default-settings.nix new file mode 100644 index 000000000..7b35db779 --- /dev/null +++ b/tests/modules/services/glance/default-settings.nix @@ -0,0 +1,15 @@ +{ ... }: + +{ + services.glance.enable = true; + + test.stubs.glance = { }; + + nmt.script = '' + configFile=home-files/.config/glance/glance.yml + serviceFile=home-files/.config/systemd/user/glance.service + + assertFileContent $configFile ${./glance-default-config.yml} + assertFileContent $serviceFile ${./glance.service} + ''; +} diff --git a/tests/modules/services/glance/default.nix b/tests/modules/services/glance/default.nix new file mode 100644 index 000000000..893ba6516 --- /dev/null +++ b/tests/modules/services/glance/default.nix @@ -0,0 +1,4 @@ +{ + glance-default-settings = ./default-settings.nix; + glance-example-settings = ./example-settings.nix; +} diff --git a/tests/modules/services/glance/example-settings.nix b/tests/modules/services/glance/example-settings.nix new file mode 100644 index 000000000..9e2101d2e --- /dev/null +++ b/tests/modules/services/glance/example-settings.nix @@ -0,0 +1,33 @@ +{ ... }: + +{ + services.glance = { + enable = true; + settings = { + server.port = 5678; + pages = [{ + name = "Home"; + columns = [{ + size = "full"; + widgets = [ + { type = "calendar"; } + { + type = "weather"; + location = "London, United Kingdom"; + } + ]; + }]; + }]; + }; + }; + + test.stubs.glance = { }; + + nmt.script = '' + configFile=home-files/.config/glance/glance.yml + serviceFile=home-files/.config/systemd/user/glance.service + + assertFileContent $configFile ${./glance-example-config.yml} + assertFileContent $serviceFile ${./glance.service} + ''; +} diff --git a/tests/modules/services/glance/glance-default-config.yml b/tests/modules/services/glance/glance-default-config.yml new file mode 100644 index 000000000..024a89649 --- /dev/null +++ b/tests/modules/services/glance/glance-default-config.yml @@ -0,0 +1,6 @@ +pages: +- columns: + - size: full + widgets: + - type: calendar + name: Calendar diff --git a/tests/modules/services/glance/glance-example-config.yml b/tests/modules/services/glance/glance-example-config.yml new file mode 100644 index 000000000..2775916ec --- /dev/null +++ b/tests/modules/services/glance/glance-example-config.yml @@ -0,0 +1,10 @@ +pages: +- columns: + - size: full + widgets: + - type: calendar + - location: London, United Kingdom + type: weather + name: Home +server: + port: 5678 diff --git a/tests/modules/services/glance/glance.service b/tests/modules/services/glance/glance.service new file mode 100644 index 000000000..07b82d1d9 --- /dev/null +++ b/tests/modules/services/glance/glance.service @@ -0,0 +1,9 @@ +[Install] +WantedBy=graphical-session.target + +[Service] +ExecStart=@glance@/bin/dummy --config /home/hm-user/.config/glance/glance.yml + +[Unit] +Description=Glance feed dashboard server +PartOf=graphical-session.target diff --git a/tests/modules/services/mpd/default.nix b/tests/modules/services/mpd/default.nix index d2fd2a292..f7919b227 100644 --- a/tests/modules/services/mpd/default.nix +++ b/tests/modules/services/mpd/default.nix @@ -1,5 +1,6 @@ { mpd-basic-configuration = ./basic-configuration.nix; mpd-before-state-version-22_11 = ./before-state-version-22_11.nix; + mpd-start-when-needed = ./start-when-needed.nix; mpd-xdg-music-dir = ./xdg-music-dir.nix; } diff --git a/tests/modules/services/mpd/start-when-needed.nix b/tests/modules/services/mpd/start-when-needed.nix new file mode 100644 index 000000000..31017c9e3 --- /dev/null +++ b/tests/modules/services/mpd/start-when-needed.nix @@ -0,0 +1,29 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + services.mpd = { + enable = true; + musicDirectory = "/my/music/dir"; + extraArgs = [ "--verbose" ]; + network.startWhenNeeded = true; + }; + + home.stateVersion = "22.11"; + + test.stubs.mpd = { }; + + nmt.script = '' + serviceFile=$(normalizeStorePaths home-files/.config/systemd/user/mpd.service) + assertFileContent "$serviceFile" ${./start-when-needed.service} + + socketFile=home-files/.config/systemd/user/mpd.socket + assertFileContent "$socketFile" ${./start-when-needed.socket} + + confFile=$(grep -o \ + '/nix/store/.*-mpd.conf' \ + $TESTED/home-files/.config/systemd/user/mpd.service) + assertFileContent "$confFile" ${./basic-configuration.conf} + ''; +} diff --git a/tests/modules/services/mpd/start-when-needed.service b/tests/modules/services/mpd/start-when-needed.service new file mode 100644 index 000000000..87eb4b79a --- /dev/null +++ b/tests/modules/services/mpd/start-when-needed.service @@ -0,0 +1,12 @@ +[Service] +Environment=PATH=/home/hm-user/.nix-profile/bin +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 + +[Unit] +After=network.target +After=sound.target +After=mpd.socket +Description=Music Player Daemon +Requires=mpd.socket diff --git a/tests/modules/services/mpd/start-when-needed.socket b/tests/modules/services/mpd/start-when-needed.socket new file mode 100644 index 000000000..b5687b117 --- /dev/null +++ b/tests/modules/services/mpd/start-when-needed.socket @@ -0,0 +1,8 @@ +[Install] +WantedBy=sockets.target + +[Socket] +Backlog=5 +KeepAlive=true +ListenStream=127.0.0.1:6600 +ListenStream=%t/mpd/socket diff --git a/tests/modules/services/nix-gc/basic.nix b/tests/modules/services/nix-gc/basic.nix index d6511a171..a06b67238 100644 --- a/tests/modules/services/nix-gc/basic.nix +++ b/tests/modules/services/nix-gc/basic.nix @@ -4,7 +4,7 @@ nix.gc = { automatic = true; frequency = "monthly"; - options = "--delete-older-than 30d"; + options = "--delete-older-than 30d --max-freed $((64 * 1024**3))"; }; test.stubs.nix = { name = "nix"; }; @@ -25,5 +25,16 @@ timerFile=$(normalizeStorePaths $timerFile) assertFileContent $timerFile ${./expected.timer} + + nixgcScriptFile=$(grep -o \ + '/nix/store/.*-nix-gc' \ + $TESTED/home-files/.config/systemd/user/nix-gc.service + ) + + assertFileExists $nixgcScriptFile + + nixgcScriptFile=$(normalizeStorePaths $nixgcScriptFile) + + assertFileContent $nixgcScriptFile ${./nix-gc-script-expected} ''; } diff --git a/tests/modules/services/nix-gc/expected.service b/tests/modules/services/nix-gc/expected.service index 4aafd6af8..47bca9895 100644 --- a/tests/modules/services/nix-gc/expected.service +++ b/tests/modules/services/nix-gc/expected.service @@ -1,5 +1,6 @@ [Service] -ExecStart=@nix@/bin/nix-collect-garbage --delete-older-than 30d +ExecStart=/nix/store/00000000000000000000000000000000-nix-gc +Type=oneshot [Unit] Description=Nix Garbage Collector diff --git a/tests/modules/services/nix-gc/nix-gc-script-expected b/tests/modules/services/nix-gc/nix-gc-script-expected new file mode 100644 index 000000000..0ce2a4f91 --- /dev/null +++ b/tests/modules/services/nix-gc/nix-gc-script-expected @@ -0,0 +1,2 @@ +#!/nix/store/00000000000000000000000000000000-bash/bin/bash +exec @nix@/bin/nix-collect-garbage --delete-older-than 30d --max-freed $((64 * 1024**3)) diff --git a/tests/modules/services/swayosd/swayosd.nix b/tests/modules/services/swayosd/swayosd.nix index 88a7c5362..1bc7d5354 100644 --- a/tests/modules/services/swayosd/swayosd.nix +++ b/tests/modules/services/swayosd/swayosd.nix @@ -23,6 +23,7 @@ [Service] ExecStart=@swayosd@/bin/swayosd-server --display DISPLAY --style '/etc/xdg/swayosd/style.css' --top-margin 0.100000 Restart=always + RestartSec=2s Type=simple [Unit] @@ -31,6 +32,8 @@ Description=Volume/backlight OSD indicator Documentation=man:swayosd(1) PartOf=graphical-session.target + StartLimitBurst=5 + StartLimitIntervalSec=10 '' } ''; 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/sway/sway-bar-focused-colors.conf b/tests/modules/services/window-managers/sway/sway-bar-focused-colors.conf index 448c41f47..100193192 100644 --- a/tests/modules/services/window-managers/sway/sway-bar-focused-colors.conf +++ b/tests/modules/services/window-managers/sway/sway-bar-focused-colors.conf @@ -108,4 +108,4 @@ bar { } } -exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE; systemctl --user start sway-session.target" +exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE; systemctl --user reset-failed && systemctl --user start sway-session.target && swaymsg -mt subscribe '[]' || true && systemctl --user stop sway-session.target" diff --git a/tests/modules/services/window-managers/sway/sway-bindkeys-to-code-and-extra-config.conf b/tests/modules/services/window-managers/sway/sway-bindkeys-to-code-and-extra-config.conf index d11f6f2bc..28513fcd5 100644 --- a/tests/modules/services/window-managers/sway/sway-bindkeys-to-code-and-extra-config.conf +++ b/tests/modules/services/window-managers/sway/sway-bindkeys-to-code-and-extra-config.conf @@ -107,5 +107,5 @@ bar { } } -exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE; systemctl --user start sway-session.target" +exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE; systemctl --user reset-failed && systemctl --user start sway-session.target && swaymsg -mt subscribe '[]' || true && systemctl --user stop sway-session.target" exec_always pkill flashfocus; flasfocus & diff --git a/tests/modules/services/window-managers/sway/sway-default.conf b/tests/modules/services/window-managers/sway/sway-default.conf index 71a0b13fb..cefe4e0af 100644 --- a/tests/modules/services/window-managers/sway/sway-default.conf +++ b/tests/modules/services/window-managers/sway/sway-default.conf @@ -105,4 +105,4 @@ bar { } } -exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE; systemctl --user start sway-session.target" +exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE; systemctl --user reset-failed && systemctl --user start sway-session.target && swaymsg -mt subscribe '[]' || true && systemctl --user stop sway-session.target" diff --git a/tests/modules/services/window-managers/sway/sway-followmouse-expected.conf b/tests/modules/services/window-managers/sway/sway-followmouse-expected.conf index af259face..f4f60ddf0 100644 --- a/tests/modules/services/window-managers/sway/sway-followmouse-expected.conf +++ b/tests/modules/services/window-managers/sway/sway-followmouse-expected.conf @@ -83,4 +83,4 @@ mode "resize" { bindsym l resize grow width 10 px } -exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE; systemctl --user start sway-session.target" +exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE; systemctl --user reset-failed && systemctl --user start sway-session.target && swaymsg -mt subscribe '[]' || true && systemctl --user stop sway-session.target" diff --git a/tests/modules/services/window-managers/sway/sway-followmouse-legacy-expected.conf b/tests/modules/services/window-managers/sway/sway-followmouse-legacy-expected.conf index 1fd0003fc..c10dbd90d 100644 --- a/tests/modules/services/window-managers/sway/sway-followmouse-legacy-expected.conf +++ b/tests/modules/services/window-managers/sway/sway-followmouse-legacy-expected.conf @@ -83,4 +83,4 @@ mode "resize" { bindsym l resize grow width 10 px } -exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE; systemctl --user start sway-session.target" +exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE; systemctl --user reset-failed && systemctl --user start sway-session.target && swaymsg -mt subscribe '[]' || true && systemctl --user stop sway-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 766d61de7..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" { @@ -117,4 +117,4 @@ bar { } } -exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE; systemctl --user start sway-session.target" +exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE; systemctl --user reset-failed && systemctl --user start sway-session.target && swaymsg -mt subscribe '[]' || true && systemctl --user stop sway-session.target" diff --git a/tests/modules/services/window-managers/sway/sway-null-package.conf b/tests/modules/services/window-managers/sway/sway-null-package.conf index 67073371f..9df934b2f 100644 --- a/tests/modules/services/window-managers/sway/sway-null-package.conf +++ b/tests/modules/services/window-managers/sway/sway-null-package.conf @@ -105,4 +105,4 @@ bar { } } -exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE; systemctl --user start sway-session.target" +exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE; systemctl --user reset-failed && systemctl --user start sway-session.target && swaymsg -mt subscribe '[]' || true && systemctl --user stop sway-session.target" diff --git a/tests/modules/services/window-managers/sway/sway-post-2003.conf b/tests/modules/services/window-managers/sway/sway-post-2003.conf index 67073371f..9df934b2f 100644 --- a/tests/modules/services/window-managers/sway/sway-post-2003.conf +++ b/tests/modules/services/window-managers/sway/sway-post-2003.conf @@ -105,4 +105,4 @@ bar { } } -exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE; systemctl --user start sway-session.target" +exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE; systemctl --user reset-failed && systemctl --user start sway-session.target && swaymsg -mt subscribe '[]' || true && systemctl --user stop sway-session.target" diff --git a/tests/modules/services/window-managers/sway/sway-systemd-variables.conf b/tests/modules/services/window-managers/sway/sway-systemd-variables.conf index 1cbb92c32..3710c5392 100644 --- a/tests/modules/services/window-managers/sway/sway-systemd-variables.conf +++ b/tests/modules/services/window-managers/sway/sway-systemd-variables.conf @@ -105,4 +105,4 @@ bar { } } -exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd XCURSOR_THEME XCURSOR_SIZE; systemctl --user start sway-session.target" +exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd XCURSOR_THEME XCURSOR_SIZE; systemctl --user reset-failed && systemctl --user start sway-session.target && swaymsg -mt subscribe '[]' || true && systemctl --user stop sway-session.target" diff --git a/tests/modules/services/window-managers/sway/sway-workspace-default-expected.conf b/tests/modules/services/window-managers/sway/sway-workspace-default-expected.conf index 5233c0bb2..4fe872821 100644 --- a/tests/modules/services/window-managers/sway/sway-workspace-default-expected.conf +++ b/tests/modules/services/window-managers/sway/sway-workspace-default-expected.conf @@ -104,4 +104,4 @@ bar { } } -exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE; systemctl --user start sway-session.target" +exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE; systemctl --user reset-failed && systemctl --user start sway-session.target && swaymsg -mt subscribe '[]' || true && systemctl --user stop sway-session.target" diff --git a/tests/modules/services/window-managers/sway/sway-workspace-output-expected.conf b/tests/modules/services/window-managers/sway/sway-workspace-output-expected.conf index 32dfd7344..7148d0030 100644 --- a/tests/modules/services/window-managers/sway/sway-workspace-output-expected.conf +++ b/tests/modules/services/window-managers/sway/sway-workspace-output-expected.conf @@ -110,4 +110,4 @@ workspace "ABC" output "DP" workspace "3: Test" output "HDMI" workspace "!"§$%&/(){}[]=?\*#<>-_.:,;²³" output "DVI" workspace "Multiple" output "DVI" "HDMI" "DP" -exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE; systemctl --user start sway-session.target" +exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE; systemctl --user reset-failed && systemctl --user start sway-session.target && swaymsg -mt subscribe '[]' || true && systemctl --user stop sway-session.target"