diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index beb9e5eb..f5d43483 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -59,6 +59,8 @@ Makefile @thiagokokada /tests/modules/misc/xdg/desktop-full-expected.desktop @cwyc /tests/modules/misc/xdg/desktop-min-expected.desktop @cwyc +/modules/misc/xfconf.nix @chuangzhu + /modules/programs/aerc.nix @lukasngl /modules/programs/aerc-accounts.nix @lukasngl /tests/modules/programs/aerc @lukasngl @@ -84,7 +86,7 @@ Makefile @thiagokokada /modules/programs/bottom.nix @polykernel /tests/modules/programs/bottom @polykernel -/modules/programs/broot.nix @aheaume +/modules/programs/broot.nix @aheaume @dermetfan /modules/programs/btop.nix @GaetanLepage /tests/modules/programs/btop.nix @GaetanLepage @@ -93,6 +95,8 @@ Makefile @thiagokokada /modules/programs/direnv.nix @rycee +/modules/programs/discocss.nix @Kranzes + /modules/programs/eclipse.nix @rycee /modules/programs/emacs.nix @rycee @@ -124,14 +128,16 @@ Makefile @thiagokokada /modules/programs/go.nix @rvolosatovs +/modules/programs/havoc.nix @AndersonTorres + /modules/programs/helix.nix @Philipp-M /tests/modules/programs/helix @Philipp-M /modules/programs/hexchat.nix @thiagokokada /tests/modules/programs/hexchat @thiagokokada -/modules/programs/himalaya.nix @ambroisie -/tests/modules/programs/himalaya @ambroisie +/modules/programs/himalaya.nix @toastal +/tests/modules/programs/himalaya @toastal /modules/programs/home-manager.nix @rycee @@ -151,6 +157,9 @@ Makefile @thiagokokada /modules/programs/just.nix @maximsmol +/modules/programs/k9s.nix @katexochen +/tests/modules/programs/k9s @katexochen + /modules/programs/keychain.nix @marsam /modules/programs/kodi.nix @dwagenk @@ -158,6 +167,8 @@ Makefile @thiagokokada /modules/programs/lazygit.nix @kalhauge +/modules/programs/ledger.nix @marsam + /modules/programs/less.nix @pamplemousse /tests/modules/programs/less @pamplemousse @@ -170,6 +181,9 @@ Makefile @thiagokokada /modules/programs/lieer.nix @tadfisher +/modules/programs/looking-glass-client.nix @j-brn +/tests/modules/programs/looking-glass-client @j-brn + /modules/programs/lsd.nix @marsam /modules/programs/matplotlib.nix @rprospero @@ -225,6 +239,9 @@ Makefile @thiagokokada /modules/programs/octant.nix @06kellyjac +/modules/programs/oh-my-posh.nix @arjan-s +/tests/modules/programs/oh-my-posh @arjan-s + /modules/programs/opam.nix @marsam /modules/programs/openssh.nix @rycee @@ -232,6 +249,9 @@ Makefile @thiagokokada /modules/programs/pandoc.nix @kirelagin /tests/modules/programs/pandoc @kirelagin +/modules/programs/papis.nix @marsam +/tests/modules/programs/papis @marsam + /modules/programs/password-store.nix @pacien /modules/programs/pazi.nix @marsam @@ -243,6 +263,12 @@ Makefile @thiagokokada /modules/programs/piston-cli.nix @ethancedwards8 +/modules/programs/pls.nix @arjan-s +/tests/modules/programs/pls @arjan-s + +/modules/programs/polybar.nix @h7x4 +/tests/modules/programs/polybar @h7x4 + /modules/programs/powerline-go.nix @DamienCassou /modules/programs/pubs.nix @loicreynier @@ -250,6 +276,8 @@ Makefile @thiagokokada /modules/programs/pylint.nix @florpe +/modules/programs/rbenv.nix @marsam + /modules/programs/rbw.nix @ambroisie /tests/modules/programs/rbw @ambroisie @@ -292,15 +320,24 @@ Makefile @thiagokokada /modules/programs/texlive.nix @rycee +/modules/programs/thunderbird.nix @d-dervishi +/tests/modules/programs/thunderbird @d-dervishi + /modules/programs/timidity.nix @amesgen /modules/programs/tint2.nix @CarlosLoboxyz /modules/programs/tiny.nix @kmaasrud +/modules/programs/tmate.nix @jlesquembre +/tests/modules/programs/tmate @jlesquembre + /modules/programs/topgrade.nix @msfjarvis /tests/modules/programs/topgrade @msfjarvis +/modules/programs/vim-vint.nix @tomodachi94 +/tests/modules/programs/vim-vint @tomodachi94 + /modules/programs/watson.nix @polykernel /tests/modules/programs/watson @polykernel @@ -314,6 +351,7 @@ Makefile @thiagokokada /tests/modules/programs/xmobar @t4ccer /modules/programs/yt-dlp.nix @marsam +/tests/modules/programs/yt-dlp @marsam /modules/programs/z-lua.nix @marsam @@ -325,15 +363,25 @@ Makefile @thiagokokada /modules/programs/zsh/prezto.nix @NickHu +/modules/services/autorandr.nix @GaetanLepage + /modules/services/barrier.nix @Kritnich /tests/modules/services/barrier @Kritnich /modules/services/betterlockscreen.nix @SebTM +/modules/programs/borgmatic.nix @DamienCassou +/modules/services/borgmatic.nix @DamienCassou +/tests/modules/programs/borgmatic @DamienCassou +/tests/modules/services/borgmatic @DamienCassou + /modules/services/caffeine.nix @uvNikita /modules/services/cbatticon.nix @pmiddend +/modules/services/clipman.nix @jwygoda +/tests/modules/services/clipman @jwygoda + /modules/services/clipmenu.nix @DamienCassou /modules/services/devilspie2.nix @dawidsowa @@ -392,6 +440,8 @@ Makefile @thiagokokada /modules/services/mbsync.nix @pjones +/modules/services/megasync.nix @GaetanLepage + /modules/services/mopidy.nix @foo-dogsquared /tests/modules/services/mopidy @foo-dogsquared @@ -447,6 +497,8 @@ Makefile @thiagokokada /modules/services/redshift-gammastep @rycee @petabyteboy @thiagokokada /tests/modules/redshift-gammastep @thiagokokada +/modules/services/safeeyes @Rosuavio + /modules/services/screen-locker.nix @jrobsonchase @rszamszur /tests/modules/services/screen-locker @jrobsonchase @rszamszur @@ -483,6 +535,8 @@ Makefile @thiagokokada /modules/services/window-managers/bspwm @ncfavier /tests/modules/services/window-managers/bspwm @ncfavier +/modules/services/window-managers/fluxbox.nix @AndersonTorres + /modules/services/window-managers/herbstluftwm @olmokramer /tests/modules/services/window-managers/herbstluftwm @olmokramer diff --git a/.github/dependabot.yml b/.github/dependabot.yml index c1d917c2..b65c1278 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -10,7 +10,7 @@ updates: - package-ecosystem: "github-actions" directory: "/" - target-branch: "release-21.11" + target-branch: "release-22.11" schedule: interval: "weekly" commit-message: diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 00000000..ba7ecffe --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,19 @@ +"mail": + - modules/programs/alot*.nix + - tests/modules/programs/alot/* + - modules/programs/mujmap.nix + - tests/modules/programs/mujmap/* + - modules/programs/notmuch.nix + - modules/programs/neomutt* + - tests/modules/programs/neomutt/* + - modules/programs/getmail* + - modules/*/mbsync* + - tests/modules/programs/mbsync/* + - modules/programs/himalaya.nix + - tests/modules/programs/himalaya/* + - modules/programs/thunderbird.nix + - tests/modules/programs/thunderbird/* + +"neovim": + - modules/programs/neovim.nix + - tests/modules/programs/neovim/**/* diff --git a/.github/workflows/github_pages.yml b/.github/workflows/github_pages.yml index 1e0a0f9a..b60812ae 100644 --- a/.github/workflows/github_pages.yml +++ b/.github/workflows/github_pages.yml @@ -11,13 +11,13 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 - - uses: cachix/install-nix-action@v17 + - uses: cachix/install-nix-action@v18 with: nix_path: nixpkgs=channel:nixos-unstable - - uses: cachix/cachix-action@v10 + - uses: cachix/cachix-action@v12 with: name: nix-community - signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}' + authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - run: | nix-build -A docs.html cp -r result/share/doc/home-manager public diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml new file mode 100644 index 00000000..daea610a --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,24 @@ +name: "Label PR" + +on: + - pull_request_target + +# WARNING: +# When extending this action, be aware that $GITHUB_TOKEN allows some write +# access to the GitHub API. This means that it should not evaluate user input in +# a way that allows code injection. + +permissions: + contents: read + pull-requests: write + +jobs: + labels: + runs-on: ubuntu-latest + if: github.repository_owner == 'nix-community' + steps: + - uses: actions/labeler@v4 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + sync-labels: true + diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 22e76b59..73ac7a00 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,13 +12,13 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 - - uses: cachix/install-nix-action@v17 + - uses: cachix/install-nix-action@v18 with: nix_path: nixpkgs=channel:nixos-unstable - - uses: cachix/cachix-action@v10 + - uses: cachix/cachix-action@v12 with: name: nix-community - signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}' + authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - run: | if grep -R --exclude stdlib-extended.nix literalExample modules ; then echo "Error: literalExample should be replaced by literalExpression" > /dev/stderr diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index e472513a..924287d7 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -12,9 +12,9 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - name: Install Nix - uses: cachix/install-nix-action@v17 + uses: cachix/install-nix-action@v18 - name: Update flake.lock - uses: DeterminateSystems/update-flake-lock@v13 + uses: DeterminateSystems/update-flake-lock@v16 with: token: ${{ secrets.GH_TOKEN_FOR_UPDATES }} pr-labels: dependencies diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 37b08ef6..a7d63798 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,17 +4,8 @@ variables: NIX_PATH: "nixpkgs=channel:nixos-unstable" stages: - - test - deploy -Run tests: - stage: test - script: - - nix-shell --pure tests -A run.files-text - rules: - - if: $CI_COMMIT_BRANCH == "master" - when: always - pages: stage: deploy script: diff --git a/.release b/.release index 8b84b727..f8c86096 100644 --- a/.release +++ b/.release @@ -1 +1 @@ -22.11 +23.05 diff --git a/README.md b/README.md index 095effcd..f792af54 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,9 @@ Before attempting to use Home Manager please read the warning below. For a systematic overview of Home Manager and its available options, please see -- the [Home Manager manual][manual] and -- the [Home Manager configuration options][configuration options]. +- the [Home Manager manual][manual], +- the [Home Manager configuration options][configuration options], and +- the 3rd party [Home Manager option search](https://mipmip.github.io/home-manager-option-search/). If you would like to contribute to Home Manager then please have a look at the [contributing][] chapter of the manual. @@ -41,7 +42,7 @@ will write to your dconf store and cannot tell whether a configuration that it is about to be overwritten was from a previous Home Manager generation or from manual configuration. -Home Manager targets [NixOS][] unstable and NixOS version 22.05 (the +Home Manager targets [NixOS][] unstable and NixOS version 22.11 (the current stable version), it may or may not work on other Linux distributions and NixOS versions. @@ -106,7 +107,7 @@ Home Manager is developed against `nixpkgs-unstable` branch, which often causes it to contain tweaks for changes/packages not yet released in stable NixOS. To avoid breaking users' configurations, Home Manager is released in branches corresponding to NixOS releases -(e.g. `release-22.05`). These branches get fixes, but usually not new +(e.g. `release-22.11`). These branches get fixes, but usually not new modules. If you need a module to be backported, then feel free to open an issue. diff --git a/docs/contributing.adoc b/docs/contributing.adoc index 0b440993..7ab95289 100644 --- a/docs/contributing.adoc +++ b/docs/contributing.adoc @@ -28,6 +28,11 @@ Assuming your clone is at `$HOME/devel/home-manager` then you can make the `home [source,console] $ home-manager -I home-manager=$HOME/devel/home-manager + +or, if using <>: ++ +[source,console] +$ home-manager --override-input home-manager ~/devel/home-manager ++ or 2. changing the default path by ensuring your configuration includes @@ -256,3 +261,8 @@ and run an individual test, for example `alacritty-empty-settings`, through [source,console] $ nix-shell --pure tests -A run.alacritty-empty-settings + +However, those invocations will impurely source the system’s nixpkgs, and may cause failures. To run against the nixpkgs from the flake.lock, use instead e.g. + +[source,console] +$ nix develop --ignore-environment .#tests.all diff --git a/docs/default.nix b/docs/default.nix index 4aad2bfc..54719b91 100644 --- a/docs/default.nix +++ b/docs/default.nix @@ -7,8 +7,8 @@ let nmdSrc = fetchTarball { url = - "https://gitlab.com/api/v4/projects/rycee%2Fnmd/repository/archive.tar.gz?sha=91dee681dd1c478d6040a00835d73c0f4a4c5c29"; - sha256 = "07szg39wmna287hv5w9hl45wvm04zbh0k54br59nv3yzvg9ymlj4"; + "https://git.sr.ht/~rycee/nmd/archive/409f1310b168f96c6c8b556d24731a3e7c26c255.tar.gz"; + sha256 = "1v43qgfwa9s84728lv1njz2zdsfzp8kas3w4s3jan7w813c8flh8"; }; nmd = import nmdSrc { inherit lib pkgs; }; diff --git a/docs/installation.adoc b/docs/installation.adoc index 1862f616..afdbe35e 100644 --- a/docs/installation.adoc +++ b/docs/installation.adoc @@ -51,23 +51,13 @@ $ nix-channel --add https://github.com/nix-community/home-manager/archive/master $ nix-channel --update ---- + -and if you follow a Nixpkgs version 22.05 channel you can run +and if you follow a Nixpkgs version 22.11 channel you can run + [source,console] ---- -$ nix-channel --add https://github.com/nix-community/home-manager/archive/release-22.05.tar.gz home-manager +$ nix-channel --add https://github.com/nix-community/home-manager/archive/release-22.11.tar.gz home-manager $ nix-channel --update ---- -+ -On non-NixOS, you may have to add -+ -[source,bash] -export NIX_PATH=$HOME/.nix-defexpr/channels:/nix/var/nix/profiles/per-user/root/channels${NIX_PATH:+:$NIX_PATH} -+ -to your shell (see https://github.com/NixOS/nix/issues/2033[nix#2033] -and -https://discourse.nixos.org/t/where-is-nix-path-supposed-to-be-set/16434/8[this -reply on the Nix Discourse]). 3. Run the Home Manager installation command and create the first Home Manager generation: @@ -133,11 +123,11 @@ $ sudo nix-channel --add https://github.com/nix-community/home-manager/archive/m $ sudo nix-channel --update ---- -and if you follow a Nixpkgs version 22.05 channel, you can run +and if you follow a Nixpkgs version 22.11 channel, you can run [source,console] ---- -$ sudo nix-channel --add https://github.com/nix-community/home-manager/archive/release-22.05.tar.gz home-manager +$ sudo nix-channel --add https://github.com/nix-community/home-manager/archive/release-22.11.tar.gz home-manager $ sudo nix-channel --update ---- @@ -244,11 +234,11 @@ $ nix-channel --add https://github.com/nix-community/home-manager/archive/master $ nix-channel --update ---- -and if you follow a Nixpkgs version 22.05 channel, you can run +and if you follow a Nixpkgs version 22.11 channel, you can run [source,console] ---- -$ nix-channel --add https://github.com/nix-community/home-manager/archive/release-22.05.tar.gz home-manager +$ nix-channel --add https://github.com/nix-community/home-manager/archive/release-22.11.tar.gz home-manager $ nix-channel --update ---- @@ -303,7 +293,7 @@ can be sourced directly by POSIX.2-like shells such as {bash}[Bash] or [NOTE] ==== By default user packages will not be ignored in favor of -`environment.systemPackages`, but they will be intalled to +`environment.systemPackages`, but they will be installed to `/etc/profiles/per-user/$USERNAME` if [source,nix] diff --git a/docs/man-home-manager.xml b/docs/man-home-manager.xml index cbc977ab..e83cab89 100644 --- a/docs/man-home-manager.xml +++ b/docs/man-home-manager.xml @@ -155,6 +155,18 @@ --keep-going + + + + -L + + + + --print-build-logs + + + + --show-trace @@ -167,6 +179,10 @@ --no-out-link + + --refresh + + @@ -546,6 +562,22 @@ + + + + + + + + + + Passed on to + nix build + + when building from a flake. + + + @@ -583,6 +615,18 @@ + + + + + + + Passed on to + nix-build + 1 + + + diff --git a/docs/nix-flakes.adoc b/docs/nix-flakes.adoc index 34b8b0f0..2e00c9e6 100644 --- a/docs/nix-flakes.adoc +++ b/docs/nix-flakes.adoc @@ -6,19 +6,31 @@ Home Manager includes a `flake.nix` file for compatibility with {nixos-wiki-flakes}[Nix Flakes]. The support is still experimental and may change in backwards incompatible ways. -[[sec-flakes-prerequisties]] -=== Prerequisties +[[sec-flakes-prerequisites]] +=== Prerequisites * Install Nix 2.4 or later, or have it in `nix-shell`. * Enable experimental features `nix-command` and `flakes`. + -Either set in `nix.conf` +** When using NixOS, add the following to your `configuration.nix` and rebuild your system. ++ +[source,nix] +nix = { + package = pkgs.nixFlakes; + extraOptions = '' + experimental-features = nix-command flakes + ''; +}; ++ +** If you are not using NixOS, add the following to `nix.conf` (located at `~/.config/nix/` or `/etc/nix/nix.conf`). + [source,bash] experimental-features = nix-command flakes + -or pass them to `nix` and `home-manager` by +You may need to restart the Nix daemon with, for example, `sudo systemctl restart nix-daemon.service`. ++ +** Alternatively, you can enable flakes on a per-command basis with the following additional flags to `nix` and `home-manager`: + [source,console] ---- @@ -78,9 +90,9 @@ writing a Home Manager configuration. ==== * The above example tracks the master branch of Home Manager and nixos-unstable branch of Nixpkgs. -If you would like to use the `release-22.05` branch, -change the `home-manager` input url to `github:nix-community/home-manager/release-22.05` -and `nixpkgs` url to `github:NixOS/nixpkgs/nixos-22.05`. +If you would like to use the `release-22.11` branch, +change the `home-manager` input url to `github:nix-community/home-manager/release-22.11` +and `nixpkgs` url to `github:NixOS/nixpkgs/nixos-22.11`. * The Home Manager library is exported by the flake under `lib.hm`. @@ -188,7 +200,7 @@ is similar to that of NixOS. The `flake.nix` would be: [source,nix] ---- { - description = "NixOS configuration"; + description = "Darwin configuration"; inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; diff --git a/docs/release-notes/release-notes.adoc b/docs/release-notes/release-notes.adoc index b5f607ae..d7058ca0 100644 --- a/docs/release-notes/release-notes.adoc +++ b/docs/release-notes/release-notes.adoc @@ -6,6 +6,8 @@ This section lists the release notes for stable versions of Home Manager and the :leveloffset: 1 +include::rl-2305.adoc[] + include::rl-2211.adoc[] include::rl-2205.adoc[] diff --git a/docs/release-notes/rl-2105.adoc b/docs/release-notes/rl-2105.adoc index 7fcfb268..ed94f888 100644 --- a/docs/release-notes/rl-2105.adoc +++ b/docs/release-notes/rl-2105.adoc @@ -8,7 +8,7 @@ The 21.05 release branch became the stable branch in May, 2021. This release has the following notable changes: -* The <> option is now a list rather than an +* The `opt-programs.broot.verbs` option is now a list rather than an attribute set. To migrate, move the keys of the attrset into the list items' `invocation` keys. For example, + diff --git a/docs/release-notes/rl-2211.adoc b/docs/release-notes/rl-2211.adoc index ed2fa55c..046995d5 100644 --- a/docs/release-notes/rl-2211.adoc +++ b/docs/release-notes/rl-2211.adoc @@ -93,4 +93,21 @@ release 20.03. Use `services.picom` instead. The state version in this release includes the changes below. These changes are only active if the `home.stateVersion` option is set to "22.11" or later. -* No changes. +* The <> option now defaults to the +value of <> if <> is +enabled. Otherwise it is undefined and must be specified in the user +configuration. + +* The activation script now resets `PATH` before running. Before, the +user's `PATH` environment variable would be used in the script and +this made it possible for commands in the activation script to run +arbitrary commands accessible to the user. We now restrict the +activation script to commands that are explicitly specified. ++ +There is no official way to restore the old behavior. We attempt to +make the activation script as reproducible as possible and honoring +the user's `PATH` reduces reproducibility. ++ +If you need to run a command in an activation script block then refer +to the command by its absolute command path, such as +`${pkgs.hello}/bin/hello`. diff --git a/docs/release-notes/rl-2305.adoc b/docs/release-notes/rl-2305.adoc new file mode 100644 index 00000000..6d16e784 --- /dev/null +++ b/docs/release-notes/rl-2305.adoc @@ -0,0 +1,23 @@ +[[sec-release-23.05]] +== Release 23.05 + +This is the current unstable branch and the information in this section is therefore not final. + +[[sec-release-23.05-highlights]] +=== Highlights + +This release has the following notable changes: + +* No highlights. + +[[sec-release-23.05-state-version-changes]] +=== State Version Changes + +The state version in this release includes the changes below. +These changes are only active if the `home.stateVersion` option is set to "23.05" or later. + +* The <>, +<>, +<>, +<>, options now default to `true` which +is consistent with the default values for those options used by `i3` and `sway`. diff --git a/docs/usage.adoc b/docs/usage.adoc index 26b9eee7..adac7b72 100644 --- a/docs/usage.adoc +++ b/docs/usage.adoc @@ -52,7 +52,7 @@ A fresh install of Home Manager will generate a minimal `~/.config/nixpkgs/home. # You can update Home Manager without changing this value. See # the Home Manager release notes for a list of state version # changes in each release. - home.stateVersion = "22.05"; + home.stateVersion = "22.11"; # Let Home Manager install and manage itself. programs.home-manager.enable = true; @@ -92,7 +92,7 @@ To satisfy the above setup we should elaborate the `home.nix` file as follows: # You can update Home Manager without changing this value. See # the Home Manager release notes for a list of state version # changes in each release. - home.stateVersion = "22.05"; + home.stateVersion = "22.11"; # Let Home Manager install and manage itself. programs.home-manager.enable = true; diff --git a/docs/writing-modules.adoc b/docs/writing-modules.adoc index 0f3336ff..d8d69e82 100644 --- a/docs/writing-modules.adoc +++ b/docs/writing-modules.adoc @@ -167,9 +167,11 @@ Builds a GVariant array containing the given list of elements, where each elemen - `hm.gvariant.type.int64` - `hm.gvariant.type.uint64` - `hm.gvariant.type.double` +- `hm.gvariant.type.variant` - `hm.gvariant.type.arrayOf type` - `hm.gvariant.type.maybeOf type` - `hm.gvariant.type.tupleOf types` +- `hm.gvariant.type.dictionaryEntryOf types` -- + where `type` and `types` are themselves a type and list of types, respectively. @@ -185,3 +187,9 @@ Builds a GVariant maybe value containing the given GVariant element. + `hm.gvariant.mkTuple elements`::: Builds a GVariant tuple containing the given list of elements, where each element is a GVariant value. ++ +`hm.gvariant.mkVariant element`::: +Builds a GVariant variant which contains the value of a GVariant element. ++ +`hm.gvariant.mkDictionaryEntry elements`::: +Builds a GVariant dictionary entry containing the given list of elements, where each element is a GVariant value. diff --git a/flake.lock b/flake.lock index e027b4cb..f8d0f32e 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1654953433, - "narHash": "sha256-TwEeh4r50NdWHFAHQSyjCk2cZxgwUfcCCAJOhPdXB28=", + "lastModified": 1675115703, + "narHash": "sha256-4zetAPSyY0D77x+Ww9QBe8RHn1akvIvHJ/kgg8kGDbk=", "owner": "nixos", "repo": "nixpkgs", - "rev": "90cd5459a1fd707819b9a3fb9c852beaaac3b79a", + "rev": "2caf4ef5005ecc68141ecb4aac271079f7371c44", "type": "github" }, "original": { @@ -24,11 +24,11 @@ }, "utils": { "locked": { - "lastModified": 1653893745, - "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", "owner": "numtide", "repo": "flake-utils", - "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index a4e570e9..e64b2ea7 100644 --- a/flake.nix +++ b/flake.nix @@ -45,27 +45,37 @@ , configuration ? null, extraModules ? null, stateVersion ? null , username ? null, homeDirectory ? null, system ? null }@args: let - throwForRemovedArg = v: - lib.throwIf (v != null) '' - The 'homeManagerConfiguration' arguments + msgForRemovedArg = '' + The 'homeManagerConfiguration' arguments - - 'configuration', - - 'username', - - 'homeDirectory' - - 'stateVersion', - - 'extraModules', and - - 'system' + - 'configuration', + - 'username', + - 'homeDirectory' + - 'stateVersion', + - 'extraModules', and + - 'system' - have been removed. Instead use the arguments 'pkgs' and - 'modules'. See the 22.11 release notes for more. - ''; + have been removed. Instead use the arguments 'pkgs' and + 'modules'. See the 22.11 release notes for more: https://nix-community.github.io/home-manager/release-notes.html#sec-release-22.11-highlights + ''; + + throwForRemovedArgs = v: + let + used = builtins.filter (n: (args.${n} or null) != null) [ + "configuration" + "username" + "homeDirectory" + "stateVersion" + "extraModules" + "system" + ]; + msg = msgForRemovedArg + '' + + + Deprecated args passed: '' + + builtins.concatStringsSep " " used; + in lib.throwIf (used != [ ]) msg v; - throwForRemovedArgs = throwForRemovedArg configuration # \ - throwForRemovedArg username # \ - throwForRemovedArg homeDirectory # \ - throwForRemovedArg stateVersion # \ - throwForRemovedArg extraModules # \ - throwForRemovedArg system; in throwForRemovedArgs (import ./modules { inherit pkgs lib check extraSpecialArgs; configuration = { ... }: { @@ -78,7 +88,9 @@ let pkgs = nixpkgs.legacyPackages.${system}; docs = import ./docs { inherit pkgs; }; + tests = import ./tests { inherit pkgs; }; in { + devShells.tests = tests.run; packages = rec { home-manager = pkgs.callPackage ./home-manager { }; docs-html = docs.manual.html; diff --git a/format b/format index 68751a3f..ef5528b7 100755 --- a/format +++ b/format @@ -21,7 +21,6 @@ find . -name '*.nix' \ ! -path ./modules/lib/default.nix \ ! -path ./modules/lib/file-type.nix \ ! -path ./modules/misc/news.nix \ - ! -path ./modules/programs/bash.nix \ ! -path ./modules/programs/ssh.nix \ ! -path ./modules/programs/zsh.nix \ ! -path ./tests/default.nix \ diff --git a/home-manager/completion.bash b/home-manager/completion.bash index ec20bbc1..152f8c32 100644 --- a/home-manager/completion.bash +++ b/home-manager/completion.bash @@ -293,9 +293,10 @@ _home-manager_completions () Options=( "-f" "--file" "-b" "-A" "-I" "-h" "--help" "-n" "--dry-run" "-v" \ "--verbose" "--cores" "--debug" "--impure" "--keep-failed" \ "--keep-going" "-j" "--max-jobs" "--no-substitute" "--no-out-link" \ + "-L" "--print-build-logs" \ "--show-trace" "--substitute" "--builders" "--version" \ "--update-input" "--override-input" "--experimental-features" \ - "--extra-experimental-features" ) + "--extra-experimental-features" "--refresh") # ^ « home-manager »'s options. diff --git a/home-manager/completion.fish b/home-manager/completion.fish index aca4943f..3781d3a7 100644 --- a/home-manager/completion.fish +++ b/home-manager/completion.fish @@ -60,6 +60,7 @@ complete -c home-manager -f -l "keep-going" -d "Keep going in case of failed bui complete -c home-manager -x -s j -l "max-jobs" -d "Max number of build jobs in parallel" complete -c home-manager -x -l "option" -d "Set Nix configuration option" complete -c home-manager -x -l "builders" -d "Remote builders" +complete -c home-manager -f -s L -l "print-build-logs" -d "Print full build logs on standard error" complete -c home-manager -f -l "show-trace" -d "Print stack trace of evaluation errors" complete -c home-manager -f -l "substitute" complete -c home-manager -f -l "no-substitute" @@ -68,3 +69,4 @@ complete -c home-manager -f -l "update-input" complete -c home-manager -f -l "override-input" complete -c home-manager -f -l "experimental-features" complete -c home-manager -f -l "extra-experimental-features" +complete -c home-manager -f -l "refresh" -d "Consider all previously downloaded files out-of-date" diff --git a/home-manager/completion.zsh b/home-manager/completion.zsh index 6e20d17d..c5d3b493 100644 --- a/home-manager/completion.zsh +++ b/home-manager/completion.zsh @@ -19,6 +19,7 @@ _arguments \ '(-j --max-jobs)'{--max-jobs,-j}'[max jobs]:NUM:()' \ '--option[option]:NAME VALUE:()' \ '--builders[builders]:SPEC:()' \ + '(-L --print-build-logs)'{--print-build-logs,-L}'[print build logs]' \ '--show-trace[show trace]' \ '--override-input[override flake input]:NAME VALUE:()' \ '--update-input[update flake input]:NAME:()' \ @@ -62,6 +63,7 @@ case "$state" in '--show-trace[show trace]' \ '--substitute[substitute]' \ '--builders[builders]:SPEC:()' \ + '--refresh[refresh]' \ '--override-input[override flake input]:NAME VALUE:()' \ '--update-input[update flake input]:NAME:()' \ '--experimental-features[set experimental Nix features]:VALUE:()' \ diff --git a/home-manager/default.nix b/home-manager/default.nix index ada4e07a..3589acb8 100644 --- a/home-manager/default.nix +++ b/home-manager/default.nix @@ -1,5 +1,5 @@ { runCommand, lib, bash, callPackage, coreutils, findutils, gettext, gnused -, less, ncurses +, less, ncurses, unixtools # used for pkgs.path for nixos-option , pkgs @@ -39,6 +39,7 @@ in runCommand "home-manager" { less ncurses nixos-option + unixtools.hostname ] }" \ --subst-var-by HOME_MANAGER_LIB '${../lib/bash/home-manager.sh}' \ diff --git a/home-manager/home-manager b/home-manager/home-manager index 6483c59f..9e0f4ae0 100644 --- a/home-manager/home-manager +++ b/home-manager/home-manager @@ -87,7 +87,7 @@ function setHomeManagerNixPath() { "${XDG_CONFIG_HOME:-$HOME/.config}/nixpkgs/home-manager" \ "$HOME/.nixpkgs/home-manager" ; do if [[ -e "$path" || "$path" =~ ^https?:// ]] ; then - export NIX_PATH="home-manager=$path${NIX_PATH:+:}$NIX_PATH" + EXTRA_NIX_PATH+=("home-manager=$path") return fi done @@ -106,10 +106,17 @@ function setFlakeAttribute() { local name="${FLAKE_ARG#*#}" ;; *) - local name="$USER@$(hostname)" - if [ "$(nix eval "$flake#homeConfigurations" --apply "x: x ? \"$name\"")" = "false" ]; then - name="$USER" - fi + local name="$USER" + # Check both long and short hostnames; long first to preserve + # pre-existing behaviour in case both happen to be defined. + for n in "$USER@$(hostname)" "$USER@$(hostname -s)"; do + if [[ "$(nix eval "$flake#homeConfigurations" --apply "x: x ? \"$n\"")" == "true" ]]; then + name="$n" + if [[ -v VERBOSE ]]; then + echo "Using flake homeConfiguration for $name" + fi + fi + done ;; esac export FLAKE_CONFIG_URI="$flake#homeConfigurations.\"$name\"" @@ -123,7 +130,6 @@ function doInspectOption() { exit 1 fi setConfigFile - setHomeManagerNixPath local extraArgs=("$@") @@ -163,7 +169,6 @@ function doInstantiate() { exit 1 fi setConfigFile - setHomeManagerNixPath local extraArgs=() @@ -185,7 +190,6 @@ function doInstantiate() { function doBuildAttr() { setConfigFile - setHomeManagerNixPath local extraArgs=("$@") @@ -282,6 +286,7 @@ function doBuild() { "$FLAKE_CONFIG_URI.activationPackage" \ ${DRY_RUN+--dry-run} \ ${NO_OUT_LINK+--no-link} \ + ${PRINT_BUILD_LOGS+--print-build-logs} \ || return else doBuildAttr \ @@ -312,6 +317,7 @@ function doSwitch() { doBuildFlake \ "$FLAKE_CONFIG_URI.activationPackage" \ --out-link "$generation" \ + ${PRINT_BUILD_LOGS+--print-build-logs} \ && "$generation/activate" || return else doBuildAttr \ @@ -480,7 +486,10 @@ function doUninstall() { y|Y) _i "Switching to empty Home Manager configuration..." HOME_MANAGER_CONFIG="$(mktemp --tmpdir home-manager.XXXXXXXXXX)" - echo "{ lib, ... }: { home.file = lib.mkForce {}; }" > "$HOME_MANAGER_CONFIG" + echo "{ lib, ... }: {" > "$HOME_MANAGER_CONFIG" + echo " home.file = lib.mkForce {};" >> "$HOME_MANAGER_CONFIG" + echo " home.stateVersion = \"18.09\";" >> "$HOME_MANAGER_CONFIG" + echo "}" >> "$HOME_MANAGER_CONFIG" doSwitch $DRY_RUN_CMD $REMOVE_CMD home-manager-path || true rm "$HOME_MANAGER_CONFIG" @@ -541,11 +550,13 @@ function doHelp() { echo " --keep-going" echo " -j, --max-jobs NUM" echo " --option NAME VALUE" + echo " -L, --print-build-logs" echo " --show-trace" echo " --(no-)substitute" echo " --no-out-link Do not create a symlink to the output path" echo " --no-write-lock-file" echo " --builders VALUE" + echo " --refresh Consider all previously downloaded files out-of-date" echo echo "Commands" echo @@ -589,6 +600,8 @@ COMMAND="" COMMAND_ARGS=() FLAKE_ARG="" +setHomeManagerNixPath + while [[ $# -gt 0 ]]; do opt="$1" shift @@ -616,7 +629,7 @@ while [[ $# -gt 0 ]]; do FLAKE_ARG="$1" shift ;; - --recreate-lock-file|--no-update-lock-file|--no-write-lock-file|--no-registries|--commit-lock-file) + --recreate-lock-file|--no-update-lock-file|--no-write-lock-file|--no-registries|--commit-lock-file|--refresh) PASSTHROUGH_OPTS+=("$opt") ;; --update-input) @@ -638,6 +651,9 @@ while [[ $# -gt 0 ]]; do --no-out-link) NO_OUT_LINK=1 ;; + -L|--print-build-logs) + PRINT_BUILD_LOGS=1 + ;; -h|--help) doHelp exit 0 @@ -661,7 +677,7 @@ while [[ $# -gt 0 ]]; do export VERBOSE=1 ;; --version) - echo 22.05 + echo 22.11 exit 0 ;; *) diff --git a/home-manager/install.nix b/home-manager/install.nix index f69508a8..f4bcbb3f 100644 --- a/home-manager/install.nix +++ b/home-manager/install.nix @@ -54,7 +54,7 @@ in runCommand "home-manager-install" { # You can update Home Manager without changing this value. See # the Home Manager release notes for a list of state version # changes in each release. - home.stateVersion = "22.05"; + home.stateVersion = "22.11"; # Let Home Manager install and manage itself. programs.home-manager.enable = true; diff --git a/home-manager/po/da.po b/home-manager/po/da.po new file mode 100644 index 00000000..aeda9100 --- /dev/null +++ b/home-manager/po/da.po @@ -0,0 +1,187 @@ +# 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: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-09-19 18:22+0000\n" +"Last-Translator: cafkafk \n" +"Language-Team: Danish \n" +"Language: da\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 4.14.1\n" + +#: home-manager/home-manager:60 +msgid "No configuration file found at %s" +msgstr "Ingen konfigurationsfiler fundet ved %s" + +#: home-manager/home-manager:79 +msgid "No configuration file found. Please create one at %s" +msgstr "Ingen konfigurationsfiler fundet. Venligst lav en ved %s" + +#: home-manager/home-manager:122 +msgid "Can't inspect options of a flake configuration" +msgstr "Kan ikke inspicere indstillinger af en flake konfiguration" + +#: home-manager/home-manager:162 +msgid "Can't instantiate a flake configuration" +msgstr "Kan ikke instantiere en flake konfiguration" + +#: home-manager/home-manager:237 +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] "" +"Der er %d ulæst og relavante nyheder.\n" +"Læs den ved at køre \"%s news\"." +msgstr[1] "" +"Der er %d ulæste og relavante nyheder.\n" +"Læs dem ved at køre \"%s news\"." + +#: home-manager/home-manager:251 +msgid "Unknown \"news.display\" setting \"%s\"." +msgstr "Ubekændt \"news.display\" indstilling \"%s\"." + +#: home-manager/home-manager:258 +#, sh-format +msgid "Please set the $EDITOR environment variable" +msgstr "Venligst sæt $EDITOR miljøvariablen" + +#: home-manager/home-manager:273 +msgid "Cannot run build in read-only directory" +msgstr "Kan ikke bygge i en læs-kun folder" + +#: home-manager/home-manager:355 +msgid "No generation with ID %s" +msgstr "Ingen generation med ID %s" + +#: home-manager/home-manager:357 +msgid "Cannot remove the current generation %s" +msgstr "Kan ikke fjerne den nuværende generation %s" + +#: home-manager/home-manager:359 +msgid "Removing generation %s" +msgstr "Fjern generation %s" + +#: home-manager/home-manager:385 +msgid "No generations to expire" +msgstr "Ingen generationer som skal udløbes" + +#: home-manager/home-manager:396 +msgid "No home-manager packages seem to be installed." +msgstr "" +"Det virker ikke som om der er nogle home-manager pakker der er installeret." + +#: home-manager/home-manager:453 +msgid "Unknown argument %s" +msgstr "Ubekendt argument %s" + +#: home-manager/home-manager:469 +msgid "This will remove Home Manager from your system." +msgstr "Dette vil fjerne Home Manager fra dit system." + +#: home-manager/home-manager:472 +msgid "This is a dry run, nothing will actually be uninstalled." +msgstr "Dette er en tør kørsel, intet vil rent faktisk blive uinstalleret." + +#: home-manager/home-manager:476 +msgid "Really uninstall Home Manager?" +msgstr "Virkelig uinstaller Home Manager?" + +#: home-manager/home-manager:481 +msgid "Switching to empty Home Manager configuration..." +msgstr "Skifter til tom Home Manager konfiguration..." + +#: home-manager/home-manager:493 +msgid "Yay!" +msgstr "Juhuu!" + +#: home-manager/home-manager:500 +msgid "Remove all Home Manager generations?" +msgstr "Fjern alle Home Manager generationer?" + +#: home-manager/home-manager:507 +msgid "All generations are now eligible for garbage collection." +msgstr "Alle generationer kan nu blive tjekket for overflødige filer." + +#: home-manager/home-manager:510 +msgid "Leaving generations but they may still be garbage collected." +msgstr "" +"Forlad generationer, men de kan stadig bliver fjernet som overflødige filer." + +#: home-manager/home-manager:514 +msgid "Home Manager is uninstalled but your home.nix is left untouched." +msgstr "" +"Home Manager bliver uinstalleret, men din home.nix bliver forladt uberørt." + +#: home-manager/home-manager:673 +msgid "%s: unknown option '%s'" +msgstr "%s: ukendt indstilling '%s'" + +#: home-manager/home-manager:674 +msgid "Run '%s --help' for usage help" +msgstr "Kør '%s --help' for brugsvejledning" + +#: home-manager/home-manager:708 +msgid "expire-generations expects one argument, got %d." +msgstr "expire-generations forventer et argument, fik %d." + +#: home-manager/home-manager:730 +msgid "Unknown command: %s" +msgstr "Ubekendt kommando: %s" + +#: home-manager/install.nix:22 +msgid "Creating initial Home Manager configuration..." +msgstr "Laver initial Home Manager konfiguration..." + +#: home-manager/install.nix:66 +msgid "Creating initial Home Manager generation..." +msgstr "Laver initial Home Manager generation..." + +#. translators: The "%s" specifier will be replaced by a file path. +#: home-manager/install.nix:71 +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 "" +"Alt er færdigt! Home-manager værktøjet burde nu være installeret, og du kan " +"ændre\n" +"\n" +" %s\n" +" \n" +"For at konfigurere Home Manager. Kør 'man home-configuration.nix' for at \n" +"se alle de mulige indstillinger." + +#. translators: The "%s" specifier will be replaced by a URL. +#: home-manager/install.nix:76 +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 "" +"Åh nej, installationen fejlede! Venligst opret en fejlrapport ved\n" +"\n" +" %s\n" +" \n" +"hvis fejlen fremstår som forskyldt af Home Manager." + +#: home-manager/install.nix:83 +msgid "This derivation is not buildable, please run it using nix-shell." +msgstr "Denne derivation er ikke bygbar, venligst kør den gennem nix-shell." diff --git a/home-manager/po/lt.po b/home-manager/po/lt.po new file mode 100644 index 00000000..52b3cab6 --- /dev/null +++ b/home-manager/po/lt.po @@ -0,0 +1,186 @@ +# 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: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2023-01-09 11:33+0000\n" +"Last-Translator: Kornelijus Tvarijanavičius \n" +"Language-Team: Lithuanian \n" +"Language: lt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n % 10 == 1 && (n % 100 < 11 || n % 100 > " +"19)) ? 0 : ((n % 10 >= 2 && n % 10 <= 9 && (n % 100 < 11 || n % 100 > 19)) ? " +"1 : 2);\n" +"X-Generator: Weblate 4.15.1-dev\n" + +#: home-manager/home-manager:60 +msgid "No configuration file found at %s" +msgstr "Nerastas konfigūracijos failas %s" + +#: home-manager/home-manager:79 +msgid "No configuration file found. Please create one at %s" +msgstr "Nerastas konfigūracijos failas. Sukurkite jį adresu %s" + +#: home-manager/home-manager:122 +msgid "Can't inspect options of a flake configuration" +msgstr "Negalima patikrinti flake konfigūracijos pasirinkimų" + +#: home-manager/home-manager:162 +msgid "Can't instantiate a flake configuration" +msgstr "Negalima sukurti pradinės flake konfigūracijos" + +#: home-manager/home-manager:237 +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] "" +"Yra %d neperskaityta ir aktuali naujiena.\n" +"Perskaitykite ją paleidus komandą \"%s news\"." +msgstr[1] "" +"Yra %d neperskaitytos ir aktualios naujienos.\n" +"Perskaitykite jas paleidus komandą \"%s news\"." +msgstr[2] "" +"Yra %d neperskaitytų ir aktualių naujienų.\n" +"Perskaitykite jas paleidus komandą \"%s news\"." + +#: home-manager/home-manager:251 +msgid "Unknown \"news.display\" setting \"%s\"." +msgstr "Nežinomas \"news.display\" nustatymas \"%s\"." + +#: home-manager/home-manager:258 +#, sh-format +msgid "Please set the $EDITOR environment variable" +msgstr "Prašome nustatyti $EDITOR aplinkos kintamąjį" + +#: home-manager/home-manager:273 +msgid "Cannot run build in read-only directory" +msgstr "" + +#: home-manager/home-manager:355 +msgid "No generation with ID %s" +msgstr "Nėra generacijos su ID %s" + +#: home-manager/home-manager:357 +msgid "Cannot remove the current generation %s" +msgstr "Negalima pašalinti esamos generacijos %s" + +#: home-manager/home-manager:359 +msgid "Removing generation %s" +msgstr "Pašalinama generacija %s" + +#: home-manager/home-manager:385 +msgid "No generations to expire" +msgstr "" + +#: home-manager/home-manager:396 +msgid "No home-manager packages seem to be installed." +msgstr "Nėra instaliuotų home-manager paketų." + +#: home-manager/home-manager:453 +msgid "Unknown argument %s" +msgstr "Nežinomas argumentas %s" + +#: home-manager/home-manager:469 +msgid "This will remove Home Manager from your system." +msgstr "Tai pašalins Home Manager iš jūsų sistemos." + +#: home-manager/home-manager:472 +msgid "This is a dry run, nothing will actually be uninstalled." +msgstr "Tai bandomasis paleidimas, niekas nebus ištrinta." + +#: home-manager/home-manager:476 +msgid "Really uninstall Home Manager?" +msgstr "Tikrai išdiegti Home Manager?" + +#: home-manager/home-manager:481 +msgid "Switching to empty Home Manager configuration..." +msgstr "Perjungiama į tuščią Home Manager konfigūraciją..." + +#: home-manager/home-manager:493 +msgid "Yay!" +msgstr "Valio!" + +#: home-manager/home-manager:500 +msgid "Remove all Home Manager generations?" +msgstr "Pašalinti visas Home Manager generacijas?" + +#: home-manager/home-manager:507 +msgid "All generations are now eligible for garbage collection." +msgstr "" +"Visos generacijos jau tinkamos šiukšlių surinkimui (garbage collection)." + +#: home-manager/home-manager:510 +msgid "Leaving generations but they may still be garbage collected." +msgstr "" + +#: home-manager/home-manager:514 +msgid "Home Manager is uninstalled but your home.nix is left untouched." +msgstr "Home Manager yra išdiegtas, bet jūsų home.nix liko nepaliestas." + +#: home-manager/home-manager:673 +msgid "%s: unknown option '%s'" +msgstr "%s: nežinomas pasirinkimas „%s“" + +#: home-manager/home-manager:674 +msgid "Run '%s --help' for usage help" +msgstr "Paleiskite „%s --help“, kad gautumėte naudojimosi instrukcijas" + +#: home-manager/home-manager:708 +msgid "expire-generations expects one argument, got %d." +msgstr "expire-generations tikisi vieno argumento, gauta %d." + +#: home-manager/home-manager:730 +msgid "Unknown command: %s" +msgstr "Nežinoma komanda: %s" + +#: home-manager/install.nix:22 +msgid "Creating initial Home Manager configuration..." +msgstr "Kuriama pradinė Home Manager konfigūracija..." + +#: home-manager/install.nix:66 +msgid "Creating initial Home Manager generation..." +msgstr "Kuriama pradinė Home Manager generacija..." + +#. translators: The "%s" specifier will be replaced by a file path. +#: home-manager/install.nix:71 +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 "" +"Viskas baigta! Įrankis home-manager turėtų būti įdiegtas ir dabar galite " +"redaguoti\n" +"\n" +". . . .%s\n" +"\n" +", kad konfigūruotumėte Home Manager. Paleiskite „man home-configuration.nix“," +"\n" +"jei norite pamatyti visus pasirinkimus." + +#. translators: The "%s" specifier will be replaced by a URL. +#: home-manager/install.nix:76 +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 "" + +#: home-manager/install.nix:83 +msgid "This derivation is not buildable, please run it using nix-shell." +msgstr "" diff --git a/home-manager/po/nb_NO.po b/home-manager/po/nb_NO.po index 55127791..4ab763af 100644 --- a/home-manager/po/nb_NO.po +++ b/home-manager/po/nb_NO.po @@ -8,16 +8,16 @@ msgstr "" "Project-Id-Version: Home Manager\n" "Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" "POT-Creation-Date: 2022-03-26 15:08+0100\n" -"PO-Revision-Date: 2021-12-13 20:50+0000\n" -"Last-Translator: Allan Nordhøy \n" -"Language-Team: Norwegian Bokmål \n" +"PO-Revision-Date: 2023-01-08 11:50+0000\n" +"Last-Translator: Petter K \n" +"Language-Team: Norwegian Bokmål \n" "Language: nb_NO\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 4.10-dev\n" +"X-Generator: Weblate 4.15.1-dev\n" #: home-manager/home-manager:60 msgid "No configuration file found at %s" @@ -139,12 +139,13 @@ msgid "Unknown command: %s" msgstr "Ukjent kommando: %s" #: home-manager/install.nix:22 +#, fuzzy msgid "Creating initial Home Manager configuration..." -msgstr "" +msgstr "Oppretter ny Home Manager-konfigurasjon..." #: home-manager/install.nix:66 msgid "Creating initial Home Manager generation..." -msgstr "" +msgstr "Oppretter ny Home Manager-generasjon..." #. translators: The "%s" specifier will be replaced by a file path. #: home-manager/install.nix:71 diff --git a/home-manager/po/nl.po b/home-manager/po/nl.po index 358d5dea..58c90c26 100644 --- a/home-manager/po/nl.po +++ b/home-manager/po/nl.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: 2022-03-26 15:08+0100\n" -"PO-Revision-Date: 2022-07-12 19:40+0000\n" -"Last-Translator: Frederik Engels \n" +"PO-Revision-Date: 2022-11-16 13:47+0000\n" +"Last-Translator: Pablo Bollansee \n" "Language-Team: Dutch \n" "Language: nl\n" @@ -17,23 +17,23 @@ 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 4.14-dev\n" +"X-Generator: Weblate 4.15-dev\n" #: home-manager/home-manager:60 msgid "No configuration file found at %s" -msgstr "" +msgstr "Geen configuratiebestand gevonden op %s" #: home-manager/home-manager:79 msgid "No configuration file found. Please create one at %s" -msgstr "" +msgstr "Geen configuratiebestand gevonden, maak er alstublieft een aan op %s" #: home-manager/home-manager:122 msgid "Can't inspect options of a flake configuration" -msgstr "" +msgstr "Kan de opties van een flake configuratie niet inspecteren" #: home-manager/home-manager:162 msgid "Can't instantiate a flake configuration" -msgstr "" +msgstr "Het is niet gelukt om de vlok-configuratie te creëren" #: home-manager/home-manager:237 msgid "" @@ -43,66 +43,68 @@ msgid_plural "" "There are %d unread and relevant news items.\n" "Read them by running the command \"%s news\"." msgstr[0] "" +"Er is %d ongelezen and relevant nieuws artikel.\n" +"Lees het door het commando \"%s news\" uit te voeren." msgstr[1] "" +"Er zijn %d ongelezen and relevante nieuws artikelen.\n" +"Lees ze door het commando \"%s news\" uit te voeren." #: home-manager/home-manager:251 msgid "Unknown \"news.display\" setting \"%s\"." -msgstr "" +msgstr "Onbekende \"new.display\" instelling \"%s\"." #: home-manager/home-manager:258 #, sh-format msgid "Please set the $EDITOR environment variable" -msgstr "" +msgstr "Gelieve de $EDITOR omgevingsvariabele in te stellen" #: home-manager/home-manager:273 msgid "Cannot run build in read-only directory" -msgstr "" +msgstr "Het is niet mogelijk om te bouwen in een read-only map" #: home-manager/home-manager:355 msgid "No generation with ID %s" -msgstr "" +msgstr "Geen generatie met de ID %s" #: home-manager/home-manager:357 msgid "Cannot remove the current generation %s" -msgstr "" +msgstr "Het is niet mogelijk om de huidige generatie %s te verwijderen" #: home-manager/home-manager:359 msgid "Removing generation %s" -msgstr "" +msgstr "Generatie %s aan het verwijderen" #: home-manager/home-manager:385 msgid "No generations to expire" -msgstr "" +msgstr "Geen generatie om te beëindigen" #: home-manager/home-manager:396 msgid "No home-manager packages seem to be installed." -msgstr "" +msgstr "Er lijkt geen home-manager pakket geïnstalleerd te zijn." #: home-manager/home-manager:453 msgid "Unknown argument %s" msgstr "Onbekend argument %s" #: home-manager/home-manager:469 -#, fuzzy msgid "This will remove Home Manager from your system." msgstr "Dit zal Home Manager van jouw systeem verwijderen." #: home-manager/home-manager:472 -#, fuzzy msgid "This is a dry run, nothing will actually be uninstalled." -msgstr "Dit is een oefening, niks word werkelijk geinstalleerd." +msgstr "Dit is een oefening, niets wordt werkelijk geïnstalleerd." #: home-manager/home-manager:476 msgid "Really uninstall Home Manager?" -msgstr "Werkelijk Home Manager verwijderen?" +msgstr "Wilt u zeker Home Manager verwijderen?" #: home-manager/home-manager:481 msgid "Switching to empty Home Manager configuration..." -msgstr "" +msgstr "Naar een lege Home Manager configuratie aan het veranderen..." #: home-manager/home-manager:493 msgid "Yay!" -msgstr "Jaaa!" +msgstr "Joepie!" #: home-manager/home-manager:500 msgid "Remove all Home Manager generations?" @@ -114,7 +116,7 @@ msgstr "Alle generaties zijn nu in aanmerking voor afvalinzameling." #: home-manager/home-manager:510 msgid "Leaving generations but they may still be garbage collected." -msgstr "" +msgstr "Generaties blijven momenteel bestaan maar worden later opgekuist." #: home-manager/home-manager:514 msgid "Home Manager is uninstalled but your home.nix is left untouched." @@ -126,11 +128,11 @@ msgstr "%s: onbekende keuze '%s'" #: home-manager/home-manager:674 msgid "Run '%s --help' for usage help" -msgstr "" +msgstr "Voer '%s --help' in om gebruiksinfo te zien" #: home-manager/home-manager:708 msgid "expire-generations expects one argument, got %d." -msgstr "" +msgstr "expire-generations verwacht één argument, maar kreeg er %d." #: home-manager/home-manager:730 msgid "Unknown command: %s" @@ -138,11 +140,11 @@ msgstr "Onbekende opdracht: %s" #: home-manager/install.nix:22 msgid "Creating initial Home Manager configuration..." -msgstr "" +msgstr "Initiële Home Manager configuratie aan het maken..." #: home-manager/install.nix:66 msgid "Creating initial Home Manager generation..." -msgstr "" +msgstr "Initiële Home Manager generatie aan het maken..." #. translators: The "%s" specifier will be replaced by a file path. #: home-manager/install.nix:71 @@ -154,6 +156,14 @@ msgid "" "to configure Home Manager. Run 'man home-configuration.nix' to\n" "see all available options." msgstr "" +"Helemaal klaar! De home-manager tool zou nu geïnstalleerd moeten zijn en je " +"kan\n" +"\n" +" %s\n" +"\n" +"aanpassen om Home Manager te configureren. Draai 'man home-" +"configuration.nix' om\n" +"alle opties te zien." #. translators: The "%s" specifier will be replaced by a URL. #: home-manager/install.nix:76 @@ -164,9 +174,13 @@ msgid "" "\n" "if the error seems to be the fault of Home Manager." msgstr "" +"Oh nee, de installatie is mislukt. Gelieve een ticket aan te maken in\n" +"\n" +" %s\n" +"\n" +"als de error de schuld van Home Manager lijkt te zijn." #: home-manager/install.nix:83 -#, fuzzy msgid "This derivation is not buildable, please run it using nix-shell." msgstr "" "Deze afleiding kan niet gebouwd worden, voer het alstublieft uit met nix-" diff --git a/lib/bash/color-echo b/lib/bash/color-echo deleted file mode 100644 index c1638180..00000000 --- a/lib/bash/color-echo +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env bash - -# The check for terminal output and color support is heavily inspired -# by https://unix.stackexchange.com/a/10065. -# -# Allow opt out by respecting the `NO_COLOR` environment variable. - -function setupColors() { - normalColor="" - errorColor="" - warnColor="" - noteColor="" - - # Enable colors for terminals, and allow opting out. - if [[ ! -v NO_COLOR && -t 1 ]]; then - # See if it supports colors. - local ncolors - ncolors=$(tput colors) - - if [[ -n "$ncolors" && "$ncolors" -ge 8 ]]; then - normalColor="$(tput sgr0)" - errorColor="$(tput bold)$(tput setaf 1)" - warnColor="$(tput setaf 3)" - noteColor="$(tput bold)$(tput setaf 6)" - fi - fi -} - -setupColors - -function errorEcho() { - echo "${errorColor}$*${normalColor}" -} - -function warnEcho() { - echo "${warnColor}$*${normalColor}" -} - -function noteEcho() { - echo "${noteColor}$*${normalColor}" -} diff --git a/lib/bash/home-manager.sh b/lib/bash/home-manager.sh index c7ff5c34..b7f3f42b 100644 --- a/lib/bash/home-manager.sh +++ b/lib/bash/home-manager.sh @@ -23,7 +23,7 @@ function setupColors() { if [[ ! -v NO_COLOR && -t 1 ]]; then # See if it supports colors. local ncolors - ncolors=$(tput colors) + ncolors=$(tput colors 2> /dev/null || echo 0) if [[ -n "$ncolors" && "$ncolors" -ge 8 ]]; then normalColor="$(tput sgr0)" diff --git a/modules/accounts/email.nix b/modules/accounts/email.nix index a5ded6a0..2d158a21 100644 --- a/modules/accounts/email.nix +++ b/modules/accounts/email.nix @@ -44,6 +44,19 @@ let ''; }; + delimiter = mkOption { + type = types.str; + default = '' + -- + ''; + example = literalExpression '' + ~*~*~*~*~*~*~*~*~*~*~*~ + ''; + description = '' + The delimiter used between the document and the signature. + ''; + }; + command = mkOption { type = with types; nullOr path; default = null; diff --git a/modules/config/home-cursor.nix b/modules/config/home-cursor.nix index d8cbb539..18bc04c1 100644 --- a/modules/config/home-cursor.nix +++ b/modules/config/home-cursor.nix @@ -97,7 +97,7 @@ in { description = '' Cursor configuration. Set to null to disable. - Top-level options declared under this submodule are backend indepedent + Top-level options declared under this submodule are backend independent options. Options declared under namespaces such as x11 are backend specific options. By default, only backend independent cursor configurations are generated. If you need configurations for specific @@ -131,8 +131,8 @@ in { # https://github.com/nix-community/home-manager/issues/2812 # https://wiki.archlinux.org/title/Cursor_themes#Environment_variable home.sessionVariables = { - XCURSOR_PATH = "$XCURSOR_PATH\${XCURSOR_PATH:+:}" - + "${config.home.profileDirectory}/share/icons"; + XCURSOR_PATH = mkDefault ("$XCURSOR_PATH\${XCURSOR_PATH:+:}" + + "${config.home.profileDirectory}/share/icons"); }; } diff --git a/modules/files.nix b/modules/files.nix index f5d7a2b8..78573201 100644 --- a/modules/files.nix +++ b/modules/files.nix @@ -4,7 +4,7 @@ with lib; let - cfg = config.home.file; + cfg = filterAttrs (n: f: f.enable) config.home.file; homeDirectory = config.home.homeDirectory; @@ -185,8 +185,9 @@ in $VERBOSE_ECHO "Skipping '$targetPath' as it is identical to '$sourcePath'" else # Place that symlink, --force + # This can still fail if the target is a directory, in which case we bail out. $DRY_RUN_CMD mkdir -p $VERBOSE_ARG "$(dirname "$targetPath")" - $DRY_RUN_CMD ln -nsf $VERBOSE_ARG "$sourcePath" "$targetPath" + $DRY_RUN_CMD ln -Tsf $VERBOSE_ARG "$sourcePath" "$targetPath" || exit 1 fi done ''; diff --git a/modules/home-environment.nix b/modules/home-environment.nix index 38576260..098e10b2 100644 --- a/modules/home-environment.nix +++ b/modules/home-environment.nix @@ -256,7 +256,7 @@ in home.sessionVariables = mkOption { default = {}; - type = types.attrs; + type = with types; lazyAttrsOf (oneOf [ str path int float ]); example = { EDITOR = "emacs"; GS_OPTIONS = "-sPAPERSIZE=a4"; }; description = '' Environment variables to always set at login. @@ -346,12 +346,18 @@ in home.emptyActivationPath = mkOption { internal = true; - default = false; type = types.bool; + default = versionAtLeast stateVersion "22.11"; + defaultText = literalExpression '' + false for state version < 22.11, + true for state version ≥ 22.11 + ''; description = '' Whether the activation script should start with an empty - PATH variable. When false - then the user's PATH will be used. + PATH variable. When false then the + user's PATH will be accessible in the script. It is + recommended to keep this at true to avoid + uncontrolled use of tools found in PATH. ''; }; @@ -581,7 +587,6 @@ in if [[ -e "$nixProfilePath"/manifest.json ]] ; then nix profile list \ | { grep 'home-manager-path$' || test $? = 1; } \ - | awk -F ' ' '{ print $4 }' \ | cut -d ' ' -f 4 \ | xargs -t $DRY_RUN_CMD nix profile remove $VERBOSE_ARG else @@ -592,22 +597,36 @@ in '' else '' + function nixReplaceProfile() { + local oldNix="$(command -v nix)" + + nix profile list \ + | { grep 'home-manager-path$' || test $? = 1; } \ + | cut -d ' ' -f 4 \ + | xargs -t $DRY_RUN_CMD nix profile remove $VERBOSE_ARG + + $DRY_RUN_CMD $oldNix profile install $1 + } + if [[ -e "$nixProfilePath"/manifest.json ]] ; then INSTALL_CMD="nix profile install" + INSTALL_CMD_ACTUAL="nixReplaceProfile" LIST_CMD="nix profile list" REMOVE_CMD_SYNTAX='nix profile remove {number | store path}' else INSTALL_CMD="nix-env -i" + INSTALL_CMD_ACTUAL="$DRY_RUN_CMD nix-env -i" LIST_CMD="nix-env -q" REMOVE_CMD_SYNTAX='nix-env -e {package name}' fi - if ! $DRY_RUN_CMD $INSTALL_CMD ${cfg.path} ; then + if ! $INSTALL_CMD_ACTUAL ${cfg.path} ; then echo _iError $'Oops, Nix failed to install your new Home Manager profile!\n\nPerhaps there is a conflict with a package that was installed using\n"%s"? Try running\n\n %s\n\nand if there is a conflicting package you can remove it with\n\n %s\n\nThen try activating your Home Manager configuration again.' "$INSTALL_CMD" "$LIST_CMD" "$REMOVE_CMD_SYNTAX" exit 1 fi - unset INSTALL_CMD LIST_CMD REMOVE_CMD_SYNTAX + unset -f nixReplaceProfile + unset INSTALL_CMD INSTALL_CMD_ACTUAL LIST_CMD REMOVE_CMD_SYNTAX '' ); @@ -659,7 +678,16 @@ in gnugrep gnused ncurses # For `tput`. - ] ++ config.home.extraActivationPath + ] + ++ config.home.extraActivationPath + ) + + ( + # Add path of the Nix binaries, if a Nix package is configured, then + # use that one, otherwise grab the path of the nix-env tool. + if config.nix.enable && config.nix.package != null then + ":${config.nix.package}/bin" + else + ":$(${pkgs.coreutils}/bin/dirname $(${pkgs.coreutils}/bin/readlink -m $(type -p nix-env)))" ) + optionalString (!cfg.emptyActivationPath) "\${PATH:+:}$PATH"; @@ -685,6 +713,8 @@ in '' mkdir -p $out + echo "${config.home.version.full}" > $out/hm-version + cp ${activationScript} $out/activate mkdir $out/bin diff --git a/modules/i18n/input-method/fcitx5.nix b/modules/i18n/input-method/fcitx5.nix index 9211d0b7..78eb9708 100644 --- a/modules/i18n/input-method/fcitx5.nix +++ b/modules/i18n/input-method/fcitx5.nix @@ -24,6 +24,7 @@ in { i18n.inputMethod.package = fcitx5Package; home.sessionVariables = { + GLFW_IM_MODULE = "ibus"; # IME support in kitty GTK_IM_MODULE = "fcitx"; QT_IM_MODULE = "fcitx"; XMODIFIERS = "@im=fcitx"; diff --git a/modules/launchd/default.nix b/modules/launchd/default.nix index 17b36cdb..34fefc17 100644 --- a/modules/launchd/default.nix +++ b/modules/launchd/default.nix @@ -162,12 +162,12 @@ in { fi if [[ -f "$dstPath" ]]; then for (( i = 0; i < bootout_retries; i++ )); do - $DRY_RUN_CMD launchctl bootout "$domain/$agentName" || err=$? + $DRY_RUN_CMD /bin/launchctl bootout "$domain/$agentName" || err=$? if [[ -v DRY_RUN ]]; then break fi if (( err != 9216 )) && - ! launchctl print "$domain/$agentName" &> /dev/null; then + ! /bin/launchctl print "$domain/$agentName" &> /dev/null; then break fi sleep 1 @@ -178,7 +178,7 @@ in { fi fi $DRY_RUN_CMD install -Dm444 -T "$srcPath" "$dstPath" - $DRY_RUN_CMD launchctl bootstrap "$domain" "$dstPath" + $DRY_RUN_CMD /bin/launchctl bootstrap "$domain" "$dstPath" done if [[ ! -e "$oldDir" ]]; then @@ -194,7 +194,7 @@ in { continue fi - $DRY_RUN_CMD launchctl bootout "$domain/$agentName" || : + $DRY_RUN_CMD /bin/launchctl bootout "$domain/$agentName" || : if [[ ! -e "$dstPath" ]]; then continue fi diff --git a/modules/launchd/launchd.nix b/modules/launchd/launchd.nix index b54345b7..2e0e6585 100644 --- a/modules/launchd/launchd.nix +++ b/modules/launchd/launchd.nix @@ -39,19 +39,19 @@ with lib; default = null; description = '' This optional key is used as a hint to launchctl(1) that it should not submit this job to launchd when - loading a job or jobs. The value of this key does NOT reflect the current state of the job on the run-ning running - ning system. If you wish to know whether a job is loaded in launchd, reading this key from a configura-tion configuration - tion file yourself is not a sufficient test. You should query launchd for the presence of the job using + loading a job or jobs. The value of this key does NOT reflect the current state of the job on the running + system. If you wish to know whether a job is loaded in launchd, reading this key from a configuration + file yourself is not a sufficient test. You should query launchd for the presence of the job using the launchctl(1) list subcommand or use the ServiceManagement framework's SMJobCopyDictionary() method. Note that as of Mac OS X v10.6, this key's value in a configuration file conveys a default value, which is changed with the [-w] option of the launchctl(1) load and unload subcommands. These subcommands no - longer modify the configuration file, so the value displayed in the configuration file is not necessar-ily necessarily - ily the value that launchctl(1) will apply. See launchctl(1) for more information. + longer modify the configuration file, so the value displayed in the configuration file is not necessarily + the value that launchctl(1) will apply. See launchctl(1) for more information. - Please also be mindful that you should only use this key if the provided on-demand and KeepAlive crite-ria criteria - ria are insufficient to describe the conditions under which your job needs to run. The cost to have a + Please also be mindful that you should only use this key if the provided on-demand and KeepAlive criteria + are insufficient to describe the conditions under which your job needs to run. The cost to have a job loaded in launchd is negligible, so there is no harm in loading a job which only runs once or very rarely. ''; @@ -147,8 +147,7 @@ with lib; type = types.nullOr types.bool; default = null; description = '' - This flag causes launchd to use the glob(3) mechanism to update the program arguments before invoca-tion. invocation. - tion. + This flag causes launchd to use the glob(3) mechanism to update the program arguments before invocation. ''; }; @@ -236,12 +235,12 @@ with lib; description = '' This optional key is used to control whether your job is to be kept continuously running or to let demand and conditions control the invocation. The default is false and therefore only demand will start - the job. The value may be set to true to unconditionally keep the job alive. Alternatively, a dictio-nary dictionary - nary of conditions may be specified to selectively control whether launchd keeps a job alive or not. If + the job. The value may be set to true to unconditionally keep the job alive. Alternatively, a dictionary + of conditions may be specified to selectively control whether launchd keeps a job alive or not. If multiple keys are provided, launchd ORs them, thus providing maximum flexibility to the job to refine the logic and stall if necessary. If launchd finds no reason to restart the job, it falls back on demand based invocation. Jobs that exit quickly and frequently when configured to be kept alive will - be throttled to converve system resources. + be throttled to conserve system resources. ''; }; @@ -677,8 +676,8 @@ with lib; XPC connections. See xpc_transaction_begin(3) for details. Interactive - Interactive jobs run with the same resource limitations as apps, that is to say, none. Interac-tive Interactive - tive jobs are critical to maintaining a responsive user experience, and this key should only be + Interactive jobs run with the same resource limitations as apps, that is to say, none. Interactive + jobs are critical to maintaining a responsive user experience, and this key should only be used if an app's ability to be responsive depends on it, and cannot be made Adaptive. ''; }; @@ -687,8 +686,8 @@ with lib; type = types.nullOr types.bool; default = null; description = '' - When a job dies, launchd kills any remaining processes with the same process group ID as the job. Set-ting Setting - ting this key to true disables that behavior. + When a job dies, launchd kills any remaining processes with the same process group ID as the job. Setting + this key to true disables that behavior. ''; }; @@ -753,9 +752,9 @@ with lib; description = '' This optional key is used to specify launch on demand sockets that can be used to let launchd know when to run the job. The job must check-in to get a copy of the file descriptors using APIs outlined in - launch(3). The keys of the top level Sockets dictionary can be anything. They are meant for the appli-cation application - cation developer to use to differentiate which descriptors correspond to which application level proto-cols protocols - cols (e.g. http vs. ftp vs. DNS...). At check-in time, the value of each Sockets dictionary key will + launch(3). The keys of the top level Sockets dictionary can be anything. They are meant for the application + developer to use to differentiate which descriptors correspond to which application level protocols + (e.g. http vs. ftp vs. DNS...). At check-in time, the value of each Sockets dictionary key will be an array of descriptors. Daemon/Agent writers should consider all descriptors of a given key to be to be effectively equivalent, even though each file descriptor likely represents a different networking protocol which conforms to the criteria specified in the job configuration file. @@ -829,8 +828,8 @@ with lib; default = null; description = '' This optional key is a variant of SockPathName. Instead of binding to a known path, a securely - generated socket is created and the path is assigned to the environment variable that is inher-ited inherited - ited by all jobs spawned by launchd. + generated socket is created and the path is assigned to the environment variable that is inherited + by all jobs spawned by launchd. ''; }; diff --git a/modules/lib-bash/color-echo.sh b/modules/lib-bash/color-echo.sh deleted file mode 100644 index ac36cedc..00000000 --- a/modules/lib-bash/color-echo.sh +++ /dev/null @@ -1,39 +0,0 @@ -# The check for terminal output and color support is heavily inspired -# by https://unix.stackexchange.com/a/10065. -# -# Allow opt out by respecting the `NO_COLOR` environment variable. - -function setupColors() { - normalColor="" - errorColor="" - warnColor="" - noteColor="" - - # Enable colors for terminals, and allow opting out. - if [[ ! -v NO_COLOR && -t 1 ]]; then - # See if it supports colors. - local ncolors - ncolors=$(tput colors) - - if [[ -n "$ncolors" && "$ncolors" -ge 8 ]]; then - normalColor="$(tput sgr0)" - errorColor="$(tput bold)$(tput setaf 1)" - warnColor="$(tput setaf 3)" - noteColor="$(tput bold)$(tput setaf 6)" - fi - fi -} - -setupColors - -function errorEcho() { - echo "${errorColor}$*${normalColor}" -} - -function warnEcho() { - echo "${warnColor}$*${normalColor}" -} - -function noteEcho() { - echo "${noteColor}$*${normalColor}" -} diff --git a/modules/lib/file-type.nix b/modules/lib/file-type.nix index f4719cd9..6f0b05c7 100644 --- a/modules/lib/file-type.nix +++ b/modules/lib/file-type.nix @@ -15,6 +15,14 @@ in fileType = basePathDesc: basePath: types.attrsOf (types.submodule ( { name, config, ... }: { options = { + enable = mkOption { + type = types.bool; + default = true; + description = '' + Whether this file should be generated. This option allows specific + files to be disabled. + ''; + }; target = mkOption { type = types.str; apply = p: diff --git a/modules/lib/gvariant.nix b/modules/lib/gvariant.nix index 7c4ca5b0..bbb97c64 100644 --- a/modules/lib/gvariant.nix +++ b/modules/lib/gvariant.nix @@ -20,6 +20,7 @@ let arrayOf = t: "a${t}"; maybeOf = t: "m${t}"; tupleOf = ts: "(${concatStrings ts})"; + dictionaryEntryOf = ts: "{${concatStrings ts}}"; string = "s"; boolean = "b"; uchar = "y"; @@ -30,6 +31,7 @@ let int64 = "x"; uint64 = "t"; double = "d"; + variant = "v"; }; # Returns the GVariant type of a given Nix value. If no type can be @@ -74,13 +76,13 @@ in rec { isGVariant = v: v._type or "" == "gvariant"; isArray = hasPrefix "a"; + isDictionaryEntry = hasPrefix "{"; isMaybe = hasPrefix "m"; isTuple = hasPrefix "("; # Returns the GVariant value that most closely matches the given Nix # value. If no GVariant value can be found then `null` is returned. - # - # No support for dictionaries, maybe types, or variants. + mkValue = v: if builtins.isBool v then mkBoolean v @@ -105,6 +107,21 @@ in rec { mkEmptyArray = elemType: mkArray elemType [ ]; + mkVariant = elem: + let gvarElem = mkValue elem; + in mkPrimitive type.variant gvarElem // { + __toString = self: "@${self.type} <${toString self.value}>"; + }; + + mkDictionaryEntry = elems: + let + gvarElems = map mkValue elems; + dictionaryType = type.dictionaryEntryOf (map (e: e.type) gvarElems); + in mkPrimitive dictionaryType gvarElems // { + __toString = self: + "@${self.type} {${concatMapStringsSep "," toString self.value}}"; + }; + mkNothing = elemType: mkMaybe elemType null; mkJust = elem: let gvarElem = mkValue elem; in mkMaybe gvarElem.type gvarElem; diff --git a/modules/lib/maintainers.nix b/modules/lib/maintainers.nix index ab224efc..267a42a3 100644 --- a/modules/lib/maintainers.nix +++ b/modules/lib/maintainers.nix @@ -37,12 +37,28 @@ github = "CarlosLoboxyz"; githubId = 86011416; }; + d-dervishi = { + email = "david.dervishi@epfl.ch"; + github = "d-dervishi"; + githubId = 61125355; + name = "David Dervishi"; + keys = [{ + longKeyId = "rsa4096/0xB1C012F0E7697195"; + fingerprint = "4C92 E3B0 21B5 5562 A1E0 CE3D B1C0 12F0 E769 7195"; + }]; + }; dwagenk = { email = "dwagenk@mailbox.org"; github = "dwagenk"; githubId = 32838899; name = "Daniel Wagenknecht"; }; + jkarlson = { + email = "jekarlson@gmail.com"; + github = "jkarlson"; + githubId = 1204734; + name = "Emil Karlson"; + }; justinlovinger = { name = "Justin Lovinger"; email = "git@justinlovinger.com"; @@ -101,6 +117,12 @@ fingerprint = "2BE3 BAFD 793E A349 ED1F F00F 04D0 CEAF 916A 9A40"; }]; }; + katexochen = { + name = "Paul Meyer"; + email = "49727155+katexochen@users.noreply.github.com"; + github = "katexochen"; + githubId = 49727155; + }; kubukoz = { name = "Jakub Kozłowski"; email = "kubukoz@users.noreply.github.com"; @@ -211,6 +233,12 @@ githubId = 1553581; name = "Josh Robson Chase"; }; + jwygoda = { + name = "Jarosław Wygoda"; + email = "jaroslaw@wygoda.me"; + github = "jwygoda"; + githubId = 20658981; + }; hawkw = { name = "Eliza Weisman"; email = "eliza@elizas.website"; @@ -289,6 +317,12 @@ github = "sebtm"; githubId = 17243347; }; + rosuavio = { + name = "Rosario Pulella"; + email = "RosarioPulella@gmail.com"; + github = "Rosuavio"; + githubId = 7164552; + }; rszamszur = { name = "Radosław Szamszur"; email = "radoslawszamszur@gmail.com"; @@ -317,4 +351,20 @@ github = "lukasngl"; githubId = 69244516; }; + toastal = { + email = "toastal+nix@posteo.net"; + matrix = "@toastal:matrix.org"; + github = "toastal"; + githubId = 561087; + name = "toastal"; + keys = + [{ fingerprint = "7944 74B7 D236 DAB9 C9EF E7F9 5CCE 6F14 66D4 7C9E"; }]; + }; + tomodachi94 = { + email = "tomodachi94+nixpkgs@protonmail.com"; + matrix = "@tomodachi94:matrix.org"; + github = "tomodachi94"; + githubId = 68489118; + name = "tomodachi94"; + }; } diff --git a/modules/lib/types.nix b/modules/lib/types.nix index d2ed24a3..0195bbfc 100644 --- a/modules/lib/types.nix +++ b/modules/lib/types.nix @@ -55,7 +55,7 @@ in rec { }; size = mkOption { - type = types.nullOr types.int; + type = types.nullOr types.number; default = null; example = "8"; description = '' @@ -95,6 +95,10 @@ in rec { mergeOneOption loc defs else if gvar.isMaybe sharedDefType && allChecked then mergeOneOption loc defs + else if gvar.isDictionaryEntry sharedDefType && allChecked then + mergeOneOption loc defs + else if gvar.type.variant == sharedDefType && allChecked then + mergeOneOption loc defs else if gvar.type.string == sharedDefType && allChecked then types.str.merge loc defs else if gvar.type.double == sharedDefType && allChecked then diff --git a/modules/misc/dconf.nix b/modules/misc/dconf.nix index d731679c..aaefdfa3 100644 --- a/modules/misc/dconf.nix +++ b/modules/misc/dconf.nix @@ -10,6 +10,14 @@ let mkIniKeyValue = key: value: "${key}=${toString (hm.gvariant.mkValue value)}"; + # The dconf keys managed by this configuration. We store this as part of the + # generation state to be able to reset keys that become unmanaged during + # switch. + stateDconfKeys = pkgs.writeText "dconf-keys.json" (builtins.toJSON + (concatLists (mapAttrsToList + (dir: entries: mapAttrsToList (key: _: "/${dir}/${key}") entries) + cfg.settings))); + in { meta.maintainers = [ maintainers.rycee ]; @@ -54,22 +62,58 @@ in { # Make sure the dconf directory exists. xdg.configFile."dconf/.keep".source = builtins.toFile "keep" ""; - home.activation.dconfSettings = hm.dag.entryAfter [ "installPackages" ] - (let iniFile = pkgs.writeText "hm-dconf.ini" (toDconfIni cfg.settings); - in '' - if [[ -v DBUS_SESSION_BUS_ADDRESS ]]; then - DCONF_DBUS_RUN_SESSION="" - else - DCONF_DBUS_RUN_SESSION="${pkgs.dbus}/bin/dbus-run-session" + home.extraBuilderCommands = '' + mkdir -p $out/state/ + ln -s ${stateDconfKeys} $out/state/${stateDconfKeys.name} + ''; + + home.activation.dconfSettings = hm.dag.entryAfter [ "installPackages" ] (let + iniFile = pkgs.writeText "hm-dconf.ini" (toDconfIni cfg.settings); + + statePath = "state/${stateDconfKeys.name}"; + + cleanup = pkgs.writeShellScript "dconf-cleanup" '' + set -euo pipefail + + ${config.lib.bash.initHomeManagerLib} + + PATH=${makeBinPath [ pkgs.dconf pkgs.jq ]}''${PATH:+:}$PATH + + oldState="$1" + newState="$2" + + # Can't do cleanup if we don't know the old state. + if [[ ! -f $oldState ]]; then + exit 0 fi - if [[ -v DRY_RUN ]]; then - echo $DCONF_DBUS_RUN_SESSION ${pkgs.dconf}/bin/dconf load / "<" ${iniFile} - else - $DCONF_DBUS_RUN_SESSION ${pkgs.dconf}/bin/dconf load / < ${iniFile} - fi + # Reset all keys that are present in the old generation but not the new + # one. + jq -r -n \ + --slurpfile old "$oldState" \ + --slurpfile new "$newState" \ + '($old[] - $new[])[]' \ + | while read -r key; do + $VERBOSE_ECHO "Resetting dconf key \"$key\"" + $DRY_RUN_CMD $DCONF_DBUS_RUN_SESSION dconf reset "$key" + done + ''; + in '' + if [[ -v DBUS_SESSION_BUS_ADDRESS ]]; then + export DCONF_DBUS_RUN_SESSION="" + else + export DCONF_DBUS_RUN_SESSION="${pkgs.dbus}/bin/dbus-run-session --dbus-daemon=${pkgs.dbus}/bin/dbus-daemon" + fi - unset DCONF_DBUS_RUN_SESSION - ''); + if [[ -v oldGenPath ]]; then + ${cleanup} \ + "$oldGenPath/${statePath}" \ + "$newGenPath/${statePath}" + fi + + $DRY_RUN_CMD $DCONF_DBUS_RUN_SESSION ${pkgs.dconf}/bin/dconf load / < ${iniFile} + + unset DCONF_DBUS_RUN_SESSION + ''); }; } diff --git a/modules/misc/news.nix b/modules/misc/news.nix index 7253b1ad..57c5574f 100644 --- a/modules/misc/news.nix +++ b/modules/misc/news.nix @@ -696,6 +696,225 @@ in A new module is available: 'programs.gallery-dl'. ''; } + + { + time = "2022-09-21T22:42:42+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'xsession.windowManager.fluxbox'. + ''; + } + + { + time = "2022-09-25T21:00:05+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.safeeyes'. + ''; + } + + { + time = "2022-09-25T22:22:17+00:00"; + message = '' + A new module is available: 'programs.tmate'. + ''; + } + + { + time = "2022-09-29T13:43:02+00:00"; + message = '' + A new module is available: 'programs.pls'. + ''; + } + + { + time = "2022-10-06T23:06:08+00:00"; + message = '' + A new module is available: 'programs.ledger'. + ''; + } + + { + time = "2022-10-06T23:19:10+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'programs.havoc'. + ''; + } + + { + time = "2022-10-12T23:10:48+00:00"; + message = '' + A new module is available: 'programs.discocss'. + ''; + } + + { + time = "2022-10-16T19:49:46+00:00"; + condition = hostPlatform.isLinux; + message = '' + Two new modules are available: + + - 'programs.borgmatic' and + - 'services.borgmatic'. + + use the first to configure the borgmatic tool and the second if you + want to automatically run scheduled backups. + ''; + } + + { + time = "2022-10-18T08:07:43+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'programs.looking-glass-client'. + ''; + } + + { + time = "2022-10-22T17:52:30+00:00"; + condition = config.programs.firefox.enable; + message = '' + It is now possible to configure the default search engine in Firefox + with + + programs.firefox.profiles..search.default + + and add custom engines with + + programs.firefox.profiles..search.engines. + + It is also recommended to set + + programs.firefox.profiles..search.force = true + + 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. + ''; + } + + { + time = "2022-10-24T22:05:27+00:00"; + message = '' + A new module is available: 'programs.k9s'. + ''; + } + + { + time = "2022-11-01T23:57:50+00:00"; + message = '' + A new module is available: 'programs.oh-my-posh'. + ''; + } + + { + time = "2022-11-02T10:56:14+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'xfconf'. + ''; + } + + { + time = "2022-11-04T14:56:46+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'programs.thunderbird'. + ''; + } + + { + time = "2022-11-13T09:05:51+00:00"; + condition = hostPlatform.isDarwin; + message = '' + A new module is available: 'programs.thunderbird'. + + Please note that the Thunderbird packages provided by Nix are + currently not working on macOS. The module can still be used to manage + configuration files by installing Thunderbird manually and setting the + 'programs.thunderbird.package' option to a dummy package, for example + using 'pkgs.runCommand'. + + This module requires you to set the following environment variables + when using an installation of Thunderbird that is not provided by Nix: + + export MOZ_LEGACY_PROFILES=1 + export MOZ_ALLOW_DOWNGRADE=1 + ''; + } + + { + time = "2022-11-27T13:14:01+00:00"; + condition = config.programs.ssh.enable; + message = '' + 'programs.ssh.matchBlocks.*' now supports literal 'Match' blocks via + 'programs.ssh.matchBlocks.*.match' option as an alternative to plain + 'Host' blocks + ''; + } + + { + time = "2022-12-16T15:01:20+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.megasync'. + ''; + } + + { + time = "2022-12-25T08:41:32+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.cachix-agent'. + ''; + } + + { + time = "2022-12-28T21:48:22+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.clipman'. + ''; + } + + { + time = "2023-01-07T10:47:03+00:00"; + condition = hostPlatform.isLinux; + message = '' + 'xsession.windowManager.i3.config.[window|floating].titlebar' and + 'wayland.windowManager.sway.config.[window|floating].titlebar' now default to 'true'. + ''; + } + + { + time = "2023-01-28T17:35:49+00:00"; + message = '' + A new module is available: 'programs.papis'. + ''; + } + + { + time = "2023-01-30T10:39:11+00:00"; + message = '' + A new module is available: 'programs.wlogout'. + ''; + } + + { + time = "2023-01-31T22:08:41+00:00"; + message = '' + A new module is available: 'programs.rbenv'. + ''; + } + + { + time = "2023-02-02T20:49:05+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.autorandr'. + ''; + } ]; }; } diff --git a/modules/misc/nix.nix b/modules/misc/nix.nix index 7214ac4b..6ae28157 100644 --- a/modules/misc/nix.nix +++ b/modules/misc/nix.nix @@ -202,7 +202,7 @@ in { nix.conf 5 - for avalaible options. + for available options. The value declared here will be translated directly to the key-value pairs Nix expects. diff --git a/modules/misc/version.nix b/modules/misc/version.nix index 25bc0afd..0c590372 100644 --- a/modules/misc/version.nix +++ b/modules/misc/version.nix @@ -16,6 +16,7 @@ with lib; "21.11" "22.05" "22.11" + "23.05" ]; description = '' It is occasionally necessary for Home Manager to change @@ -30,5 +31,39 @@ with lib; conversion or moving files. ''; }; + + home.version = { + full = mkOption { + internal = true; + readOnly = true; + type = types.str; + default = let + inherit (config.home.version) release revision; + suffix = + optionalString (revision != null) "+${substring 0 8 revision}"; + in "${release}${suffix}"; + example = "22.11+213a0629"; + description = "The full Home Manager version."; + }; + + release = mkOption { + internal = true; + readOnly = true; + type = types.str; + default = fileContents ../../.release; + example = "22.11"; + description = "The Home Manager release."; + }; + + revision = mkOption { + internal = true; + type = types.nullOr types.str; + default = let gitRepo = "${toString ./../..}/.git"; + in if pathIsGitRepo gitRepo then commitIdFromGitRepo gitRepo else null; + description = '' + The Git revision from which this Home Manager configuration was built. + ''; + }; + }; }; } diff --git a/modules/misc/xdg-user-dirs.nix b/modules/misc/xdg-user-dirs.nix index 9d29729a..2ea07709 100644 --- a/modules/misc/xdg-user-dirs.nix +++ b/modules/misc/xdg-user-dirs.nix @@ -33,50 +33,66 @@ in { # https://gitlab.freedesktop.org/xdg/xdg-user-dirs/blob/master/man/user-dirs.dirs.xml desktop = mkOption { - type = with types; coercedTo path toString str; - default = "$HOME/Desktop"; + type = with types; nullOr (coercedTo path toString str); + default = "${config.home.homeDirectory}/Desktop"; + defaultText = + literalExpression ''"''${config.home.homeDirectory}/Desktop"''; description = "The Desktop directory."; }; documents = mkOption { - type = with types; coercedTo path toString str; - default = "$HOME/Documents"; + type = with types; nullOr (coercedTo path toString str); + default = "${config.home.homeDirectory}/Documents"; + defaultText = + literalExpression ''"''${config.home.homeDirectory}/Documents"''; description = "The Documents directory."; }; download = mkOption { - type = with types; coercedTo path toString str; - default = "$HOME/Downloads"; + type = with types; nullOr (coercedTo path toString str); + default = "${config.home.homeDirectory}/Downloads"; + defaultText = + literalExpression ''"''${config.home.homeDirectory}/Downloads"''; description = "The Downloads directory."; }; music = mkOption { - type = with types; coercedTo path toString str; - default = "$HOME/Music"; + type = with types; nullOr (coercedTo path toString str); + default = "${config.home.homeDirectory}/Music"; + defaultText = + literalExpression ''"''${config.home.homeDirectory}/Music"''; description = "The Music directory."; }; pictures = mkOption { - type = with types; coercedTo path toString str; - default = "$HOME/Pictures"; + type = with types; nullOr (coercedTo path toString str); + default = "${config.home.homeDirectory}/Pictures"; + defaultText = + literalExpression ''"''${config.home.homeDirectory}/Pictures"''; description = "The Pictures directory."; }; publicShare = mkOption { - type = with types; coercedTo path toString str; - default = "$HOME/Public"; + type = with types; nullOr (coercedTo path toString str); + default = "${config.home.homeDirectory}/Public"; + defaultText = + literalExpression ''"''${config.home.homeDirectory}/Public"''; description = "The Public share directory."; }; templates = mkOption { - type = with types; coercedTo path toString str; - default = "$HOME/Templates"; + type = with types; nullOr (coercedTo path toString str); + default = "${config.home.homeDirectory}/Templates"; + defaultText = + literalExpression ''"''${config.home.homeDirectory}/Templates"''; description = "The Templates directory."; }; videos = mkOption { - type = with types; coercedTo path toString str; - default = "$HOME/Videos"; + type = with types; nullOr (coercedTo path toString str); + default = "${config.home.homeDirectory}/Videos"; + defaultText = + literalExpression ''"''${config.home.homeDirectory}/Videos"''; description = "The Videos directory."; }; @@ -86,7 +102,7 @@ in { defaultText = literalExpression "{ }"; example = literalExpression '' { - XDG_MISC_DIR = "$HOME/Misc"; + XDG_MISC_DIR = "''${config.home.homeDirectory}/Misc"; } ''; description = "Other user directories."; @@ -97,7 +113,7 @@ in { }; config = let - directories = { + directories = (filterAttrs (n: v: !isNull v) { XDG_DESKTOP_DIR = cfg.desktop; XDG_DOCUMENTS_DIR = cfg.documents; XDG_DOWNLOAD_DIR = cfg.download; @@ -106,7 +122,7 @@ in { XDG_PUBLICSHARE_DIR = cfg.publicShare; XDG_TEMPLATES_DIR = cfg.templates; XDG_VIDEOS_DIR = cfg.videos; - } // cfg.extraConfig; + }) // cfg.extraConfig; in mkIf cfg.enable { assertions = [ (hm.assertions.assertPlatform "xdg.userDirs" pkgs platforms.linux) ]; diff --git a/modules/misc/xfconf.nix b/modules/misc/xfconf.nix new file mode 100644 index 00000000..b4141bf5 --- /dev/null +++ b/modules/misc/xfconf.nix @@ -0,0 +1,102 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.xfconf; + + withType = v: + if builtins.isBool v then [ + "-t" + "bool" + "-s" + (if v then "true" else "false") + ] else if builtins.isInt v then [ + "-t" + "int" + "-s" + (toString v) + ] else if builtins.isFloat v then [ + "-t" + "double" + "-s" + (toString v) + ] else if builtins.isString v then [ + "-t" + "string" + "-s" + v + ] else if builtins.isList v then + [ "-a" ] ++ concatMap withType v + else + throw "unexpected xfconf type: ${builtins.typeOf v}"; + +in { + meta.maintainers = [ maintainers.chuangzhu ]; + + options.xfconf = { + enable = mkOption { + type = types.bool; + default = true; + visible = false; + description = '' + Whether to enable Xfconf settings. + + Note, if you use NixOS then you must add + programs.xfconf.enable = true + to your system configuration. Otherwise you will see a systemd error + message when your configuration is activated. + ''; + }; + + settings = mkOption { + type = with types; + attrsOf (attrsOf (oneOf [ + bool + int + float + str + (listOf (oneOf [ bool int float str ])) + ])) // { + description = "xfconf settings"; + }; + default = { }; + example = literalExpression '' + { + xfce4-session = { + "startup/ssh-agent/enabled" = false; + "general/LockCommand" = "''${pkgs.lightdm}/bin/dm-tool lock"; + }; + xfce4-desktop = { + "backdrop/screen0/monitorLVDS-1/workspace0/last-image" = + "''${pkgs.nixos-artwork.wallpapers.stripes-logo.gnomeFilePath}"; + }; + } + ''; + description = '' + Settings to write to the Xfconf configuration system. + ''; + }; + }; + + config = mkIf (cfg.enable && cfg.settings != { }) { + assertions = + [ (hm.assertions.assertPlatform "xfconf" pkgs platforms.linux) ]; + + home.activation.xfconfSettings = hm.dag.entryAfter [ "installPackages" ] + (let + mkCommand = channel: property: value: '' + $DRY_RUN_CMD ${pkgs.xfce.xfconf}/bin/xfconf-query \ + ${ + escapeShellArgs + ([ "-n" "-c" channel "-p" "/${property}" ] ++ withType value) + } + ''; + + commands = mapAttrsToList + (channel: properties: mapAttrsToList (mkCommand channel) properties) + cfg.settings; + in concatMapStrings concatStrings commands); + }; +} diff --git a/modules/modules.nix b/modules/modules.nix index 2c1e6601..391ad5bd 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -43,6 +43,7 @@ let ./misc/xdg-system-dirs.nix ./misc/xdg-user-dirs.nix ./misc/xdg.nix + ./misc/xfconf.nix ./programs/abook.nix ./programs/aerc.nix ./programs/afew.nix @@ -57,6 +58,7 @@ let ./programs/bashmount.nix ./programs/bat.nix ./programs/beets.nix + ./programs/borgmatic.nix ./programs/bottom.nix ./programs/broot.nix ./programs/browserpass.nix @@ -65,6 +67,7 @@ let ./programs/command-not-found/command-not-found.nix ./programs/dircolors.nix ./programs/direnv.nix + ./programs/discocss.nix ./programs/eclipse.nix ./programs/emacs.nix ./programs/eww.nix @@ -82,6 +85,7 @@ let ./programs/gnome-terminal.nix ./programs/go.nix ./programs/gpg.nix + ./programs/havoc.nix ./programs/helix.nix ./programs/hexchat.nix ./programs/himalaya.nix @@ -96,16 +100,19 @@ let ./programs/java.nix ./programs/jq.nix ./programs/just.nix + ./programs/k9s.nix ./programs/kakoune.nix ./programs/keychain.nix ./programs/kitty.nix ./programs/kodi.nix ./programs/lazygit.nix + ./programs/ledger.nix ./programs/less.nix ./programs/lesspipe.nix ./programs/lf.nix ./programs/librewolf.nix ./programs/lieer.nix + ./programs/looking-glass-client.nix ./programs/lsd.nix ./programs/man.nix ./programs/mangohud.nix @@ -134,14 +141,17 @@ let ./programs/obs-studio.nix ./programs/octant.nix ./programs/offlineimap.nix + ./programs/oh-my-posh.nix ./programs/opam.nix ./programs/pandoc.nix + ./programs/papis.nix ./programs/password-store.nix ./programs/pazi.nix ./programs/pet.nix ./programs/pidgin.nix ./programs/pistol.nix ./programs/piston-cli.nix + ./programs/pls.nix ./programs/powerline-go.nix ./programs/pubs.nix ./programs/pylint.nix @@ -167,19 +177,24 @@ let ./programs/terminator.nix ./programs/termite.nix ./programs/texlive.nix + ./programs/thunderbird.nix ./programs/timidity.nix ./programs/tint2.nix ./programs/tiny.nix + ./programs/tmate.nix ./programs/tmux.nix ./programs/topgrade.nix ./programs/urxvt.nix ./programs/vim.nix + ./programs/vim-vint.nix ./programs/vscode.nix ./programs/vscode/haskell.nix ./programs/pywal.nix + ./programs/rbenv.nix ./programs/watson.nix ./programs/waybar.nix ./programs/wezterm.nix + ./programs/wlogout.nix ./programs/xmobar.nix ./programs/yt-dlp.nix ./programs/z-lua.nix @@ -189,11 +204,15 @@ let ./programs/zplug.nix ./programs/zsh.nix ./programs/zsh/prezto.nix + ./services/autorandr.nix ./services/barrier.nix ./services/betterlockscreen.nix ./services/blueman-applet.nix + ./services/borgmatic.nix + ./services/cachix-agent.nix ./services/caffeine.nix ./services/cbatticon.nix + ./services/clipman.nix ./services/clipmenu.nix ./services/devilspie2.nix ./services/dropbox.nix @@ -226,6 +245,7 @@ let ./services/lorri.nix ./services/mako.nix ./services/mbsync.nix + ./services/megasync.nix ./services/mopidy.nix ./services/mpd.nix ./services/mpdris2.nix @@ -256,6 +276,7 @@ let ./services/redshift-gammastep/gammastep.nix ./services/redshift-gammastep/redshift.nix ./services/rsibreak.nix + ./services/safeeyes.nix ./services/screen-locker.nix ./services/sctd.nix ./services/spotifyd.nix @@ -276,6 +297,7 @@ let ./services/volnoti.nix ./services/window-managers/awesome.nix ./services/window-managers/bspwm/default.nix + ./services/window-managers/fluxbox.nix ./services/window-managers/herbstluftwm.nix ./services/window-managers/i3-sway/i3.nix ./services/window-managers/i3-sway/sway.nix diff --git a/modules/po/da.po b/modules/po/da.po new file mode 100644 index 00000000..d2f5467e --- /dev/null +++ b/modules/po/da.po @@ -0,0 +1,124 @@ +# 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: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-09-19 18:22+0000\n" +"Last-Translator: cafkafk \n" +"Language-Team: Danish \n" +"Language: da\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 4.14.1\n" + +#: modules/files.nix:233 +msgid "Creating home file links in %s" +msgstr "Skaber hjemme fil links i %s" + +#: modules/files.nix:246 +msgid "Cleaning up orphan links from %s" +msgstr "Opryder forældreløse links fra %s" + +#: modules/files.nix:262 +msgid "Creating profile generation %s" +msgstr "Kreere profil generation %s" + +#: modules/files.nix:276 +msgid "No change so reusing latest profile generation %s" +msgstr "Ingen ændring så genbrug den seneste profil generation %s" + +#: modules/home-environment.nix:607 +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 "" +"Åh nej, Nix fejlede i at installere din nye Home Manager profil! \n" +" \n" +"Måske er der en konflikt med en pakke der blev installeret gennem\n" +"\"%s\"? Prøv at køre \n" +"\n" +" %s\n" +" \n" +"og hvis der er en pakke konflikt, kan du fjerne pakken med \n" +" \n" +" %s\n" +" \n" +"og så prøve at genaktivere din Home Manager konfiguration igen." + +#: modules/home-environment.nix:639 +msgid "Activating %s" +msgstr "Aktivere %s" + +#: modules/lib-bash/activation-init.sh:31 +msgid "Sanity checking oldGenNum and oldGenPath" +msgstr "Tjekker fornuften af oldGenNum and oldGenPath" + +#: modules/lib-bash/activation-init.sh:34 +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 "" +"Den forrige generations nummer og sti er i konflikt! Disse\n" +"skal enten begge være tomme, eller begge være sat, men er nu sat til \n" +" \n" +" '%s' and '%s'\n" +" \n" +"Hvis du ikke har noget mod at miste tidligere profil generationer så\n" +"er den nemmeste løsning nok at køre \n" +" \n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +" \n" +"og så prøve at køre home-manager switch igen. Held og lykke!" + +#: modules/lib-bash/activation-init.sh:51 +msgid "Starting Home Manager activation" +msgstr "Starter Home Manager aktivation" + +#: modules/lib-bash/activation-init.sh:55 +msgid "Sanity checking Nix" +msgstr "Udføre fornuft check af Nix" + +#: modules/lib-bash/activation-init.sh:61 +msgid "This is a dry run" +msgstr "Dette er en tør kørsel" + +#: modules/lib-bash/activation-init.sh:64 +msgid "This is a live run" +msgstr "Dette er en direkte kørsel" + +#: modules/lib-bash/activation-init.sh:69 +msgid "Using Nix version: %s" +msgstr "Bruger Nix version: %s" + +#: modules/lib-bash/activation-init.sh:72 +msgid "Activation variables:" +msgstr "Aktivere variable:" diff --git a/modules/po/it.po b/modules/po/it.po index cec8b104..b4c475c5 100644 --- a/modules/po/it.po +++ b/modules/po/it.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: Home Manager Modules\n" "Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" "POT-Creation-Date: 2022-03-26 15:08+0100\n" -"PO-Revision-Date: 2022-04-20 18:18+0000\n" -"Last-Translator: Frankie McEyes \n" +"PO-Revision-Date: 2022-12-15 08:50+0000\n" +"Last-Translator: Walter Franzini \n" "Language-Team: Italian \n" "Language: it\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.12-dev\n" +"X-Generator: Weblate 4.15-dev\n" #: modules/files.nix:233 msgid "Creating home file links in %s" @@ -57,7 +57,7 @@ msgstr "Attivando %s" #: modules/lib-bash/activation-init.sh:31 msgid "Sanity checking oldGenNum and oldGenPath" -msgstr "" +msgstr "Controllando oldGenNum e oldGenPath" #: modules/lib-bash/activation-init.sh:34 msgid "" diff --git a/modules/po/lt.po b/modules/po/lt.po new file mode 100644 index 00000000..166bf808 --- /dev/null +++ b/modules/po/lt.po @@ -0,0 +1,97 @@ +# 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: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: lt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: modules/files.nix:233 +msgid "Creating home file links in %s" +msgstr "" + +#: modules/files.nix:246 +msgid "Cleaning up orphan links from %s" +msgstr "" + +#: modules/files.nix:262 +msgid "Creating profile generation %s" +msgstr "" + +#: modules/files.nix:276 +msgid "No change so reusing latest profile generation %s" +msgstr "" + +#: modules/home-environment.nix:607 +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:639 +msgid "Activating %s" +msgstr "" + +#: modules/lib-bash/activation-init.sh:31 +msgid "Sanity checking oldGenNum and oldGenPath" +msgstr "" + +#: modules/lib-bash/activation-init.sh:34 +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:51 +msgid "Starting Home Manager activation" +msgstr "" + +#: modules/lib-bash/activation-init.sh:55 +msgid "Sanity checking Nix" +msgstr "" + +#: modules/lib-bash/activation-init.sh:61 +msgid "This is a dry run" +msgstr "" + +#: modules/lib-bash/activation-init.sh:64 +msgid "This is a live run" +msgstr "" + +#: modules/lib-bash/activation-init.sh:69 +msgid "Using Nix version: %s" +msgstr "" + +#: modules/lib-bash/activation-init.sh:72 +msgid "Activation variables:" +msgstr "" diff --git a/modules/po/nl.po b/modules/po/nl.po index 7c239502..de46344b 100644 --- a/modules/po/nl.po +++ b/modules/po/nl.po @@ -8,29 +8,33 @@ msgstr "" "Project-Id-Version: Home Manager Modules\n" "Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" "POT-Creation-Date: 2022-03-26 15:08+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" +"PO-Revision-Date: 2022-11-16 13:47+0000\n" +"Last-Translator: Pablo Bollansee \n" +"Language-Team: Dutch \n" "Language: nl\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 4.15-dev\n" #: modules/files.nix:233 msgid "Creating home file links in %s" -msgstr "" +msgstr "Home-bestandskoppelingen aan het maken in %s" #: modules/files.nix:246 msgid "Cleaning up orphan links from %s" -msgstr "" +msgstr "Wees links van %s aan het opkuisen" #: modules/files.nix:262 msgid "Creating profile generation %s" -msgstr "" +msgstr "Profiel generatie %s aan het maken" #: modules/files.nix:276 msgid "No change so reusing latest profile generation %s" msgstr "" +"Geen veranderingen dus de laatste profiel generatie %s wordt hergebruikt" #: modules/home-environment.nix:607 msgid "" @@ -47,14 +51,27 @@ msgid "" "\n" "Then try activating your Home Manager configuration again." msgstr "" +"Oei, het is Nix niet gelukt om je nieuwe Home Manager profiel te installeren!" +"\n" +"\n" +"Misschien is er een conflict met het pakket dat geïnstalleerd was met\n" +"\"%s\"? Probeer het volgende te draaien\n" +"\n" +" %s\n" +"\n" +"en als er een pakket is dat een conflict geeft kan je dat verwijderen met\n" +"\n" +" %s\n" +"\n" +"Probeer daarna je Home Manager configuratie opnieuw te activeren." #: modules/home-environment.nix:639 msgid "Activating %s" -msgstr "" +msgstr "%s aan het activeren" #: modules/lib-bash/activation-init.sh:31 msgid "Sanity checking oldGenNum and oldGenPath" -msgstr "" +msgstr "oldGenNum en oldGenPath aan het sanity checken" #: modules/lib-bash/activation-init.sh:34 msgid "" @@ -71,27 +88,39 @@ msgid "" "\n" "and trying home-manager switch again. Good luck!" msgstr "" +"Er is een conflict met de generatie nummer en pad! Deze\n" +"moeten beide leeg of beide ingevuld zijn, maar zijn nu\n" +"\n" +" '%s' en '%s'\n" +"\n" +"Als je het niet erg vindt je vorige profiel generaties te verliezen dan\n" +"is waarschijnlijk de eenvoudigste oplossing om het volgende te draaien\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"en dan opnieuw 'home-manager switch' te proberen. Veel succes!" #: modules/lib-bash/activation-init.sh:51 msgid "Starting Home Manager activation" -msgstr "" +msgstr "Home manager activatie aan het starten" #: modules/lib-bash/activation-init.sh:55 msgid "Sanity checking Nix" -msgstr "" +msgstr "Nix aan het sanity checken" #: modules/lib-bash/activation-init.sh:61 msgid "This is a dry run" -msgstr "" +msgstr "Dit is een oefening" #: modules/lib-bash/activation-init.sh:64 msgid "This is a live run" -msgstr "" +msgstr "Dit is voor echt" #: modules/lib-bash/activation-init.sh:69 msgid "Using Nix version: %s" -msgstr "" +msgstr "Nix versie %s wordt gebruikt" #: modules/lib-bash/activation-init.sh:72 msgid "Activation variables:" -msgstr "" +msgstr "Activatie variabelen:" diff --git a/modules/po/pl.po b/modules/po/pl.po index e9262433..307ffc01 100644 --- a/modules/po/pl.po +++ b/modules/po/pl.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: Home Manager Modules\n" "Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" "POT-Creation-Date: 2022-03-26 15:08+0100\n" -"PO-Revision-Date: 2022-03-01 13:58+0000\n" -"Last-Translator: Anon Ymous \n" +"PO-Revision-Date: 2022-11-16 13:47+0000\n" +"Last-Translator: Jakub Janczak \n" "Language-Team: Polish \n" "Language: pl\n" @@ -18,7 +18,7 @@ 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 4.11.1-dev\n" +"X-Generator: Weblate 4.15-dev\n" #: modules/files.nix:233 msgid "Creating home file links in %s" @@ -51,6 +51,18 @@ msgid "" "\n" "Then try activating your Home Manager configuration again." msgstr "" +"Oops, Nix nie zdołał zainstalować twojego profilu Home Manager'a!\n" +"\n" +"Być może zaistniał konflikt z pakietem zainstalowanym przez\n" +"\"%s\"? Spróbuj uruchomić\n" +"\n" +" %s\n" +"\n" +"i jeśli istnieje konflikt możesz spróbować go rozwiązać uruchamiając\n" +"\n" +" %s\n" +"\n" +"Następnie spróbuj aktywować konfigurację Home Manager'a ponownie." #: modules/home-environment.nix:639 msgid "Activating %s" @@ -75,6 +87,18 @@ msgid "" "\n" "and trying home-manager switch again. Good luck!" msgstr "" +"Istnieje konflikt pomiędzy poprzednią generacją i ścieżką! Powinny\n" +"być obie puste lub ustawione, a efektywnie są ustawione na:\n" +"\n" +" '%s' i '%s'\n" +"\n" +"Jeśli możesz sobie pozwolić na utratę poprzednich generacji,\n" +"możesz uruchomić\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"i spróbować uruchomić home-manager switch raz jeszcze. Powodzenia!" #: modules/lib-bash/activation-init.sh:51 msgid "Starting Home Manager activation" @@ -85,19 +109,17 @@ msgid "Sanity checking Nix" msgstr "Sprawdzanie poprawności Nix" #: modules/lib-bash/activation-init.sh:61 -#, fuzzy msgid "This is a dry run" -msgstr "To jest próbne wykonanie" +msgstr "To jest wykonanie testowe" #: modules/lib-bash/activation-init.sh:64 msgid "This is a live run" -msgstr "" +msgstr "To jest wykonanie właściwe" #: modules/lib-bash/activation-init.sh:69 msgid "Using Nix version: %s" msgstr "Używając wersji Nix: %s" #: modules/lib-bash/activation-init.sh:72 -#, fuzzy msgid "Activation variables:" msgstr "Zmienne aktywacyjne:" diff --git a/modules/po/zh_Hant.po b/modules/po/zh_Hant.po index 06f379e0..0e7fc6f8 100644 --- a/modules/po/zh_Hant.po +++ b/modules/po/zh_Hant.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: Home Manager Modules\n" "Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" "POT-Creation-Date: 2022-03-26 15:08+0100\n" -"PO-Revision-Date: 2021-12-29 08:48+0000\n" -"Last-Translator: WhiredPlanck \n" +"PO-Revision-Date: 2023-01-08 11:50+0000\n" +"Last-Translator: Eric Ho \n" "Language-Team: Chinese (Traditional) \n" "Language: zh_Hant\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 4.10.1\n" +"X-Generator: Weblate 4.15.1-dev\n" #: modules/files.nix:233 msgid "Creating home file links in %s" @@ -50,6 +50,18 @@ msgid "" "\n" "Then try activating your Home Manager configuration again." msgstr "" +"糟糕,Nix 未能安裝您的新 Home Manager 配置文件!\n" +"\n" +"也許這裏和使用 \"%s\" 安裝的包有衝突?\n" +"嘗試運行\n" +"\n" +" %s\n" +"\n" +"如果有衝突的包,你可以用\n" +"\n" +" %s\n" +"\n" +"來移除。然後嘗試再次啟用您的 Home Manager 配置。" #: modules/home-environment.nix:639 msgid "Activating %s" @@ -57,7 +69,7 @@ msgstr "正在啟用 %s" #: modules/lib-bash/activation-init.sh:31 msgid "Sanity checking oldGenNum and oldGenPath" -msgstr "" +msgstr "正在進行 oldGenNum 和 oldGenPath 的完整性檢查" #: modules/lib-bash/activation-init.sh:34 msgid "" @@ -81,20 +93,20 @@ msgstr "正在啟動 Home Manager 初始化程式" #: modules/lib-bash/activation-init.sh:55 msgid "Sanity checking Nix" -msgstr "" +msgstr "正在進行 Nix 完整性檢查" #: modules/lib-bash/activation-init.sh:61 msgid "This is a dry run" -msgstr "" +msgstr "這是試運行" #: modules/lib-bash/activation-init.sh:64 msgid "This is a live run" -msgstr "" +msgstr "這是在實際運行" #: modules/lib-bash/activation-init.sh:69 msgid "Using Nix version: %s" -msgstr "" +msgstr "正在使用的 Nix 版本: %s" #: modules/lib-bash/activation-init.sh:72 msgid "Activation variables:" -msgstr "" +msgstr "啟用的變數:" diff --git a/modules/programs/autorandr.nix b/modules/programs/autorandr.nix index 3eeedfc2..9e7c6fcc 100644 --- a/modules/programs/autorandr.nix +++ b/modules/programs/autorandr.nix @@ -305,7 +305,7 @@ in { DPI=144 ;; *) - echo "Unknown profle: $AUTORANDR_CURRENT_PROFILE" + echo "Unknown profile: $AUTORANDR_CURRENT_PROFILE" exit 1 esac diff --git a/modules/programs/bash.nix b/modules/programs/bash.nix index 0f9fd922..0c0643da 100644 --- a/modules/programs/bash.nix +++ b/modules/programs/bash.nix @@ -6,16 +6,15 @@ let cfg = config.programs.bash; - writeBashScript = name: text: pkgs.writeTextFile { - inherit name text; - checkPhase = '' - ${pkgs.stdenv.shellDryRun} "$target" - ''; - }; + writeBashScript = name: text: + pkgs.writeTextFile { + inherit name text; + checkPhase = '' + ${pkgs.stdenv.shellDryRun} "$target" + ''; + }; -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; imports = [ @@ -70,20 +69,18 @@ in }; historyControl = mkOption { - type = types.listOf (types.enum [ - "erasedups" - "ignoredups" - "ignorespace" - ]); - default = []; + type = + types.listOf (types.enum [ "erasedups" "ignoredups" "ignorespace" ]); + default = [ ]; description = "Controlling how commands are saved on the history list."; }; historyIgnore = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; example = [ "ls" "cd" "exit" ]; - description = "List of commands that should not be saved to the history list."; + description = + "List of commands that should not be saved to the history list."; }; shellOptions = mkOption { @@ -103,10 +100,7 @@ in # Warn if closing shell with running jobs. "checkjobs" ]; - example = [ - "extglob" - "-cdspell" - ]; + example = [ "extglob" "-cdspell" ]; description = '' Shell options to set. Prefix an option with - to unset. @@ -114,7 +108,7 @@ in }; sessionVariables = mkOption { - default = {}; + default = { }; type = types.attrs; example = { MAILCHECK = 30; }; description = '' @@ -123,7 +117,7 @@ in }; shellAliases = mkOption { - default = {}; + default = { }; type = types.attrsOf types.str; example = literalExpression '' { @@ -175,80 +169,71 @@ in }; }; - config = ( - let - aliasesStr = concatStringsSep "\n" ( - mapAttrsToList (k: v: "alias ${k}=${escapeShellArg v}") cfg.shellAliases - ); + config = let + aliasesStr = concatStringsSep "\n" + (mapAttrsToList (k: v: "alias ${k}=${escapeShellArg v}") + cfg.shellAliases); - shoptsStr = let - switch = v: if hasPrefix "-" v then "-u" else "-s"; - in concatStringsSep "\n" ( - map (v: "shopt ${switch v} ${removePrefix "-" v}") cfg.shellOptions - ); + shoptsStr = let switch = v: if hasPrefix "-" v then "-u" else "-s"; + in concatStringsSep "\n" + (map (v: "shopt ${switch v} ${removePrefix "-" v}") cfg.shellOptions); - sessionVarsStr = config.lib.shell.exportAll cfg.sessionVariables; + sessionVarsStr = config.lib.shell.exportAll cfg.sessionVariables; - historyControlStr = - concatStringsSep "\n" (mapAttrsToList (n: v: "${n}=${v}") ( - { - HISTFILESIZE = toString cfg.historyFileSize; - HISTSIZE = toString cfg.historySize; - } - // optionalAttrs (cfg.historyFile != null) { - HISTFILE = "\"${cfg.historyFile}\""; - } - // optionalAttrs (cfg.historyControl != []) { - HISTCONTROL = concatStringsSep ":" cfg.historyControl; - } - // optionalAttrs (cfg.historyIgnore != []) { - HISTIGNORE = concatStringsSep ":" cfg.historyIgnore; - } - )); - in mkIf cfg.enable { - home.file.".bash_profile".source = writeBashScript "bash_profile" '' - # include .profile if it exists - [[ -f ~/.profile ]] && . ~/.profile + historyControlStr = concatStringsSep "\n" + (mapAttrsToList (n: v: "${n}=${v}") ({ + HISTFILESIZE = toString cfg.historyFileSize; + HISTSIZE = toString cfg.historySize; + } // optionalAttrs (cfg.historyFile != null) { + HISTFILE = ''"${cfg.historyFile}"''; + } // optionalAttrs (cfg.historyControl != [ ]) { + HISTCONTROL = concatStringsSep ":" cfg.historyControl; + } // optionalAttrs (cfg.historyIgnore != [ ]) { + HISTIGNORE = escapeShellArg (concatStringsSep ":" cfg.historyIgnore); + })); + in mkIf cfg.enable { + home.file.".bash_profile".source = writeBashScript "bash_profile" '' + # include .profile if it exists + [[ -f ~/.profile ]] && . ~/.profile - # include .bashrc if it exists - [[ -f ~/.bashrc ]] && . ~/.bashrc - ''; + # include .bashrc if it exists + [[ -f ~/.bashrc ]] && . ~/.bashrc + ''; - # If completion is enabled then make sure it is sourced very early. This - # is to avoid problems if any other initialization code attempts to set up - # completion. - programs.bash.initExtra = mkIf cfg.enableCompletion (mkOrder 100 '' - if [[ ! -v BASH_COMPLETION_VERSINFO ]]; then - . "${pkgs.bash-completion}/etc/profile.d/bash_completion.sh" - fi - ''); + # If completion is enabled then make sure it is sourced very early. This + # is to avoid problems if any other initialization code attempts to set up + # completion. + programs.bash.initExtra = mkIf cfg.enableCompletion (mkOrder 100 '' + if [[ ! -v BASH_COMPLETION_VERSINFO ]]; then + . "${pkgs.bash-completion}/etc/profile.d/bash_completion.sh" + fi + ''); - home.file.".profile".source = writeBashScript "profile" '' - . "${config.home.profileDirectory}/etc/profile.d/hm-session-vars.sh" + home.file.".profile".source = writeBashScript "profile" '' + . "${config.home.profileDirectory}/etc/profile.d/hm-session-vars.sh" - ${sessionVarsStr} + ${sessionVarsStr} - ${cfg.profileExtra} - ''; + ${cfg.profileExtra} + ''; - home.file.".bashrc".source = writeBashScript "bashrc" '' - ${cfg.bashrcExtra} + home.file.".bashrc".source = writeBashScript "bashrc" '' + ${cfg.bashrcExtra} - # Commands that should be applied only for interactive shells. - [[ $- == *i* ]] || return + # Commands that should be applied only for interactive shells. + [[ $- == *i* ]] || return - ${historyControlStr} + ${historyControlStr} - ${shoptsStr} + ${shoptsStr} - ${aliasesStr} + ${aliasesStr} - ${cfg.initExtra} - ''; + ${cfg.initExtra} + ''; - home.file.".bash_logout" = mkIf (cfg.logoutExtra != "") { - source = writeBashScript "bash_logout" cfg.logoutExtra; - }; - } - ); + home.file.".bash_logout" = mkIf (cfg.logoutExtra != "") { + source = writeBashScript "bash_logout" cfg.logoutExtra; + }; + }; } diff --git a/modules/programs/bat.nix b/modules/programs/bat.nix index 30b0bbb7..df2e4968 100644 --- a/modules/programs/bat.nix +++ b/modules/programs/bat.nix @@ -30,6 +30,16 @@ in { ''; }; + extraPackages = mkOption { + type = types.listOf types.package; + default = [ ]; + example = literalExpression + "with pkgs.bat-extras; [ batdiff batman batgrep batwatch ];"; + description = '' + Additional bat packages to install. + ''; + }; + themes = mkOption { type = types.attrsOf types.lines; default = { }; @@ -51,7 +61,7 @@ in { }; config = mkIf cfg.enable { - home.packages = [ pkgs.bat ]; + home.packages = [ pkgs.bat ] ++ cfg.extraPackages; xdg.configFile = mkMerge ([{ "bat/config" = diff --git a/modules/programs/borgmatic.nix b/modules/programs/borgmatic.nix new file mode 100644 index 00000000..d6980388 --- /dev/null +++ b/modules/programs/borgmatic.nix @@ -0,0 +1,196 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.borgmatic; + + mkNullableOption = args: + lib.mkOption (args // { + type = lib.types.nullOr args.type; + default = null; + }); + + mkRetentionOption = frequency: + mkNullableOption { + type = types.int; + description = + "Number of ${frequency} archives to keep. Use -1 for no limit."; + example = 3; + }; + + extraConfigOption = mkOption { + type = with types; attrsOf (oneOf [ str bool path int (listOf str) ]); + default = { }; + description = "Extra settings."; + }; + + consistencyCheckModule = types.submodule { + options = { + name = mkOption { + type = types.enum [ "repository" "archives" "data" "extract" ]; + description = "Name of consistency check to run."; + example = "repository"; + }; + + frequency = mkNullableOption { + type = types.strMatching "([[:digit:]]+ .*)|always"; + description = "Frequency of this type of check"; + example = "2 weeks"; + }; + }; + }; + + configModule = types.submodule { + options = { + location = { + sourceDirectories = mkOption { + type = types.listOf types.str; + description = "Directories to backup."; + example = literalExpression "[config.home.homeDirectory]"; + }; + + repositories = mkOption { + type = types.listOf types.str; + description = "Paths to repositories."; + example = + literalExpression ''["ssh://myuser@myrepo.myserver.com/./repo"]''; + }; + + extraConfig = extraConfigOption; + }; + + storage = { + encryptionPasscommand = mkNullableOption { + type = types.str; + description = "Command writing the passphrase to standard output."; + example = + literalExpression ''"''${pkgs.password-store}/bin/pass borg-repo"''; + }; + extraConfig = extraConfigOption; + }; + + retention = { + keepWithin = mkNullableOption { + type = types.strMatching "[[:digit:]]+[Hdwmy]"; + description = "Keep all archives within this time interval."; + example = "2d"; + }; + + keepSecondly = mkRetentionOption "secondly"; + keepMinutely = mkRetentionOption "minutely"; + keepHourly = mkRetentionOption "hourly"; + keepDaily = mkRetentionOption "daily"; + keepWeekly = mkRetentionOption "weekly"; + keepMonthly = mkRetentionOption "monthly"; + keepYearly = mkRetentionOption "yearly"; + + extraConfig = extraConfigOption; + }; + + consistency = { + checks = mkOption { + type = types.listOf consistencyCheckModule; + default = [ ]; + description = "Consistency checks to run"; + example = literalExpression '' + [ + { + name = "repository"; + frequency = "2 weeks"; + } + { + name = "archives"; + frequency = "4 weeks"; + } + { + name = "data"; + frequency = "6 weeks"; + } + { + name = "extract"; + frequency = "6 weeks"; + } + ]; + ''; + }; + + extraConfig = extraConfigOption; + }; + }; + }; + + removeNullValues = attrSet: filterAttrs (key: value: value != null) attrSet; + + writeConfig = config: + generators.toYAML { } { + location = removeNullValues { + source_directories = config.location.sourceDirectories; + repositories = config.location.repositories; + } // config.location.extraConfig; + storage = removeNullValues { + encryption_passcommand = config.storage.encryptionPasscommand; + } // config.storage.extraConfig; + retention = removeNullValues { + keep_within = config.retention.keepWithin; + keep_secondly = config.retention.keepSecondly; + keep_minutely = config.retention.keepMinutely; + keep_hourly = config.retention.keepHourly; + keep_daily = config.retention.keepDaily; + keep_weekly = config.retention.keepWeekly; + keep_monthly = config.retention.keepMonthly; + keep_yearly = config.retention.keepYearly; + } // config.retention.extraConfig; + consistency = removeNullValues { checks = config.consistency.checks; } + // config.consistency.extraConfig; + }; +in { + meta.maintainers = [ maintainers.DamienCassou ]; + + options = { + programs.borgmatic = { + enable = mkEnableOption "Borgmatic"; + + package = mkPackageOption pkgs "borgmatic" { }; + + backups = mkOption { + type = types.attrsOf configModule; + description = '' + Borgmatic allows for several named backup configurations, + each with its own source directories and repositories. + ''; + example = literalExpression '' + { + personal = { + location = { + sourceDirectories = [ "/home/me/personal" ]; + repositories = [ "ssh://myuser@myserver.com/./personal-repo" ]; + }; + }; + work = { + location = { + sourceDirectories = [ "/home/me/work" ]; + repositories = [ "ssh://myuser@myserver.com/./work-repo" ]; + }; + }; + }; + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "programs.borgmatic" pkgs + lib.platforms.linux) + ]; + + xdg.configFile = with lib.attrsets; + mapAttrs' (configName: config: + nameValuePair ("borgmatic.d/" + configName + ".yaml") { + text = writeConfig config; + }) cfg.backups; + + home.packages = [ cfg.package ]; + }; +} diff --git a/modules/programs/broot.nix b/modules/programs/broot.nix index f37470d7..d78074ef 100644 --- a/modules/programs/broot.nix +++ b/modules/programs/broot.nix @@ -8,15 +8,160 @@ let tomlFormat = pkgs.formats.toml { }; - brootConf = { - verbs = cfg.verbs; - skin = cfg.skin; - modal = cfg.modal; + settingsModule = { + freeformType = tomlFormat.type; + + options = { + modal = mkEnableOption "modal (vim) mode"; + + verbs = mkOption { + type = with types; listOf (attrsOf (either bool str)); + default = [ ]; + example = literalExpression '' + [ + { invocation = "p"; execution = ":parent"; } + { invocation = "edit"; shortcut = "e"; execution = "$EDITOR {file}" ; } + { invocation = "create {subpath}"; execution = "$EDITOR {directory}/{subpath}"; } + { invocation = "view"; execution = "less {file}"; } + { + invocation = "blop {name}\\.{type}"; + execution = "mkdir {parent}/{type} && ''${pkgs.neovim}/bin/nvim {parent}/{type}/{name}.{type}"; + from_shell = true; + } + ] + ''; + description = '' + Define new verbs. For more information, see + . + + The possible attributes are: + + + + + + invocation (optional) + how the verb is called by the user, with placeholders for arguments + + + execution (mandatory) + how the verb is executed + + + key (optional) + a keyboard key triggering execution + + + shortcut (optional) + an alternate way to call the verb (without + the arguments part) + + + leave_broot (optional) + whether to quit broot on execution + (default: true) + + + from_shell (optional) + whether the verb must be executed from the + parent shell (default: + false) + + + ''; + }; + + skin = mkOption { + type = types.attrsOf types.str; + default = { }; + example = literalExpression '' + { + status_normal_fg = "grayscale(18)"; + status_normal_bg = "grayscale(3)"; + status_error_fg = "red"; + status_error_bg = "yellow"; + tree_fg = "red"; + selected_line_bg = "grayscale(7)"; + permissions_fg = "grayscale(12)"; + size_bar_full_bg = "red"; + size_bar_void_bg = "black"; + directory_fg = "lightyellow"; + input_fg = "cyan"; + flag_value_fg = "lightyellow"; + table_border_fg = "red"; + code_fg = "lightyellow"; + } + ''; + description = '' + Color configuration. + + Complete list of keys (expected to change before the v1 of broot): + + + char_match + code + directory + exe + file + file_error + flag_label + flag_value + input + link + permissions + selected_line + size_bar_full + size_bar_void + size_text + spinner + status_error + status_normal + table_border + tree + unlisted + + + + Add _fg for a foreground color and + _bg for a background colors. + ''; + }; + }; }; + shellInit = shell: + # Using mkAfter to make it more likely to appear after other + # manipulations of the prompt. + mkAfter '' + source ${ + pkgs.runCommand "br.${shell}" { nativeBuildInputs = [ cfg.package ]; } + "broot --print-shell-function ${shell} > $out" + } + ''; in { meta.maintainers = [ hm.maintainers.aheaume ]; + imports = [ + (mkRenamedOptionModule [ "programs" "broot" "modal" ] [ + "programs" + "broot" + "settings" + "modal" + ]) + (mkRenamedOptionModule [ "programs" "broot" "verbs" ] [ + "programs" + "broot" + "settings" + "verbs" + ]) + (mkRenamedOptionModule [ "programs" "broot" "skin" ] [ + "programs" + "broot" + "settings" + "skin" + ]) + ]; + options.programs.broot = { enable = mkEnableOption "Broot, a better way to navigate directories"; @@ -44,83 +189,6 @@ in { ''; }; - modal = mkEnableOption "modal (vim) mode"; - - verbs = mkOption { - type = with types; listOf (attrsOf (either bool str)); - default = [ - { - invocation = "p"; - execution = ":parent"; - } - { - invocation = "edit"; - shortcut = "e"; - execution = "$EDITOR {file}"; - } - { - invocation = "create {subpath}"; - execution = "$EDITOR {directory}/{subpath}"; - } - { - invocation = "view"; - execution = "less {file}"; - } - ]; - example = literalExpression '' - [ - { invocation = "p"; execution = ":parent"; } - { invocation = "edit"; shortcut = "e"; execution = "$EDITOR {file}" ; } - { invocation = "create {subpath}"; execution = "$EDITOR {directory}/{subpath}"; } - { invocation = "view"; execution = "less {file}"; } - { - invocation = "blop {name}\\.{type}"; - execution = "/bin/mkdir {parent}/{type} && /usr/bin/nvim {parent}/{type}/{name}.{type}"; - from_shell = true; - } - ] - ''; - description = '' - Define new verbs. For more information, see - . - - The possible attributes are: - - - - - - invocation (optional) - how the verb is called by the user, with placeholders for arguments - - - execution (mandatory) - how the verb is executed - - - key (optional) - a keyboard key triggering execution - - - shortcut (optional) - an alternate way to call the verb (without - the arguments part) - - - leave_broot (optional) - whether to quit broot on execution - (default: true) - - - from_shell (optional) - whether the verb must be executed from the - parent shell (default: - false) - - - ''; - }; - package = mkOption { type = types.package; default = pkgs.broot; @@ -128,149 +196,48 @@ in { description = "Package providing broot"; }; - skin = mkOption { - type = types.attrsOf types.str; + settings = mkOption { + type = types.submodule settingsModule; default = { }; - example = literalExpression '' - { - status_normal_fg = "grayscale(18)"; - status_normal_bg = "grayscale(3)"; - status_error_fg = "red"; - status_error_bg = "yellow"; - tree_fg = "red"; - selected_line_bg = "grayscale(7)"; - permissions_fg = "grayscale(12)"; - size_bar_full_bg = "red"; - size_bar_void_bg = "black"; - directory_fg = "lightyellow"; - input_fg = "cyan"; - flag_value_fg = "lightyellow"; - table_border_fg = "red"; - code_fg = "lightyellow"; - } - ''; - description = '' - Color configuration. - - Complete list of keys (expected to change before the v1 of broot): - - - char_match - code - directory - exe - file - file_error - flag_label - flag_value - input - link - permissions - selected_line - size_bar_full - size_bar_void - size_text - spinner - status_error - status_normal - table_border - tree - unlisted - - - - Add _fg for a foreground color and - _bg for a background colors. - ''; + description = "Verbatim config entries"; }; }; config = mkIf cfg.enable { home.packages = [ cfg.package ]; - xdg.configFile."broot/conf.toml".source = - tomlFormat.generate "broot-config" brootConf; + xdg.configFile."broot" = { + recursive = true; + source = pkgs.symlinkJoin { + name = "xdg.configFile.broot"; + paths = [ + (pkgs.writeTextDir "conf.toml" (builtins.readFile + (tomlFormat.generate "broot-config" cfg.settings))) - # Dummy file to prevent broot from trying to reinstall itself - xdg.configFile."broot/launcher/installed-v1".text = ""; + # Copy all files under /resources/default-conf + "${cfg.package.src}/resources/default-conf" - programs.bash.initExtra = mkIf cfg.enableBashIntegration ( - # Using mkAfter to make it more likely to appear after other - # manipulations of the prompt. - mkAfter '' - # This script was automatically generated by the broot function - # More information can be found in https://github.com/Canop/broot - # This function starts broot and executes the command - # it produces, if any. - # It's needed because some shell commands, like `cd`, - # have no useful effect if executed in a subshell. - function br { - f=$(mktemp) - ( - set +e - broot --outcmd "$f" "$@" - code=$? - if [ "$code" != 0 ]; then - rm -f "$f" - exit "$code" - fi - ) - code=$? - if [ "$code" != 0 ]; then - return "$code" - fi - d=$(cat "$f") - rm -f "$f" - eval "$d" - } - ''); + # Dummy file to prevent broot from trying to reinstall itself + (pkgs.writeTextDir "launcher/installed-v1" "") + ]; - programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' - # This script was automatically generated by the broot function - # More information can be found in https://github.com/Canop/broot - # This function starts broot and executes the command - # it produces, if any. - # It's needed because some shell commands, like `cd`, - # have no useful effect if executed in a subshell. - function br { - f=$(mktemp) - ( - set +e - broot --outcmd "$f" "$@" - code=$? - if [ "$code" != 0 ]; then - rm -f "$f" - exit "$code" - fi - ) - code=$? - if [ "$code" != 0 ]; then - return "$code" - fi - d=$(cat "$f") - rm -f "$f" - eval "$d" + # Remove conf.hjson, whose content has been merged into programs.broot.settings + postBuild = '' + rm $out/conf.hjson + ''; + }; + }; + + programs.broot.settings = builtins.fromJSON (builtins.readFile + (pkgs.runCommand "default-conf.json" { + nativeBuildInputs = [ pkgs.hjson ]; } - ''; + "hjson -c ${cfg.package.src}/resources/default-conf/conf.hjson > $out")); - programs.fish.shellInit = mkIf cfg.enableFishIntegration '' - # This script was automatically generated by the broot function - # More information can be found in https://github.com/Canop/broot - # This function starts broot and executes the command - # it produces, if any. - # It's needed because some shell commands, like `cd`, - # have no useful effect if executed in a subshell. - function br - set f (mktemp) - broot --outcmd $f $argv - if test $status -ne 0 - rm -f "$f" - return "$code" - end - set d (cat "$f") - rm -f "$f" - eval "$d" - end - ''; + programs.bash.initExtra = mkIf cfg.enableBashIntegration (shellInit "bash"); + + programs.zsh.initExtra = mkIf cfg.enableZshIntegration (shellInit "zsh"); + + programs.fish.shellInit = mkIf cfg.enableFishIntegration (shellInit "fish"); }; } diff --git a/modules/programs/chromium.nix b/modules/programs/chromium.nix index 429543c5..646d8473 100644 --- a/modules/programs/chromium.nix +++ b/modules/programs/chromium.nix @@ -64,7 +64,7 @@ let id = mkOption { type = strMatching "[a-zA-Z]{32}"; description = '' - The extension's ID from the Chome Web Store url or the unpacked crx. + The extension's ID from the Chrome Web Store url or the unpacked crx. ''; default = ""; }; diff --git a/modules/programs/direnv.nix b/modules/programs/direnv.nix index 03210827..1d6ef212 100644 --- a/modules/programs/direnv.nix +++ b/modules/programs/direnv.nix @@ -29,7 +29,7 @@ in { default = { }; description = '' Configuration written to - $XDG_CONFIG_HOME/direnv/config.toml. + $XDG_CONFIG_HOME/direnv/direnv.toml. See @@ -80,6 +80,15 @@ in { ''; }; + enableNushellIntegration = mkOption { + default = true; + type = types.bool; + readOnly = true; + description = '' + Whether to enable Nushell integration. + ''; + }; + nix-direnv = { enable = mkEnableOption '' !(any (p: p.name == cfg.discordPackage.name) config.home.packages); + message = + "To use discocss with discordAlias you have to remove discord from home.packages, or set discordAlias to false."; + }]; + + home.packages = [ + (cfg.package.override { + discordAlias = cfg.discordAlias; + discord = cfg.discordPackage; + }) + ]; + + xdg.configFile."discocss/custom.css".text = cfg.css; + }; +} diff --git a/modules/programs/emacs.nix b/modules/programs/emacs.nix index 4253cb3b..a9a77949 100644 --- a/modules/programs/emacs.nix +++ b/modules/programs/emacs.nix @@ -52,6 +52,10 @@ in { Configuration to include in the Emacs default init file. See for more. + + Note, the inhibit-startup-message Emacs option + cannot be set here since Emacs disallows setting it from the default + initialization file. ''; }; diff --git a/modules/programs/exa.nix b/modules/programs/exa.nix index a7dfeb2b..a1b4a271 100644 --- a/modules/programs/exa.nix +++ b/modules/programs/exa.nix @@ -20,11 +20,14 @@ in { options.programs.exa = { enable = mkEnableOption "exa, a modern replacement for ls"; + enableAliases = mkEnableOption "recommended exa aliases"; + + package = mkPackageOption pkgs "exa" { }; }; config = mkIf cfg.enable { - home.packages = [ pkgs.exa ]; + home.packages = [ cfg.package ]; programs.bash.shellAliases = mkIf cfg.enableAliases aliases; diff --git a/modules/programs/feh.nix b/modules/programs/feh.nix index e098342b..15aac175 100644 --- a/modules/programs/feh.nix +++ b/modules/programs/feh.nix @@ -27,6 +27,8 @@ in { options.programs.feh = { enable = mkEnableOption "feh - a fast and light image viewer"; + package = mkPackageOption pkgs "feh" { }; + buttons = mkOption { default = { }; type = with types; bindingsOf (either str int); @@ -69,7 +71,7 @@ in { "To disable a keybinding, use `null` instead of an empty string."; }]; - home.packages = [ pkgs.feh ]; + home.packages = [ cfg.package ]; xdg.configFile."feh/buttons" = mkIf (cfg.buttons != { }) { text = renderBindings cfg.buttons + "\n"; }; diff --git a/modules/programs/firefox.nix b/modules/programs/firefox.nix index 63adf02b..4b3f288c 100644 --- a/modules/programs/firefox.nix +++ b/modules/programs/firefox.nix @@ -8,6 +8,8 @@ let cfg = config.programs.firefox; + jsonFormat = pkgs.formats.json { }; + mozillaConfigPath = if isDarwin then "Library/Application Support/Mozilla" else ".mozilla"; @@ -40,6 +42,12 @@ let 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) { @@ -50,7 +58,7 @@ let // Generated by Home Manager. ${concatStrings (mapAttrsToList (name: value: '' - user_pref("${name}", ${builtins.toJSON value}); + user_pref("${name}", ${userPrefValue value}); '') prefs')} ${extraPrefs} @@ -106,7 +114,7 @@ let ''; in { - meta.maintainers = [ maintainers.rycee ]; + meta.maintainers = [ maintainers.rycee maintainers.kira-bruneau ]; imports = [ (mkRemovedOptionModule [ "programs" "firefox" "enableAdobeFlash" ] @@ -151,7 +159,6 @@ in { default = [ ]; example = literalExpression '' with pkgs.nur.repos.rycee.firefox-addons; [ - https-everywhere privacy-badger ] ''; @@ -200,7 +207,10 @@ in { }; settings = mkOption { - type = with types; attrsOf (either bool (either int str)); + type = types.attrsOf (jsonFormat.type // { + description = + "Firefox preference (int, bool, string, and also attrs, list, float as a JSON string)"; + }); default = { }; example = literalExpression '' { @@ -210,9 +220,19 @@ in { "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."; + 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 { @@ -351,6 +371,87 @@ in { 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. + ''; + }; + + 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://nixos.wiki/index.php?search={searchTerms}"; }]; + iconUpdateURL = "https://nixos.wiki/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 metaData specified will + be treated as builtin to Firefox. + + See SearchEngine.jsm + 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, icon is also a special option + added by Home Manager to make it convenient to specify + absolute icon paths. + ''; + }; + }; }; })); default = { }; @@ -363,7 +464,7 @@ in { description = '' Whether to enable the GNOME Shell native host connector. Note, you also need to set the NixOS option - services.gnome3.chrome-gnome-shell.enable to + services.gnome.gnome-browser-connector.enable to true. ''; }; @@ -444,6 +545,134 @@ in { mkUserJs profile.settings profile.extraConfig profile.bookmarks; }; + "${profilesPath}/${profile.path}/search.json.mozlz4" = mkIf + (profile.search.default != 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 { }; + }; + in sortEngineConfigs (mapAttrs buildEngineConfig engineInput); + + metaData = optionalAttrs (profile.search.default != null) { + current = profile.search.default; + hash = "@hash@"; + } // { + 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 = profile.path + profile.search.default + + disclaimer "Firefox"; + in pkgs.runCommand "search.json.mozlz4" { + nativeBuildInputs = with pkgs; [ mozlz4a openssl ]; + json = builtins.toJSON settings; + inherit salt; + } '' + export hash=$(echo -n "$salt" | openssl dgst -sha256 -binary | base64) + mozlz4a <(substituteStream json search.json.in --subst-var hash) "$out" + ''; + }; + "${profilesPath}/${profile.path}/extensions" = mkIf (cfg.extensions != [ ]) { source = "${extensionsEnvPkg}/share/mozilla/${extensionPath}"; diff --git a/modules/programs/fish.nix b/modules/programs/fish.nix index 7eda6eb6..39dc246c 100644 --- a/modules/programs/fish.nix +++ b/modules/programs/fish.nix @@ -145,6 +145,13 @@ let aliasesStr = concatStringsSep "\n" (mapAttrsToList (k: v: "alias ${k} ${escapeShellArg v}") cfg.shellAliases); + fishIndent = name: text: + pkgs.runCommand name { + nativeBuildInputs = [ cfg.package ]; + inherit text; + passAsFile = [ "text" ]; + } "env HOME=$(mktemp -d) fish_indent < $textPath > $out"; + in { imports = [ (mkRemovedOptionModule [ "programs" "fish" "promptInit" ] '' @@ -278,7 +285,6 @@ in { . ''; }; - }; config = mkIf cfg.enable (mkMerge [ @@ -340,7 +346,7 @@ in { end ''; - xdg.configFile."fish/config.fish".text = '' + xdg.configFile."fish/config.fish".source = fishIndent "config.fish" '' # ~/.config/fish/config.fish: DO NOT EDIT -- this file has been generated # automatically by home-manager. @@ -369,7 +375,7 @@ in { # Aliases ${aliasesStr} - # Interactive shell intialisation + # Interactive shell initialisation ${cfg.interactiveShellInit} end @@ -379,7 +385,7 @@ in { xdg.configFile = mapAttrs' (name: def: { name = "fish/functions/${name}.fish"; value = { - text = let + source = let modifierStr = n: v: optional (v != null) ''--${n}="${toString v}"''; modifierStrs = n: v: optional (v != null) "--${n}=${toString v}"; modifierBool = n: v: optional (v != null && v) "--${n}"; @@ -397,9 +403,9 @@ in { modifiers = if isAttrs def then " ${toString mods}" else ""; body = if isAttrs def then def.body else def; - in '' + in fishIndent "${name}.fish" '' function ${name}${modifiers} - ${body} + ${lib.strings.removeSuffix "\n" body} end ''; }; @@ -410,34 +416,35 @@ in { # in the paths and any initialization scripts. (mkIf (length cfg.plugins > 0) { xdg.configFile = mkMerge ((map (plugin: { - "fish/conf.d/plugin-${plugin.name}.fish".text = '' - # Plugin ${plugin.name} - set -l plugin_dir ${plugin.src} + "fish/conf.d/plugin-${plugin.name}.fish".source = + fishIndent "${plugin.name}.fish" '' + # Plugin ${plugin.name} + set -l plugin_dir ${plugin.src} - # Set paths to import plugin components - if test -d $plugin_dir/functions - set fish_function_path $fish_function_path[1] $plugin_dir/functions $fish_function_path[2..-1] - end - - if test -d $plugin_dir/completions - set fish_complete_path $fish_complete_path[1] $plugin_dir/completions $fish_complete_path[2..-1] - end - - # Source initialization code if it exists. - if test -d $plugin_dir/conf.d - for f in $plugin_dir/conf.d/*.fish - source $f + # Set paths to import plugin components + if test -d $plugin_dir/functions + set fish_function_path $fish_function_path[1] $plugin_dir/functions $fish_function_path[2..-1] end - end - if test -f $plugin_dir/key_bindings.fish - source $plugin_dir/key_bindings.fish - end + if test -d $plugin_dir/completions + set fish_complete_path $fish_complete_path[1] $plugin_dir/completions $fish_complete_path[2..-1] + end - if test -f $plugin_dir/init.fish - source $plugin_dir/init.fish - end - ''; + # Source initialization code if it exists. + if test -d $plugin_dir/conf.d + for f in $plugin_dir/conf.d/*.fish + source $f + end + end + + if test -f $plugin_dir/key_bindings.fish + source $plugin_dir/key_bindings.fish + end + + if test -f $plugin_dir/init.fish + source $plugin_dir/init.fish + end + ''; }) cfg.plugins)); }) ]); diff --git a/modules/programs/fzf.nix b/modules/programs/fzf.nix index d8eef49c..fe1e720d 100644 --- a/modules/programs/fzf.nix +++ b/modules/programs/fzf.nix @@ -6,6 +6,10 @@ let cfg = config.programs.fzf; + renderedColors = colors: + concatStringsSep "," + (mapAttrsToList (name: value: "${name}:${value}") colors); + in { imports = [ (mkRemovedOptionModule [ "programs" "fzf" "historyWidgetCommand" ] @@ -88,6 +92,24 @@ in { ''; }; + colors = mkOption { + type = types.attrsOf types.str; + default = { }; + example = literalExpression '' + { + bg = "#1e1e1e"; + "bg+" = "#1e1e1e"; + fg = "#d4d4d4"; + "fg+" = "#d4d4d4"; + } + ''; + description = '' + Color scheme options added to FZF_DEFAULT_OPTS. See + + for documentation. + ''; + }; + tmux = { enableShellIntegration = mkEnableOption '' setting FZF_TMUX=1 which causes shell integration to use fzf-tmux @@ -141,7 +163,9 @@ in { FZF_CTRL_T_COMMAND = cfg.fileWidgetCommand; FZF_CTRL_T_OPTS = cfg.fileWidgetOptions; FZF_DEFAULT_COMMAND = cfg.defaultCommand; - FZF_DEFAULT_OPTS = cfg.defaultOptions; + FZF_DEFAULT_OPTS = cfg.defaultOptions + ++ lib.optionals (cfg.colors != { }) + [ "--color ${renderedColors cfg.colors}" ]; FZF_TMUX = if cfg.tmux.enableShellIntegration then "1" else null; FZF_TMUX_OPTS = cfg.tmux.shellIntegrationOptions; }); diff --git a/modules/programs/git.nix b/modules/programs/git.nix index 363ed333..5bd828b3 100644 --- a/modules/programs/git.nix +++ b/modules/programs/git.nix @@ -267,7 +267,7 @@ in { difftastic = { enable = mkEnableOption "" // { description = '' - Enable the difft syntax highlighter. + Enable the difftastic syntax highlighter. See . ''; }; @@ -278,7 +278,7 @@ in { example = "dark"; description = '' Determines whether difftastic should use the lighter or darker colors - for syntax highlithing. + for syntax highlighting. ''; }; @@ -527,10 +527,7 @@ in { "--background ${cfg.difftastic.background}" "--display ${cfg.difftastic.display}" ]; - in { - diff.external = difftCommand; - core.pager = "${pkgs.less}/bin/less -XF"; - }; + in { diff.external = difftCommand; }; }) (mkIf cfg.delta.enable { diff --git a/modules/programs/gitui.nix b/modules/programs/gitui.nix index ee6572bc..710e3fd9 100644 --- a/modules/programs/gitui.nix +++ b/modules/programs/gitui.nix @@ -41,6 +41,8 @@ in { selected_tab: Reset, command_fg: White, selection_bg: Blue, + selection_fg: White, + cmdbar_bg: Blue, cmdbar_extra_lines_bg: Blue, disabled_fg: DarkGray, diff_line_add: Green, @@ -55,6 +57,8 @@ in { danger_fg: Red, push_gauge_bg: Blue, push_gauge_fg: Reset, + tag_fg: LightMagenta, + branch_fg: LightYellow, ) ''; description = '' diff --git a/modules/programs/havoc.nix b/modules/programs/havoc.nix new file mode 100644 index 00000000..6ae89c1d --- /dev/null +++ b/modules/programs/havoc.nix @@ -0,0 +1,64 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.havoc; + iniFormat = pkgs.formats.ini { }; + +in { + meta.maintainers = with lib.maintainers; [ AndersonTorres ]; + + options.programs.havoc = { + enable = mkEnableOption "Havoc terminal"; + + package = mkPackageOption pkgs "havoc" { }; + + settings = mkOption { + type = iniFormat.type; + default = { }; + description = '' + Configuration written to + $XDG_CONFIG_HOME/havoc.cfg. See + for a list of available options. + ''; + example = literalExpression '' + { + child.program = "bash"; + window.opacity = 240; + window.margin = no; + terminal = { + rows = 80; + columns = 24; + scrollback = 2000; + }; + bind = { + "C-S-c" = "copy"; + "C-S-v" = "paste"; + "C-S-r" = "reset"; + "C-S-Delete" = "hard reset"; + "C-S-j" = "scroll down"; + "C-S-k" = "scroll up"; + "C-S-Page_Down" = "scroll down page"; + "C-S-Page_Up" = "scroll up page"; + "C-S-End" = "scroll to bottom"; + "C-S-Home" = "scroll to top"; + }; + } + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = + [ (hm.assertions.assertPlatform "programs.havoc" pkgs platforms.linux) ]; + + home.packages = [ cfg.package ]; + + xdg.configFile."havoc.cfg" = mkIf (cfg.settings != { }) { + source = iniFormat.generate "havoc.cfg" cfg.settings; + }; + }; +} diff --git a/modules/programs/hexchat.nix b/modules/programs/hexchat.nix index a23ea622..4eda0755 100644 --- a/modules/programs/hexchat.nix +++ b/modules/programs/hexchat.nix @@ -170,7 +170,7 @@ let servers = mkOption { type = listOf str; default = [ ]; - example = [ "chat.freenode.net" "irc.freenode.net" ]; + example = [ "irc.oftc.net" ]; description = "IRC Server Address List."; }; }; @@ -239,11 +239,10 @@ in { default = { }; example = literalExpression '' { - freenode = { + oftc = { autojoin = [ "#home-manager" "#linux" - "#nixos" ]; charset = "UTF-8 (Unicode)"; commands = [ @@ -263,8 +262,7 @@ in { password = "my_password"; realName = "my_realname"; servers = [ - "chat.freenode.net" - "irc.freenode.net" + "irc.oftc.net" ]; userName = "my_username"; }; diff --git a/modules/programs/himalaya.nix b/modules/programs/himalaya.nix index 1faee820..92328153 100644 --- a/modules/programs/himalaya.nix +++ b/modules/programs/himalaya.nix @@ -11,7 +11,7 @@ let toHimalayaConfig = account: { email = account.address; - name = account.realName; + display-name = account.realName; default = account.primary; mailboxes = { @@ -20,30 +20,46 @@ let draft = account.folders.drafts; # NOTE: himalaya does not support configuring the name of the trash folder }; - + } // (lib.optionalAttrs (account.signature.showSignature == "append") { + # FIXME: signature cannot be attached + signature = account.signature.text; + signature-delim = account.signature.delimiter; + }) // (if account.himalaya.backend == null then { + backend = "none"; + } else if account.himalaya.backend == "imap" then { # FIXME: does not support disabling TLS altogether # NOTE: does not accept sequence of strings for password commands + backend = account.himalaya.backend; imap-login = account.userName; imap-passwd-cmd = lib.escapeShellArgs account.passwordCommand; imap-host = account.imap.host; imap-port = account.imap.port; imap-starttls = account.imap.tls.useStartTls; - + } else if account.himalaya.backend == "maildir" then { + backend = account.himalaya.backend; + maildir-root-dir = account.maildirBasePath; + } else + throw "Unsupported backend: ${account.himalaya.backend}") + // (if account.himalaya.sender == null then { + sender = "none"; + } else if account.himalaya.sender == "smtp" then { + sender = account.himalaya.sender; smtp-login = account.userName; smtp-passwd-cmd = lib.escapeShellArgs account.passwordCommand; smtp-host = account.smtp.host; smtp-port = account.smtp.port; smtp-starttls = account.smtp.tls.useStartTls; - } // (lib.optionalAttrs (account.signature.showSignature == "append") { - # FIXME: signature cannot be attached - signature = account.signature.text; - }) // account.himalaya.settings; + } else if account.himalaya.sender == "sendmail" then { + sender = account.himalaya.sender; + } else + throw "Unsupported sender: ${account.himalaya.sender}") + // account.himalaya.settings; in { # NOTE: will not start without this configured, but each account overrides it - name = ""; + display-name = ""; } // cfg.settings // (lib.mapAttrs (_: toHimalayaConfig) enabledAccounts); in { - meta.maintainers = with lib.hm.maintainers; [ ambroisie ]; + meta.maintainers = with lib.hm.maintainers; [ toastal ]; options = with lib; { programs.himalaya = { @@ -63,7 +79,8 @@ in { default = { }; example = lib.literalExpression '' { - default-page-size = 50; + email-listing-page-size = 50; + watch-cmds = [ "mbsync -a" ] } ''; description = '' @@ -80,6 +97,22 @@ in { the himalaya mail client for this account ''; + backend = mkOption { + # TODO: “notmuch” (requires compile flag for himalaya, libnotmuch) + type = types.nullOr (types.enum [ "imap" "maildir" ]); + description = '' + The method for which himalaya will fetch, store, + etc. mail. + ''; + }; + + sender = mkOption { + type = types.nullOr (types.enum [ "smtp" "sendmail" ]); + description = '' + The method for which himalaya will send mail. + ''; + }; + settings = mkOption { type = tomlFormat.type; default = { }; diff --git a/modules/programs/i3status.nix b/modules/programs/i3status.nix index ca1f133e..5fd4f741 100644 --- a/modules/programs/i3status.nix +++ b/modules/programs/i3status.nix @@ -138,6 +138,8 @@ in { } ''; }; + + package = mkPackageOption pkgs "i3status" { }; }; config = mkIf cfg.enable { @@ -197,7 +199,7 @@ in { }; }; - home.packages = [ pkgs.i3status ]; + home.packages = [ cfg.package ]; xdg.configFile."i3status/config".text = concatStringsSep "\n" ([ ] ++ optional (cfg.general != { }) (formatModule "general" cfg.general) diff --git a/modules/programs/irssi.nix b/modules/programs/irssi.nix index 3d830a4f..d0953ed7 100644 --- a/modules/programs/irssi.nix +++ b/modules/programs/irssi.nix @@ -23,6 +23,11 @@ let type = "${v.type}"; nick = "${quoteStr v.nick}"; autosendcmd = "${concatMapStringsSep ";" quoteStr v.autoCommands}"; + ${ + lib.optionalString (v.saslExternal) '' + sasl_username = "${quoteStr v.nick}"; + sasl_mechanism = "EXTERNAL";'' + } }; '')); @@ -36,7 +41,7 @@ let ssl_verify = "${lib.hm.booleans.yesNo v.server.ssl.verify}"; autoconnect = "${lib.hm.booleans.yesNo v.server.autoConnect}"; ${ - lib.optionalString (v.server.ssl.certificateFile != null) '' + optionalString (v.server.ssl.certificateFile != null) '' ssl_cert = "${v.server.ssl.certificateFile}"; '' } @@ -142,6 +147,15 @@ let type = types.attrsOf channelType; default = { }; }; + + saslExternal = mkOption { + type = types.bool; + default = false; + description = '' + Enable SASL external authentication. This requires setting a path in + . + ''; + }; }; }); @@ -171,10 +185,10 @@ in { default = { }; example = literalExpression '' { - freenode = { + liberachat = { nick = "hmuser"; server = { - address = "chat.freenode.net"; + address = "irc.libera.chat"; port = 6697; autoConnect = true; }; diff --git a/modules/programs/java.nix b/modules/programs/java.nix index 5b2a0129..d10f64c5 100644 --- a/modules/programs/java.nix +++ b/modules/programs/java.nix @@ -36,11 +36,8 @@ in { config = mkIf cfg.enable { home.packages = [ cfg.package ]; - home.sessionVariables = { - JAVA_HOME = fileContents (pkgs.runCommandLocal "java-home" { } '' - source "${cfg.package}/nix-support/setup-hook" - echo "$JAVA_HOME" > $out - ''); - }; + # some instances of `jdk-linux-base.nix` pass through `result` without turning it onto a path-string. + # while I suspect this is incorrect, the documentation is unclear. + home.sessionVariables.JAVA_HOME = "${cfg.package.home}"; }; } diff --git a/modules/programs/just.nix b/modules/programs/just.nix index 6d5447c3..79006a51 100644 --- a/modules/programs/just.nix +++ b/modules/programs/just.nix @@ -9,44 +9,14 @@ let in { meta.maintainers = [ hm.maintainers.maximsmol ]; - options.programs.just = { - enable = mkEnableOption - "just, a handy way to save and run project-specific commands"; - - package = mkOption { - type = types.package; - default = pkgs.just; - defaultText = literalExpression "pkgs.just"; - description = "Package providing the just tool."; - }; - - 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 ]; - - programs.bash.initExtra = mkIf cfg.enableBashIntegration '' - source ${cfg.package}/share/bash-completion/completions/just.bash - ''; - - programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' - source ${cfg.package}/share/zsh/site-functions/_just - ''; - - programs.fish.shellInit = mkIf cfg.enableFishIntegration '' - source ${cfg.package}/share/fish/vendor_completions.d/just.fish - ''; - - }; + imports = let + msg = '' + 'program.just' is deprecated, simply add 'pkgs.just' to 'home.packages' instead. + See https://github.com/nix-community/home-manager/issues/3449#issuecomment-1329823502''; + in [ + (mkRemovedOptionModule [ "programs" "just" "enable" ] msg) + (mkRemovedOptionModule [ "programs" "just" "enableBashIntegration" ] msg) + (mkRemovedOptionModule [ "programs" "just" "enableZshIntegration" ] msg) + (mkRemovedOptionModule [ "programs" "just" "enableFishIntegration" ] msg) + ]; } diff --git a/modules/programs/k9s.nix b/modules/programs/k9s.nix new file mode 100644 index 00000000..11ac2bfd --- /dev/null +++ b/modules/programs/k9s.nix @@ -0,0 +1,65 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.k9s; + yamlFormat = pkgs.formats.yaml { }; + +in { + meta.maintainers = [ hm.maintainers.katexochen ]; + + options.programs.k9s = { + enable = + mkEnableOption "k9s - Kubernetes CLI To Manage Your Clusters In Style"; + + package = mkPackageOption pkgs "k9s" { }; + + settings = mkOption { + type = yamlFormat.type; + default = { }; + description = '' + Configuration written to + $XDG_CONFIG_HOME/k9s/config.yml. See + + for supported values. + ''; + example = literalExpression '' + k9s = { + refreshRate = 2; + }; + ''; + }; + + skin = mkOption { + type = yamlFormat.type; + default = { }; + description = '' + Skin written to + $XDG_CONFIG_HOME/k9s/skin.yml. See + + for supported values. + ''; + example = literalExpression '' + k9s = { + body = { + fgColor = "dodgerblue"; + }; + }; + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."k9s/config.yml" = mkIf (cfg.settings != { }) { + source = yamlFormat.generate "k9s-config" cfg.settings; + }; + + xdg.configFile."k9s/skin.yml" = mkIf (cfg.skin != { }) { + source = yamlFormat.generate "k9s-skin" cfg.skin; + }; + }; +} diff --git a/modules/programs/kakoune.nix b/modules/programs/kakoune.nix index 495ef8e1..32f71890 100644 --- a/modules/programs/kakoune.nix +++ b/modules/programs/kakoune.nix @@ -10,13 +10,9 @@ let options = { name = mkOption { type = types.enum [ - "NormalBegin" "NormalIdle" - "NormalEnd" "NormalKey" - "InsertBegin" "InsertIdle" - "InsertEnd" "InsertKey" "InsertChar" "InsertDelete" @@ -48,8 +44,11 @@ let "RawKey" "InsertCompletionShow" "InsertCompletionHide" - "InsertCompletionSelect" "ModuleLoaded" + "ClientCreate" + "ClientClose" + "RegisterModified" + "User" ]; example = "SetOption"; description = '' @@ -489,9 +488,8 @@ let }; }; - kakouneWithPlugins = pkgs.wrapKakoune pkgs.kakoune-unwrapped { - configure = { plugins = cfg.plugins; }; - }; + kakouneWithPlugins = + pkgs.wrapKakoune cfg.package { configure = { plugins = cfg.plugins; }; }; configFile = let wrapOptions = with cfg.config.wrapLines; @@ -624,6 +622,8 @@ in { programs.kakoune = { enable = mkEnableOption "the kakoune text editor"; + package = mkPackageOption pkgs "kakoune-unwrapped" { }; + config = mkOption { type = types.nullOr configModule; default = { }; diff --git a/modules/programs/kitty.nix b/modules/programs/kitty.nix index 196ecbdb..1a6258a3 100644 --- a/modules/programs/kitty.nix +++ b/modules/programs/kitty.nix @@ -119,14 +119,6 @@ in { }; config = mkIf cfg.enable { - assertions = [{ - assertion = (cfg.darwinLaunchOptions != null) - -> pkgs.stdenv.hostPlatform.isDarwin; - message = '' - The 'programs.kitty.darwinLaunchOptions' option is only available on darwin. - ''; - }]; - home.packages = [ cfg.package ] ++ optionalPackage cfg.font; xdg.configFile."kitty/kitty.conf" = { @@ -158,8 +150,8 @@ in { ''; }; - xdg.configFile."kitty/macos-launch-services-cmdline" = - mkIf (cfg.darwinLaunchOptions != null) { + xdg.configFile."kitty/macos-launch-services-cmdline" = mkIf + (cfg.darwinLaunchOptions != null && pkgs.stdenv.hostPlatform.isDarwin) { text = concatStringsSep " " cfg.darwinLaunchOptions; }; }; diff --git a/modules/programs/kodi.nix b/modules/programs/kodi.nix index 36169948..bae862ae 100644 --- a/modules/programs/kodi.nix +++ b/modules/programs/kodi.nix @@ -82,7 +82,7 @@ let attrsetToXml = attrs: name: stylesheet: pkgs.runCommand name { # Package splicing for libxslt does not work correctly leading to errors - # when cross-compiling. Use the version from buildPackages explicitely to + # when cross-compiling. Use the version from buildPackages explicitly to # fix this. nativeBuildInputs = [ pkgs.buildPackages.libxslt.bin ]; xml = builtins.toXML attrs; @@ -131,9 +131,8 @@ in { type = types.package; default = pkgs.kodi; defaultText = literalExpression "pkgs.kodi"; - example = literalExpression '' - { pkgs.kodi.withPackages (exts: [ exts.pvr-iptvsimple ]) } - ''; + example = literalExpression + "pkgs.kodi.withPackages (exts: [ exts.pvr-iptvsimple ])"; description = '' The kodi package to use. Can be used to specify extensions. diff --git a/modules/programs/lazygit.nix b/modules/programs/lazygit.nix index 1752b151..84dab379 100644 --- a/modules/programs/lazygit.nix +++ b/modules/programs/lazygit.nix @@ -16,6 +16,8 @@ in { options.programs.lazygit = { enable = mkEnableOption "lazygit, a simple terminal UI for git commands"; + package = mkPackageOption pkgs "lazygit" { }; + settings = mkOption { type = yamlFormat.type; default = { }; @@ -41,7 +43,7 @@ in { }; config = mkIf cfg.enable { - home.packages = [ pkgs.lazygit ]; + home.packages = [ cfg.package ]; home.file."Library/Application Support/lazygit/config.yml" = mkIf (cfg.settings != { } && isDarwin) { diff --git a/modules/programs/ledger.nix b/modules/programs/ledger.nix new file mode 100644 index 00000000..c51ed7d1 --- /dev/null +++ b/modules/programs/ledger.nix @@ -0,0 +1,39 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.ledger; + +in { + meta.maintainers = [ maintainers.marsam ]; + + options.programs.ledger = { + enable = mkEnableOption "ledger, a double-entry accounting system"; + + package = mkPackageOption pkgs "ledger" { }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = literalExpression '' + --sort date + --effective + --date-format %Y-%m-%d + ''; + description = '' + Configuration written to $XDG_CONFIG_HOME/ledger/ledgerrc. + See + for explanation about possible values. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."ledger/ledgerrc" = + mkIf (cfg.extraConfig != "") { text = cfg.extraConfig; }; + }; +} diff --git a/modules/programs/lieer.nix b/modules/programs/lieer.nix index e0369ffc..15fda1ae 100644 --- a/modules/programs/lieer.nix +++ b/modules/programs/lieer.nix @@ -238,8 +238,8 @@ in { package = mkOption { type = types.package; - default = pkgs.gmailieer; - defaultText = "pkgs.gmailieer"; + default = pkgs.lieer; + defaultText = "pkgs.lieer"; description = '' lieer package to use. ''; diff --git a/modules/programs/looking-glass-client.nix b/modules/programs/looking-glass-client.nix new file mode 100644 index 00000000..1c14282b --- /dev/null +++ b/modules/programs/looking-glass-client.nix @@ -0,0 +1,60 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.looking-glass-client; + settingsFormat = pkgs.formats.ini { }; +in { + meta.maintainers = with maintainers; [ j-brn ]; + + options.programs.looking-glass-client = { + enable = mkEnableOption "looking-glass-client"; + + package = mkPackageOption pkgs "looking-glass-client" { }; + + settings = mkOption { + type = settingsFormat.type; + default = { }; + description = "looking-glass-client settings."; + example = literalExpression '' + { + app = { + allowDMA = true; + shmFile = "/dev/kvmfr0"; + }; + + win = { + fullScreen = true; + showFPS = false; + jitRender = true; + }; + + spice = { + enable = true; + audio = true; + }; + + input = { + rawMouse = true; + escapeKey = 62; + }; + } + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (hm.assertions.assertPlatform "programs.looking-glass-client" pkgs + platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + xdg.configFile."looking-glass/client.ini" = mkIf (cfg.settings != { }) { + source = + settingsFormat.generate ("looking-glass-client.ini") cfg.settings; + }; + }; +} diff --git a/modules/programs/man.nix b/modules/programs/man.nix index f3134b37..69ae5cac 100644 --- a/modules/programs/man.nix +++ b/modules/programs/man.nix @@ -69,7 +69,7 @@ in { echo "MANDB_MAP ${manualPages}/share/man $out" > man.conf # Run mandb to generate cache files: - ${pkgs.man-db}/bin/mandb -C man.conf --no-straycats --create \ + ${cfg.package}/bin/mandb -C man.conf --no-straycats --create \ ${manualPages}/share/man ''; in '' diff --git a/modules/programs/mangohud.nix b/modules/programs/mangohud.nix index c41d5003..f095e073 100644 --- a/modules/programs/mangohud.nix +++ b/modules/programs/mangohud.nix @@ -56,7 +56,7 @@ in { description = '' Configuration written to $XDG_CONFIG_HOME/MangoHud/MangoHud.conf. See - + for the default configuration. ''; }; @@ -75,7 +75,7 @@ in { Sets MangoHud settings per application. Configuration written to $XDG_CONFIG_HOME/MangoHud/{application_name}.conf. See - + for the default configuration. ''; }; diff --git a/modules/programs/mbsync-accounts.nix b/modules/programs/mbsync-accounts.nix index fa3f00ab..af368b9d 100644 --- a/modules/programs/mbsync-accounts.nix +++ b/modules/programs/mbsync-accounts.nix @@ -4,7 +4,8 @@ with lib; let - extraConfigType = with lib.types; attrsOf (either (either str int) bool); + extraConfigType = with lib.types; + attrsOf (oneOf [ str int bool (listOf str) ]); perAccountGroups = { name, config, ... }: { options = { diff --git a/modules/programs/mbsync.nix b/modules/programs/mbsync.nix index 373828a0..8694d200 100644 --- a/modules/programs/mbsync.nix +++ b/modules/programs/mbsync.nix @@ -84,7 +84,7 @@ let genSection "IMAPAccount ${name}" ({ Host = imap.host; User = userName; - PassCmd = toString passwordCommand; + PassCmd = lib.escapeShellArgs passwordCommand; } // genTlsConfig imap.tls // optionalAttrs (imap.port != null) { Port = toString imap.port; } // mbsync.extraConfig.account) + "\n" @@ -174,7 +174,7 @@ let flatten (optionals (group.channels != { }) ([ "Group ${group.name}" ] ++ (genChannelStrings group.name group.channels))); # Given set of groups, generates list of strings, where each string is one - # of the groups and its consituent channels. + # of the groups and its constituent channels. genGroupsStrings = mapAttrsToList (name: info: concatStringsSep "\n" (genGroupChannelString groups.${name})) groups; # Join all non-empty groups. diff --git a/modules/programs/mu.nix b/modules/programs/mu.nix index 58b8b3df..835be361 100644 --- a/modules/programs/mu.nix +++ b/modules/programs/mu.nix @@ -52,7 +52,7 @@ in { # In theory, mu is the only thing that creates that directory, and it is # only created during the initial index. if [[ ! -d "${dbLocation}" ]]; then - $DRY_RUN_CMD mu init ${maildirOption} ${myAddresses} $VERBOSE_ARG; + $DRY_RUN_CMD ${pkgs.mu}/bin/mu init ${maildirOption} ${myAddresses} $VERBOSE_ARG; fi ''; }; diff --git a/modules/programs/mujmap.nix b/modules/programs/mujmap.nix index 9d290fef..291b9656 100644 --- a/modules/programs/mujmap.nix +++ b/modules/programs/mujmap.nix @@ -186,7 +186,7 @@ let default = null; example = "https://jmap.example.com/.well-known/jmap"; description = '' - Sesion URL to connect to. + Session URL to connect to. Mutually exclusive with . diff --git a/modules/programs/ncmpcpp.nix b/modules/programs/ncmpcpp.nix index e3784951..5f9bd36e 100644 --- a/modules/programs/ncmpcpp.nix +++ b/modules/programs/ncmpcpp.nix @@ -62,7 +62,7 @@ in { }; mpdMusicDir = mkOption { - type = types.nullOr types.path; + type = with types; nullOr (coercedTo path toString str); default = let mpdCfg = config.services.mpd; in if pkgs.stdenv.hostPlatform.isLinux && mpdCfg.enable then mpdCfg.musicDirectory @@ -123,7 +123,7 @@ in { xdg.configFile = { "ncmpcpp/config" = let settings = cfg.settings // optionalAttrs (cfg.mpdMusicDir != null) { - mpd_music_dir = toString cfg.mpdMusicDir; + mpd_music_dir = cfg.mpdMusicDir; }; in mkIf (settings != { }) { text = renderSettings settings + "\n"; }; diff --git a/modules/programs/neovim.nix b/modules/programs/neovim.nix index 7123f07a..df4b487d 100644 --- a/modules/programs/neovim.nix +++ b/modules/programs/neovim.nix @@ -13,32 +13,13 @@ let jsonFormat = pkgs.formats.json { }; - extraPython3PackageType = mkOptionType { - name = "extra-python3-packages"; - description = "python3 packages in python.withPackages format"; - check = with types; - (x: if isFunction x then isList (x pkgs.python3Packages) else false); - merge = mergeOneOption; - }; - - # Currently, upstream Neovim is pinned on Lua 5.1 for LuaJIT support. - # This will need to be updated if Neovim ever migrates to a newer - # version of Lua. - extraLua51PackageType = mkOptionType { - name = "extra-lua51-packages"; - description = "lua5.1 packages in lua5_1.withPackages format"; - check = with types; - (x: if isFunction x then isList (x pkgs.lua51Packages) else false); - merge = mergeOneOption; - }; - pluginWithConfigType = types.submodule { options = { config = mkOption { - type = types.lines; + type = types.nullOr types.lines; description = "Script to configure this plugin. The scripting language should match type."; - default = ""; + default = null; }; type = mkOption { @@ -80,19 +61,23 @@ let optional = false; }; + luaPackages = cfg.finalPackage.unwrapped.lua.pkgs; + resolvedExtraLuaPackages = cfg.extraLuaPackages luaPackages; + extraMakeWrapperArgs = lib.optionalString (cfg.extraPackages != [ ]) ''--suffix PATH : "${lib.makeBinPath cfg.extraPackages}"''; - extraMakeWrapperLuaCArgs = lib.optionalString (cfg.extraLuaPackages != [ ]) '' - --suffix LUA_CPATH ";" "${ - lib.concatMapStringsSep ";" pkgs.lua51Packages.getLuaCPath - cfg.extraLuaPackages - }"''; - extraMakeWrapperLuaArgs = lib.optionalString (cfg.extraLuaPackages != [ ]) '' - --suffix LUA_PATH ";" "${ - lib.concatMapStringsSep ";" pkgs.lua51Packages.getLuaPath - cfg.extraLuaPackages - }"''; - + extraMakeWrapperLuaCArgs = + lib.optionalString (resolvedExtraLuaPackages != [ ]) '' + --suffix LUA_CPATH ";" "${ + lib.concatMapStringsSep ";" luaPackages.getLuaCPath + resolvedExtraLuaPackages + }"''; + extraMakeWrapperLuaArgs = lib.optionalString (resolvedExtraLuaPackages != [ ]) + '' + --suffix LUA_PATH ";" "${ + lib.concatMapStringsSep ";" luaPackages.getLuaPath + resolvedExtraLuaPackages + }"''; in { imports = [ (mkRemovedOptionModule [ "programs" "neovim" "withPython" ] @@ -164,24 +149,51 @@ in { }; extraPython3Packages = mkOption { - type = with types; either extraPython3PackageType (listOf package); - default = (_: [ ]); + # In case we get a plain list, we need to turn it into a function, + # as expected by the function in nixpkgs. + # The only way to do so is to call `const`, which will ignore its input. + type = with types; + let fromType = listOf package; + in coercedTo fromType (flip warn const '' + Assigning a plain list to extraPython3Packages is deprecated. + Please assign a function taking a package set as argument, so + extraPython3Packages = [ pkgs.python3Packages.xxx ]; + should become + extraPython3Packages = ps: [ ps.xxx ]; + '') (functionTo fromType); + default = _: [ ]; defaultText = literalExpression "ps: [ ]"; - example = literalExpression "(ps: with ps; [ python-language-server ])"; + example = + literalExpression "pyPkgs: with pyPkgs; [ python-language-server ]"; description = '' - A function in python.withPackages format, which returns a - list of Python 3 packages required for your plugins to work. + The extra Python 3 packages required for your plugins to work. + This option accepts a function that takes a Python 3 package set as an argument, + and selects the required Python 3 packages from this package set. + See the example for more info. ''; }; + # We get the Lua package from the final package and use its + # Lua packageset to evaluate the function that this option was set to. + # This ensures that we always use the same Lua version as the Neovim package. extraLuaPackages = mkOption { - type = with types; either extraLua51PackageType (listOf package); - default = [ ]; - defaultText = literalExpression "[ ]"; - example = literalExpression "(ps: with ps; [ luautf8 ])"; + type = with types; + let fromType = listOf package; + in coercedTo fromType (flip warn const '' + Assigning a plain list to extraLuaPackages is deprecated. + Please assign a function taking a package set as argument, so + extraLuaPackages = [ pkgs.lua51Packages.xxx ]; + should become + extraLuaPackages = ps: [ ps.xxx ]; + '') (functionTo fromType); + default = _: [ ]; + defaultText = literalExpression "ps: [ ]"; + example = literalExpression "luaPkgs: with luaPkgs; [ luautf8 ]"; description = '' - A function in lua5_1.withPackages format, which returns a - list of Lua packages required for your plugins to work. + The extra Lua packages required for your plugins to work. + This option accepts a function that takes a Lua package set as an argument, + and selects the required Lua packages from this package set. + See the example for more info. ''; }; @@ -229,6 +241,15 @@ in { description = "Resulting customized neovim package."; }; + defaultEditor = mkOption { + type = types.bool; + default = false; + description = '' + Whether to configure nvim as the default + editor using the EDITOR environment variable. + ''; + }; + extraConfig = mkOption { type = types.lines; default = ""; @@ -240,6 +261,17 @@ in { ''; }; + extraLuaConfig = mkOption { + type = types.lines; + default = ""; + example = '' + vim.opt.nobackup = true + ''; + description = '' + Custom lua lines. + ''; + }; + extraPackages = mkOption { type = with types; listOf package; default = [ ]; @@ -280,7 +312,7 @@ in { }; settings = mkOption { - type = jsonFormat.type; + inherit (jsonFormat) type; default = { }; example = literalExpression '' { @@ -326,7 +358,7 @@ in { defaultPlugin = { type = "viml"; plugin = null; - config = ""; + config = null; optional = false; runtime = { }; }; @@ -337,7 +369,7 @@ in { allPlugins; suppressNotVimlConfig = p: - if p.type != "viml" then p // { config = ""; } else p; + if p.type != "viml" then p // { config = null; } else p; neovimConfig = pkgs.neovimUtils.makeNeovimConfig { inherit (cfg) extraPython3Packages withPython3 withRuby viAlias vimAlias; @@ -353,26 +385,35 @@ in { programs.neovim.generatedConfigs = let grouped = lib.lists.groupBy (x: x.type) pluginsNormalized; concatConfigs = lib.concatMapStrings (p: p.config); - in mapAttrs (name: vals: concatConfigs vals) grouped; + configsOnly = lib.foldl + (acc: p: if p.config != null then acc ++ [ p.config ] else acc) [ ]; + in mapAttrs (name: vals: lib.concatStringsSep "\n" (configsOnly vals)) + grouped; home.packages = [ cfg.finalPackage ]; - xdg.configFile = mkMerge ( - # writes runtime - (map (x: x.runtime) pluginsNormalized) ++ [{ - "nvim/init.vim" = mkIf (neovimConfig.neovimRcContent != "") { - text = neovimConfig.neovimRcContent + lib.optionalString - (hasAttr "lua" config.programs.neovim.generatedConfigs) - "lua require('init-home-manager')"; - }; - "nvim/lua/init-home-manager.lua" = - mkIf (hasAttr "lua" config.programs.neovim.generatedConfigs) { - text = config.programs.neovim.generatedConfigs.lua; + home.sessionVariables = mkIf cfg.defaultEditor { EDITOR = "nvim"; }; + + xdg.configFile = + let hasLuaConfig = hasAttr "lua" config.programs.neovim.generatedConfigs; + in mkMerge ( + # writes runtime + (map (x: x.runtime) pluginsNormalized) ++ [{ + "nvim/init.lua" = let + luaRcContent = + lib.optionalString (neovimConfig.neovimRcContent != "") + "vim.cmd [[source ${ + pkgs.writeText "nvim-init-home-manager.vim" + neovimConfig.neovimRcContent + }]]" + config.programs.neovim.extraLuaConfig + + lib.optionalString hasLuaConfig + config.programs.neovim.generatedConfigs.lua; + in mkIf (luaRcContent != "") { text = luaRcContent; }; + + "nvim/coc-settings.json" = mkIf cfg.coc.enable { + source = jsonFormat.generate "coc-settings.json" cfg.coc.settings; }; - "nvim/coc-settings.json" = mkIf cfg.coc.enable { - source = jsonFormat.generate "coc-settings.json" cfg.coc.settings; - }; - }]); + }]); programs.neovim.finalPackage = pkgs.wrapNeovimUnstable cfg.package (neovimConfig // { diff --git a/modules/programs/newsboat.nix b/modules/programs/newsboat.nix index ba074a42..d2782bf2 100644 --- a/modules/programs/newsboat.nix +++ b/modules/programs/newsboat.nix @@ -68,7 +68,10 @@ in { url = "http://example.com"; tags = [ "foo" "bar" ]; }]; - description = "List of news feeds."; + description = '' + List of news feeds. Leave it empty if you want to manage feeds + imperatively, for example, using Syncthing. + ''; }; maxItems = mkOption { @@ -121,16 +124,24 @@ in { }; config = mkIf cfg.enable { + assertions = [{ + assertion = cfg.queries != { } -> cfg.urls != [ ]; + message = '' + Cannot specify queries if urls is empty. Unset queries if you + want to manage urls imperatively. + ''; + }]; + home.packages = [ pkgs.newsboat ]; # Use ~/.newsboat on stateVersion < 21.05 and use ~/.config/newsboat for # stateVersion >= 21.05. home.file = mkIf (versionOlder config.home.stateVersion "21.05") { - ".newsboat/urls".text = urlsFileContents; + ".newsboat/urls" = mkIf (cfg.urls != [ ]) { text = urlsFileContents; }; ".newsboat/config".text = configFileContents; }; xdg.configFile = mkIf (versionAtLeast config.home.stateVersion "21.05") { - "newsboat/urls".text = urlsFileContents; + "newsboat/urls" = mkIf (cfg.urls != [ ]) { text = urlsFileContents; }; "newsboat/config".text = configFileContents; }; }; diff --git a/modules/programs/nushell.nix b/modules/programs/nushell.nix index 58b47798..da01672b 100644 --- a/modules/programs/nushell.nix +++ b/modules/programs/nushell.nix @@ -6,14 +6,22 @@ let cfg = config.programs.nushell; - tomlFormat = pkgs.formats.toml { }; + configDir = if pkgs.stdenv.isDarwin then + "Library/Application Support/nushell" + else + "${config.xdg.configHome}/nushell"; linesOrSource = name: types.submodule ({ config, ... }: { options = { text = mkOption { type = types.lines; - default = ""; + default = if config.source != null then + builtins.readFile config.source + else + ""; + defaultText = literalExpression + "if source is defined, the content of source, otherwise empty"; description = '' Text of the nushell ${name} file. If unset then the source option will be preferred. @@ -22,18 +30,14 @@ let source = mkOption { type = types.nullOr types.path; - default = pkgs.writeTextFile { - inherit (config) text; - name = hm.strings.storeFileName name; - }; - defaultText = literalExpression "file containing text"; + default = null; description = '' Path of the nushell ${name} file to use. + If the text option is set, it will be preferred. ''; }; }; }); - in { meta.maintainers = [ maintainers.Philipp-M ]; @@ -91,14 +95,39 @@ in { See for more information. ''; }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Additional configuration to add to the nushell configuration file. + ''; + }; + + extraEnv = mkOption { + type = types.lines; + default = ""; + description = '' + Additional configuration to add to the nushell environment variables file. + ''; + }; }; config = mkIf cfg.enable { home.packages = [ cfg.package ]; - - xdg.configFile = mkMerge [ - (mkIf (cfg.configFile != null) { "nushell/config.nu" = cfg.configFile; }) - (mkIf (cfg.envFile != null) { "nushell/env.nu" = cfg.envFile; }) + home.file = mkMerge [ + (mkIf (cfg.configFile != null || cfg.extraConfig != "") { + "${configDir}/config.nu".text = mkMerge [ + (mkIf (cfg.configFile != null) cfg.configFile.text) + cfg.extraConfig + ]; + }) + (mkIf (cfg.envFile != null || cfg.extraEnv != "") { + "${configDir}/env.nu".text = mkMerge [ + (mkIf (cfg.envFile != null) cfg.envFile.text) + cfg.extraEnv + ]; + }) ]; }; } diff --git a/modules/programs/oh-my-posh.nix b/modules/programs/oh-my-posh.nix new file mode 100644 index 00000000..d1dfda97 --- /dev/null +++ b/modules/programs/oh-my-posh.nix @@ -0,0 +1,94 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + + cfg = config.programs.oh-my-posh; + + jsonFormat = pkgs.formats.json { }; + + configArgument = if cfg.settings != { } then + "--config ${config.xdg.configHome}/oh-my-posh/config.json" + else if cfg.useTheme != null then + "--config ${cfg.package}/share/oh-my-posh/themes/${cfg.useTheme}.omp.json" + else + ""; + +in { + meta.maintainers = [ maintainers.arjan-s ]; + + options.programs.oh-my-posh = { + enable = mkEnableOption "oh-my-posh, a prompt theme engine for any shell"; + + package = mkPackageOption pkgs "oh-my-posh" { }; + + settings = mkOption { + type = jsonFormat.type; + default = { }; + example = literalExpression '' + builtins.fromJSON (builtins.unsafeDiscardStringContext (builtins.readFile "''${pkgs.oh-my-posh}/share/oh-my-posh/themes/space.omp.json"))''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/oh-my-posh/config.json. See + + for details. The useTheme option is ignored when this + option is used. + ''; + }; + + useTheme = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Use one of the official themes. This should be a name from this list: + . Because a theme + is essentially a configuration file, this option is not used when a + configFile is set. + ''; + }; + + enableBashIntegration = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable Bash integration. + ''; + }; + + enableZshIntegration = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable Zsh integration. + ''; + }; + + enableFishIntegration = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable Fish integration. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."oh-my-posh/config.json" = mkIf (cfg.settings != { }) { + source = jsonFormat.generate "oh-my-posh-settings" cfg.settings; + }; + + programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + eval "$(${cfg.package}/bin/oh-my-posh init bash ${configArgument})" + ''; + + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + eval "$(${cfg.package}/bin/oh-my-posh init zsh ${configArgument})" + ''; + + programs.fish.shellInit = mkIf cfg.enableFishIntegration '' + ${cfg.package}/bin/oh-my-posh init fish ${configArgument} | source + ''; + }; +} diff --git a/modules/programs/opam.nix b/modules/programs/opam.nix index 9cd76d95..0606d35b 100644 --- a/modules/programs/opam.nix +++ b/modules/programs/opam.nix @@ -34,6 +34,14 @@ in { Whether to enable Zsh integration. ''; }; + + enableFishIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Fish integration. + ''; + }; }; config = mkIf cfg.enable { @@ -46,5 +54,9 @@ in { programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' eval "$(${cfg.package}/bin/opam env --shell=zsh)" ''; + + programs.fish.shellInit = mkIf cfg.enableFishIntegration '' + eval (${cfg.package}/bin/opam env --shell=fish) + ''; }; } diff --git a/modules/programs/papis.nix b/modules/programs/papis.nix new file mode 100644 index 00000000..8e127e26 --- /dev/null +++ b/modules/programs/papis.nix @@ -0,0 +1,91 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.papis; + + defaultLibraries = remove null + (mapAttrsToList (n: v: if v.isDefault then n else null) cfg.libraries); + + settingsIni = (lib.mapAttrs (n: v: v.settings) cfg.libraries) // { + settings = cfg.settings // { "default-library" = head defaultLibraries; }; + }; + +in { + meta.maintainers = [ maintainers.marsam ]; + + options.programs.papis = { + enable = mkEnableOption "papis"; + + settings = mkOption { + type = with types; attrsOf (oneOf [ bool int str ]); + default = { }; + example = literalExpression '' + { + editor = "nvim"; + file-browser = "ranger" + add-edit = true; + } + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/papis/config. See + + for supported values. + ''; + }; + + libraries = mkOption { + type = types.attrsOf (types.submodule ({ config, name, ... }: { + options = { + name = mkOption { + type = types.str; + default = name; + readOnly = true; + description = "This library's name."; + }; + + isDefault = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + Whether this is a default library. There must be exactly one + default library. + ''; + }; + + settings = mkOption { + type = with types; attrsOf (oneOf [ bool int str ]); + default = { }; + example = literalExpression '' + { + dir = "~/papers/"; + } + ''; + description = '' + Configuration for this library. + ''; + }; + }; + })); + }; + }; + + config = mkIf cfg.enable { + assertions = [{ + assertion = cfg.libraries == { } || length defaultLibraries == 1; + message = "Must have exactly one default papis library, but found " + + toString (length defaultLibraries) + + optionalString (length defaultLibraries > 1) + (", namely " + concatStringsSep "," defaultLibraries); + }]; + + home.packages = [ pkgs.papis ]; + + xdg.configFile."papis/config" = + mkIf (cfg.libraries != { }) { text = generators.toINI { } settingsIni; }; + }; +} diff --git a/modules/programs/password-store.nix b/modules/programs/password-store.nix index e2f463ec..076db93e 100644 --- a/modules/programs/password-store.nix +++ b/modules/programs/password-store.nix @@ -59,6 +59,9 @@ in { home.packages = [ cfg.package ]; home.sessionVariables = cfg.settings; + services.pass-secret-service.storePath = + mkDefault cfg.settings.PASSWORD_STORE_DIR; + xsession.importedVariables = mkIf config.xsession.enable (mapAttrsToList (name: value: name) cfg.settings); }; diff --git a/modules/programs/pet.nix b/modules/programs/pet.nix index e75b10df..48e972ae 100644 --- a/modules/programs/pet.nix +++ b/modules/programs/pet.nix @@ -99,8 +99,9 @@ in { else { General = cfg.settings; }); - "pet/snippet.toml".source = - format.generate "snippet.toml" { snippets = cfg.snippets; }; + "pet/snippet.toml" = mkIf (cfg.snippets != [ ]) { + source = format.generate "snippet.toml" { snippets = cfg.snippets; }; + }; }; }; } diff --git a/modules/programs/pistol.nix b/modules/programs/pistol.nix index 8d5d6d71..4d6a1d29 100644 --- a/modules/programs/pistol.nix +++ b/modules/programs/pistol.nix @@ -3,31 +3,55 @@ with lib; let - cfg = config.programs.pistol; - configFile = - concatStringsSep "\n" (mapAttrsToList (k: v: "${k} ${v}") cfg.config); + configFile = concatStringsSep "\n" (map ({ fpath, mime, command }: + if fpath == "" then "${mime} ${command}" else "fpath ${fpath} ${command}") + cfg.associations); + association = types.submodule { + options = { + command = mkOption { + type = types.str; + description = "Preview command for files matched by this association."; + }; + + fpath = mkOption { + type = types.str; + default = ""; + description = "File path regex that this association should match."; + }; + + mime = mkOption { + type = types.str; + default = ""; + description = "Mime type regex that this association should match."; + }; + }; + }; in { + imports = [ + (mkRemovedOptionModule [ "programs" "pistol" "config" ] + "Pistol is now configured with programs.pistol.associations.") + ]; + meta.maintainers = [ hm.maintainers.mtoohey ]; options.programs.pistol = { - enable = mkEnableOption '' - Pistol, a general purpose file previewer designed for terminal file - managers''; + enable = mkEnableOption "file previewer for terminal file managers"; - config = mkOption { - type = with types; attrsOf str; - default = { }; + associations = mkOption { + type = types.listOf association; + default = [ ]; example = literalExpression '' - { - "text/*" = "bat --paging=never --color=always %pistol-filename%"; - "inode/directory" = "ls -l --color %pistol-filename%"; - } + [ + { mime = "application/json"; command = "bat %pistol-filename%"; } + { mime = "application/*"; command = "hexyl %pistol-filename%"; } + { fpath = ".*.md$"; command = "sh: bat --paging=never --color=always %pistol-filename% | head -8"; } + ] ''; description = '' - Pistol configuration written to + Associations written to the Pistol configuration at $XDG_CONFIG_HOME/pistol/pistol.conf. ''; }; @@ -35,14 +59,26 @@ in { }; config = mkIf cfg.enable (mkMerge [ - { home.packages = [ pkgs.pistol ]; } + { + assertions = [{ + assertion = all ({ fpath, mime, ... }: + (fpath != "" && mime == "") || (fpath == "" && mime != "")) + cfg.associations; + message = '' + Each entry in programs.pistol.associations must contain exactly one + of fpath or mime. + ''; + }]; - (mkIf (cfg.config != { } && pkgs.stdenv.hostPlatform.isDarwin) { + home.packages = [ pkgs.pistol ]; + } + + (mkIf (cfg.associations != [ ] && pkgs.stdenv.hostPlatform.isDarwin) { home.file."Library/Application Support/pistol/pistol.conf".text = configFile; }) - (mkIf (cfg.config != { } && !pkgs.stdenv.hostPlatform.isDarwin) { + (mkIf (cfg.associations != [ ] && !pkgs.stdenv.hostPlatform.isDarwin) { xdg.configFile."pistol/pistol.conf".text = configFile; }) ]); diff --git a/modules/programs/pls.nix b/modules/programs/pls.nix new file mode 100644 index 00000000..1c5af378 --- /dev/null +++ b/modules/programs/pls.nix @@ -0,0 +1,36 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.pls; + + aliases = { + ls = "${cfg.package}/bin/pls"; + ll = + "${cfg.package}/bin/pls -d perms -d user -d group -d size -d mtime -d git"; + }; + +in { + meta.maintainers = [ hm.maintainers.kalhauge ]; + + options.programs.pls = { + enable = + mkEnableOption "pls, a modern replacement for ls"; + + package = mkPackageOption pkgs "pls" { }; + + enableAliases = mkEnableOption "recommended pls aliases"; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + programs.bash.shellAliases = mkIf cfg.enableAliases aliases; + + programs.fish.shellAliases = mkIf cfg.enableAliases aliases; + + programs.zsh.shellAliases = mkIf cfg.enableAliases aliases; + }; +} diff --git a/modules/programs/rbenv.nix b/modules/programs/rbenv.nix new file mode 100644 index 00000000..b204d4f0 --- /dev/null +++ b/modules/programs/rbenv.nix @@ -0,0 +1,93 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.rbenv; + + pluginModule = types.submodule { + options = { + src = mkOption { + type = types.path; + description = '' + Path to the plugin folder. + ''; + }; + name = mkOption { + type = types.str; + description = '' + Name of the plugin. + ''; + }; + }; + }; + +in { + meta.maintainers = [ maintainers.marsam ]; + + options.programs.rbenv = { + enable = mkEnableOption "rbenv"; + + package = mkPackageOption pkgs "rbenv" { }; + + plugins = mkOption { + type = types.listOf pluginModule; + default = [ ]; + example = literalExpression '' + [ + { + name = "ruby-build"; + src = pkgs.fetchFromGitHub { + owner = "rbenv"; + repo = "ruby-build"; + rev = "v20221225"; + hash = "sha256-Kuq0Z1kh2mvq7rHEgwVG9XwzR5ZUtU/h8SQ7W4/mBU0="; + }; + } + ] + ''; + description = '' + rbenv plugins to install in $HOME/.rbenv/plugins/. + + See + for the full list of plugins. + ''; + }; + + 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 ]; + + home.file.".rbenv/plugins" = mkIf (cfg.plugins != [ ]) { + source = pkgs.linkFarm "rbenv-plugins" (builtins.map (p: { + name = p.name; + path = p.src; + }) cfg.plugins); + }; + + programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + eval "$(${cfg.package}/bin/rbenv init - bash)" + ''; + + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + eval "$(${cfg.package}/bin/rbenv init - zsh)" + ''; + + programs.fish.shellInit = mkIf cfg.enableFishIntegration '' + ${cfg.package}/bin/rbenv init - fish | source + ''; + }; +} diff --git a/modules/programs/rtorrent.nix b/modules/programs/rtorrent.nix index 95015e2c..5cfbe2f1 100644 --- a/modules/programs/rtorrent.nix +++ b/modules/programs/rtorrent.nix @@ -9,10 +9,16 @@ let in { meta.maintainers = [ maintainers.marsam ]; + imports = [ + (mkRenamedOptionModule # \ + [ "programs" "rtorrent" "settings" ] # \ + [ "programs" "rtorrent" "extraConfig" ]) + ]; + options.programs.rtorrent = { enable = mkEnableOption "rTorrent"; - settings = mkOption { + extraConfig = mkOption { type = types.lines; default = ""; description = '' @@ -29,6 +35,6 @@ in { home.packages = [ pkgs.rtorrent ]; xdg.configFile."rtorrent/rtorrent.rc" = - mkIf (cfg.settings != "") { text = cfg.settings; }; + mkIf (cfg.extraConfig != "") { text = cfg.extraConfig; }; }; } diff --git a/modules/programs/sbt.nix b/modules/programs/sbt.nix index bf355a80..3e8dbc10 100644 --- a/modules/programs/sbt.nix +++ b/modules/programs/sbt.nix @@ -8,13 +8,27 @@ let addSbtPlugin("${plugin.org}" % "${plugin.artifact}" % "${plugin.version}") ''; - renderCredential = cred: '' - credentials += Credentials("${cred.realm}", "${cred.host}", "${cred.user}", "${cred.passwordCommand}".!!.trim) - ''; + renderCredential = idx: cred: + let symbol = "credential_${toString idx}"; + in '' + lazy val ${symbol} = "${cred.passwordCommand}".!!.trim + credentials += Credentials("${cred.realm}", "${cred.host}", "${cred.user}", ${symbol}) + ''; renderCredentials = creds: '' import scala.sys.process._ - ${concatStrings (map renderCredential creds)}''; + ${concatStrings (imap0 renderCredential creds)}''; + + renderRepository = value: + if isString value then '' + ${value} + '' else '' + ${concatStrings (mapAttrsToList (name: value: "${name}: ${value}") value)} + ''; + + renderRepositories = repos: '' + [repositories] + ${concatStrings (map renderRepository cfg.repositories)}''; sbtTypes = { plugin = types.submodule { @@ -68,6 +82,11 @@ let cfg = config.programs.sbt; in { + imports = [ + (mkRemovedOptionModule [ "programs" "sbt" "baseConfigPath" ] + "Use programs.sbt.baseUserConfigPath instead, but note that the semantics are slightly different.") + ]; + meta.maintainers = [ maintainers.kubukoz ]; options.programs.sbt = { @@ -80,10 +99,13 @@ in { description = "The package with sbt to be installed."; }; - baseConfigPath = mkOption { + baseUserConfigPath = mkOption { type = types.str; - default = ".sbt/1.0"; - description = "Where the plugins and credentials should be located."; + default = ".sbt"; + description = '' + Where the sbt configuration files should be located, relative + HOME. + ''; }; plugins = mkOption { @@ -123,19 +145,63 @@ in { A list of credentials to define in the sbt configuration directory. ''; }; + + repositories = mkOption { + type = with types; + listOf + (either (enum [ "local" "maven-central" "maven-local" ]) (attrsOf str)); + default = [ ]; + example = literalExpression '' + [ + "local" + { my-ivy-proxy-releases = "http://repo.company.com/ivy-releases/, [organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext]" } + { my-maven-proxy-releases = "http://repo.company.com/maven-releases/" } + "maven-central" + ] + ''; + description = '' + A list of repositories to use when resolving dependencies. Defined as a + list of pre-defined repository or custom repository as a set of name to + URL. The list will be used populate the ~/.sbt/repositories + file in the order specified. + + + + Pre-defined repositories must be one of local, + maven-local, maven-central. + + + + Custom repositories are defined as + { name-of-repo = "https://url.to.repo.com"}. + + + + See + + about this configuration section and + + to read about proxy repositories. + ''; + }; }; config = mkIf cfg.enable (mkMerge [ { home.packages = [ cfg.package ]; } (mkIf (cfg.plugins != [ ]) { - home.file."${cfg.baseConfigPath}/plugins/plugins.sbt".text = + home.file."${cfg.baseUserConfigPath}/1.0/plugins/plugins.sbt".text = concatStrings (map renderPlugin cfg.plugins); }) (mkIf (cfg.credentials != [ ]) { - home.file."${cfg.baseConfigPath}/credentials.sbt".text = + home.file."${cfg.baseUserConfigPath}/1.0/credentials.sbt".text = renderCredentials cfg.credentials; }) + + (mkIf (cfg.repositories != [ ]) { + home.file."${cfg.baseUserConfigPath}/repositories".text = + renderRepositories cfg.repositories; + }) ]); } diff --git a/modules/programs/scmpuff.nix b/modules/programs/scmpuff.nix index 5f36ca02..0a573af0 100644 --- a/modules/programs/scmpuff.nix +++ b/modules/programs/scmpuff.nix @@ -31,6 +31,14 @@ in { Whether to enable Zsh integration. ''; }; + + enableFishIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable fish integration. + ''; + }; }; config = mkIf cfg.enable { @@ -43,5 +51,10 @@ in { programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' eval "$(${cfg.package}/bin/scmpuff init -s)" ''; + + programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration + (mkAfter '' + ${cfg.package}/bin/scmpuff init -s --shell=fish | source + ''); }; } diff --git a/modules/programs/sioyek.nix b/modules/programs/sioyek.nix index 9ef32746..63bf5b6f 100644 --- a/modules/programs/sioyek.nix +++ b/modules/programs/sioyek.nix @@ -1,11 +1,16 @@ { config, lib, pkgs, ... }: + with lib; + let + cfg = config.programs.sioyek; - renderAttrs = attrs: - concatStringsSep "\n" - (mapAttrsToList (name: value: "${name} ${value}") attrs); + renderConfig = generators.toKeyValue { + mkKeyValue = key: value: "${key} ${value}"; + listsAsDuplicateKeys = true; + }; + in { options = { programs.sioyek = { @@ -24,8 +29,11 @@ in { Input configuration written to $XDG_CONFIG_HOME/sioyek/keys_user.config. See . + + Each attribute could also accept a list of strings to set multiple + bindings of the same command. ''; - type = types.attrsOf types.str; + type = with types; attrsOf (either str (listOf str)); default = { }; example = literalExpression '' { @@ -33,6 +41,8 @@ in { "move_down" = "j"; "move_left" = "h"; "move_right" = "l"; + "screen_down" = [ "d" "" ]; + "screen_up" = [ "u" "" ]; } ''; }; @@ -59,10 +69,10 @@ in { config = mkIf cfg.enable (mkMerge [ { home.packages = [ cfg.package ]; } (mkIf (cfg.config != { }) { - xdg.configFile."sioyek/prefs_user.config".text = renderAttrs cfg.config; + xdg.configFile."sioyek/prefs_user.config".text = renderConfig cfg.config; }) (mkIf (cfg.bindings != { }) { - xdg.configFile."sioyek/keys_user.config".text = renderAttrs cfg.bindings; + xdg.configFile."sioyek/keys_user.config".text = renderConfig cfg.bindings; }) ]); diff --git a/modules/programs/ssh.nix b/modules/programs/ssh.nix index 05d16a2c..f906d1bc 100644 --- a/modules/programs/ssh.nix +++ b/modules/programs/ssh.nix @@ -60,10 +60,37 @@ let matchBlockModule = types.submodule ({ dagName, ... }: { options = { host = mkOption { - type = types.str; + type = types.nullOr types.str; + default = null; example = "*.example.org"; description = '' - The host pattern used by this conditional block. + Host pattern used by this conditional block. + See + + ssh_config + 5 + + for Host block details. + This option is ignored if + + if defined. + ''; + }; + + match = mkOption { + type = types.nullOr types.str; + default = null; + example = "host canonical\nhost exec \"ping -c1 -q 192.168.17.1\""; + description = '' + Match block conditions used by this block. See + + ssh_config + 5 + + for Match block details. + This option takes precedence over + + if defined. ''; }; @@ -276,11 +303,16 @@ let }; }; - config.host = mkDefault dagName; +# config.host = mkDefault dagName; }); - matchBlockStr = cf: concatStringsSep "\n" ( - ["Host ${cf.host}"] + matchBlockStr = key: cf: concatStringsSep "\n" ( + let + hostOrDagName = if cf.host != null then cf.host else key; + matchHead = if cf.match != null + then "Match ${cf.match}" + else "Host ${hostOrDagName}"; + in [ "${matchHead}" ] ++ optional (cf.port != null) " Port ${toString cf.port}" ++ optional (cf.forwardAgent != null) " ForwardAgent ${lib.hm.booleans.yesNo cf.forwardAgent}" ++ optional cf.forwardX11 " ForwardX11 yes" @@ -492,7 +524,7 @@ in ++ (optional (cfg.includes != [ ]) '' Include ${concatStringsSep " " cfg.includes} '') - ++ (map (block: matchBlockStr block.data) matchBlocks) + ++ (map (block: matchBlockStr block.name block.data) matchBlocks) )} Host * @@ -508,5 +540,9 @@ in ${replaceStrings ["\n"] ["\n "] cfg.extraConfig} ''; + + warnings = mapAttrsToList + (n: v: "The SSH config match block `programs.ssh.matchBlocks.${n}` sets both of the host and match options.\nThe match option takes precedence.") + (filterAttrs (n: v: v.data.host != null && v.data.match != null) cfg.matchBlocks); }; } diff --git a/modules/programs/starship.nix b/modules/programs/starship.nix index 58ec518a..05763c0b 100644 --- a/modules/programs/starship.nix +++ b/modules/programs/starship.nix @@ -89,6 +89,14 @@ in { Whether to enable Ion integration. ''; }; + + enableNushellIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Nushell integration. + ''; + }; }; config = mkIf cfg.enable { @@ -121,5 +129,22 @@ in { eval $(${starshipCmd} init ion) end ''; + + programs.nushell = mkIf cfg.enableNushellIntegration { + # Unfortunately nushell doesn't allow conditionally sourcing nor + # conditionally setting (global) environment variables, which is why the + # check for terminal compatibility (as seen above for the other shells) is + # not done here. + extraEnv = '' + let starship_cache = "${config.xdg.cacheHome}/starship" + if not ($starship_cache | path exists) { + mkdir $starship_cache + } + ${starshipCmd} init nu | save --force ${config.xdg.cacheHome}/starship/init.nu + ''; + extraConfig = '' + source ${config.xdg.cacheHome}/starship/init.nu + ''; + }; }; } diff --git a/modules/programs/thunderbird.nix b/modules/programs/thunderbird.nix new file mode 100644 index 00000000..8c5a4b86 --- /dev/null +++ b/modules/programs/thunderbird.nix @@ -0,0 +1,306 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + inherit (pkgs.stdenv.hostPlatform) isDarwin; + + cfg = config.programs.thunderbird; + + enabledAccounts = attrValues + (filterAttrs (_: a: a.thunderbird.enable) config.accounts.email.accounts); + + enabledAccountsWithId = + map (a: a // { id = builtins.hashString "sha256" a.name; }) enabledAccounts; + + thunderbirdConfigPath = + if isDarwin then "Library/Thunderbird" else ".thunderbird"; + + thunderbirdProfilesPath = if isDarwin then + "${thunderbirdConfigPath}/Profiles" + else + thunderbirdConfigPath; + + profilesWithId = + imap0 (i: v: v // { id = toString i; }) (attrValues cfg.profiles); + + profilesIni = foldl recursiveUpdate { + General = { + StartWithLastProfile = 1; + Version = 2; + }; + } (flip map profilesWithId (profile: { + "Profile${profile.id}" = { + Name = profile.name; + Path = if isDarwin then "Profiles/${profile.name}" else profile.name; + IsRelative = 1; + Default = if profile.isDefault then 1 else 0; + }; + })); + + toThunderbirdAccount = account: profile: + let id = account.id; + in { + "mail.account.account_${id}.identities" = "id_${id}"; + "mail.account.account_${id}.server" = "server_${id}"; + "mail.identity.id_${id}.fullName" = account.realName; + "mail.identity.id_${id}.useremail" = account.address; + "mail.identity.id_${id}.valid" = true; + } // optionalAttrs account.primary { + "mail.accountmanager.defaultaccount" = "account_${id}"; + } // optionalAttrs (account.gpg != null) { + "mail.identity.id_${id}.attachPgpKey" = false; + "mail.identity.id_${id}.autoEncryptDrafts" = true; + "mail.identity.id_${id}.e2etechpref" = 0; + "mail.identity.id_${id}.encryptionpolicy" = + if account.gpg.encryptByDefault then 2 else 0; + "mail.identity.id_${id}.is_gnupg_key_id" = true; + "mail.identity.id_${id}.last_entered_external_gnupg_key_id" = + account.gpg.key; + "mail.identity.id_${id}.openpgp_key_id" = account.gpg.key; + "mail.identity.id_${id}.protectSubject" = true; + "mail.identity.id_${id}.sign_mail" = account.gpg.signByDefault; + } // optionalAttrs (account.imap != null) { + "mail.server.server_${id}.directory" = + "${thunderbirdProfilesPath}/${profile.name}/ImapMail/${id}"; + "mail.server.server_${id}.directory-rel" = "[ProfD]ImapMail/${id}"; + "mail.server.server_${id}.hostname" = account.imap.host; + "mail.server.server_${id}.login_at_startup" = true; + "mail.server.server_${id}.name" = account.name; + "mail.server.server_${id}.port" = + if (account.imap.port != null) then account.imap.port else 143; + "mail.server.server_${id}.socketType" = if !account.imap.tls.enable then + 0 + else if account.imap.tls.useStartTls then + 2 + else + 3; + "mail.server.server_${id}.type" = "imap"; + "mail.server.server_${id}.userName" = account.userName; + } // optionalAttrs (account.smtp != null) { + "mail.identity.id_${id}.smtpServer" = "smtp_${id}"; + "mail.smtpserver.smtp_${id}.authMethod" = 3; + "mail.smtpserver.smtp_${id}.hostname" = account.smtp.host; + "mail.smtpserver.smtp_${id}.port" = + if (account.smtp.port != null) then account.smtp.port else 587; + "mail.smtpserver.smtp_${id}.try_ssl" = if !account.smtp.tls.enable then + 0 + else if account.smtp.tls.useStartTls then + 2 + else + 3; + "mail.smtpserver.smtp_${id}.username" = account.userName; + } // optionalAttrs (account.smtp != null && account.primary) { + "mail.smtp.defaultserver" = "smtp_${id}"; + } // account.thunderbird.settings id; + + mkUserJs = prefs: '' + // Generated by Home Manager. + + ${concatStrings (mapAttrsToList (name: value: '' + user_pref("${name}", ${builtins.toJSON value}); + '') prefs)} + ''; +in { + meta.maintainers = with hm.maintainers; [ d-dervishi jkarlson ]; + + options = { + programs.thunderbird = { + enable = mkEnableOption "Thunderbird"; + + package = mkOption { + type = types.package; + default = pkgs.thunderbird; + defaultText = literalExpression "pkgs.thunderbird"; + example = literalExpression "pkgs.thunderbird-91"; + description = "The Thunderbird package to use."; + }; + + profiles = mkOption { + type = with types; + attrsOf (submodule ({ config, name, ... }: { + options = { + name = mkOption { + type = types.str; + default = name; + readOnly = true; + description = "This profile's name."; + }; + + isDefault = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + Whether this is a default profile. There must be exactly one + default profile. + ''; + }; + + settings = mkOption { + type = with types; attrsOf (oneOf [ bool int str ]); + default = { }; + example = literalExpression '' + { + "mail.spellcheck.inline" = false; + } + ''; + description = '' + Preferences to add to this profile's + user.js. + ''; + }; + + withExternalGnupg = mkOption { + type = types.bool; + default = false; + example = true; + description = "Allow using external GPG keys with GPGME."; + }; + }; + })); + }; + + settings = mkOption { + type = with types; attrsOf (oneOf [ bool int str ]); + default = { }; + example = literalExpression '' + { + "general.useragent.override" = ""; + "privacy.donottrackheader.enabled" = true; + } + ''; + description = '' + Attribute set of Thunderbird preferences to be added to + all profiles. + ''; + }; + + darwinSetupWarning = mkOption { + type = types.bool; + default = true; + example = false; + visible = isDarwin; + readOnly = !isDarwin; + description = '' + Warn to set environment variables before using this module. Only + relevant on Darwin. + ''; + }; + }; + + accounts.email.accounts = mkOption { + type = with types; + attrsOf (submodule { + options.thunderbird = { + enable = + mkEnableOption "the Thunderbird mail client for this account"; + + profiles = mkOption { + type = with types; listOf str; + default = [ ]; + example = literalExpression '' + [ "profile1" "profile2" ] + ''; + description = '' + List of Thunderbird profiles for which this account should be + enabled. If this list is empty (the default), this account will + be enabled for all declared profiles. + ''; + }; + + settings = mkOption { + type = with types; functionTo (attrsOf (oneOf [ bool int str ])); + default = _: { }; + defaultText = literalExpression "_: { }"; + example = literalExpression '' + id: { + "mail.identity.id_''${id}.protectSubject" = false; + "mail.identity.id_''${id}.autoEncryptDrafts" = false; + }; + ''; + description = '' + Extra settings to add to this Thunderbird account configuration. + The id given as argument is an automatically + generated account identifier. + ''; + }; + }; + }); + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (let defaults = catAttrs "name" (filter (a: a.isDefault) profilesWithId); + in { + assertion = cfg.profiles == { } || length defaults == 1; + message = "Must have exactly one default Thunderbird profile but found " + + toString (length defaults) + optionalString (length defaults > 1) + (", namely " + concatStringsSep "," defaults); + }) + + (let + profiles = catAttrs "name" profilesWithId; + selectedProfiles = + concatMap (a: a.thunderbird.profiles) enabledAccounts; + in { + assertion = (intersectLists profiles selectedProfiles) + == selectedProfiles; + message = "Cannot enable an account for a non-declared profile. " + + "The declared profiles are " + (concatStringsSep "," profiles) + + ", but the used profiles are " + + (concatStringsSep "," selectedProfiles); + }) + ]; + + warnings = optional (isDarwin && cfg.darwinSetupWarning) '' + Thunderbird packages are not yet supported on Darwin. You can still use + this module to manage your accounts and profiles by setting + 'programs.thunderbird.package' to a dummy value, for example using + 'pkgs.runCommand'. + + Note that this module requires you to set the following environment + variables when using an installation of Thunderbird that is not provided + by Nix: + + export MOZ_LEGACY_PROFILES=1 + export MOZ_ALLOW_DOWNGRADE=1 + ''; + + home.packages = [ cfg.package ] + ++ optional (any (p: p.withExternalGnupg) (attrValues cfg.profiles)) + pkgs.gpgme; + + home.file = mkMerge ([{ + "${thunderbirdConfigPath}/profiles.ini" = + mkIf (cfg.profiles != { }) { text = generators.toINI { } profilesIni; }; + }] ++ flip mapAttrsToList cfg.profiles (name: profile: { + "${thunderbirdProfilesPath}/${name}/user.js" = let + accounts = filter (a: + a.thunderbird.profiles == [ ] + || any (p: p == name) a.thunderbird.profiles) enabledAccountsWithId; + + smtp = filter (a: a.smtp != null) accounts; + in { + text = mkUserJs (builtins.foldl' (a: b: a // b) { } ([ + cfg.settings + + (optionalAttrs (length accounts != 0) { + "mail.accountmanager.accounts" = + concatStringsSep "," (map (a: "account_${a.id}") accounts); + }) + + (optionalAttrs (length smtp != 0) { + "mail.smtpservers" = + concatStringsSep "," (map (a: "smtp_${a.id}") smtp); + }) + + { "mail.openpgp.allow_external_gnupg" = profile.withExternalGnupg; } + + profile.settings + ] ++ (map (a: toThunderbirdAccount a profile) accounts))); + }; + })); + }; +} diff --git a/modules/programs/tmate.nix b/modules/programs/tmate.nix new file mode 100644 index 00000000..6681baf6 --- /dev/null +++ b/modules/programs/tmate.nix @@ -0,0 +1,80 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.tmate; + +in { + meta.maintainers = [ maintainers.jlesquembre ]; + + options = { + programs.tmate = { + enable = mkEnableOption "tmate"; + + package = mkOption { + type = types.package; + default = pkgs.tmate; + defaultText = literalExpression "pkgs.tmate"; + example = literalExpression "pkgs.tmate"; + description = "The tmate package to install."; + }; + + host = mkOption { + type = with types; nullOr str; + default = null; + example = literalExpression "tmate.io"; + description = "Tmate server address."; + }; + + port = mkOption { + type = with types; nullOr port; + default = null; + example = 2222; + description = "Tmate server port."; + }; + + dsaFingerprint = mkOption { + type = with types; nullOr string; + default = null; + example = literalExpression + "SHA256:1111111111111111111111111111111111111111111"; + description = "Tmate server EdDSA key fingerprint."; + }; + + rsaFingerprint = mkOption { + type = with types; nullOr string; + default = null; + example = literalExpression + "SHA256:1111111111111111111111111111111111111111111"; + description = "Tmate server RSA key fingerprint."; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Additional content written at the end of + ~/.tmate.conf. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + home.file.".tmate.conf".text = let + conf = + optional (cfg.host != null) ''set -g tmate-server-host "${cfg.host}"'' + ++ optional (cfg.port != null) + "set -g tmate-server-port ${builtins.toString cfg.port}" + ++ optional (cfg.dsaFingerprint != null) + ''set -g tmate-server-ed25519-fingerprint "${cfg.dsaFingerprint}"'' + ++ optional (cfg.rsaFingerprint != null) + ''set -g tmate-server-rsa-fingerprint "${cfg.rsaFingerprint}"'' + ++ optional (cfg.extraConfig != "") cfg.extraConfig; + in concatStringsSep "\n" conf + "\n"; + }; +} diff --git a/modules/programs/tmux.nix b/modules/programs/tmux.nix index bf98a3f3..df3ed11d 100644 --- a/modules/programs/tmux.nix +++ b/modules/programs/tmux.nix @@ -94,6 +94,7 @@ let bind-key -N "Kill the current pane" x kill-pane ''} + set -g mouse ${boolToStr cfg.mouse} setw -g aggressive-resize ${boolToStr cfg.aggressiveResize} setw -g clock-mode-style ${if cfg.clock24 then "24" else "12"} set -s escape-time ${toString cfg.escapeTime} @@ -204,6 +205,8 @@ in { description = "VI or Emacs style shortcuts."; }; + mouse = mkEnableOption "mouse support"; + newSession = mkOption { default = false; type = types.bool; @@ -333,7 +336,7 @@ in { (mkIf cfg.secureSocket { home.sessionVariables = { - TMUX_TMPDIR = ''''${XDG_RUNTIME_DIR:-"/run/user/\$(id -u)"}''; + TMUX_TMPDIR = ''''${XDG_RUNTIME_DIR:-"/run/user/$(id -u)"}''; }; }) diff --git a/modules/programs/urxvt.nix b/modules/programs/urxvt.nix index 905e14c1..545a1e7f 100644 --- a/modules/programs/urxvt.nix +++ b/modules/programs/urxvt.nix @@ -12,8 +12,8 @@ in { package = mkOption { type = types.package; - default = pkgs.rxvt_unicode; - defaultText = literalExpression "pkgs.rxvt_unicode"; + default = pkgs.rxvt-unicode; + defaultText = literalExpression "pkgs.rxvt-unicode"; description = "rxvt-unicode package to install."; }; diff --git a/modules/programs/vim-vint.nix b/modules/programs/vim-vint.nix new file mode 100644 index 00000000..e44d96e4 --- /dev/null +++ b/modules/programs/vim-vint.nix @@ -0,0 +1,36 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.vim-vint; + + yamlFormat = pkgs.formats.yaml { }; + +in { + meta.maintainers = [ maintainers.tomodachi94 ]; + + options = { + programs.vim-vint = { + enable = mkEnableOption "the Vint linter for Vimscript"; + package = mkPackageOption pkgs "vim-vint" { }; + + settings = mkOption { + type = yamlFormat.type; + default = { }; + description = '' + Configuration written to + $XDG_CONFIG_HOME/.vintrc.yaml + ''; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile.".vintrc.yaml".source = + yamlFormat.generate "vim-vint-config" cfg.settings; + }; +} diff --git a/modules/programs/vim.nix b/modules/programs/vim.nix index 46e5f95d..e4d993a6 100644 --- a/modules/programs/vim.nix +++ b/modules/programs/vim.nix @@ -127,9 +127,19 @@ in { packageConfigurable = mkOption { type = types.package; - description = "Configurable vim package"; - default = pkgs.vim_configurable; - defaultText = "pkgs.vim_configurable"; + description = "Vim package to customize"; + default = pkgs.vim-full or pkgs.vim_configurable; + defaultText = literalExpression "pkgs.vim-full"; + example = literalExpression "pkgs.vim"; + }; + + defaultEditor = mkOption { + type = types.bool; + default = false; + description = '' + Whether to configure vim as the default + editor using the EDITOR environment variable. + ''; }; }; }; @@ -170,6 +180,8 @@ in { home.packages = [ cfg.package ]; + home.sessionVariables = mkIf cfg.defaultEditor { EDITOR = "vim"; }; + programs.vim = { package = vim; plugins = defaultPlugins; diff --git a/modules/programs/vscode.nix b/modules/programs/vscode.nix index dcfed07b..27faf39b 100644 --- a/modules/programs/vscode.nix +++ b/modules/programs/vscode.nix @@ -34,6 +34,11 @@ let # TODO: On Darwin where are the extensions? extensionPath = ".${extensionDir}/extensions"; + mergedUserSettings = cfg.userSettings + // optionalAttrs (!cfg.enableUpdateCheck) { "update.mode" = "none"; } + // optionalAttrs (!cfg.enableExtensionUpdateCheck) { + "extensions.autoCheckUpdates" = false; + }; in { imports = [ (mkChangedOptionModule [ "programs" "vscode" "immutableExtensionsDir" ] [ @@ -56,12 +61,28 @@ in { ''; }; + enableUpdateCheck = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable update checks/notifications. + ''; + }; + + enableExtensionUpdateCheck = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable update notifications for extensions. + ''; + }; + userSettings = mkOption { type = jsonFormat.type; default = { }; example = literalExpression '' { - "update.channel" = "none"; + "files.autoSave" = "off"; "[nix]"."editor.tabSize" = 2; } ''; @@ -76,14 +97,14 @@ in { default = { }; example = literalExpression '' { - "version": "2.0.0", - "tasks": [ + version = "2.0.0"; + tasks = [ { - "type": "shell", - "label": "Hello task", - "command": "hello", + type = "shell"; + label = "Hello task"; + command = "hello"; } - ] + ]; } ''; description = '' @@ -164,9 +185,9 @@ in { home.packages = [ cfg.package ]; home.file = mkMerge [ - (mkIf (cfg.userSettings != { }) { + (mkIf (mergedUserSettings != { }) { "${configFilePath}".source = - jsonFormat.generate "vscode-user-settings" cfg.userSettings; + jsonFormat.generate "vscode-user-settings" mergedUserSettings; }) (mkIf (cfg.userTasks != { }) { "${tasksFilePath}".source = diff --git a/modules/programs/wlogout.nix b/modules/programs/wlogout.nix new file mode 100644 index 00000000..49e59b07 --- /dev/null +++ b/modules/programs/wlogout.nix @@ -0,0 +1,151 @@ +{ config, lib, pkgs, ... }: + +let + inherit (lib) all filterAttrs isStorePath literalExpression types; + inherit (lib.options) mkEnableOption mkPackageOption mkOption; + inherit (lib.modules) mkIf; + inherit (lib.strings) concatMapStrings; + inherit (builtins) toJSON; + + cfg = config.programs.wlogout; + + jsonFormat = pkgs.formats.json { }; + + wlogoutLayoutConfig = with types; + submodule { + freeformType = jsonFormat.type; + + options = { + label = mkOption { + type = str; + default = ""; + example = "shutdown"; + description = "CSS label of button."; + }; + + action = mkOption { + type = either path str; + default = ""; + example = "systemctl poweroff"; + description = "Command to execute when clicked."; + }; + + text = mkOption { + type = str; + default = ""; + example = "Shutdown"; + description = "Text displayed on button."; + }; + + keybind = mkOption { + type = str; + default = ""; + example = "s"; + description = "Keyboard character to trigger this action."; + }; + + height = mkOption { + type = nullOr (numbers.between 0 1); + default = null; + example = 0.5; + description = "Relative height of tile."; + }; + + width = mkOption { + type = nullOr (numbers.between 0 1); + default = null; + example = 0.5; + description = "Relative width of tile."; + }; + + circular = mkOption { + type = nullOr bool; + default = null; + example = true; + description = "Make button circular."; + }; + }; + }; +in { + meta.maintainers = [ lib.maintainers.Scrumplex ]; + + options.programs.wlogout = with lib.types; { + enable = mkEnableOption "wlogout"; + + package = mkPackageOption pkgs "wlogout" { }; + + layout = mkOption { + type = listOf wlogoutLayoutConfig; + default = [ ]; + description = '' + Layout configuration for wlogout, see + for supported values. + ''; + example = literalExpression '' + [ + { + label = "shutdown"; + action = "systemctl poweroff"; + text = "Shutdown"; + keybind = "s"; + } + ] + ''; + }; + + style = mkOption { + type = nullOr (either path str); + default = null; + description = '' + CSS style of the bar. + + + See + for the documentation. + + + If the value is set to a path literal, then the path will be used as the css file. + ''; + example = '' + window { + background: #16191C; + } + + button { + color: #AAB2BF; + } + ''; + }; + }; + + config = let + # Removes nulls because wlogout ignores them. + # This is not recursive. + removeTopLevelNulls = filterAttrs (_: v: v != null); + cleanJSON = foo: toJSON (removeTopLevelNulls foo); + + # wlogout doesn't want a JSON array, it just wants a list of JSON objects + layoutJsons = map cleanJSON cfg.layout; + layoutContent = concatMapStrings (l: l + "\n") layoutJsons; + + in mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "programs.wlogout" pkgs + lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + xdg.configFile."wlogout/layout" = mkIf (cfg.layout != [ ]) { + source = pkgs.writeText "wlogout/layout" layoutContent; + }; + + xdg.configFile."wlogout/style.css" = mkIf (cfg.style != null) { + source = if builtins.isPath cfg.style || isStorePath cfg.style then + cfg.style + else + pkgs.writeText "wlogout/style.css" cfg.style; + }; + }; +} diff --git a/modules/programs/yt-dlp.nix b/modules/programs/yt-dlp.nix index 19e9c7e0..af74db16 100644 --- a/modules/programs/yt-dlp.nix +++ b/modules/programs/yt-dlp.nix @@ -6,6 +6,12 @@ let cfg = config.programs.yt-dlp; + renderSettings = mapAttrsToList (name: value: + if isBool value then + if value then "--${name}" else "--no-${name}" + else + "--${name} ${toString value}"); + in { meta.maintainers = [ maintainers.marsam ]; @@ -19,29 +25,50 @@ in { description = "Package providing the yt-dlp tool."; }; - extraConfig = mkOption { - type = types.lines; - default = ""; + settings = mkOption { + type = with types; attrsOf (oneOf [ bool int str ]); + default = { }; example = literalExpression '' - --embed-thumbnail - --embed-subs - --sub-langs all - --downloader aria2c - --downloader-args aria2c:'-c -x8 -s8 -k1M' + { + embed-thumbnail = true; + embed-subs = true; + sub-langs = "all"; + downloader = "aria2c"; + downloader-args = "aria2c:'-c -x8 -s8 -k1M'"; + } ''; description = '' Configuration written to - $XDG_CONFIG_HOME/yt-dlp/config. See - + $XDG_CONFIG_HOME/yt-dlp/config. + + Options must be specified in their long form, for + example, update = true; instead of U = true;. + Short options can be specified in the extraConfig option. + See for explanation about possible values. ''; }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = '' + --update + -F + ''; + description = '' + Extra configuration to add to + $XDG_CONFIG_HOME/yt-dlp/config. + ''; + }; }; config = mkIf cfg.enable { home.packages = [ cfg.package ]; - xdg.configFile."yt-dlp/config" = - mkIf (cfg.extraConfig != "") { text = cfg.extraConfig; }; + xdg.configFile."yt-dlp/config" = mkIf (cfg.settings != { }) { + text = concatStringsSep "\n" + (remove "" (renderSettings cfg.settings ++ [ cfg.extraConfig ])) + "\n"; + }; }; } diff --git a/modules/programs/zplug.nix b/modules/programs/zplug.nix index 5f2b4431..7c731444 100644 --- a/modules/programs/zplug.nix +++ b/modules/programs/zplug.nix @@ -45,10 +45,10 @@ in { home.packages = [ pkgs.zplug ]; programs.zsh.initExtraBeforeCompInit = '' - source ${pkgs.zplug}/init.zsh - export ZPLUG_HOME=${cfg.zplugHome} + source ${pkgs.zplug}/init.zsh + ${optionalString (cfg.plugins != [ ]) '' ${concatStrings (map (plugin: '' zplug "${plugin.name}"${ diff --git a/modules/programs/zsh.nix b/modules/programs/zsh.nix index e595e5c2..9ffe9dfa 100644 --- a/modules/programs/zsh.nix +++ b/modules/programs/zsh.nix @@ -18,10 +18,6 @@ let mapAttrsToList (k: v: "alias ${k}=${lib.escapeShellArg v}") cfg.shellAliases ); - globalAliasesStr = concatStringsSep "\n" ( - mapAttrsToList (k: v: "alias -g ${k}=${lib.escapeShellArg v}") cfg.shellGlobalAliases - ); - dirHashesStr = concatStringsSep "\n" ( mapAttrsToList (k: v: ''hash -d ${k}="${v}"'') cfg.dirHashes ); @@ -488,35 +484,36 @@ in ++ optional cfg.enableCompletion nix-zsh-completions ++ optional cfg.oh-my-zsh.enable oh-my-zsh; - home.file."${relToDotDir ".zshrc"}".text = '' - ${cfg.initExtraFirst} + home.file."${relToDotDir ".zshrc"}".text = concatStringsSep "\n" ([ + cfg.initExtraFirst + "typeset -U path cdpath fpath manpath" - typeset -U path cdpath fpath manpath - - ${optionalString (cfg.cdpath != []) '' + (optionalString (cfg.cdpath != []) '' cdpath+=(${concatStringsSep " " cfg.cdpath}) - ''} + '') + '' for profile in ''${(z)NIX_PROFILES}; do fpath+=($profile/share/zsh/site-functions $profile/share/zsh/$ZSH_VERSION/functions $profile/share/zsh/vendor-completions) done HELPDIR="${pkgs.zsh}/share/zsh/$ZSH_VERSION/help" + '' - ${optionalString (cfg.defaultKeymap != null) '' + (optionalString (cfg.defaultKeymap != null) '' # Use ${cfg.defaultKeymap} keymap as the default. ${getAttr cfg.defaultKeymap bindkeyCommands} - ''} + '') + localVarsStr - ${localVarsStr} + cfg.initExtraBeforeCompInit - ${cfg.initExtraBeforeCompInit} - - ${concatStrings (map (plugin: '' + (concatStrings (map (plugin: '' path+="$HOME/${pluginsDir}/${plugin.name}" fpath+="$HOME/${pluginsDir}/${plugin.name}" - '') cfg.plugins)} + '') cfg.plugins)) + '' # Oh-My-Zsh/Prezto calls compinit during initialization, # calling it twice causes slight start up slowdown # as all $fpath entries will be traversed again. @@ -575,27 +572,29 @@ in # Aliases ${aliasesStr} - - # Global Aliases - ${globalAliasesStr} - + '' + ] + ++ (mapAttrsToList (k: v: "alias -g ${k}=${lib.escapeShellArg v}") cfg.shellGlobalAliases) + ++ [ ('' # Named Directory Hashes ${dirHashesStr} + '') - ${optionalString cfg.enableSyntaxHighlighting + (optionalString cfg.enableSyntaxHighlighting # Load zsh-syntax-highlighting after all custom widgets have been created # https://github.com/zsh-users/zsh-syntax-highlighting#faq "source ${pkgs.zsh-syntax-highlighting}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh" - } - ${optionalString (cfg.historySubstringSearch.enable or false) + ) + + (optionalString (cfg.historySubstringSearch.enable or false) # Load zsh-history-substring-search after zsh-syntax-highlighting # https://github.com/zsh-users/zsh-history-substring-search#usage '' source ${pkgs.zsh-history-substring-search}/share/zsh-history-substring-search/zsh-history-substring-search.zsh bindkey '${cfg.historySubstringSearch.searchUpKey}' history-substring-search-up bindkey '${cfg.historySubstringSearch.searchDownKey}' history-substring-search-down - ''} - ''; + '') + ]); } (mkIf cfg.oh-my-zsh.enable { diff --git a/modules/services/autorandr.nix b/modules/services/autorandr.nix new file mode 100644 index 00000000..84791a66 --- /dev/null +++ b/modules/services/autorandr.nix @@ -0,0 +1,53 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let cfg = config.services.autorandr; + +in { + + meta.maintainers = [ maintainers.GaetanLepage ]; + + options = { + services.autorandr = { + enable = mkEnableOption "" // { + description = '' + Whether to enable the Autorandr systemd service. + This module is complementary to programs.autorandr which handles the + configuration (profiles). + ''; + }; + + ignoreLid = mkOption { + default = false; + type = types.bool; + description = + "Treat outputs as connected even if their lids are closed."; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.autorandr" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.autorandr = { + Unit = { + Description = "autorandr"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Service = { + Type = "oneshot"; + ExecStart = "${pkgs.autorandr}/bin/autorandr --change ${ + optionalString cfg.ignoreLid "--ignore-lid" + }"; + }; + + Install.WantedBy = [ "graphical-session.target" ]; + }; + }; +} diff --git a/modules/services/borgmatic.nix b/modules/services/borgmatic.nix new file mode 100644 index 00000000..c2f2963a --- /dev/null +++ b/modules/services/borgmatic.nix @@ -0,0 +1,88 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + serviceConfig = config.services.borgmatic; + programConfig = config.programs.borgmatic; +in { + meta.maintainers = [ maintainers.DamienCassou ]; + + options = { + services.borgmatic = { + enable = mkEnableOption "Borgmatic service"; + + frequency = mkOption { + type = types.str; + default = "hourly"; + description = '' + How often to run borgmatic when + services.borgmatic.enable = true. + This value is passed to the systemd timer configuration as + the onCalendar option. See + + systemd.time + 7 + + for more information about the format. + ''; + }; + }; + }; + + config = mkIf serviceConfig.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.borgmatic" pkgs + lib.platforms.linux) + ]; + + systemd.user = { + services.borgmatic = { + Unit = { + Description = "borgmatic backup"; + # Prevent borgmatic from running unless the machine is + # plugged into power: + ConditionACPower = true; + }; + Service = { + Type = "oneshot"; + + # Lower CPU and I/O priority: + Nice = 19; + CPUSchedulingPolicy = "batch"; + IOSchedulingClass = "best-effort"; + IOSchedulingPriority = 7; + IOWeight = 100; + + Restart = "no"; + LogRateLimitIntervalSec = 0; + + # Delay start to prevent backups running during boot: + ExecStartPre = "${pkgs.coreutils}/bin/sleep 3m"; + + ExecStart = '' + ${pkgs.systemd}/bin/systemd-inhibit \ + --who="borgmatic" \ + --what="sleep:shutdown" \ + --why="Prevent interrupting scheduled backup" \ + ${programConfig.package}/bin/borgmatic \ + --stats \ + --verbosity -1 \ + --list \ + --syslog-verbosity 1 + ''; + }; + }; + + timers.borgmatic = { + Unit.Description = "Run borgmatic backup"; + Timer = { + OnCalendar = serviceConfig.frequency; + Persistent = true; + RandomizedDelaySec = "10m"; + }; + Install.WantedBy = [ "timers.target" ]; + }; + }; + }; +} diff --git a/modules/services/cachix-agent.nix b/modules/services/cachix-agent.nix new file mode 100644 index 00000000..01eca05b --- /dev/null +++ b/modules/services/cachix-agent.nix @@ -0,0 +1,84 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + + cfg = config.services.cachix-agent; + +in { + meta.maintainers = [ maintainers.rycee ]; + + options.services.cachix-agent = { + enable = mkEnableOption '' + Cachix Deploy Agent: ''; + + name = mkOption { + type = types.str; + description = "The unique agent name."; + }; + + verbose = mkEnableOption "verbose output"; + + profile = mkOption { + type = types.str; + default = "home-manager"; + description = '' + The Nix profile name. + ''; + }; + + host = mkOption { + type = types.nullOr types.str; + default = null; + description = "Cachix URI to use."; + }; + + package = mkPackageOption pkgs "cachix" { }; + + credentialsFile = mkOption { + type = types.path; + default = "${config.xdg.configHome}/cachix-agent.token"; + defaultText = + literalExpression ''"''${config.xdg.configHome}/cachix-agent.token"''; + description = '' + Required file that needs to contain + CACHIX_AGENT_TOKEN=.... + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.cachix-agent" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.cachix-agent = { + Unit.Description = "Cachix Deploy Agent"; + + Service = { + Environment = [ + "PATH=${ + if config.nix.enable && config.nix.package != null then + config.nix.package + else + pkgs.nix + }/bin" + ]; + EnvironmentFile = cfg.credentialsFile; + + # We don't want to kill children processes as those are deployments. + KillMode = "process"; + Restart = "on-failure"; + ExecStart = escapeShellArgs ([ "${cfg.package}/bin/cachix" ] + ++ optional cfg.verbose "--verbose" + ++ optional (cfg.host != null) "--host ${cfg.host}" + ++ [ "deploy" "agent" cfg.name ] + ++ optional (cfg.profile != null) cfg.profile); + }; + + Install.WantedBy = [ "default.target" ]; + }; + }; +} diff --git a/modules/services/clipman.nix b/modules/services/clipman.nix new file mode 100644 index 00000000..4afee9a3 --- /dev/null +++ b/modules/services/clipman.nix @@ -0,0 +1,58 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.clipman; + +in { + meta.maintainers = [ maintainers.jwygoda ]; + + options.services.clipman = { + enable = mkEnableOption "clipman, a simple clipboard manager for Wayland"; + + package = mkPackageOption pkgs "clipman" { }; + + systemdTarget = mkOption { + type = types.str; + default = "graphical-session.target"; + example = "sway-session.target"; + description = '' + The systemd target that will automatically start the Waybar service. + + + When setting this value to "sway-session.target", + make sure to also enable , + otherwise the service may never be started. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.clipman" pkgs + lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + systemd.user.services.clipman = { + Unit = { + Description = "Clipboard management daemon"; + PartOf = [ "graphical-session.target" ]; + After = [ "graphical-session.target" ]; + }; + + Service = { + ExecStart = + "${pkgs.wl-clipboard}/bin/wl-paste -t text --watch ${cfg.package}/bin/clipman store"; + ExecReload = "${pkgs.coreutils}/bin/kill -SIGUSR2 $MAINPID"; + Restart = "on-failure"; + KillMode = "mixed"; + }; + + Install = { WantedBy = [ cfg.systemdTarget ]; }; + }; + }; +} diff --git a/modules/services/easyeffects.nix b/modules/services/easyeffects.nix index 001ff5d0..9dd01b94 100644 --- a/modules/services/easyeffects.nix +++ b/modules/services/easyeffects.nix @@ -20,6 +20,13 @@ in { to your system configuration for the daemon to work correctly''; + package = mkOption { + type = types.package; + default = pkgs.easyeffects; + defaultText = literalExpression "pkgs.easyeffects"; + description = "The easyeffects package to use."; + }; + preset = mkOption { type = types.str; default = ""; @@ -38,7 +45,7 @@ in { # running easyeffects will just attach itself to gapplication service # at-spi2-core is to minimize journalctl noise of: # "AT-SPI: Error retrieving accessibility bus address: org.freedesktop.DBus.Error.ServiceUnknown: The name org.a11y.Bus was not provided by any .service files" - home.packages = with pkgs; [ easyeffects at-spi2-core ]; + home.packages = with pkgs; [ cfg.package at-spi2-core ]; systemd.user.services.easyeffects = { Unit = { @@ -52,8 +59,8 @@ in { Service = { ExecStart = - "${pkgs.easyeffects}/bin/easyeffects --gapplication-service ${presetOpts}"; - ExecStop = "${pkgs.easyeffects}/bin/easyeffects --quit"; + "${cfg.package}/bin/easyeffects --gapplication-service ${presetOpts}"; + ExecStop = "${cfg.package}/bin/easyeffects --quit"; Restart = "on-failure"; RestartSec = 5; }; diff --git a/modules/services/fnott.nix b/modules/services/fnott.nix index 762f5303..aa9e9181 100644 --- a/modules/services/fnott.nix +++ b/modules/services/fnott.nix @@ -61,7 +61,7 @@ in { fnott.ini 5 - for a list of avaliable options and for a list of available options and for an example configuration. ''; diff --git a/modules/services/gpg-agent.nix b/modules/services/gpg-agent.nix index ca70406f..fb59d709 100644 --- a/modules/services/gpg-agent.nix +++ b/modules/services/gpg-agent.nix @@ -9,11 +9,18 @@ let homedir = config.programs.gpg.homedir; + gpgSshSupportStr = '' + ${gpgPkg}/bin/gpg-connect-agent updatestartuptty /bye > /dev/null + ''; + gpgInitStr = '' GPG_TTY="$(tty)" export GPG_TTY - '' + optionalString cfg.enableSshSupport - "${gpgPkg}/bin/gpg-connect-agent updatestartuptty /bye > /dev/null"; + '' + optionalString cfg.enableSshSupport gpgSshSupportStr; + + gpgFishInitStr = '' + set -gx GPG_TTY (tty) + '' + optionalString cfg.enableSshSupport gpgSshSupportStr; # mimic `gpgconf` output for use in `systemd` unit definitions. # we cannot use `gpgconf` directly because it heavily depends on system @@ -238,9 +245,8 @@ in { programs.bash.initExtra = mkIf cfg.enableBashIntegration gpgInitStr; programs.zsh.initExtra = mkIf cfg.enableZshIntegration gpgInitStr; - programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration '' - set -gx GPG_TTY (tty) - ''; + programs.fish.interactiveShellInit = + mkIf cfg.enableFishIntegration gpgFishInitStr; } (mkIf (cfg.sshKeys != null) { diff --git a/modules/services/imapnotify.nix b/modules/services/imapnotify.nix index 6a464ec8..0197ec54 100644 --- a/modules/services/imapnotify.nix +++ b/modules/services/imapnotify.nix @@ -6,7 +6,7 @@ let cfg = config.services.imapnotify; - safeName = lib.replaceChars [ "@" ":" "\\" "[" "]" ] [ "-" "-" "-" "" "" ]; + safeName = lib.replaceStrings [ "@" ":" "\\" "[" "]" ] [ "-" "-" "-" "" "" ]; imapnotifyAccounts = filter (a: a.imapnotify.enable) (attrValues config.accounts.email.accounts); diff --git a/modules/services/kanshi.nix b/modules/services/kanshi.nix index 3d4451e9..cdef4c72 100644 --- a/modules/services/kanshi.nix +++ b/modules/services/kanshi.nix @@ -109,7 +109,7 @@ let example = "[ \${pkg.sway}/bin/swaymsg workspace 1, move workspace to eDP-1 ]"; description = '' - Commands executed after the profile is succesfully applied. + Commands executed after the profile is successfully applied. Note that if you provide multiple commands, they will be executed asynchronously with no guaranteed ordering. ''; diff --git a/modules/services/kdeconnect.nix b/modules/services/kdeconnect.nix index 82de1f0e..87c57c4e 100644 --- a/modules/services/kdeconnect.nix +++ b/modules/services/kdeconnect.nix @@ -5,7 +5,7 @@ with lib; let cfg = config.services.kdeconnect; - package = pkgs.kdeconnect; + package = pkgs.plasma5Packages.kdeconnect-kde; in { meta.maintainers = [ maintainers.adisbladis ]; diff --git a/modules/services/lorri.nix b/modules/services/lorri.nix index 0a49cb54..85b75682 100644 --- a/modules/services/lorri.nix +++ b/modules/services/lorri.nix @@ -12,12 +12,22 @@ in { options.services.lorri = { enable = mkEnableOption "lorri build daemon"; + enableNotifications = mkEnableOption "lorri build notifications"; + package = mkOption { type = types.package; default = pkgs.lorri; defaultText = literalExpression "pkgs.lorri"; description = "Which lorri package to install."; }; + + nixPackage = mkOption { + type = types.package; + default = pkgs.nix; + defaultText = literalExpression "pkgs.nix"; + example = literalExpression "pkgs.nixVersions.unstable"; + description = "Which nix package to use."; + }; }; config = mkIf cfg.enable { @@ -45,7 +55,7 @@ in { Restart = "on-failure"; Environment = let path = with pkgs; - makeSearchPath "bin" [ nix gitMinimal gnutar gzip ]; + makeSearchPath "bin" [ cfg.nixPackage gitMinimal gnutar gzip ]; in [ "PATH=${path}" ]; }; }; @@ -60,6 +70,37 @@ in { Install = { WantedBy = [ "sockets.target" ]; }; }; + + services.lorri-notify = mkIf cfg.enableNotifications { + Unit = { + Description = "lorri build notifications"; + After = "lorri.service"; + Requires = "lorri.service"; + }; + + Service = { + ExecStart = let + jqFile = '' + ( + (.Started? | values | "Build starting in \(.nix_file)"), + (.Completed? | values | "Build complete in \(.nix_file)"), + (.Failure? | values | "Build failed in \(.nix_file)") + ) + ''; + + notifyScript = pkgs.writeShellScript "lorri-notify" '' + lorri internal stream-events --kind live \ + | jq --unbuffered '${jqFile}' \ + | xargs -n 1 notify-send "Lorri Build" + ''; + in toString notifyScript; + Restart = "on-failure"; + Environment = let + path = makeSearchPath "bin" + (with pkgs; [ bash jq findutils libnotify cfg.package ]); + in "PATH=${path}"; + }; + }; }; }; } diff --git a/modules/services/mako.nix b/modules/services/mako.nix index 88068e0b..fb711ca4 100644 --- a/modules/services/mako.nix +++ b/modules/services/mako.nix @@ -129,9 +129,9 @@ in { type = types.nullOr types.str; description = '' Set margin of each edge specified in pixels. Specify single value to - apply margin on all sides. Two comma-seperated values will set - vertical and horizontal edges seperately. Four comma-seperated will - give each edge a seperate value. + apply margin on all sides. Two comma-separated values will set + vertical and horizontal edges separately. Four comma-separated will + give each edge a separate value. For example: 10,20,5 will set top margin to 10, left and right to 20 and bottom to five. ''; @@ -142,9 +142,9 @@ in { type = types.nullOr types.str; description = '' Set padding of each edge specified in pixels. Specify single value to - apply margin on all sides. Two comma-seperated values will set - vertical and horizontal edges seperately. Four comma-seperated will - give each edge a seperate value. + apply margin on all sides. Two comma-separated values will set + vertical and horizontal edges separately. Four comma-separated will + give each edge a separate value. For example: 10,20,5 will set top margin to 10, left and right to 20 and bottom to five. ''; diff --git a/modules/services/megasync.nix b/modules/services/megasync.nix new file mode 100644 index 00000000..c519ba51 --- /dev/null +++ b/modules/services/megasync.nix @@ -0,0 +1,40 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.megasync; + +in { + meta.maintainers = [ maintainers.GaetanLepage ]; + + options = { + services.megasync = { + enable = mkEnableOption "Megasync client"; + + package = mkPackageOption pkgs "megasync" { }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.megasync" pkgs + lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + systemd.user.services.megasync = { + Unit = { + Description = "megasync"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { ExecStart = "${cfg.package}/bin/megasync"; }; + }; + }; +} diff --git a/modules/services/mpd-discord-rpc.nix b/modules/services/mpd-discord-rpc.nix index a865d337..5e7a6664 100644 --- a/modules/services/mpd-discord-rpc.nix +++ b/modules/services/mpd-discord-rpc.nix @@ -46,7 +46,7 @@ in { Description = "Discord Rich Presence for MPD"; Documentation = "https://github.com/JakeStanger/mpd-discord-rpc"; After = [ "graphical-session-pre.target" ]; - PartOf = [ "graphical-session.desktop" ]; + PartOf = [ "graphical-session.target" ]; }; Service = { ExecStart = "${cfg.package}/bin/mpd-discord-rpc"; diff --git a/modules/services/mpd.nix b/modules/services/mpd.nix index f71d96a4..6ba93a19 100644 --- a/modules/services/mpd.nix +++ b/modules/services/mpd.nix @@ -52,11 +52,18 @@ in { musicDirectory = mkOption { type = with types; either path str; - default = "${config.home.homeDirectory}/music"; - defaultText = "$HOME/music"; + defaultText = literalExpression '' + ''${home.homeDirectory}/music if state version < 22.11 + ''${xdg.userDirs.music} if xdg.userDirs.enable == true + undefined otherwise + ''; apply = toString; # Prevent copies to Nix store. description = '' The directory where mpd reads music from. + + If is + true then the defined XDG music directory is used. + Otherwise, you must explicitly specify a value. ''; }; @@ -146,6 +153,17 @@ in { (lib.hm.assertions.assertPlatform "services.mpd" pkgs lib.platforms.linux) ]; + services.mpd = mkMerge [ + (mkIf (versionAtLeast config.home.stateVersion "22.11" + && config.xdg.userDirs.enable) { + musicDirectory = mkOptionDefault config.xdg.userDirs.music; + }) + + (mkIf (versionOlder config.home.stateVersion "22.11") { + musicDirectory = mkOptionDefault "${config.home.homeDirectory}/music"; + }) + ]; + systemd.user.services.mpd = { Unit = { After = [ "network.target" "sound.target" ]; @@ -164,6 +182,7 @@ in { ${pkgs.bash}/bin/bash -c "${pkgs.coreutils}/bin/mkdir -p '${cfg.dataDir}' '${cfg.playlistDirectory}'"''; }; }; + systemd.user.sockets.mpd = mkIf cfg.network.startWhenNeeded { Socket = { ListenStream = let @@ -179,6 +198,8 @@ in { Install = { WantedBy = [ "sockets.target" ]; }; }; + + home.packages = [ cfg.package ]; }; } diff --git a/modules/services/parcellite.nix b/modules/services/parcellite.nix index 6ed9946b..39b81e86 100644 --- a/modules/services/parcellite.nix +++ b/modules/services/parcellite.nix @@ -12,6 +12,15 @@ in { options.services.parcellite = { enable = mkEnableOption "Parcellite"; + extraOptions = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "--no-icon" ]; + description = '' + Command line arguments passed to Parcellite. + ''; + }; + package = mkOption { type = types.package; default = pkgs.parcellite; @@ -40,7 +49,9 @@ in { Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { - ExecStart = "${cfg.package}/bin/${cfg.package.pname}"; + ExecStart = "${cfg.package}/bin/${cfg.package.pname} ${ + escapeShellArgs cfg.extraOptions + }"; Restart = "on-abort"; }; }; diff --git a/modules/services/pass-secret-service.nix b/modules/services/pass-secret-service.nix index 06b5be1f..8459099c 100644 --- a/modules/services/pass-secret-service.nix +++ b/modules/services/pass-secret-service.nix @@ -2,31 +2,46 @@ with lib; -let serviceCfg = config.services.pass-secret-service; +let + cfg = config.services.pass-secret-service; + + serviceArgs = + optionalString (cfg.storePath != null) "--path ${cfg.storePath}"; in { - meta.maintainers = [ maintainers.cab404 ]; + meta.maintainers = with maintainers; [ cab404 houstdav000 ]; + options.services.pass-secret-service = { enable = mkEnableOption "Pass libsecret service"; + + package = mkPackageOption pkgs "pass-secret-service" { }; + + storePath = mkOption { + type = with types; nullOr str; + default = null; + defaultText = "~/.password-store"; + example = "/home/user/.local/share/password-store"; + description = "Absolute path to password store."; + }; }; - config = mkIf serviceCfg.enable { + + config = mkIf cfg.enable { assertions = [ (hm.assertions.assertPlatform "services.pass-secret-service" pkgs platforms.linux) - - { - assertion = config.programs.password-store.enable; - message = "The 'services.pass-secret-service' module requires" - + " 'programs.password-store.enable = true'."; - } ]; systemd.user.services.pass-secret-service = { - Unit = { Description = "Pass libsecret service"; }; - Service = { - # pass-secret-service doesn't use environment variables for some reason. - ExecStart = - "${pkgs.pass-secret-service}/bin/pass_secret_service --path ${config.programs.password-store.settings.PASSWORD_STORE_DIR}"; + Unit = { + AssertFileIsExecutable = "${cfg.package}/bin/pass_secret_service"; + Description = "Pass libsecret service"; + Documentation = "https://github.com/mdellweg/pass_secret_service"; + PartOf = [ "default.target" ]; }; + + Service = { + ExecStart = "${cfg.package}/bin/pass_secret_service ${serviceArgs}"; + }; + Install = { WantedBy = [ "default.target" ]; }; }; }; diff --git a/modules/services/picom.nix b/modules/services/picom.nix index a279c155..f4f8edb4 100644 --- a/modules/services/picom.nix +++ b/modules/services/picom.nix @@ -16,16 +16,6 @@ let description = "pair of ${x.description}"; }; - floatBetween = a: b: - with types; - let - # toString prints floats with hardcoded high precision - floatToString = f: toJSON f; - in addCheck float (x: x <= b && x >= a) // { - description = "a floating point number in " - + "range [${floatToString a}, ${floatToString b}]"; - }; - mkDefaultAttrs = mapAttrs (n: v: mkDefault v); # Basically a tinkered lib.generators.mkKeyValueDefault @@ -64,6 +54,8 @@ in { imports = [ (mkRemovedOptionModule [ "services" "picom" "refreshRate" ] "The option `refresh-rate` has been deprecated by upstream.") + (mkRemovedOptionModule [ "services" "picom" "experimentalBackends" ] + "The option `--experimental-backends` has been removed by upstream.") (mkRemovedOptionModule [ "services" "picom" "extraOptions" ] "This option has been replaced by `services.picom.settings`.") (mkRenamedOptionModule [ "services" "picom" "opacityRule" ] [ @@ -76,8 +68,6 @@ in { options.services.picom = { enable = mkEnableOption "Picom X11 compositor"; - experimentalBackends = mkEnableOption "the new experimental backends"; - fade = mkOption { type = types.bool; default = false; @@ -96,7 +86,7 @@ in { }; fadeSteps = mkOption { - type = pairOf (floatBetween 1.0e-2 1); + type = pairOf (types.numbers.between 1.0e-2 1); default = [ 2.8e-2 3.0e-2 ]; example = [ 4.0e-2 4.0e-2 ]; description = '' @@ -132,7 +122,7 @@ in { }; shadowOpacity = mkOption { - type = floatBetween 0 1; + type = types.numbers.between 0 1; default = 0.75; example = 0.8; description = '' @@ -151,7 +141,7 @@ in { }; activeOpacity = mkOption { - type = floatBetween 0 1; + type = types.numbers.between 0 1; default = 1.0; example = 0.8; description = '' @@ -160,7 +150,7 @@ in { }; inactiveOpacity = mkOption { - type = floatBetween 0.1 1; + type = types.numbers.between 0.1 1; default = 1.0; example = 0.8; description = '' @@ -169,7 +159,7 @@ in { }; menuOpacity = mkOption { - type = floatBetween 0 1; + type = types.numbers.between 0 1; default = 1.0; example = 0.8; description = '' @@ -208,10 +198,10 @@ in { }; backend = mkOption { - type = types.enum [ "glx" "xrender" "xr_glx_hybrid" ]; + type = types.enum [ "egl" "glx" "xrender" "xr_glx_hybrid" ]; default = "xrender"; description = '' - Backend to use: glx, xrender or xr_glx_hybrid. + Backend to use: egl, glx, xrender or xr_glx_hybrid. ''; }; @@ -223,6 +213,15 @@ in { ''; }; + extraArgs = mkOption { + type = with types; listOf str; + default = [ ]; + example = literalExpression ''[ "--legacy-backends" ]''; + description = '' + Extra arguments to be passed to the picom executable. + ''; + }; + package = mkOption { type = types.package; default = pkgs.picom; @@ -316,7 +315,7 @@ in { ExecStart = concatStringsSep " " ([ "${cfg.package}/bin/picom" "--config ${config.xdg.configFile."picom/picom.conf".source}" - ] ++ optional cfg.experimentalBackends "--experimental-backends"); + ] ++ cfg.extraArgs); Restart = "always"; RestartSec = 3; }; diff --git a/modules/services/polybar.nix b/modules/services/polybar.nix index da0c617e..d3ac68de 100644 --- a/modules/services/polybar.nix +++ b/modules/services/polybar.nix @@ -1,10 +1,11 @@ -{ config, lib, pkgs, ... }: +{ config, options, lib, pkgs, ... }: with lib; let cfg = config.services.polybar; + opt = options.services.polybar; eitherStrBoolIntList = with types; either str (either bool (either int (listOf str))); @@ -54,11 +55,17 @@ let in "${key}=${value'}"; }; - configFile = pkgs.writeText "polybar.conf" '' - ${toPolybarIni cfg.config} - ${toPolybarIni (mapAttrs convertPolybarSection cfg.settings)} - ${cfg.extraConfig} - ''; + configFile = let + isDeclarativeConfig = cfg.settings != opt.settings.default || cfg.config + != opt.config.default || cfg.extraConfig != opt.extraConfig.default; + in if isDeclarativeConfig then + pkgs.writeText "polybar.conf" '' + ${toPolybarIni cfg.config} + ${toPolybarIni (mapAttrs convertPolybarSection cfg.settings)} + ${cfg.extraConfig} + '' + else + null; in { options = { @@ -198,15 +205,17 @@ in { lib.platforms.linux) ]; + meta.maintainers = with maintainers; [ h7x4 ]; + home.packages = [ cfg.package ]; - xdg.configFile."polybar/config.ini".source = configFile; + xdg.configFile."polybar/config.ini" = + mkIf (configFile != null) { source = configFile; }; systemd.user.services.polybar = { Unit = { Description = "Polybar status bar"; PartOf = [ "tray.target" ]; - X-Restart-Triggers = - [ "${config.xdg.configFile."polybar/config.ini".source}" ]; + X-Restart-Triggers = mkIf (configFile != null) "${configFile}"; }; Service = { diff --git a/modules/services/poweralertd.nix b/modules/services/poweralertd.nix index cae44c75..bc02dead 100644 --- a/modules/services/poweralertd.nix +++ b/modules/services/poweralertd.nix @@ -8,7 +8,7 @@ in { meta.maintainers = [ maintainers.thibautmarty ]; options.services.poweralertd.enable = - mkEnableOption "the Upower-powered power alerterd"; + mkEnableOption "the Upower-powered power alertd"; config = mkIf cfg.enable { assertions = [ diff --git a/modules/services/pueue.nix b/modules/services/pueue.nix index b812e271..3375f49d 100644 --- a/modules/services/pueue.nix +++ b/modules/services/pueue.nix @@ -39,7 +39,8 @@ in { home.packages = [ cfg.package ]; - xdg.configFile."pueue/pueue.yml".source = configFile; + xdg.configFile = + mkIf (cfg.settings != { }) { "pueue/pueue.yml".source = configFile; }; systemd.user = { services.pueued = { diff --git a/modules/services/redshift-gammastep/lib/options.nix b/modules/services/redshift-gammastep/lib/options.nix index a5aeac55..4c9d68ab 100644 --- a/modules/services/redshift-gammastep/lib/options.nix +++ b/modules/services/redshift-gammastep/lib/options.nix @@ -110,6 +110,8 @@ in { ''; }; + enableVerboseLogging = mkEnableOption "verbose service logging"; + tray = mkOption { type = types.bool; default = false; @@ -199,7 +201,10 @@ in { ExecStart = let command = if cfg.tray then appletExecutable else mainExecutable; configFullPath = config.xdg.configHome + "/${xdgConfigFilePath}"; - in "${cfg.package}/bin/${command} -v -c ${configFullPath}"; + in "${cfg.package}/bin/${command} " + cli.toGNUCommandLineShell { } { + v = cfg.enableVerboseLogging; + c = configFullPath; + }; RestartSec = 3; Restart = "on-failure"; }; diff --git a/modules/services/safeeyes.nix b/modules/services/safeeyes.nix new file mode 100644 index 00000000..15662469 --- /dev/null +++ b/modules/services/safeeyes.nix @@ -0,0 +1,44 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.safeeyes; + +in { + meta.maintainers = [ hm.maintainers.rosuavio ]; + + options = { + services.safeeyes = { + enable = mkEnableOption "The Safe Eyes OSGI service"; + + package = mkPackageOption pkgs "safeeyes" { }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (hm.assertions.assertPlatform "services.safeeyes" pkgs platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + systemd.user.services.safeeyes = { + Install.WantedBy = [ "graphical-session.target" ]; + + Unit = { + Description = "Safe Eyes"; + PartOf = [ "graphical-session.target" ]; + StartLimitIntervalSec = 350; + StartLimitBurst = 30; + }; + + Service = { + ExecStart = getExe pkgs.safeeyes; + Restart = "on-failure"; + RestartSec = 3; + }; + }; + }; +} diff --git a/modules/services/screen-locker.nix b/modules/services/screen-locker.nix index 3ea84ebe..155896cd 100644 --- a/modules/services/screen-locker.nix +++ b/modules/services/screen-locker.nix @@ -99,7 +99,7 @@ in { type = types.int; default = 600; description = '' - X server's screensaver cycle value expresed as seconds. + The X server's screensaver cycle value expressed as seconds. This will be used with xset to configure the cycle along with timeout. ''; diff --git a/modules/services/swayidle.nix b/modules/services/swayidle.nix index 66b4340c..db54f9e2 100644 --- a/modules/services/swayidle.nix +++ b/modules/services/swayidle.nix @@ -73,7 +73,7 @@ in { default = [ ]; example = literalExpression '' [ - { timeout = 60; command = "swaylock -fF"; } + { timeout = 60; command = "${pkgs.swaylock}/bin/swaylock -fF"; } ] ''; description = "List of commands to run after idle timeout."; @@ -84,11 +84,11 @@ in { default = [ ]; example = literalExpression '' [ - { event = "before-sleep"; command = "swaylock"; } + { event = "before-sleep"; command = "${pkgs.swaylock}/bin/swaylock"; } { event = "lock"; command = "lock"; } ] ''; - description = "Run command on occurence of a event."; + description = "Run command on occurrence of a event."; }; extraArgs = mkOption { diff --git a/modules/services/syncthing.nix b/modules/services/syncthing.nix index 97ad5862..2f9cecdb 100644 --- a/modules/services/syncthing.nix +++ b/modules/services/syncthing.nix @@ -57,6 +57,11 @@ in { config = mkMerge [ (mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.syncthing" pkgs + lib.platforms.linux) + ]; + home.packages = [ (getOutput "man" pkgs.syncthing) ]; systemd.user.services = { diff --git a/modules/services/udiskie.nix b/modules/services/udiskie.nix index 0d9ae2eb..d53d7cc8 100644 --- a/modules/services/udiskie.nix +++ b/modules/services/udiskie.nix @@ -25,7 +25,16 @@ in { options = { services.udiskie = { - enable = mkEnableOption "udiskie mount daemon"; + enable = mkEnableOption "udiskie mount daemon" // { + description = '' + Whether to enable the udiskie mount daemon. + + Note, if you use NixOS then you must add + services.udisks2.enable = true + to your system configuration. Otherwise mounting will fail because + the Udisk2 DBus service is not found. + ''; + }; settings = mkOption { type = yaml.type; diff --git a/modules/services/window-managers/awesome.nix b/modules/services/window-managers/awesome.nix index a012a03c..d79e72fe 100644 --- a/modules/services/window-managers/awesome.nix +++ b/modules/services/window-managers/awesome.nix @@ -6,7 +6,7 @@ let cfg = config.xsession.windowManager.awesome; awesome = cfg.package; - getLuaPath = lib: dir: "${lib}/${dir}/lua/${pkgs.luaPackages.lua.luaversion}"; + getLuaPath = lib: dir: "${lib}/${dir}/lua/${awesome.lua.luaversion}"; makeSearchPath = lib.concatMapStrings (path: " --search ${getLuaPath path "share"}" + " --search ${getLuaPath path "lib"}"); diff --git a/modules/services/window-managers/fluxbox.nix b/modules/services/window-managers/fluxbox.nix new file mode 100644 index 00000000..6b05d295 --- /dev/null +++ b/modules/services/window-managers/fluxbox.nix @@ -0,0 +1,122 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.xsession.windowManager.fluxbox; + +in { + meta.maintainers = [ maintainers.AndersonTorres ]; + + options = { + xsession.windowManager.fluxbox = { + enable = mkEnableOption "Fluxbox window manager"; + + package = mkPackageOption pkgs "fluxbox" { }; + + init = mkOption { + type = types.lines; + default = ""; + description = '' + Init configuration for Fluxbox, written to + ~/.fluxbox/init. Look at the + + fluxbox + 1 manpage for details. + ''; + }; + + apps = mkOption { + type = types.lines; + default = ""; + description = '' + Apps configuration for Fluxbox, written to + ~/.fluxbox/apps. Look at the + fluxbox + 1 manpage for details. + ''; + }; + + keys = mkOption { + type = types.lines; + default = ""; + description = '' + Keyboard shortcuts configuration for Fluxbox, written to + ~/.fluxbox/keys. Look at the + fluxbox-keys + 1 manpage for details. + ''; + }; + + menu = mkOption { + type = types.lines; + default = ""; + description = '' + Menu configuration for Fluxbox, written to + ~/.fluxbox/menu. Look at the + fluxbox-menu + 1 manpage for details. + ''; + }; + + slitlist = mkOption { + type = types.lines; + default = ""; + description = '' + Slitlist configuration for Fluxbox, written to + ~/.fluxbox/slitlist. Look at the + fluxbox + 1 manpage for details. + ''; + }; + + windowmenu = mkOption { + type = types.lines; + default = ""; + description = '' + Window menu configuration for Fluxbox, written to + ~/.fluxbox/windowmenu. Look at the + fluxbox-menu + 1 + manpage for details. + ''; + }; + + extraCommandLineArgs = mkOption { + type = with types; listOf str; + default = [ ]; + example = [ "-log" "/tmp/fluxbox.log" ]; + description = '' + Extra command line arguments to pass to fluxbox. + Look at the + fluxbox + 1 manpage for details. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (hm.assertions.assertPlatform "xsession.windowManager.fluxbox" pkgs + platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + home.file = { + ".fluxbox/init" = mkIf (cfg.init != "") { text = cfg.init; }; + ".fluxbox/apps" = mkIf (cfg.apps != "") { text = cfg.apps; }; + ".fluxbox/keys" = mkIf (cfg.keys != "") { text = cfg.keys; }; + ".fluxbox/menu" = mkIf (cfg.menu != "") { text = cfg.menu; }; + ".fluxbox/slitlist" = mkIf (cfg.slitlist != "") { text = cfg.slitlist; }; + ".fluxbox/windowmenu" = + mkIf (cfg.windowmenu != "") { text = cfg.windowmenu; }; + }; + + xsession.windowManager.command = concatStringsSep " " + ([ "${cfg.package}/bin/fluxbox" ] + ++ escapeShellArgs (remove "" cfg.extraCommandLineArgs)); + }; +} diff --git a/modules/services/window-managers/herbstluftwm.nix b/modules/services/window-managers/herbstluftwm.nix index cbbe3cef..67457e95 100644 --- a/modules/services/window-managers/herbstluftwm.nix +++ b/modules/services/window-managers/herbstluftwm.nix @@ -141,19 +141,22 @@ in { herbstclient attr theme.tiling.reset 1 herbstclient attr theme.floating.reset 1 herbstclient keyunbind --all + herbstclient mouseunbind --all herbstclient unrule --all ${renderSettings cfg.settings} - if ${cfg.package}/bin/herbstclient object_tree tags.by-name | ${pkgs.gnugrep}/bin/grep default; then - herbstclient rename default ${ - lib.escapeShellArg (builtins.head cfg.tags) - } - fi + ${lib.optionalString (cfg.tags != [ ]) '' + if ${cfg.package}/bin/herbstclient object_tree tags.default &>/dev/null; then + herbstclient rename default ${ + lib.escapeShellArg (builtins.head cfg.tags) + } + fi - for tag in ${lib.escapeShellArgs cfg.tags}; do - herbstclient add "$tag" - done + for tag in ${lib.escapeShellArgs cfg.tags}; do + herbstclient add "$tag" + done + ''} ${renderKeybinds cfg.keybinds} diff --git a/modules/services/window-managers/i3-sway/i3.nix b/modules/services/window-managers/i3-sway/i3.nix index 16e82d16..b4742c78 100644 --- a/modules/services/window-managers/i3-sway/i3.nix +++ b/modules/services/window-managers/i3-sway/i3.nix @@ -9,7 +9,6 @@ let commonOptions = import ./lib/options.nix { inherit config lib cfg pkgs; moduleName = "i3"; - isGaps = cfg.package == pkgs.i3-gaps; }; configModule = types.submodule { @@ -105,7 +104,7 @@ let in lib.mkOptionDefault { "''${modifier}+Return" = "exec i3-sensible-terminal"; "''${modifier}+Shift+q" = "kill"; - "''${modifier}+d" = "exec \${pkgs.dmenu}/bin/dmenu_run"; + "''${modifier}+d" = "exec ''${pkgs.dmenu}/bin/dmenu_run"; } ''; }; @@ -161,7 +160,7 @@ let "floating_modifier ${floating.modifier}" (windowBorderString window floating) "hide_edge_borders ${window.hideEdgeBorders}" - "force_focus_wrapping ${lib.hm.booleans.yesNo focus.forceWrapping}" + "focus_wrapping ${focus.wrapping}" "focus_follows_mouse ${lib.hm.booleans.yesNo focus.followMouse}" "focus_on_window_activation ${focus.newWindow}" "mouse_warping ${if focus.mouseWarping then "output" else "none"}" @@ -193,7 +192,7 @@ let # We have to make sure the wrapper does not start a dbus session export DBUS_SESSION_BUS_ADDRESS=1 - # A zero exit code means i3 succesfully validated the configuration + # A zero exit code means i3 successfully validated the configuration i3 -c ${configFile} -C -d all || { echo "i3 configuration validation failed" echo "For a verbose log of the failure, run 'i3 -c ${configFile} -C -d all'" @@ -209,16 +208,7 @@ in { xsession.windowManager.i3 = { enable = mkEnableOption "i3 window manager"; - package = mkOption { - type = types.package; - default = pkgs.i3; - defaultText = literalExpression "pkgs.i3"; - example = literalExpression "pkgs.i3-gaps"; - description = '' - i3 package to use. - If 'i3.config.gaps' settings are specified, 'pkgs.i3-gaps' will be set as a default package. - ''; - }; + package = mkPackageOption pkgs "i3" { }; config = mkOption { type = types.nullOr configModule; @@ -249,35 +239,32 @@ in { xdg.configFile."i3/config" = { source = checkI3Config; onChange = '' - i3Socket=''${XDG_RUNTIME_DIR:-/run/user/$UID}/i3/ipc-socket.* - if [ -S $i3Socket ]; then - ${cfg.package}/bin/i3-msg -s $i3Socket reload >/dev/null - fi + # There may be several sockets after log out/log in, but the old ones + # will fail with "Connection refused". + for i3Socket in ''${XDG_RUNTIME_DIR:-/run/user/$UID}/i3/ipc-socket.*; do + if [[ -S $i3Socket ]]; then + ${cfg.package}/bin/i3-msg -s $i3Socket reload >/dev/null |& grep -v "Connection refused" || true + fi + done ''; }; } - (mkIf (cfg.config != null) { - xsession.windowManager.i3.package = - mkDefault (if (cfg.config.gaps != null) then pkgs.i3-gaps else pkgs.i3); - }) - (mkIf (cfg.config != null) { warnings = (optional (isList cfg.config.fonts) "Specifying i3.config.fonts as a list is deprecated. Use the attrset version instead.") ++ flatten (map (b: optional (isList b.fonts) "Specifying i3.config.bars[].fonts as a list is deprecated. Use the attrset version instead.") - cfg.config.bars); + cfg.config.bars) ++ [ + (mkIf (any (s: s.workspace != null) cfg.config.startup) + ("'xsession.windowManager.i3.config.startup.*.workspace' is deprecated, " + + "use 'xsession.windowManager.i3.config.assigns' instead." + + "See https://github.com/nix-community/home-manager/issues/265.")) + (mkIf cfg.config.focus.forceWrapping + ("'xsession.windowManager.i3.config.focus.forceWrapping' is deprecated, " + + "use 'xsession.windowManager.i3.config.focus.wrapping' instead.")) + ]; }) - - (mkIf (cfg.config != null - && (any (s: s.workspace != null) cfg.config.startup)) { - warnings = [ - ("'xsession.windowManager.i3.config.startup.*.workspace' is deprecated, " - + "use 'xsession.windowManager.i3.config.assigns' instead." - + "See https://github.com/nix-community/home-manager/issues/265.") - ]; - }) ]); } diff --git a/modules/services/window-managers/i3-sway/lib/options.nix b/modules/services/window-managers/i3-sway/lib/options.nix index cae9c3a6..3fe0b755 100644 --- a/modules/services/window-managers/i3-sway/lib/options.nix +++ b/modules/services/window-managers/i3-sway/lib/options.nix @@ -1,5 +1,4 @@ -{ config, lib, moduleName, cfg, pkgs, capitalModuleName ? moduleName -, isGaps ? true }: +{ config, lib, moduleName, cfg, pkgs, capitalModuleName ? moduleName }: with lib; @@ -7,6 +6,8 @@ let isI3 = moduleName == "i3"; isSway = !isI3; + inherit (config.home) stateVersion; + fontOptions = types.submodule { options = { names = mkOption { @@ -77,7 +78,7 @@ let barModule = types.submodule { options = let - versionAtLeast2009 = versionAtLeast config.home.stateVersion "20.09"; + versionAtLeast2009 = versionAtLeast stateVersion "20.09"; mkNullableOption = { type, default, ... }@args: mkOption (args // { type = types.nullOr type; @@ -158,7 +159,7 @@ let defaultText = "i3bar"; description = "Command that will be used to start a bar."; example = if isI3 then - "\${pkgs.i3-gaps}/bin/i3bar -t" + "\${pkgs.i3}/bin/i3bar -t" else "\${pkgs.waybar}/bin/waybar"; }; @@ -389,11 +390,17 @@ in { options = { titlebar = mkOption { type = types.bool; - default = !isGaps; - defaultText = if isI3 then - "xsession.windowManager.i3.package != nixpkgs.i3-gaps (titlebar should be disabled for i3-gaps)" + default = if versionOlder stateVersion "23.05" then + (isI3 && (cfg.config.gaps == null)) else - "false"; + true; + defaultText = if isI3 then '' + true for state version ≥ 23.05 + config.gaps == null for state version < 23.05 + '' else '' + true for state version ≥ 23.05 + false for state version < 23.05 + ''; description = "Whether to show window titlebars."; }; @@ -432,11 +439,17 @@ in { options = { titlebar = mkOption { type = types.bool; - default = !isGaps; - defaultText = if isI3 then - "xsession.windowManager.i3.package != nixpkgs.i3-gaps (titlebar should be disabled for i3-gaps)" + default = if versionOlder stateVersion "23.05" then + (isI3 && (cfg.config.gaps == null)) else - "false"; + true; + defaultText = if isI3 then '' + true for state version ≥ 23.05 + config.gaps == null for state version < 23.05 + '' else '' + true for state version ≥ 23.05 + false for state version < 23.05 + ''; description = "Whether to show floating window titlebars."; }; @@ -497,13 +510,28 @@ in { if (isSway && isBool val) then (lib.hm.booleans.yesNo val) else val; }; + wrapping = mkOption { + type = types.enum [ "yes" "no" "force" "workspace" ]; + default = { + i3 = if cfg.config.focus.forceWrapping then "force" else "yes"; + # the sway module's logic was inverted and incorrect, + # so preserve it for backwards compatibility purposes + sway = if cfg.config.focus.forceWrapping then "yes" else "no"; + }.${moduleName}; + description = '' + Whether the window focus commands automatically wrap around the edge of containers. + + See + ''; + }; + forceWrapping = mkOption { type = types.bool; default = false; description = '' - Whether to force focus wrapping in tabbed or stacked container. + Whether to force focus wrapping in tabbed or stacked containers. - See + This option is deprecated, use instead. ''; }; @@ -670,7 +698,7 @@ in { bars = mkOption { type = types.listOf barModule; - default = if versionAtLeast config.home.stateVersion "20.09" then [{ + default = if versionAtLeast stateVersion "20.09" then [{ mode = "dock"; hiddenState = "hide"; position = "bottom"; @@ -826,19 +854,14 @@ in { }; }); default = null; - description = if isSway then '' + description = '' Gaps related settings. - '' else '' - i3Gaps related settings. The i3-gaps package must be used for these features to work. ''; }; terminal = mkOption { type = types.str; - default = if isI3 then - "i3-sensible-terminal" - else - "${pkgs.rxvt-unicode-unwrapped}/bin/urxvt"; + default = if isI3 then "i3-sensible-terminal" else "${pkgs.foot}/bin/foot"; description = "Default terminal to run."; example = "alacritty"; }; diff --git a/modules/services/window-managers/i3-sway/sway.nix b/modules/services/window-managers/i3-sway/sway.nix index 725fac7d..a18a4212 100644 --- a/modules/services/window-managers/i3-sway/sway.nix +++ b/modules/services/window-managers/i3-sway/sway.nix @@ -271,7 +271,7 @@ let "floating_modifier ${floating.modifier}" (windowBorderString window floating) "hide_edge_borders ${window.hideEdgeBorders}" - "focus_wrapping ${lib.hm.booleans.yesNo focus.forceWrapping}" + "focus_wrapping ${focus.wrapping}" "focus_follows_mouse ${focus.followMouse}" "focus_on_window_activation ${focus.newWindow}" "mouse_warping ${ @@ -317,7 +317,7 @@ let ) else [ ]) ++ (optional cfg.systemdIntegration '' - exec "${pkgs.dbus}/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP; systemctl --user start sway-session.target"'') + exec "${pkgs.dbus}/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP XDG_SESSION_TYPE; systemctl --user start sway-session.target"'') ++ (optional (!cfg.xwayland) "xwayland disable") ++ [ cfg.extraConfig ])); defaultSwayPackage = pkgs.sway.override { @@ -442,7 +442,10 @@ in { ++ flatten (map (b: optional (isList b.fonts) "Specifying sway.config.bars[].fonts as a list is deprecated. Use the attrset version instead.") - cfg.config.bars); + cfg.config.bars) ++ [ + (mkIf cfg.config.focus.forceWrapping + "sway.config.focus.forceWrapping is deprecated, use focus.wrapping instead.") + ]; }) { diff --git a/modules/services/window-managers/i3-sway/swaynag.nix b/modules/services/window-managers/i3-sway/swaynag.nix index 97d6f473..8b77b55f 100644 --- a/modules/services/window-managers/i3-sway/swaynag.nix +++ b/modules/services/window-managers/i3-sway/swaynag.nix @@ -33,7 +33,7 @@ in { swaynag 5 - for a list of avaliable options and an example configuration. + for a list of available options and an example configuration. Note, configurations declared under <config> will override the default type values of swaynag. ''; diff --git a/modules/systemd.nix b/modules/systemd.nix index ff70edf8..e4c36ae4 100644 --- a/modules/systemd.nix +++ b/modules/systemd.nix @@ -8,7 +8,7 @@ let # From mkPathSafeName = - lib.replaceChars [ "@" ":" "\\" "[" "]" ] [ "-" "-" "-" "" "" ]; + lib.replaceStrings [ "@" ":" "\\" "[" "]" ] [ "-" "-" "-" "" "" ]; enabled = cfg.services != { } # \ || cfg.slices != { } # \ @@ -107,7 +107,7 @@ in { systemd.user = { systemctlPath = mkOption { default = "${pkgs.systemd}/bin/systemctl"; - defaultText = "\${pkgs.systemd}/bin/systemctl"; + defaultText = literalExpression ''"''${pkgs.systemd}/bin/systemctl"''; type = types.str; description = '' Absolute path to the systemctl tool. This @@ -125,9 +125,9 @@ in { slices = mkOption { default = { }; - type = unitType "slices"; - description = unitDescription "slices"; - example = unitExample "Slices"; + type = unitType "slice"; + description = unitDescription "slice"; + example = unitExample "Slice"; }; sockets = mkOption { @@ -263,7 +263,7 @@ in { (mkIf (pkgs.stdenv.isLinux && config.home.username != "root") { xdg.configFile = mkMerge [ (lib.listToAttrs ((buildServices "service" cfg.services) - ++ (buildServices "slices" cfg.slices) + ++ (buildServices "slice" cfg.slices) ++ (buildServices "socket" cfg.sockets) ++ (buildServices "target" cfg.targets) ++ (buildServices "timer" cfg.timers) diff --git a/modules/targets/darwin/linkapps.nix b/modules/targets/darwin/linkapps.nix index 118321e8..0d434234 100644 --- a/modules/targets/darwin/linkapps.nix +++ b/modules/targets/darwin/linkapps.nix @@ -1,9 +1,7 @@ { config, lib, pkgs, ... }: { - # Disabled for now due to conflicting behavior with nix-darwin. See - # https://github.com/nix-community/home-manager/issues/1341#issuecomment-687286866 - config = lib.mkIf (false && pkgs.stdenv.hostPlatform.isDarwin) { + config = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin { # Install MacOS applications to the user environment. home.file."Applications/Home Manager Apps".source = let apps = pkgs.buildEnv { diff --git a/modules/targets/darwin/user-defaults/default.nix b/modules/targets/darwin/user-defaults/default.nix index dfb9b61e..c44d4f9c 100644 --- a/modules/targets/darwin/user-defaults/default.nix +++ b/modules/targets/darwin/user-defaults/default.nix @@ -13,9 +13,9 @@ let cliFlags = lib.optionalString isLocal "-currentHost"; toActivationCmd = domain: attrs: - "$DRY_RUN_CMD defaults ${cliFlags} import ${escapeShellArg domain} ${ - toDefaultsFile domain attrs - }"; + "$DRY_RUN_CMD /usr/bin/defaults ${cliFlags} import ${ + escapeShellArg domain + } ${toDefaultsFile domain attrs}"; nonNullDefaults = mapAttrs (domain: attrs: (filterAttrs (n: v: v != null) attrs)) diff --git a/modules/targets/darwin/user-defaults/opts-allhosts.nix b/modules/targets/darwin/user-defaults/opts-allhosts.nix index 67399775..832318a9 100644 --- a/modules/targets/darwin/user-defaults/opts-allhosts.nix +++ b/modules/targets/darwin/user-defaults/opts-allhosts.nix @@ -50,7 +50,7 @@ in { AppleMetricUnits = mkNullableEnableOption "the metric system"; NSAutomaticCapitalizationEnabled = - mkNullableEnableOption "automatic captilization"; + mkNullableEnableOption "automatic capitalization"; NSAutomaticDashSubstitutionEnabled = mkNullableEnableOption "smart dashes"; diff --git a/modules/targets/generic-linux.nix b/modules/targets/generic-linux.nix index aad74afb..b5a07d5f 100644 --- a/modules/targets/generic-linux.nix +++ b/modules/targets/generic-linux.nix @@ -8,6 +8,8 @@ let profileDirectory = config.home.profileDirectory; + nixPkg = if config.nix.package == null then pkgs.nix else config.nix.package; + in { imports = [ (mkRenamedOptionModule [ "targets" "genericLinux" "extraXdgDataDirs" ] [ @@ -55,7 +57,7 @@ in { }; home.sessionVariablesExtra = '' - . "${pkgs.nix}/etc/profile.d/nix.sh" + . "${nixPkg}/etc/profile.d/nix.sh" # reset TERM with new TERMINFO available (if any) export TERM="$TERM" @@ -64,7 +66,7 @@ in { # We need to source both nix.sh and hm-session-vars.sh as noted in # https://github.com/nix-community/home-manager/pull/797#issuecomment-544783247 programs.bash.initExtra = '' - . "${pkgs.nix}/etc/profile.d/nix.sh" + . "${nixPkg}/etc/profile.d/nix.sh" . "${profileDirectory}/etc/profile.d/hm-session-vars.sh" ''; diff --git a/nix-darwin/default.nix b/nix-darwin/default.nix index c1c07dc1..018e9bab 100644 --- a/nix-darwin/default.nix +++ b/nix-darwin/default.nix @@ -15,7 +15,7 @@ in { system.activationScripts.postActivation.text = concatStringsSep "\n" (mapAttrsToList (username: usercfg: '' echo Activating home-manager configuration for ${username} - sudo -u ${username} -s --set-home ${ + sudo -u ${username} --set-home ${ pkgs.writeShellScript "activation-${username}" '' ${lib.optionalString (cfg.backupFileExtension != null) "export HOME_MANAGER_BACKUP_EXT=${ diff --git a/nixos/common.nix b/nixos/common.nix index bbc0f976..25872b25 100644 --- a/nixos/common.nix +++ b/nixos/common.nix @@ -35,7 +35,7 @@ let # Make activation script use same version of Nix as system as a whole. # This avoids problems with Nix not being in PATH. - home.extraActivationPath = [ config.nix.package ]; + nix.package = config.nix.package; }; }) ] ++ cfg.sharedModules; diff --git a/templates/nix-darwin/flake.nix b/templates/nix-darwin/flake.nix index 85b1db41..ff73efd8 100644 --- a/templates/nix-darwin/flake.nix +++ b/templates/nix-darwin/flake.nix @@ -1,5 +1,5 @@ { - description = "NixOS configuration"; + description = "Darwin configuration"; inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; diff --git a/tests/default.nix b/tests/default.nix index 5b173a7f..9bbdaebb 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -80,6 +80,7 @@ import nmt { ./modules/programs/hyfetch ./modules/programs/i3status ./modules/programs/irssi + ./modules/programs/k9s ./modules/programs/kakoune ./modules/programs/kitty ./modules/programs/less @@ -99,9 +100,12 @@ import nmt { ./modules/programs/nix-index ./modules/programs/nnn ./modules/programs/nushell + ./modules/programs/oh-my-posh ./modules/programs/pandoc + ./modules/programs/papis ./modules/programs/pet ./modules/programs/pistol + ./modules/programs/pls ./modules/programs/powerline-go ./modules/programs/pubs ./modules/programs/qutebrowser @@ -109,13 +113,16 @@ import nmt { ./modules/programs/sagemath ./modules/programs/sbt ./modules/programs/scmpuff + ./modules/programs/sioyek ./modules/programs/sm64ex ./modules/programs/ssh ./modules/programs/starship ./modules/programs/taskwarrior ./modules/programs/texlive + ./modules/programs/tmate ./modules/programs/tmux ./modules/programs/topgrade + ./modules/programs/vim-vint ./modules/programs/vscode ./modules/programs/watson ./modules/programs/wezterm @@ -138,6 +145,7 @@ import nmt { ./modules/misc/xsession ./modules/programs/abook ./modules/programs/autorandr + ./modules/programs/borgmatic ./modules/programs/firefox ./modules/programs/foot ./modules/programs/getmail @@ -145,6 +153,7 @@ import nmt { ./modules/programs/hexchat ./modules/programs/i3status-rust ./modules/programs/kodi + ./modules/programs/looking-glass-client ./modules/programs/mangohud ./modules/programs/ncmpcpp-linux ./modules/programs/neovim # Broken package dependency on Darwin. @@ -153,9 +162,15 @@ import nmt { ./modules/programs/rofi-pass ./modules/programs/swaylock ./modules/programs/terminator + ./modules/programs/thunderbird ./modules/programs/waybar + ./modules/programs/wlogout ./modules/programs/xmobar + ./modules/programs/yt-dlp ./modules/services/barrier + ./modules/services/borgmatic + ./modules/services/cachix-agent + ./modules/services/clipman ./modules/services/devilspie2 ./modules/services/dropbox ./modules/services/emacs @@ -174,6 +189,8 @@ import nmt { ./modules/services/mpd ./modules/services/mpdris2 ./modules/services/pantalaimon + ./modules/services/parcellite + ./modules/services/pass-secret-service ./modules/services/pbgopy ./modules/services/picom ./modules/services/playerctld diff --git a/tests/lib/types/gvariant-merge.nix b/tests/lib/types/gvariant-merge.nix index c4de6827..5a04848a 100644 --- a/tests/lib/types/gvariant-merge.nix +++ b/tests/lib/types/gvariant-merge.nix @@ -50,6 +50,11 @@ in { { maybe1 = mkNothing type.string; } { maybe2 = mkJust (mkUint32 4); } + + { variant1 = mkVariant "foo"; } + { variant2 = mkVariant 42; } + + { dictionaryEntry = mkDictionaryEntry [ 1 [ "foo" ] ]; } ]; home.file."result.txt".text = let @@ -65,6 +70,7 @@ in { array1 = @as ['one','two'] array2 = @au [1,2] bool = true + dictionaryEntry = @{ias} {1,@as ['foo']} emptyArray1 = @as [] emptyArray2 = @au [] escapedString = '\'\\\n' @@ -79,6 +85,8 @@ in { uint16 = @q 42 uint32 = @u 42 uint64 = @t 42 + variant1 = @v <'foo'> + variant2 = @v <42> '' } ''; diff --git a/tests/modules/files/default.nix b/tests/modules/files/default.nix index 52e44d22..2c35b9a2 100644 --- a/tests/modules/files/default.nix +++ b/tests/modules/files/default.nix @@ -1,4 +1,5 @@ { + files-disabled = ./disabled.nix; files-executable = ./executable.nix; files-hidden-source = ./hidden-source.nix; files-out-of-store-symlink = ./out-of-store-symlink.nix; diff --git a/tests/modules/files/disabled.nix b/tests/modules/files/disabled.nix new file mode 100644 index 00000000..b9ed858a --- /dev/null +++ b/tests/modules/files/disabled.nix @@ -0,0 +1,14 @@ +{ ... }: + +{ + home.file."disabled" = { + enable = false; + text = '' + This file should not exist + ''; + }; + + nmt.script = '' + assertPathNotExists home-files/disabled + ''; +} diff --git a/tests/modules/misc/debug/default.nix b/tests/modules/misc/debug/default.nix index 19ff4e2b..7eb28666 100644 --- a/tests/modules/misc/debug/default.nix +++ b/tests/modules/misc/debug/default.nix @@ -15,7 +15,7 @@ assertFileRegex home-path/etc/profile.d/hm-session-vars.sh \ 'NIX_DEBUG_INFO_DIRS=.*/lib/debug' - # We need to override NIX_DEBUG_INFO_DIRS here as $HOME evalutes to the home + # We need to override NIX_DEBUG_INFO_DIRS here as $HOME evaluates to the home # of the user who executes this testcase :/ { echo quit | PATH="$TESTED/home-path/bin''${PATH:+:}$PATH" NIX_DEBUG_INFO_DIRS=$TESTED/home-path/lib/debug \ gdb curl 2>&1 | \ diff --git a/tests/modules/misc/xdg/default.nix b/tests/modules/misc/xdg/default.nix index f3fef092..4cce5baf 100644 --- a/tests/modules/misc/xdg/default.nix +++ b/tests/modules/misc/xdg/default.nix @@ -4,4 +4,5 @@ xdg-desktop-entries = ./desktop-entries.nix; xdg-file-gen = ./file-gen.nix; xdg-default-locations = ./default-locations.nix; + xdg-user-dirs-null = ./user-dirs-null.nix; } diff --git a/tests/modules/misc/xdg/user-dirs-null.nix b/tests/modules/misc/xdg/user-dirs-null.nix new file mode 100644 index 00000000..6e8c4f18 --- /dev/null +++ b/tests/modules/misc/xdg/user-dirs-null.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +{ + config = { + xdg.userDirs = { + enable = true; + desktop = null; + }; + + nmt.script = '' + configFile=home-files/.config/user-dirs.dirs + assertFileExists $configFile + assertFileContent $configFile ${ + pkgs.writeText "expected" '' + XDG_DOCUMENTS_DIR="/home/hm-user/Documents" + XDG_DOWNLOAD_DIR="/home/hm-user/Downloads" + XDG_MUSIC_DIR="/home/hm-user/Music" + XDG_PICTURES_DIR="/home/hm-user/Pictures" + XDG_PUBLICSHARE_DIR="/home/hm-user/Public" + XDG_TEMPLATES_DIR="/home/hm-user/Templates" + XDG_VIDEOS_DIR="/home/hm-user/Videos" + '' + } + ''; + }; +} diff --git a/tests/modules/programs/aerc/extraAccounts.expected b/tests/modules/programs/aerc/extraAccounts.expected index 15749c03..9377384f 100644 --- a/tests/modules/programs/aerc/extraAccounts.expected +++ b/tests/modules/programs/aerc/extraAccounts.expected @@ -59,15 +59,15 @@ source = maildir:///home/hm-user/Maildir/i_maildir-mbsync from = Foo Bar source = maildir:///home/hm-user/Maildir/j_maildir-offlineimap -[l_smpt-auth-none] +[l_smtp-auth-none] from = Foo Bar outgoing = smtps+none://foobar@smtp.host.invalid:42 -[m_smpt-auth-plain] +[m_smtp-auth-plain] from = Foo Bar outgoing = smtps+plain://foobar@smtp.host.invalid:42 -[n_smpt-auth-login] +[n_smtp-auth-login] from = Foo Bar outgoing = smtps+login://foobar@smtp.host.invalid:42 diff --git a/tests/modules/programs/aerc/settings.nix b/tests/modules/programs/aerc/settings.nix index 2fded9cc..1f3c25a9 100644 --- a/tests/modules/programs/aerc/settings.nix +++ b/tests/modules/programs/aerc/settings.nix @@ -193,7 +193,7 @@ with lib; i_maildir-mbsync = basics // { mbsync.enable = true; }; j_maildir-offlineimap = basics // { offlineimap.enable = true; }; k_notEnabled = basics // { aerc.enable = false; }; - l_smpt-auth-none = basics // { + l_smtp-auth-none = basics // { smtp = { host = "smtp.host.invalid"; port = 42; @@ -203,7 +203,7 @@ with lib; smtpAuth = "none"; }; }; - m_smpt-auth-plain = basics // { + m_smtp-auth-plain = basics // { smtp = { host = "smtp.host.invalid"; port = 42; @@ -213,7 +213,7 @@ with lib; smtpAuth = "plain"; }; }; - n_smpt-auth-login = basics // { + n_smtp-auth-login = basics // { smtp = { host = "smtp.host.invalid"; port = 42; diff --git a/tests/modules/programs/atuin/fish.nix b/tests/modules/programs/atuin/fish.nix index 77232dba..527943d6 100644 --- a/tests/modules/programs/atuin/fish.nix +++ b/tests/modules/programs/atuin/fish.nix @@ -13,7 +13,6 @@ test.stubs = { atuin = { }; bash-preexec = { }; - fish = { }; }; nmt.script = '' diff --git a/tests/modules/programs/atuin/no-shell.nix b/tests/modules/programs/atuin/no-shell.nix index b636f7c0..381bcc0c 100644 --- a/tests/modules/programs/atuin/no-shell.nix +++ b/tests/modules/programs/atuin/no-shell.nix @@ -20,7 +20,6 @@ test.stubs = { atuin = { }; bash-preexec = { }; - fish = { }; }; nmt.script = '' diff --git a/tests/modules/programs/borgmatic/basic-configuration.nix b/tests/modules/programs/borgmatic/basic-configuration.nix new file mode 100644 index 00000000..b9988d47 --- /dev/null +++ b/tests/modules/programs/borgmatic/basic-configuration.nix @@ -0,0 +1,116 @@ +{ config, pkgs, ... }: + +let + boolToString = bool: if bool then "true" else "false"; + backups = config.programs.borgmatic.backups; +in { + config = { + programs.borgmatic = { + enable = true; + backups = { + main = { + location = { + sourceDirectories = [ "/my-stuff-to-backup" ]; + repositories = [ "/mnt/disk1" "/mnt/disk2" ]; + extraConfig = { + one_file_system = true; + exclude_patterns = [ "*.swp" ]; + }; + }; + + storage = { + encryptionPasscommand = "fetch-the-password.sh"; + extraConfig = { checkpoint_interval = 200; }; + }; + + retention = { + keepWithin = "14d"; + keepSecondly = 12; + extraConfig = { prefix = "hostname"; }; + }; + + consistency = { + checks = [ + { + name = "repository"; + frequency = "2 weeks"; + } + { + name = "archives"; + frequency = "4 weeks"; + } + ]; + + extraConfig = { prefix = "hostname"; }; + }; + }; + }; + }; + + test.stubs.borgmatic = { }; + + nmt.script = '' + config_file=$TESTED/home-files/.config/borgmatic.d/main.yaml + assertFileExists $config_file + + declare -A expectations + + expectations[location.source_directories[0]]="${ + builtins.elemAt backups.main.location.sourceDirectories 0 + }" + expectations[location.repositories[0]]="${ + builtins.elemAt backups.main.location.repositories 0 + }" + expectations[location.repositories[1]]="${ + builtins.elemAt backups.main.location.repositories 1 + }" + expectations[location.one_file_system]="${ + boolToString backups.main.location.extraConfig.one_file_system + }" + expectations[location.exclude_patterns[0]]="${ + builtins.elemAt backups.main.location.extraConfig.exclude_patterns 0 + }" + + expectations[storage.encryption_passcommand]="${backups.main.storage.encryptionPasscommand}" + expectations[storage.checkpoint_interval]="${ + toString backups.main.storage.extraConfig.checkpoint_interval + }" + + expectations[retention.keep_within]="${backups.main.retention.keepWithin}" + expectations[retention.keep_secondly]="${ + toString backups.main.retention.keepSecondly + }" + expectations[retention.prefix]="${backups.main.retention.extraConfig.prefix}" + + expectations[consistency.checks[0].name]="${ + (builtins.elemAt backups.main.consistency.checks 0).name + }" + expectations[consistency.checks[0].frequency]="${ + (builtins.elemAt backups.main.consistency.checks 0).frequency + }" + expectations[consistency.checks[1].name]="${ + (builtins.elemAt backups.main.consistency.checks 1).name + }" + expectations[consistency.checks[1].frequency]="${ + (builtins.elemAt backups.main.consistency.checks 1).frequency + }" + expectations[consistency.prefix]="${backups.main.consistency.extraConfig.prefix}" + + yq=${pkgs.yq-go}/bin/yq + + for filter in "''${!expectations[@]}"; do + expected_value="''${expectations[$filter]}" + actual_value="$($yq ".$filter" $config_file)" + + if [[ "$actual_value" != "$expected_value" ]]; then + fail "Expected '$filter' to be '$expected_value' but was '$actual_value'" + fi + done + + one_file_system=$($yq ".location.one_file_system" $config_file) + if [[ $one_file_system != "true" ]]; then + fail "Expected one_file_system to be true but it was $one_file_system" + fi + ''; + }; +} diff --git a/tests/modules/programs/borgmatic/default.nix b/tests/modules/programs/borgmatic/default.nix new file mode 100644 index 00000000..721c4823 --- /dev/null +++ b/tests/modules/programs/borgmatic/default.nix @@ -0,0 +1 @@ +{ borgmatic-program-basic-configuration = ./basic-configuration.nix; } diff --git a/tests/modules/programs/broot/broot.nix b/tests/modules/programs/broot/broot.nix index a2dddca3..b39929e3 100644 --- a/tests/modules/programs/broot/broot.nix +++ b/tests/modules/programs/broot/broot.nix @@ -1,42 +1,26 @@ -{ config, lib, pkgs, ... }: - -with lib; +{ ... }: { - config = { - programs.broot = { - enable = true; - modal = true; - }; - - test.stubs.broot = { }; - - nmt.script = '' - assertFileExists home-files/.config/broot/conf.toml - assertFileContent home-files/.config/broot/conf.toml ${ - pkgs.writeText "broot.expected" '' - modal = true - - [[verbs]] - execution = ":parent" - invocation = "p" - - [[verbs]] - execution = "$EDITOR {file}" - invocation = "edit" - shortcut = "e" - - [[verbs]] - execution = "$EDITOR {directory}/{subpath}" - invocation = "create {subpath}" - - [[verbs]] - execution = "less {file}" - invocation = "view" - - [skin] - '' - } - ''; + programs.broot = { + enable = true; + settings.modal = true; }; + + nmt.script = '' + assertFileExists home-files/.config/broot/conf.toml + assertFileContent home-files/.config/broot/conf.toml ${ + builtins.toFile "broot.expected" '' + content_search_max_file_size = "10MB" + imports = ["verbs.hjson", {file = "dark-blue-skin.hjson", luma = ["dark", "unknown"]}, {file = "white-skin.hjson", luma = "light"}] + modal = true + show_selection_mark = true + verbs = [] + + [skin] + + [special_paths] + "/media" = "no-enter" + '' + } + ''; } diff --git a/tests/modules/programs/direnv/default.nix b/tests/modules/programs/direnv/default.nix index 3efad2b6..a0e61848 100644 --- a/tests/modules/programs/direnv/default.nix +++ b/tests/modules/programs/direnv/default.nix @@ -1,6 +1,7 @@ { direnv-bash = ./bash.nix; direnv-nix-direnv = ./nix-direnv.nix; + direnv-nushell = ./nushell.nix; direnv-stdlib = ./stdlib.nix; direnv-stdlib-and-nix-direnv = ./stdlib-and-nix-direnv.nix; } diff --git a/tests/modules/programs/direnv/nushell.nix b/tests/modules/programs/direnv/nushell.nix new file mode 100644 index 00000000..3041770c --- /dev/null +++ b/tests/modules/programs/direnv/nushell.nix @@ -0,0 +1,19 @@ +{ pkgs, ... }: + +{ + programs.nushell.enable = true; + programs.direnv.enable = true; + + test.stubs.nushell = { }; + + nmt.script = let + configFile = if pkgs.stdenv.isDarwin then + "home-files/Library/Application Support/nushell/config.nu" + else + "home-files/.config/nushell/config.nu"; + in '' + assertFileExists "${configFile}" + assertFileRegex "${configFile}" \ + 'let direnv = (/nix/store/.*direnv.*/bin/direnv export json | from json)' + ''; +} diff --git a/tests/modules/programs/firefox/profile-settings-expected-bookmarks.html b/tests/modules/programs/firefox/profile-settings-expected-bookmarks.html index 3bdcac0f..d60e88ff 100644 --- a/tests/modules/programs/firefox/profile-settings-expected-bookmarks.html +++ b/tests/modules/programs/firefox/profile-settings-expected-bookmarks.html @@ -17,10 +17,9 @@
homepage
wiki

Nix sites

-

-

homepage -
wiki -

+

+

homepage +
wiki

diff --git a/tests/modules/programs/firefox/profile-settings-expected-search.json b/tests/modules/programs/firefox/profile-settings-expected-search.json new file mode 100644 index 00000000..ceee27ee --- /dev/null +++ b/tests/modules/programs/firefox/profile-settings-expected-search.json @@ -0,0 +1,75 @@ +{ + "engines": [ + { + "_definedAliases": [ + "@np" + ], + "_iconURL": "file:///run/current-system/sw/share/icons/hicolor/scalable/apps/nix-snowflake.svg", + "_isAppProvided": false, + "_loadPath": "[home-manager]/programs.firefox.profiles.search.search.engines.\"Nix Packages\"", + "_metaData": { + "order": 1 + }, + "_name": "Nix Packages", + "_urls": [ + { + "params": [ + { + "name": "type", + "value": "packages" + }, + { + "name": "query", + "value": "{searchTerms}" + } + ], + "template": "https://search.nixos.org/packages" + } + ] + }, + { + "_definedAliases": [ + "@nw" + ], + "_iconURL": "https://nixos.wiki/favicon.png", + "_iconUpdateURL": "https://nixos.wiki/favicon.png", + "_isAppProvided": false, + "_loadPath": "[home-manager]/programs.firefox.profiles.search.search.engines.\"NixOS Wiki\"", + "_metaData": { + "order": 2 + }, + "_name": "NixOS Wiki", + "_updateInterval": 86400000, + "_urls": [ + { + "template": "https://nixos.wiki/index.php?search={searchTerms}" + } + ] + }, + { + "_isAppProvided": true, + "_metaData": { + "hidden": true + }, + "_name": "Bing" + }, + { + "_isAppProvided": true, + "_metaData": {}, + "_name": "DuckDuckGo" + }, + { + "_isAppProvided": true, + "_metaData": { + "alias": "@g" + }, + "_name": "Google" + } + ], + "metaData": { + "current": "DuckDuckGo", + "hash": "BWvqUiaCuMJ20lbymFf2dqzWyl1cgm1LZhhdWNEp0Cc=", + "useSavedOrder": true + }, + "version": 6 +} diff --git a/tests/modules/programs/firefox/profile-settings-expected-user.js b/tests/modules/programs/firefox/profile-settings-expected-user.js index 0edd47b9..d929df2b 100644 --- a/tests/modules/programs/firefox/profile-settings-expected-user.js +++ b/tests/modules/programs/firefox/profile-settings-expected-user.js @@ -1,5 +1,6 @@ // Generated by Home Manager. +user_pref("browser.newtabpage.pinned", "[{\"title\":\"NixOS\",\"url\":\"https://nixos.org\"}]"); user_pref("general.smoothScroll", false); diff --git a/tests/modules/programs/firefox/profile-settings.nix b/tests/modules/programs/firefox/profile-settings.nix index 23bf1285..278f3dbb 100644 --- a/tests/modules/programs/firefox/profile-settings.nix +++ b/tests/modules/programs/firefox/profile-settings.nix @@ -9,7 +9,13 @@ lib.mkIf config.test.enableBig { profiles.test = { id = 1; - settings = { "general.smoothScroll" = false; }; + settings = { + "general.smoothScroll" = false; + "browser.newtabpage.pinned" = [{ + title = "NixOS"; + url = "https://nixos.org"; + }]; + }; }; profiles.bookmarks = { @@ -60,6 +66,49 @@ lib.mkIf config.test.enableBig { } ]; }; + + profiles.search = { + id = 3; + search = { + force = true; + default = "DuckDuckGo"; + order = [ "Nix Packages" "NixOS Wiki" ]; + engines = { + "Nix Packages" = { + urls = [{ + template = "https://search.nixos.org/packages"; + params = [ + { + name = "type"; + value = "packages"; + } + { + name = "query"; + value = "{searchTerms}"; + } + ]; + }]; + + icon = + "/run/current-system/sw/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; + + definedAliases = [ "@np" ]; + }; + + "NixOS Wiki" = { + urls = [{ + template = "https://nixos.wiki/index.php?search={searchTerms}"; + }]; + iconUpdateURL = "https://nixos.wiki/favicon.png"; + updateInterval = 24 * 60 * 60 * 1000; + definedAliases = [ "@nw" ]; + }; + + "Bing".metaData.hidden = true; + "Google".metaData.alias = "@g"; + }; + }; + }; }; nixpkgs.overlays = [ @@ -101,5 +150,15 @@ lib.mkIf config.test.enableBig { assertFileContent \ $bookmarksFile \ ${./profile-settings-expected-bookmarks.html} + + compressedSearch=$(normalizeStorePaths \ + home-files/.mozilla/firefox/search/search.json.mozlz4) + + decompressedSearch=$(dirname $compressedSearch)/search.json + ${pkgs.mozlz4a}/bin/mozlz4a -d "$compressedSearch" >(${pkgs.jq}/bin/jq . > "$decompressedSearch") + + assertFileContent \ + $decompressedSearch \ + ${./profile-settings-expected-search.json} ''; } diff --git a/tests/modules/programs/fish/default.nix b/tests/modules/programs/fish/default.nix index 99fe8136..3ed5b9cf 100644 --- a/tests/modules/programs/fish/default.nix +++ b/tests/modules/programs/fish/default.nix @@ -1,4 +1,5 @@ { + fish-format-scripts = ./format-scripts.nix; fish-functions = ./functions.nix; fish-no-functions = ./no-functions.nix; fish-plugins = ./plugins.nix; diff --git a/tests/modules/programs/fish/format-scripts.nix b/tests/modules/programs/fish/format-scripts.nix new file mode 100644 index 00000000..2ba58cae --- /dev/null +++ b/tests/modules/programs/fish/format-scripts.nix @@ -0,0 +1,50 @@ +{ config, pkgs, ... }: + +let + + expectedFunc = pkgs.writeText "func.fish" '' + function func + echo foo + end + ''; + + expectedFuncMulti = pkgs.writeText "func-multi.fish" '' + function func-multi + echo bar + if foo + bar + baz + end + end + ''; + +in { + config = { + programs.fish = { + enable = true; + + formatFishScripts = true; + + functions = { + func = ''echo "foo"''; + func-multi = '' + echo bar + if foo + bar + baz + end + ''; + }; + }; + + nmt.script = '' + assertFileExists home-files/.config/fish/functions/func.fish + echo ${expectedFunc} + assertFileContent home-files/.config/fish/functions/func.fish ${expectedFunc} + + assertFileExists home-files/.config/fish/functions/func-multi.fish + echo ${expectedFuncMulti} + assertFileContent home-files/.config/fish/functions/func-multi.fish ${expectedFuncMulti} + ''; + }; +} diff --git a/tests/modules/programs/fish/functions.nix b/tests/modules/programs/fish/functions.nix index 67f8ba0d..b8b5793a 100644 --- a/tests/modules/programs/fish/functions.nix +++ b/tests/modules/programs/fish/functions.nix @@ -6,13 +6,13 @@ let func = pkgs.writeText "func.fish" '' function func - echo "Hello" + echo Hello end ''; funcEvent = pkgs.writeText "func-event.fish" '' function func-event --on-event="fish_command_not_found" - echo "Not found!" + echo "Not found!" end ''; @@ -34,8 +34,6 @@ in { xdg.dataFile."fish/home-manager_generated_completions".source = lib.mkForce (builtins.toFile "empty" ""); - test.stubs.fish = { }; - nmt = { description = "if fish.function is set, check file exists and contents match"; diff --git a/tests/modules/programs/fish/no-functions.nix b/tests/modules/programs/fish/no-functions.nix index 0ab38a09..125ed884 100644 --- a/tests/modules/programs/fish/no-functions.nix +++ b/tests/modules/programs/fish/no-functions.nix @@ -14,8 +14,6 @@ with lib; xdg.dataFile."fish/home-manager_generated_completions".source = lib.mkForce (builtins.toFile "empty" ""); - test.stubs.fish = { }; - nmt = { description = "if fish.functions is blank, the functions folder should not exist."; diff --git a/tests/modules/programs/fish/plugins.nix b/tests/modules/programs/fish/plugins.nix index 6b02dd46..88684b3b 100644 --- a/tests/modules/programs/fish/plugins.nix +++ b/tests/modules/programs/fish/plugins.nix @@ -12,26 +12,26 @@ let # Set paths to import plugin components if test -d $plugin_dir/functions - set fish_function_path $fish_function_path[1] $plugin_dir/functions $fish_function_path[2..-1] + set fish_function_path $fish_function_path[1] $plugin_dir/functions $fish_function_path[2..-1] end if test -d $plugin_dir/completions - set fish_complete_path $fish_complete_path[1] $plugin_dir/completions $fish_complete_path[2..-1] + set fish_complete_path $fish_complete_path[1] $plugin_dir/completions $fish_complete_path[2..-1] end # Source initialization code if it exists. if test -d $plugin_dir/conf.d - for f in $plugin_dir/conf.d/*.fish - source $f - end + for f in $plugin_dir/conf.d/*.fish + source $f + end end if test -f $plugin_dir/key_bindings.fish - source $plugin_dir/key_bindings.fish + source $plugin_dir/key_bindings.fish end if test -f $plugin_dir/init.fish - source $plugin_dir/init.fish + source $plugin_dir/init.fish end ''; @@ -50,8 +50,6 @@ in { xdg.dataFile."fish/home-manager_generated_completions".source = lib.mkForce (builtins.toFile "empty" ""); - test.stubs.fish = { }; - nmt = { description = "if fish.plugins set, check conf.d file exists and contents match"; diff --git a/tests/modules/programs/gpg/immutable-keyfiles.nix b/tests/modules/programs/gpg/immutable-keyfiles.nix index b66d770f..55a38ecc 100644 --- a/tests/modules/programs/gpg/immutable-keyfiles.nix +++ b/tests/modules/programs/gpg/immutable-keyfiles.nix @@ -12,7 +12,7 @@ source = pkgs.fetchurl { url = "https://keybase.io/rycee/pgp_keys.asc?fingerprint=36cacf52d098cc0e78fb0cb13573356c25c424d4"; - sha256 = "082mjy6llvrdry6i9r5gx97nw9d89blnam7bghza4ynsjk1mmx6c"; + hash = "sha256-5z2kTUXQp0f7kyP0Id6NS3rCdzGGrrkIYzGK42Qy9Sw="; }; trust = 1; # "unknown" } diff --git a/tests/modules/programs/hexchat/basic-configuration-expected-serverlist-config b/tests/modules/programs/hexchat/basic-configuration-expected-serverlist-config index 29d23284..e550ca48 100644 --- a/tests/modules/programs/hexchat/basic-configuration-expected-serverlist-config +++ b/tests/modules/programs/hexchat/basic-configuration-expected-serverlist-config @@ -8,7 +8,7 @@ S=irc.mzima.net S=irc.prison.net J=#computers -N=freenode +N=oftc L=6 E=UTF-8 (Unicode) F=12 @@ -17,8 +17,6 @@ i=user_ R=real_user U=user P=password -S=chat.freenode.net -S=irc.freenode.net +S=irc.oftc.net J=#home-manager -J=#nixos diff --git a/tests/modules/programs/hexchat/basic-configuration.nix b/tests/modules/programs/hexchat/basic-configuration.nix index 1aa39bd4..6371a0e0 100644 --- a/tests/modules/programs/hexchat/basic-configuration.nix +++ b/tests/modules/programs/hexchat/basic-configuration.nix @@ -6,7 +6,7 @@ enable = true; overwriteConfigFiles = true; channels = { - freenode = { + oftc = { charset = "UTF-8 (Unicode)"; userName = "user"; password = "password"; @@ -18,8 +18,8 @@ autoconnect = true; forceSSL = true; }; - servers = [ "chat.freenode.net" "irc.freenode.net" ]; - autojoin = [ "#home-manager" "#nixos" ]; + servers = [ "irc.oftc.net" ]; + autojoin = [ "#home-manager" ]; }; efnet = { options = { forceSSL = true; }; diff --git a/tests/modules/programs/himalaya/himalaya-expected.toml b/tests/modules/programs/himalaya/himalaya-expected.toml index 6c2dfb84..ca7ada66 100644 --- a/tests/modules/programs/himalaya/himalaya-expected.toml +++ b/tests/modules/programs/himalaya/himalaya-expected.toml @@ -1,16 +1,18 @@ +display-name = "" downloads-dir = "/data/download" -name = "" ["hm@example.com"] +backend = "imap" default = true -default-page-size = 50 +display-name = "H. M. Test" email = "hm@example.com" +email-listing-page-size = 50 imap-host = "imap.example.com" imap-login = "home.manager" imap-passwd-cmd = "'password-command'" imap-port = 995 imap-starttls = false -name = "H. M. Test" +sender = "smtp" smtp-host = "smtp.example.com" smtp-login = "home.manager" smtp-passwd-cmd = "'password-command'" diff --git a/tests/modules/programs/himalaya/himalaya.nix b/tests/modules/programs/himalaya/himalaya.nix index 13872d15..4d556ff8 100644 --- a/tests/modules/programs/himalaya/himalaya.nix +++ b/tests/modules/programs/himalaya/himalaya.nix @@ -10,7 +10,9 @@ with lib; himalaya = { enable = true; - settings = { default-page-size = 50; }; + backend = "imap"; + sender = "smtp"; + settings = { email-listing-page-size = 50; }; }; folders = { @@ -38,4 +40,3 @@ with lib; } ''; } - diff --git a/tests/modules/programs/i3status-rust/with-custom.nix b/tests/modules/programs/i3status-rust/with-custom.nix index d89e2ddc..c4131e02 100644 --- a/tests/modules/programs/i3status-rust/with-custom.nix +++ b/tests/modules/programs/i3status-rust/with-custom.nix @@ -102,14 +102,14 @@ with lib; icons = "awesome5" theme = "gruvbox-dark" [[block]] - alert = 10 + alert = 10.0 alias = "/" block = "disk_space" info_type = "available" interval = 60 path = "/" unit = "GB" - warning = 20 + warning = 20.0 [[block]] block = "memory" diff --git a/tests/modules/programs/i3status-rust/with-default.nix b/tests/modules/programs/i3status-rust/with-default.nix index 3da74ac0..b5c20cee 100644 --- a/tests/modules/programs/i3status-rust/with-default.nix +++ b/tests/modules/programs/i3status-rust/with-default.nix @@ -16,14 +16,14 @@ with lib; icons = "none" theme = "plain" [[block]] - alert = 10 + alert = 10.0 alias = "/" block = "disk_space" info_type = "available" interval = 60 path = "/" unit = "GB" - warning = 20 + warning = 20.0 [[block]] block = "memory" diff --git a/tests/modules/programs/i3status-rust/with-extra-settings.nix b/tests/modules/programs/i3status-rust/with-extra-settings.nix index 63458662..aad7618e 100644 --- a/tests/modules/programs/i3status-rust/with-extra-settings.nix +++ b/tests/modules/programs/i3status-rust/with-extra-settings.nix @@ -111,14 +111,14 @@ with lib; pkgs.writeText "i3status-rust-expected-config" '' icons = "awesome5" [[block]] - alert = 10 + alert = 10.0 alias = "/" block = "disk_space" info_type = "available" interval = 60 path = "/" unit = "GB" - warning = 20 + warning = 20.0 [[block]] block = "memory" diff --git a/tests/modules/programs/i3status-rust/with-multiple-bars.nix b/tests/modules/programs/i3status-rust/with-multiple-bars.nix index eab7f42d..a8ffd373 100644 --- a/tests/modules/programs/i3status-rust/with-multiple-bars.nix +++ b/tests/modules/programs/i3status-rust/with-multiple-bars.nix @@ -62,14 +62,14 @@ with lib; icons = "none" theme = "plain" [[block]] - alert = 10 + alert = 10.0 alias = "/" block = "disk_space" info_type = "available" interval = 60 path = "/" unit = "GB" - warning = 20 + warning = 20.0 [[block]] block = "memory" diff --git a/tests/modules/programs/i3status/with-custom.nix b/tests/modules/programs/i3status/with-custom.nix index 830bc6c9..8b673b8a 100644 --- a/tests/modules/programs/i3status/with-custom.nix +++ b/tests/modules/programs/i3status/with-custom.nix @@ -16,6 +16,8 @@ with lib; interval = 1; }; + package = config.lib.test.mkStubPackage { }; + modules = { "volume master" = { position = 1; diff --git a/tests/modules/programs/irssi/example-settings-expected.config b/tests/modules/programs/irssi/example-settings-expected.config index 8c54243b..6857eccf 100644 --- a/tests/modules/programs/irssi/example-settings-expected.config +++ b/tests/modules/programs/irssi/example-settings-expected.config @@ -13,6 +13,8 @@ oftc = { type = "IRC"; nick = "nick"; autosendcmd = ""; + sasl_username = "nick"; + sasl_mechanism = "EXTERNAL"; }; }; diff --git a/tests/modules/programs/irssi/example-settings.nix b/tests/modules/programs/irssi/example-settings.nix index 93cf9f2d..f279b03c 100644 --- a/tests/modules/programs/irssi/example-settings.nix +++ b/tests/modules/programs/irssi/example-settings.nix @@ -8,6 +8,7 @@ with lib; enable = true; networks.oftc = { nick = "nick"; + saslExternal = true; server = { address = "irc.oftc.net"; port = 6697; diff --git a/tests/modules/programs/k9s/default.nix b/tests/modules/programs/k9s/default.nix new file mode 100644 index 00000000..58d9f32f --- /dev/null +++ b/tests/modules/programs/k9s/default.nix @@ -0,0 +1,4 @@ +{ + k9s-example-settings = ./example-settings.nix; + k9s-empty-settings = ./empty-settings.nix; +} diff --git a/tests/modules/programs/k9s/empty-settings.nix b/tests/modules/programs/k9s/empty-settings.nix new file mode 100644 index 00000000..5084be4f --- /dev/null +++ b/tests/modules/programs/k9s/empty-settings.nix @@ -0,0 +1,11 @@ +{ ... }: + +{ + programs.k9s.enable = true; + + test.stubs.k9s = { }; + + nmt.script = '' + assertPathNotExists home-files/.config/k9s + ''; +} diff --git a/tests/modules/programs/k9s/example-config-expected.yml b/tests/modules/programs/k9s/example-config-expected.yml new file mode 100644 index 00000000..019ee7a7 --- /dev/null +++ b/tests/modules/programs/k9s/example-config-expected.yml @@ -0,0 +1,5 @@ +k9s: + enableMouse: true + headless: false + maxConnRetry: 5 + refreshRate: 2 diff --git a/tests/modules/programs/k9s/example-settings.nix b/tests/modules/programs/k9s/example-settings.nix new file mode 100644 index 00000000..ffe52144 --- /dev/null +++ b/tests/modules/programs/k9s/example-settings.nix @@ -0,0 +1,42 @@ +{ config, ... }: + +{ + programs.k9s = { + enable = true; + package = config.lib.test.mkStubPackage { }; + + settings = { + k9s = { + refreshRate = 2; + maxConnRetry = 5; + enableMouse = true; + headless = false; + }; + }; + + skin = { + k9s = { + body = { + fgColor = "dodgerblue"; + bgColor = "#ffffff"; + logoColor = "#0000ff"; + }; + info = { + fgColor = "lightskyblue"; + sectionColor = "steelblue"; + }; + }; + }; + }; + + nmt.script = '' + assertFileExists home-files/.config/k9s/config.yml + assertFileContent \ + home-files/.config/k9s/config.yml \ + ${./example-config-expected.yml} + assertFileExists home-files/.config/k9s/skin.yml + assertFileContent \ + home-files/.config/k9s/skin.yml \ + ${./example-skin-expected.yml} + ''; +} diff --git a/tests/modules/programs/k9s/example-skin-expected.yml b/tests/modules/programs/k9s/example-skin-expected.yml new file mode 100644 index 00000000..94f7e6eb --- /dev/null +++ b/tests/modules/programs/k9s/example-skin-expected.yml @@ -0,0 +1,8 @@ +k9s: + body: + bgColor: '#ffffff' + fgColor: dodgerblue + logoColor: '#0000ff' + info: + fgColor: lightskyblue + sectionColor: steelblue diff --git a/tests/modules/programs/looking-glass-client/default.nix b/tests/modules/programs/looking-glass-client/default.nix new file mode 100644 index 00000000..fdbbb25a --- /dev/null +++ b/tests/modules/programs/looking-glass-client/default.nix @@ -0,0 +1,4 @@ +{ + looking-glass-client-example-settings = ./example-settings.nix; + looking-glass-client-empty-settings = ./empty-settings.nix; +} diff --git a/tests/modules/programs/looking-glass-client/empty-settings.nix b/tests/modules/programs/looking-glass-client/empty-settings.nix new file mode 100644 index 00000000..10c177a9 --- /dev/null +++ b/tests/modules/programs/looking-glass-client/empty-settings.nix @@ -0,0 +1,16 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.looking-glass-client = { + enable = true; + package = config.lib.test.mkStubPackage { }; + }; + + nmt.script = '' + assertPathNotExists home-files/.config/looking-glass/client.ini + ''; + }; +} diff --git a/tests/modules/programs/looking-glass-client/example-config.ini b/tests/modules/programs/looking-glass-client/example-config.ini new file mode 100644 index 00000000..db006d3f --- /dev/null +++ b/tests/modules/programs/looking-glass-client/example-config.ini @@ -0,0 +1,16 @@ +[app] +allowDMA=true +shmFile=/dev/kvmfr0 + +[input] +escapeKey=62 +rawMouse=true + +[spice] +audio=true +enable=true + +[win] +fullScreen=true +jitRender=true +showFPS=false diff --git a/tests/modules/programs/looking-glass-client/example-settings.nix b/tests/modules/programs/looking-glass-client/example-settings.nix new file mode 100644 index 00000000..6ac8f018 --- /dev/null +++ b/tests/modules/programs/looking-glass-client/example-settings.nix @@ -0,0 +1,41 @@ +{ config, lib, ... }: + +with lib; + +{ + config = { + programs.looking-glass-client = { + enable = true; + package = config.lib.test.mkStubPackage { }; + + settings = { + app = { + allowDMA = true; + shmFile = "/dev/kvmfr0"; + }; + + win = { + fullScreen = true; + showFPS = false; + jitRender = true; + }; + + spice = { + enable = true; + audio = true; + }; + + input = { + rawMouse = true; + escapeKey = 62; + }; + }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.config/looking-glass/client.ini \ + ${./example-config.ini} + ''; + }; +} diff --git a/tests/modules/programs/mbsync/mbsync-expected.conf b/tests/modules/programs/mbsync/mbsync-expected.conf index c1ca921a..b6c77ea1 100644 --- a/tests/modules/programs/mbsync/mbsync-expected.conf +++ b/tests/modules/programs/mbsync/mbsync-expected.conf @@ -3,7 +3,7 @@ IMAPAccount hm-account CertificateFile /etc/ssl/certs/ca-certificates.crt Host imap.example.org -PassCmd "password-command 2" +PassCmd "'password-command' '2'" SSLType IMAPS User home.manager.jr @@ -55,8 +55,9 @@ Channel hm-account-strangeHostBoxName IMAPAccount hm@example.com CertificateFile /etc/ssl/certs/ca-certificates.crt Host imap.example.com -PassCmd password-command +PassCmd 'password-command' SSLType IMAPS +SSLVersions TLSv1.3 TLSv1.2 User home.manager IMAPStore hm@example.com-remote diff --git a/tests/modules/programs/mbsync/mbsync-master-slave-change.nix b/tests/modules/programs/mbsync/mbsync-master-slave-change.nix index 2e877320..c6861374 100644 --- a/tests/modules/programs/mbsync/mbsync-master-slave-change.nix +++ b/tests/modules/programs/mbsync/mbsync-master-slave-change.nix @@ -16,7 +16,7 @@ with lib; # programs.mbsync.groups and # accounts.email.accounts..mbsync.groups should NOT be used at the # same time. - # If they are, then the new version will take precendence. + # If they are, then the new version will take precedence. groups.inboxes = { "hm@example.com" = [ "Inbox1" "Inbox2" ]; hm-account = [ "Inbox" ]; diff --git a/tests/modules/programs/mbsync/mbsync.nix b/tests/modules/programs/mbsync/mbsync.nix index 7042760a..ffc1635e 100644 --- a/tests/modules/programs/mbsync/mbsync.nix +++ b/tests/modules/programs/mbsync/mbsync.nix @@ -11,7 +11,7 @@ with lib; # programs.mbsync.groups and # accounts.email.accounts..mbsync.groups should NOT be used at the # same time. - # If they are, then the new version will take precendence. + # If they are, then the new version will take precedence. groups.inboxes = { "hm@example.com" = [ "Inbox1" "Inbox2" ]; hm-account = [ "Inbox" ]; @@ -21,6 +21,7 @@ with lib; accounts.email.accounts = { "hm@example.com".mbsync = { enable = true; + extraConfig.account.SSLVersions = [ "TLSv1.3" "TLSv1.2" ]; groups.inboxes = { channels = { inbox1 = { diff --git a/tests/modules/programs/mu/basic-configuration.nix b/tests/modules/programs/mu/basic-configuration.nix index 1e1deeea..4b315c2e 100644 --- a/tests/modules/programs/mu/basic-configuration.nix +++ b/tests/modules/programs/mu/basic-configuration.nix @@ -19,6 +19,6 @@ 'if [[ ! -d "/home/hm-user/.cache/mu" ]]; then' assertFileContains activate \ - '$DRY_RUN_CMD mu init --maildir=/home/hm-user/Mail --my-address=hm@example.com --my-address=foo@example.com $VERBOSE_ARG;' + '$DRY_RUN_CMD @mu@/bin/mu init --maildir=/home/hm-user/Mail --my-address=hm@example.com --my-address=foo@example.com $VERBOSE_ARG;' ''; } diff --git a/tests/modules/programs/ncmpcpp-linux/default.nix b/tests/modules/programs/ncmpcpp-linux/default.nix index b1185c85..41933927 100644 --- a/tests/modules/programs/ncmpcpp-linux/default.nix +++ b/tests/modules/programs/ncmpcpp-linux/default.nix @@ -1 +1,4 @@ -{ ncmpcpp-use-mpd-config = ./ncmpcpp-use-mpd-config.nix; } +{ + ncmpcpp-use-mpd-config = ./ncmpcpp-use-mpd-config.nix; + ncmpcpp-issue-3560 = ./ncmpcpp-issue-3560.nix; +} diff --git a/tests/modules/programs/ncmpcpp-linux/ncmpcpp-issue-3560-expected-config b/tests/modules/programs/ncmpcpp-linux/ncmpcpp-issue-3560-expected-config new file mode 100644 index 00000000..24a2f3bc --- /dev/null +++ b/tests/modules/programs/ncmpcpp-linux/ncmpcpp-issue-3560-expected-config @@ -0,0 +1 @@ +mpd_music_dir=~/music diff --git a/tests/modules/programs/ncmpcpp-linux/ncmpcpp-issue-3560.nix b/tests/modules/programs/ncmpcpp-linux/ncmpcpp-issue-3560.nix new file mode 100644 index 00000000..ba1607ab --- /dev/null +++ b/tests/modules/programs/ncmpcpp-linux/ncmpcpp-issue-3560.nix @@ -0,0 +1,25 @@ +{ pkgs, ... }: + +{ + config = { + # Minimal config reproducing + # https://github.com/nix-community/home-manager/issues/3560 + programs.ncmpcpp.enable = true; + + services.mpd.enable = true; + services.mpd.musicDirectory = "~/music"; + + test.stubs = { + ncmpcpp = { }; + mpd = { }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.config/ncmpcpp/config \ + ${./ncmpcpp-issue-3560-expected-config} + + assertPathNotExists home-files/.config/ncmpcpp/bindings + ''; + }; +} diff --git a/tests/modules/programs/neovim/default.nix b/tests/modules/programs/neovim/default.nix index 3950dc8b..d3224666 100644 --- a/tests/modules/programs/neovim/default.nix +++ b/tests/modules/programs/neovim/default.nix @@ -5,4 +5,5 @@ # waiting for a nixpkgs patch neovim-no-init = ./no-init.nix; + neovim-extra-lua-init = ./extra-lua-init.nix; } diff --git a/tests/modules/programs/neovim/extra-lua-init.nix b/tests/modules/programs/neovim/extra-lua-init.nix new file mode 100644 index 00000000..2abaa6e9 --- /dev/null +++ b/tests/modules/programs/neovim/extra-lua-init.nix @@ -0,0 +1,23 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.neovim = { + enable = true; + + extraLuaConfig = '' + -- extraLuaConfig + ''; + }; + nmt.script = '' + nvimFolder="home-files/.config/nvim" + assertFileContent "$nvimFolder/init.lua" ${ + pkgs.writeText "init.lua-expected" '' + -- extraLuaConfig + '' + } + ''; + }; +} diff --git a/tests/modules/programs/neovim/no-init.nix b/tests/modules/programs/neovim/no-init.nix index 3ec9b067..693bdede 100644 --- a/tests/modules/programs/neovim/no-init.nix +++ b/tests/modules/programs/neovim/no-init.nix @@ -12,10 +12,17 @@ with lib; withRuby = false; extraPython3Packages = (ps: with ps; [ jedi pynvim ]); + + # plugins without associated config should not trigger the creation of init.vim + plugins = with pkgs.vimPlugins; [ + vim-fugitive + ({ plugin = vim-sensible; }) + ]; }; nmt.script = '' - vimrc="home-files/.config/nvim/init.vim" - assertPathNotExists "$vimrc" + nvimFolder="home-files/.config/nvim" + assertPathNotExists "$nvimFolder/init.vim" + assertPathNotExists "$nvimFolder/init.lua" ''; }; } diff --git a/tests/modules/programs/neovim/plugin-config.nix b/tests/modules/programs/neovim/plugin-config.nix index 9647fb5a..e4921aae 100644 --- a/tests/modules/programs/neovim/plugin-config.nix +++ b/tests/modules/programs/neovim/plugin-config.nix @@ -7,16 +7,14 @@ with lib; programs.neovim = { enable = true; extraConfig = '' - " This 'extraConfig' should be present in vimrc + let g:hmExtraConfig='HM_EXTRA_CONFIG' ''; plugins = with pkgs.vimPlugins; [ vim-nix { plugin = vim-commentary; config = '' - " plugin-specific config - autocmd FileType c setlocal commentstring=//\ %s - autocmd FileType c setlocal comments=:// + let g:hmPlugins='HM_PLUGINS_CONFIG' ''; } ]; @@ -24,11 +22,12 @@ with lib; }; nmt.script = '' - vimrc="$TESTED/home-files/.config/nvim/init.vim" - vimrcNormalized="$(normalizeStorePaths "$vimrc")" - - assertFileExists "$vimrc" - assertFileContent "$vimrcNormalized" "${./plugin-config.vim}" + vimout=$(mktemp) + echo "redir >> /dev/stdout | echo g:hmExtraConfig | echo g:hmPlugins | redir END" \ + | ${pkgs.neovim}/bin/nvim -es -u "$TESTED/home-files/.config/nvim/init.lua" \ + > "$vimout" + assertFileContains "$vimout" "HM_EXTRA_CONFIG" + assertFileContains "$vimout" "HM_PLUGINS_CONFIG" ''; }; } diff --git a/tests/modules/programs/neovim/plugin-config.vim b/tests/modules/programs/neovim/plugin-config.vim deleted file mode 100644 index 8b5f3546..00000000 --- a/tests/modules/programs/neovim/plugin-config.vim +++ /dev/null @@ -1,6 +0,0 @@ - -" plugin-specific config -autocmd FileType c setlocal commentstring=//\ %s -autocmd FileType c setlocal comments=:// - -" This 'extraConfig' should be present in vimrc diff --git a/tests/modules/programs/neovim/runtime.nix b/tests/modules/programs/neovim/runtime.nix index 839b2790..b9d9638a 100644 --- a/tests/modules/programs/neovim/runtime.nix +++ b/tests/modules/programs/neovim/runtime.nix @@ -4,28 +4,36 @@ with lib; { config = { - programs.neovim = { - enable = true; - plugins = with pkgs.vimPlugins; [ - vim-nix - { - plugin = vim-commentary; - runtime = { - "after/ftplugin/c.vim".text = '' - " plugin-specific config - setlocal commentstring=//\ %s - setlocal comments=:// - ''; - }; - } - ]; + programs.neovim = lib.mkMerge [ + { + enable = true; + plugins = with pkgs.vimPlugins; [ + vim-nix + { + plugin = vim-commentary; + runtime = { + "after/ftplugin/c.vim".text = '' + " plugin-specific config + setlocal commentstring=//\ %s + setlocal comments=:// + ''; + }; + } + ]; + } + { + extraPython3Packages = ps: with ps; [ jedi pynvim ]; + extraLuaPackages = ps: with ps; [ luacheck ]; + } + { + extraPython3Packages = with pkgs.python3Packages; [ jedi pynvim ]; + extraLuaPackages = with pkgs.lua51Packages; [ luacheck ]; + } + ]; - extraPython3Packages = (ps: with ps; [ jedi pynvim ]); - }; nmt.script = '' ftplugin="home-files/.config/nvim/after/ftplugin/c.vim" assertFileExists "$ftplugin" ''; }; } - diff --git a/tests/modules/programs/nix-index/assert-on-command-not-found.nix b/tests/modules/programs/nix-index/assert-on-command-not-found.nix index 0fa6ee79..94d7efc3 100644 --- a/tests/modules/programs/nix-index/assert-on-command-not-found.nix +++ b/tests/modules/programs/nix-index/assert-on-command-not-found.nix @@ -12,10 +12,7 @@ xdg.dataFile."fish/home-manager_generated_completions".source = lib.mkForce (builtins.toFile "empty" ""); - test.stubs = { - zsh = { }; - fish = { }; - }; + test.stubs.zsh = { }; programs.nix-index.enable = true; diff --git a/tests/modules/programs/nix-index/integrations.nix b/tests/modules/programs/nix-index/integrations.nix index 1ae46df5..2fd5253a 100644 --- a/tests/modules/programs/nix-index/integrations.nix +++ b/tests/modules/programs/nix-index/integrations.nix @@ -16,10 +16,7 @@ in { xdg.dataFile."fish/home-manager_generated_completions".source = lib.mkForce (builtins.toFile "empty" ""); - test.stubs = { - zsh = { }; - fish = { }; - }; + test.stubs.zsh = { }; programs.nix-index.enable = true; diff --git a/tests/modules/programs/nushell/config-expected.nu b/tests/modules/programs/nushell/config-expected.nu index 7fa80723..c70286d7 100644 --- a/tests/modules/programs/nushell/config-expected.nu +++ b/tests/modules/programs/nushell/config-expected.nu @@ -3,3 +3,4 @@ let $config = { table_mode: rounded use_ls_colors: true } + diff --git a/tests/modules/programs/nushell/env-expected.nu b/tests/modules/programs/nushell/env-expected.nu index 5a820ca8..280b59bf 100644 --- a/tests/modules/programs/nushell/env-expected.nu +++ b/tests/modules/programs/nushell/env-expected.nu @@ -1 +1,2 @@ let-env FOO = 'BAR' + diff --git a/tests/modules/programs/nushell/example-settings.nix b/tests/modules/programs/nushell/example-settings.nix index d1eca320..21d94a70 100644 --- a/tests/modules/programs/nushell/example-settings.nix +++ b/tests/modules/programs/nushell/example-settings.nix @@ -1,4 +1,4 @@ -{ ... }: +{ pkgs, ... }: { programs.nushell = { @@ -19,12 +19,17 @@ test.stubs.nushell = { }; - nmt.script = '' + nmt.script = let + configDir = if pkgs.stdenv.isDarwin then + "home-files/Library/Application Support/nushell" + else + "home-files/.config/nushell"; + in '' assertFileContent \ - home-files/.config/nushell/config.nu \ + "${configDir}/config.nu" \ ${./config-expected.nu} assertFileContent \ - home-files/.config/nushell/env.nu \ + "${configDir}/env.nu" \ ${./env-expected.nu} ''; } diff --git a/tests/modules/programs/oh-my-posh/bash.nix b/tests/modules/programs/oh-my-posh/bash.nix new file mode 100644 index 00000000..2e3d93ac --- /dev/null +++ b/tests/modules/programs/oh-my-posh/bash.nix @@ -0,0 +1,21 @@ +{ ... }: + +{ + programs = { + bash.enable = true; + + oh-my-posh = { + enable = true; + useTheme = "jandedobbeleer"; + }; + }; + + test.stubs.oh-my-posh = { }; + + nmt.script = '' + assertFileExists home-files/.bashrc + assertFileContains \ + home-files/.bashrc \ + '/bin/oh-my-posh init bash --config' + ''; +} diff --git a/tests/modules/programs/oh-my-posh/default.nix b/tests/modules/programs/oh-my-posh/default.nix new file mode 100644 index 00000000..65526256 --- /dev/null +++ b/tests/modules/programs/oh-my-posh/default.nix @@ -0,0 +1,5 @@ +{ + oh-my-posh-bash = ./bash.nix; + oh-my-posh-zsh = ./zsh.nix; + oh-my-posh-fish = ./fish.nix; +} diff --git a/tests/modules/programs/oh-my-posh/fish.nix b/tests/modules/programs/oh-my-posh/fish.nix new file mode 100644 index 00000000..07137b98 --- /dev/null +++ b/tests/modules/programs/oh-my-posh/fish.nix @@ -0,0 +1,25 @@ +{ lib, ... }: + +{ + programs = { + fish.enable = true; + + oh-my-posh = { + enable = true; + useTheme = "jandedobbeleer"; + }; + }; + + # Needed to avoid error with dummy fish package. + xdg.dataFile."fish/home-manager_generated_completions".source = + lib.mkForce (builtins.toFile "empty" ""); + + test.stubs.oh-my-posh = { }; + + nmt.script = '' + assertFileExists home-files/.config/fish/config.fish + assertFileContains \ + home-files/.config/fish/config.fish \ + '/bin/oh-my-posh init fish --config' + ''; +} diff --git a/tests/modules/programs/oh-my-posh/zsh.nix b/tests/modules/programs/oh-my-posh/zsh.nix new file mode 100644 index 00000000..6d2a5bed --- /dev/null +++ b/tests/modules/programs/oh-my-posh/zsh.nix @@ -0,0 +1,24 @@ +{ ... }: + +{ + programs = { + zsh.enable = true; + + oh-my-posh = { + enable = true; + useTheme = "jandedobbeleer"; + }; + }; + + test.stubs = { + oh-my-posh = { }; + zsh = { }; + }; + + nmt.script = '' + assertFileExists home-files/.zshrc + assertFileContains \ + home-files/.zshrc \ + '/bin/oh-my-posh init zsh --config' + ''; +} diff --git a/tests/modules/programs/papis/default.nix b/tests/modules/programs/papis/default.nix new file mode 100644 index 00000000..a849be85 --- /dev/null +++ b/tests/modules/programs/papis/default.nix @@ -0,0 +1 @@ +{ papis = ./papis.nix; } diff --git a/tests/modules/programs/papis/papis.nix b/tests/modules/programs/papis/papis.nix new file mode 100644 index 00000000..507056be --- /dev/null +++ b/tests/modules/programs/papis/papis.nix @@ -0,0 +1,46 @@ +{ ... }: + +{ + programs.papis = { + enable = true; + settings = { + picktool = "fzf"; + file-browser = "ranger"; + add-edit = true; + }; + libraries = { + papers = { + isDefault = true; + settings = { + dir = "~/papers"; + opentool = "okular"; + }; + }; + books.settings = { + dir = "~/books"; + opentool = "firefox"; + }; + }; + }; + + test.stubs.papis = { }; + + nmt.script = '' + assertFileContent home-files/.config/papis/config \ + ${builtins.toFile "papis-expected-settings.ini" '' + [books] + dir=~/books + opentool=firefox + + [papers] + dir=~/papers + opentool=okular + + [settings] + add-edit=true + default-library=papers + file-browser=ranger + picktool=fzf + ''} + ''; +} diff --git a/tests/modules/programs/pistol/associations.nix b/tests/modules/programs/pistol/associations.nix new file mode 100644 index 00000000..764060ba --- /dev/null +++ b/tests/modules/programs/pistol/associations.nix @@ -0,0 +1,38 @@ +{ pkgs, ... }: + +{ + programs.pistol = { + enable = true; + associations = [ + { + mime = "application/json"; + command = "bat %pistol-filename%"; + } + { + mime = "application/*"; + command = "hexyl %pistol-filename%"; + } + { + fpath = ".*.md$"; + command = + "sh: bat --paging=never --color=always %pistol-filename% | head -8"; + } + ]; + }; + + test.stubs.pistol = { }; + + nmt.script = let + expected = builtins.toFile "config-expected" '' + application/json bat %pistol-filename% + application/* hexyl %pistol-filename% + fpath .*.md$ sh: bat --paging=never --color=always %pistol-filename% | head -8''; + path = if pkgs.stdenv.hostPlatform.isDarwin then + "home-files/Library/Application Support/pistol/pistol.conf" + else + "home-files/.config/pistol/pistol.conf"; + in '' + assertFileExists '${path}' + assertFileContent '${path}' '${expected}' + ''; +} diff --git a/tests/modules/programs/pistol/config.nix b/tests/modules/programs/pistol/config.nix index 324304d3..1999befa 100644 --- a/tests/modules/programs/pistol/config.nix +++ b/tests/modules/programs/pistol/config.nix @@ -1,12 +1,4 @@ -{ pkgs, ... }: - -let - - expected = builtins.toFile "settings-expected" '' - application/json bat --paging=never --color=always --style=auto --wrap=character --terminal-width=%pistol-extra0% --line-range=1:%pistol-extra1% %pistol-filename% - text/* bat --paging=never --color=always --style=auto --wrap=character --terminal-width=%pistol-extra0% --line-range=1:%pistol-extra1% %pistol-filename%''; - -in { +{ programs.pistol = { enable = true; config = { @@ -19,13 +11,11 @@ in { test.stubs.pistol = { }; - nmt.script = let - path = if pkgs.stdenv.hostPlatform.isDarwin then - "home-files/Library/Application Support/pistol/pistol.conf" - else - "home-files/.config/pistol/pistol.conf"; - in '' - assertFileExists '${path}' - assertFileContent '${path}' '${expected}' - ''; + test.asserts.assertions.expected = [ + (let offendingFile = toString ./config.nix; + in '' + The option definition `programs.pistol.config' in `${offendingFile}' no longer has any effect; please remove it. + Pistol is now configured with programs.pistol.associations. + '') + ]; } diff --git a/tests/modules/programs/pistol/default.nix b/tests/modules/programs/pistol/default.nix index ac147c37..1efcbc6a 100644 --- a/tests/modules/programs/pistol/default.nix +++ b/tests/modules/programs/pistol/default.nix @@ -1 +1,6 @@ -{ pistol-config = ./config.nix; } +{ + pistol-associations = ./associations.nix; + pistol-config = ./config.nix; + pistol-double-association = ./double-association.nix; + pistol-missing-association = ./missing-association.nix; +} diff --git a/tests/modules/programs/pistol/double-association.nix b/tests/modules/programs/pistol/double-association.nix new file mode 100644 index 00000000..103f4d05 --- /dev/null +++ b/tests/modules/programs/pistol/double-association.nix @@ -0,0 +1,18 @@ +{ + programs.pistol = { + enable = true; + # contains both fpath and mime + associations = [{ + fpath = ".*.md$"; + mime = "application/json"; + command = "bat %pistol-filename%"; + }]; + }; + + test.stubs.pistol = { }; + + test.asserts.assertions.expected = ['' + Each entry in programs.pistol.associations must contain exactly one + of fpath or mime. + '']; +} diff --git a/tests/modules/programs/pistol/missing-association.nix b/tests/modules/programs/pistol/missing-association.nix new file mode 100644 index 00000000..6ea0a448 --- /dev/null +++ b/tests/modules/programs/pistol/missing-association.nix @@ -0,0 +1,14 @@ +{ + programs.pistol = { + enable = true; + # contains no fpath or mime value + associations = [{ command = "bat %pistol-filename%"; }]; + }; + + test.stubs.pistol = { }; + + test.asserts.assertions.expected = ['' + Each entry in programs.pistol.associations must contain exactly one + of fpath or mime. + '']; +} diff --git a/tests/modules/programs/pls/bash.nix b/tests/modules/programs/pls/bash.nix new file mode 100644 index 00000000..d6fff5f4 --- /dev/null +++ b/tests/modules/programs/pls/bash.nix @@ -0,0 +1,29 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs = { + bash.enable = true; + + pls = { + enable = true; + enableAliases = true; + package = config.lib.test.mkStubPackage { outPath = "@pls@"; }; + }; + }; + + test.stubs.pls = { }; + + nmt.script = '' + assertFileExists home-files/.bashrc + assertFileContains \ + home-files/.bashrc \ + "alias ls='@pls@/bin/pls'" + assertFileContains \ + home-files/.bashrc \ + "alias ll='@pls@/bin/pls -d perms -d user -d group -d size -d mtime -d git'" + ''; + }; +} diff --git a/tests/modules/programs/pls/default.nix b/tests/modules/programs/pls/default.nix new file mode 100644 index 00000000..fe80aad5 --- /dev/null +++ b/tests/modules/programs/pls/default.nix @@ -0,0 +1,5 @@ +{ + pls-bash = ./bash.nix; + pls-fish = ./fish.nix; + pls-zsh = ./zsh.nix; +} diff --git a/tests/modules/programs/pls/fish.nix b/tests/modules/programs/pls/fish.nix new file mode 100644 index 00000000..d555a11c --- /dev/null +++ b/tests/modules/programs/pls/fish.nix @@ -0,0 +1,33 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs = { + fish.enable = true; + + pls = { + enable = true; + enableAliases = true; + package = config.lib.test.mkStubPackage { outPath = "@pls@"; }; + }; + }; + + # Needed to avoid error with dummy fish package. + xdg.dataFile."fish/home-manager_generated_completions".source = + mkForce (builtins.toFile "empty" ""); + + test.stubs.pls = { }; + + nmt.script = '' + assertFileExists home-files/.config/fish/config.fish + assertFileContains \ + home-files/.config/fish/config.fish \ + "alias ls '@pls@/bin/pls'" + assertFileContains \ + home-files/.config/fish/config.fish \ + "alias ll '@pls@/bin/pls -d perms -d user -d group -d size -d mtime -d git'" + ''; + }; +} diff --git a/tests/modules/programs/pls/zsh.nix b/tests/modules/programs/pls/zsh.nix new file mode 100644 index 00000000..f3bcbf2a --- /dev/null +++ b/tests/modules/programs/pls/zsh.nix @@ -0,0 +1,32 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs = { + zsh.enable = true; + + pls = { + enable = true; + enableAliases = true; + package = config.lib.test.mkStubPackage { outPath = "@pls@"; }; + }; + }; + + test.stubs = { + pls = { }; + zsh = { }; + }; + + nmt.script = '' + assertFileExists home-files/.zshrc + assertFileContains \ + home-files/.zshrc \ + "alias ls='@pls@/bin/pls'" + assertFileContains \ + home-files/.zshrc \ + "alias ll='@pls@/bin/pls -d perms -d user -d group -d size -d mtime -d git'" + ''; + }; +} diff --git a/tests/modules/programs/powerline-go/fish.nix b/tests/modules/programs/powerline-go/fish.nix index b7891bbf..4861d1ba 100644 --- a/tests/modules/programs/powerline-go/fish.nix +++ b/tests/modules/programs/powerline-go/fish.nix @@ -22,10 +22,7 @@ with lib; xdg.dataFile."fish/home-manager_generated_completions".source = mkForce (builtins.toFile "empty" ""); - test.stubs = { - powerline-go = { }; - fish = { }; - }; + test.stubs.powerline-go = { }; nmt.script = '' assertFileExists home-files/.config/fish/config.fish diff --git a/tests/modules/programs/sbt/credentials.nix b/tests/modules/programs/sbt/credentials.nix index 55c3936a..1a79582a 100644 --- a/tests/modules/programs/sbt/credentials.nix +++ b/tests/modules/programs/sbt/credentials.nix @@ -19,8 +19,10 @@ let ]; expectedCredentialsSbt = pkgs.writeText "credentials.sbt" '' import scala.sys.process._ - credentials += Credentials("Sonatype Nexus Repository Manager", "example.com", "user", "echo password".!!.trim) - credentials += Credentials("Sonatype Nexus Repository Manager X", "v2.example.com", "user1", "echo password1".!!.trim) + lazy val credential_0 = "echo password".!!.trim + credentials += Credentials("Sonatype Nexus Repository Manager", "example.com", "user", credential_0) + lazy val credential_1 = "echo password1".!!.trim + credentials += Credentials("Sonatype Nexus Repository Manager X", "v2.example.com", "user1", credential_1) ''; credentialsSbtPath = ".sbt/1.0/credentials.sbt"; in { diff --git a/tests/modules/programs/sbt/default.nix b/tests/modules/programs/sbt/default.nix index 59ad89da..2d506b68 100644 --- a/tests/modules/programs/sbt/default.nix +++ b/tests/modules/programs/sbt/default.nix @@ -1,4 +1,7 @@ { - sbt-plugins = ./plugins.nix; sbt-credentials = ./credentials.nix; + sbt-deprecated-options = ./deprecated-options.nix; + sbt-plugins = ./plugins.nix; + sbt-repositories = ./repositories.nix; + sbt-user-config-path = ./user-config-path.nix; } diff --git a/tests/modules/programs/sbt/deprecated-options.nix b/tests/modules/programs/sbt/deprecated-options.nix new file mode 100644 index 00000000..c760354a --- /dev/null +++ b/tests/modules/programs/sbt/deprecated-options.nix @@ -0,0 +1,18 @@ +{ ... }: + +{ + programs.sbt = { + enable = true; + baseConfigPath = "gone"; + }; + + test.stubs.sbt = { }; + + test.asserts.assertions.expected = [ + (let offendingFile = toString ./deprecated-options.nix; + in '' + The option definition `programs.sbt.baseConfigPath' in `${offendingFile}' no longer has any effect; please remove it. + Use programs.sbt.baseUserConfigPath instead, but note that the semantics are slightly different. + '') + ]; +} diff --git a/tests/modules/programs/sbt/repositories.nix b/tests/modules/programs/sbt/repositories.nix new file mode 100644 index 00000000..0def44f7 --- /dev/null +++ b/tests/modules/programs/sbt/repositories.nix @@ -0,0 +1,38 @@ +{ pkgs, ... }: + +let + repositories = [ + "local" + { my-maven-proxy = "http://repo.mavenproxy.io/a/b/c/d"; } + "maven-local" + { + my-ivy-proxy = + "http://repo.company.com/ivy-releases/, [organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext]"; + } + "maven-central" + ]; + + expectedRepositories = builtins.toFile "repositories" '' + [repositories] + local + my-maven-proxy: http://repo.mavenproxy.io/a/b/c/d + maven-local + my-ivy-proxy: http://repo.company.com/ivy-releases/, [organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext] + maven-central + ''; + + repositoriesSbtPath = ".sbt/repositories"; +in { + config = { + programs.sbt = { + enable = true; + repositories = repositories; + package = pkgs.writeScriptBin "sbt" ""; + }; + + nmt.script = '' + assertFileExists "home-files/${repositoriesSbtPath}" + assertFileContent "home-files/${repositoriesSbtPath}" "${expectedRepositories}" + ''; + }; +} diff --git a/tests/modules/programs/sbt/user-config-path.nix b/tests/modules/programs/sbt/user-config-path.nix new file mode 100644 index 00000000..ef7c2ca8 --- /dev/null +++ b/tests/modules/programs/sbt/user-config-path.nix @@ -0,0 +1,39 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + plugins = [{ + org = "a"; + artifact = "b"; + version = "c"; + }]; + + credentials = [{ + realm = "a"; + host = "b"; + user = "c"; + passwordCommand = "d"; + }]; + + repositories = [ "local" ]; + + baseSbtPath = ".config/sbt"; +in { + config = { + programs.sbt = { + enable = true; + plugins = plugins; + credentials = credentials; + repositories = repositories; + baseUserConfigPath = ".config/sbt"; + package = pkgs.writeScriptBin "sbt" ""; + }; + + nmt.script = '' + assertFileExists "home-files/${baseSbtPath}/1.0/plugins/plugins.sbt" + assertFileExists "home-files/${baseSbtPath}/1.0/credentials.sbt" + assertFileExists "home-files/${baseSbtPath}/repositories" + ''; + }; +} diff --git a/tests/modules/programs/scmpuff/default.nix b/tests/modules/programs/scmpuff/default.nix index 5852c5b6..bf162a9b 100644 --- a/tests/modules/programs/scmpuff/default.nix +++ b/tests/modules/programs/scmpuff/default.nix @@ -4,4 +4,6 @@ scmpuff-no-shell = ./no-shell.nix; scmpuff-no-zsh = ./no-zsh.nix; scmpuff-zsh = ./zsh.nix; + scmpuff-fish = ./fish.nix; + scmpuff-no-fish = ./no-fish.nix; } diff --git a/tests/modules/programs/scmpuff/fish.nix b/tests/modules/programs/scmpuff/fish.nix new file mode 100644 index 00000000..5326995f --- /dev/null +++ b/tests/modules/programs/scmpuff/fish.nix @@ -0,0 +1,19 @@ +{ pkgs, lib, ... }: { + programs = { + scmpuff.enable = true; + fish.enable = true; + }; + + # Needed to avoid error with dummy fish package. + xdg.dataFile."fish/home-manager_generated_completions".source = + lib.mkForce (builtins.toFile "empty" ""); + + test.stubs.scmpuff = { }; + + nmt.script = '' + assertFileExists home-files/.config/fish/config.fish + assertFileContains \ + home-files/.config/fish/config.fish \ + '@scmpuff@/bin/scmpuff init -s --shell=fish | source' + ''; +} diff --git a/tests/modules/programs/scmpuff/no-fish.nix b/tests/modules/programs/scmpuff/no-fish.nix new file mode 100644 index 00000000..94666a59 --- /dev/null +++ b/tests/modules/programs/scmpuff/no-fish.nix @@ -0,0 +1,19 @@ +{ pkgs, lib, ... }: { + programs = { + scmpuff = { + enable = true; + enableFishIntegration = false; + }; + fish.enable = true; + }; + + # Needed to avoid error with dummy fish package. + xdg.dataFile."fish/home-manager_generated_completions".source = + lib.mkForce (builtins.toFile "empty" ""); + + test.stubs.scmpuff = { }; + + nmt.script = '' + assertFileNotRegex home-files/.config/fish/config.fish '@scmpuff@' + ''; +} diff --git a/tests/modules/programs/sioyek/default.nix b/tests/modules/programs/sioyek/default.nix new file mode 100644 index 00000000..c35f1c9f --- /dev/null +++ b/tests/modules/programs/sioyek/default.nix @@ -0,0 +1 @@ +{ sioyek = ./sioyek-basic-configuration.nix; } diff --git a/tests/modules/programs/sioyek/sioyek-basic-configuration.nix b/tests/modules/programs/sioyek/sioyek-basic-configuration.nix new file mode 100644 index 00000000..42eb1302 --- /dev/null +++ b/tests/modules/programs/sioyek/sioyek-basic-configuration.nix @@ -0,0 +1,36 @@ +{ config, pkgs, ... }: + +{ + programs.sioyek = { + enable = true; + bindings = { + "move_down" = "j"; + "move_left" = "h"; + "move_right" = "l"; + "move_up" = "k"; + "screen_down" = [ "d" "" ]; + "screen_up" = [ "u" "" ]; + }; + config = { + "dark_mode_background_color" = "0.0 0.0 0.0"; + "dark_mode_contrast" = "0.8"; + }; + }; + + test.stubs.sioyek = { }; + + nmt = { + description = "Sioyek basic setup with sample configuration"; + script = '' + assertFileExists home-files/.config/sioyek/prefs_user.config + assertFileContent home-files/.config/sioyek/prefs_user.config ${ + ./test_prefs_user.config + } + + assertFileExists home-files/.config/sioyek/keys_user.config + assertFileContent home-files/.config/sioyek/keys_user.config ${ + ./test_keys_user.config + } + ''; + }; +} diff --git a/tests/modules/programs/sioyek/test_keys_user.config b/tests/modules/programs/sioyek/test_keys_user.config new file mode 100644 index 00000000..f1be89c3 --- /dev/null +++ b/tests/modules/programs/sioyek/test_keys_user.config @@ -0,0 +1,8 @@ +move_down j +move_left h +move_right l +move_up k +screen_down d +screen_down +screen_up u +screen_up diff --git a/tests/modules/programs/sioyek/test_prefs_user.config b/tests/modules/programs/sioyek/test_prefs_user.config new file mode 100644 index 00000000..730dd51b --- /dev/null +++ b/tests/modules/programs/sioyek/test_prefs_user.config @@ -0,0 +1,2 @@ +dark_mode_background_color 0.0 0.0 0.0 +dark_mode_contrast 0.8 diff --git a/tests/modules/programs/ssh/default.nix b/tests/modules/programs/ssh/default.nix index b2f832c9..c5e17599 100644 --- a/tests/modules/programs/ssh/default.nix +++ b/tests/modules/programs/ssh/default.nix @@ -2,6 +2,7 @@ ssh-defaults = ./default-config.nix; ssh-includes = ./includes.nix; ssh-match-blocks = ./match-blocks-attrs.nix; + ssh-match-blocks-match-and-hosts = ./match-blocks-match-and-hosts.nix; ssh-forwards-dynamic-valid-bind-no-asserts = ./forwards-dynamic-valid-bind-no-asserts.nix; diff --git a/tests/modules/programs/ssh/match-blocks-match-and-hosts-expected.conf b/tests/modules/programs/ssh/match-blocks-match-and-hosts-expected.conf new file mode 100644 index 00000000..d50343b9 --- /dev/null +++ b/tests/modules/programs/ssh/match-blocks-match-and-hosts-expected.conf @@ -0,0 +1,19 @@ +Host * !github.com + Port 516 +Host abc + Port 2222 +Match host xyz canonical + Port 2223 + +Host * + ForwardAgent no + Compression no + ServerAliveInterval 0 + ServerAliveCountMax 3 + HashKnownHosts no + UserKnownHostsFile ~/.ssh/known_hosts + ControlMaster no + ControlPath ~/.ssh/master-%r@%n:%p + ControlPersist no + + diff --git a/tests/modules/programs/ssh/match-blocks-match-and-hosts.nix b/tests/modules/programs/ssh/match-blocks-match-and-hosts.nix new file mode 100644 index 00000000..aa1e40d0 --- /dev/null +++ b/tests/modules/programs/ssh/match-blocks-match-and-hosts.nix @@ -0,0 +1,32 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.ssh = { + enable = true; + matchBlocks = { + abc = { port = 2222; }; + + xyz = { + match = "host xyz canonical"; + port = 2223; + }; + + "* !github.com" = { port = 516; }; + }; + }; + + home.file.assertions.text = builtins.toJSON + (map (a: a.message) (filter (a: !a.assertion) config.assertions)); + + nmt.script = '' + assertFileExists home-files/.ssh/config + assertFileContent \ + home-files/.ssh/config \ + ${./match-blocks-match-and-hosts-expected.conf} + assertFileContent home-files/assertions ${./no-assertions.json} + ''; + }; +} diff --git a/tests/modules/programs/thunderbird/default.nix b/tests/modules/programs/thunderbird/default.nix new file mode 100644 index 00000000..48729778 --- /dev/null +++ b/tests/modules/programs/thunderbird/default.nix @@ -0,0 +1 @@ +{ thunderbird = ./thunderbird.nix; } diff --git a/tests/modules/programs/thunderbird/thunderbird-expected-first.js b/tests/modules/programs/thunderbird/thunderbird-expected-first.js new file mode 100644 index 00000000..de677575 --- /dev/null +++ b/tests/modules/programs/thunderbird/thunderbird-expected-first.js @@ -0,0 +1,61 @@ +// Generated by Home Manager. + +user_pref("general.useragent.override", ""); +user_pref("mail.account.account_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.identities", "id_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc"); +user_pref("mail.account.account_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.server", "server_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc"); +user_pref("mail.account.account_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.identities", "id_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f"); +user_pref("mail.account.account_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.server", "server_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f"); +user_pref("mail.accountmanager.accounts", "account_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc,account_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f"); +user_pref("mail.accountmanager.defaultaccount", "account_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f"); +user_pref("mail.identity.id_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.autoEncryptDrafts", false); +user_pref("mail.identity.id_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.fullName", "H. M. Test Jr."); +user_pref("mail.identity.id_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.protectSubject", false); +user_pref("mail.identity.id_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.smtpServer", "smtp_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc"); +user_pref("mail.identity.id_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.useremail", "hm@example.org"); +user_pref("mail.identity.id_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.valid", true); +user_pref("mail.identity.id_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.attachPgpKey", false); +user_pref("mail.identity.id_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.autoEncryptDrafts", true); +user_pref("mail.identity.id_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.e2etechpref", 0); +user_pref("mail.identity.id_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.encryptionpolicy", 0); +user_pref("mail.identity.id_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.fullName", "H. M. Test"); +user_pref("mail.identity.id_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.is_gnupg_key_id", true); +user_pref("mail.identity.id_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.last_entered_external_gnupg_key_id", "ABC"); +user_pref("mail.identity.id_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.openpgp_key_id", "ABC"); +user_pref("mail.identity.id_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.protectSubject", true); +user_pref("mail.identity.id_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.sign_mail", false); +user_pref("mail.identity.id_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.smtpServer", "smtp_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f"); +user_pref("mail.identity.id_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.useremail", "hm@example.com"); +user_pref("mail.identity.id_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.valid", true); +user_pref("mail.openpgp.allow_external_gnupg", true); +user_pref("mail.server.server_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.directory", ".thunderbird/first/ImapMail/bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc"); +user_pref("mail.server.server_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.directory-rel", "[ProfD]ImapMail/bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc"); +user_pref("mail.server.server_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.hostname", "imap.example.org"); +user_pref("mail.server.server_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.login_at_startup", true); +user_pref("mail.server.server_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.name", "hm-account"); +user_pref("mail.server.server_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.port", 143); +user_pref("mail.server.server_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.socketType", 3); +user_pref("mail.server.server_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.type", "imap"); +user_pref("mail.server.server_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.userName", "home.manager.jr"); +user_pref("mail.server.server_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.directory", ".thunderbird/first/ImapMail/cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f"); +user_pref("mail.server.server_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.directory-rel", "[ProfD]ImapMail/cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f"); +user_pref("mail.server.server_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.hostname", "imap.example.com"); +user_pref("mail.server.server_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.login_at_startup", true); +user_pref("mail.server.server_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.name", "hm@example.com"); +user_pref("mail.server.server_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.port", 123); +user_pref("mail.server.server_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.socketType", 3); +user_pref("mail.server.server_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.type", "imap"); +user_pref("mail.server.server_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.userName", "home.manager"); +user_pref("mail.smtp.defaultserver", "smtp_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f"); +user_pref("mail.smtpserver.smtp_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.authMethod", 3); +user_pref("mail.smtpserver.smtp_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.hostname", "smtp.example.org"); +user_pref("mail.smtpserver.smtp_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.port", 587); +user_pref("mail.smtpserver.smtp_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.try_ssl", 2); +user_pref("mail.smtpserver.smtp_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.username", "home.manager.jr"); +user_pref("mail.smtpserver.smtp_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.authMethod", 3); +user_pref("mail.smtpserver.smtp_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.hostname", "smtp.example.com"); +user_pref("mail.smtpserver.smtp_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.port", 456); +user_pref("mail.smtpserver.smtp_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.try_ssl", 3); +user_pref("mail.smtpserver.smtp_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f.username", "home.manager"); +user_pref("mail.smtpservers", "smtp_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc,smtp_cda3f13b64c1db7d4b58ce07a31304a362d7dcaf14476bfabcca913ae41ada9f"); +user_pref("privacy.donottrackheader.enabled", true); + diff --git a/tests/modules/programs/thunderbird/thunderbird-expected-profiles.ini b/tests/modules/programs/thunderbird/thunderbird-expected-profiles.ini new file mode 100644 index 00000000..4191f160 --- /dev/null +++ b/tests/modules/programs/thunderbird/thunderbird-expected-profiles.ini @@ -0,0 +1,15 @@ +[General] +StartWithLastProfile=1 +Version=2 + +[Profile0] +Default=1 +IsRelative=1 +Name=first +Path=first + +[Profile1] +Default=0 +IsRelative=1 +Name=second +Path=second diff --git a/tests/modules/programs/thunderbird/thunderbird-expected-second.js b/tests/modules/programs/thunderbird/thunderbird-expected-second.js new file mode 100644 index 00000000..12d7991e --- /dev/null +++ b/tests/modules/programs/thunderbird/thunderbird-expected-second.js @@ -0,0 +1,31 @@ +// Generated by Home Manager. + +user_pref("general.useragent.override", ""); +user_pref("mail.account.account_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.identities", "id_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc"); +user_pref("mail.account.account_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.server", "server_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc"); +user_pref("mail.accountmanager.accounts", "account_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc"); +user_pref("mail.identity.id_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.autoEncryptDrafts", false); +user_pref("mail.identity.id_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.fullName", "H. M. Test Jr."); +user_pref("mail.identity.id_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.protectSubject", false); +user_pref("mail.identity.id_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.smtpServer", "smtp_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc"); +user_pref("mail.identity.id_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.useremail", "hm@example.org"); +user_pref("mail.identity.id_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.valid", true); +user_pref("mail.openpgp.allow_external_gnupg", false); +user_pref("mail.server.server_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.directory", ".thunderbird/second/ImapMail/bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc"); +user_pref("mail.server.server_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.directory-rel", "[ProfD]ImapMail/bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc"); +user_pref("mail.server.server_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.hostname", "imap.example.org"); +user_pref("mail.server.server_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.login_at_startup", true); +user_pref("mail.server.server_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.name", "hm-account"); +user_pref("mail.server.server_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.port", 143); +user_pref("mail.server.server_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.socketType", 3); +user_pref("mail.server.server_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.type", "imap"); +user_pref("mail.server.server_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.userName", "home.manager.jr"); +user_pref("mail.smtpserver.smtp_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.authMethod", 3); +user_pref("mail.smtpserver.smtp_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.hostname", "smtp.example.org"); +user_pref("mail.smtpserver.smtp_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.port", 587); +user_pref("mail.smtpserver.smtp_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.try_ssl", 2); +user_pref("mail.smtpserver.smtp_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc.username", "home.manager.jr"); +user_pref("mail.smtpservers", "smtp_bcd3ace52bed41febb6cdc2fb1303aebaa573e0d993872da503950901bb6c6fc"); +user_pref("privacy.donottrackheader.enabled", true); +user_pref("second.setting", "some-test-setting"); + diff --git a/tests/modules/programs/thunderbird/thunderbird.nix b/tests/modules/programs/thunderbird/thunderbird.nix new file mode 100644 index 00000000..ee16efa0 --- /dev/null +++ b/tests/modules/programs/thunderbird/thunderbird.nix @@ -0,0 +1,64 @@ +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + accounts.email.accounts = { + "hm@example.com" = { + thunderbird = { + enable = true; + profiles = [ "first" ]; + }; + + gpg.key = "ABC"; + + imap = { + port = 123; + tls.enable = true; + }; + smtp.port = 456; + }; + + hm-account = { + thunderbird = { + enable = true; + settings = id: { + "mail.identity.id_${id}.protectSubject" = false; + "mail.identity.id_${id}.autoEncryptDrafts" = false; + }; + }; + }; + }; + + programs.thunderbird = { + enable = true; + + profiles = { + first = { + isDefault = true; + withExternalGnupg = true; + }; + + second.settings = { "second.setting" = "some-test-setting"; }; + }; + + settings = { + "general.useragent.override" = ""; + "privacy.donottrackheader.enabled" = true; + }; + }; + + test.stubs.thunderbird = { }; + + nmt.script = '' + assertFileExists home-files/.thunderbird/profiles.ini + assertFileContent home-files/.thunderbird/profiles.ini \ + ${./thunderbird-expected-profiles.ini} + + assertFileExists home-files/.thunderbird/first/user.js + assertFileContent home-files/.thunderbird/first/user.js \ + ${./thunderbird-expected-first.js} + + assertFileExists home-files/.thunderbird/second/user.js + assertFileContent home-files/.thunderbird/second/user.js \ + ${./thunderbird-expected-second.js} + ''; +} diff --git a/tests/modules/programs/tmate/default.nix b/tests/modules/programs/tmate/default.nix new file mode 100644 index 00000000..c5e05d56 --- /dev/null +++ b/tests/modules/programs/tmate/default.nix @@ -0,0 +1 @@ +{ tmate = ./tmate.nix; } diff --git a/tests/modules/programs/tmate/tmate.nix b/tests/modules/programs/tmate/tmate.nix new file mode 100644 index 00000000..4beb84c1 --- /dev/null +++ b/tests/modules/programs/tmate/tmate.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +{ + programs.tmate = { + enable = true; + port = 222; + dsaFingerprint = "SHA256:1111111111111111111111111111111111111111111"; + extraConfig = ''set tmate-session-name "session-name"''; + }; + + test.stubs.tmate = { }; + + nmt.script = let + expectedConfig = '' + set -g tmate-server-port 222 + set -g tmate-server-ed25519-fingerprint "SHA256:1111111111111111111111111111111111111111111" + set tmate-session-name "session-name" + ''; + in '' + assertFileExists home-files/.tmate.conf + assertFileContent home-files/.tmate.conf ${ + builtins.toFile "config" expectedConfig + } + ''; +} diff --git a/tests/modules/programs/tmux/default-shell.conf b/tests/modules/programs/tmux/default-shell.conf index a3362363..8eb4e40f 100644 --- a/tests/modules/programs/tmux/default-shell.conf +++ b/tests/modules/programs/tmux/default-shell.conf @@ -23,6 +23,7 @@ set -g mode-keys emacs +set -g mouse off setw -g aggressive-resize off setw -g clock-mode-style 12 set -s escape-time 500 diff --git a/tests/modules/programs/tmux/default.nix b/tests/modules/programs/tmux/default.nix index be78c262..979774a7 100644 --- a/tests/modules/programs/tmux/default.nix +++ b/tests/modules/programs/tmux/default.nix @@ -7,4 +7,5 @@ tmux-default-shell = ./default-shell.nix; tmux-shortcut-without-prefix = ./shortcut-without-prefix.nix; tmux-prefix = ./prefix.nix; + tmux-mouse-enabled = ./mouse-enabled.nix; } diff --git a/tests/modules/programs/tmux/disable-confirmation-prompt.conf b/tests/modules/programs/tmux/disable-confirmation-prompt.conf index e97a94d1..b4359316 100644 --- a/tests/modules/programs/tmux/disable-confirmation-prompt.conf +++ b/tests/modules/programs/tmux/disable-confirmation-prompt.conf @@ -23,6 +23,7 @@ bind-key -N "Kill the current window" & kill-window bind-key -N "Kill the current pane" x kill-pane +set -g mouse off setw -g aggressive-resize off setw -g clock-mode-style 12 set -s escape-time 500 diff --git a/tests/modules/programs/tmux/emacs-with-plugins.conf b/tests/modules/programs/tmux/emacs-with-plugins.conf index d0150192..54ddce13 100644 --- a/tests/modules/programs/tmux/emacs-with-plugins.conf +++ b/tests/modules/programs/tmux/emacs-with-plugins.conf @@ -23,6 +23,7 @@ set -g mode-keys emacs +set -g mouse off setw -g aggressive-resize on setw -g clock-mode-style 24 set -s escape-time 500 diff --git a/tests/modules/programs/tmux/mouse-enabled.conf b/tests/modules/programs/tmux/mouse-enabled.conf new file mode 100644 index 00000000..2069920d --- /dev/null +++ b/tests/modules/programs/tmux/mouse-enabled.conf @@ -0,0 +1,29 @@ +# ============================================= # +# Start with defaults from the Sensible plugin # +# --------------------------------------------- # +run-shell @sensible_rtp@ +# ============================================= # + +set -g default-terminal "screen" +set -g base-index 0 +setw -g pane-base-index 0 + + + + + +set -g status-keys emacs +set -g mode-keys emacs + + + + + + + +set -g mouse on +setw -g aggressive-resize off +setw -g clock-mode-style 12 +set -s escape-time 500 +set -g history-limit 2000 + diff --git a/tests/modules/programs/tmux/mouse-enabled.nix b/tests/modules/programs/tmux/mouse-enabled.nix new file mode 100644 index 00000000..6fc5b526 --- /dev/null +++ b/tests/modules/programs/tmux/mouse-enabled.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.tmux = { + enable = true; + mouse = true; + }; + + nixpkgs.overlays = [ + (self: super: { + tmuxPlugins = super.tmuxPlugins // { + sensible = super.tmuxPlugins.sensible // { rtp = "@sensible_rtp@"; }; + }; + }) + ]; + + nmt.script = '' + assertFileExists home-files/.config/tmux/tmux.conf + assertFileContent home-files/.config/tmux/tmux.conf \ + ${./mouse-enabled.conf} + ''; + }; +} diff --git a/tests/modules/programs/tmux/prefix.conf b/tests/modules/programs/tmux/prefix.conf index 831ec3b0..00f950e0 100644 --- a/tests/modules/programs/tmux/prefix.conf +++ b/tests/modules/programs/tmux/prefix.conf @@ -26,6 +26,7 @@ bind -N "Send the prefix key through to the application" \ +set -g mouse off setw -g aggressive-resize off setw -g clock-mode-style 12 set -s escape-time 500 diff --git a/tests/modules/programs/tmux/secure-socket-enabled.nix b/tests/modules/programs/tmux/secure-socket-enabled.nix index ca2de663..60b3f708 100644 --- a/tests/modules/programs/tmux/secure-socket-enabled.nix +++ b/tests/modules/programs/tmux/secure-socket-enabled.nix @@ -12,7 +12,7 @@ with lib; nmt.script = '' assertFileExists home-path/etc/profile.d/hm-session-vars.sh assertFileContains home-path/etc/profile.d/hm-session-vars.sh \ - 'export TMUX_TMPDIR="''${XDG_RUNTIME_DIR:-"/run/user/\$(id -u)"}"' + 'export TMUX_TMPDIR="''${XDG_RUNTIME_DIR:-"/run/user/$(id -u)"}"' ''; }; } diff --git a/tests/modules/programs/tmux/shortcut-without-prefix.conf b/tests/modules/programs/tmux/shortcut-without-prefix.conf index 4fd89ad2..938ecfa8 100644 --- a/tests/modules/programs/tmux/shortcut-without-prefix.conf +++ b/tests/modules/programs/tmux/shortcut-without-prefix.conf @@ -27,6 +27,7 @@ bind C-a last-window +set -g mouse off setw -g aggressive-resize off setw -g clock-mode-style 12 set -s escape-time 500 diff --git a/tests/modules/programs/tmux/vi-all-true.conf b/tests/modules/programs/tmux/vi-all-true.conf index 6a6fd611..03bf2f5a 100644 --- a/tests/modules/programs/tmux/vi-all-true.conf +++ b/tests/modules/programs/tmux/vi-all-true.conf @@ -23,6 +23,7 @@ set -g mode-keys vi +set -g mouse off setw -g aggressive-resize on setw -g clock-mode-style 24 set -s escape-time 500 diff --git a/tests/modules/programs/vim-vint/basic-configuration.nix b/tests/modules/programs/vim-vint/basic-configuration.nix new file mode 100644 index 00000000..59bfafa5 --- /dev/null +++ b/tests/modules/programs/vim-vint/basic-configuration.nix @@ -0,0 +1,27 @@ +{ config, pkgs, lib, xdg, ... }: + +{ + programs.vim-vint = { + enable = true; + settings = { + cmdargs = { + severity = "error"; + color = true; + env = { neovim = true; }; + }; + policies = { + ProhibitEqualTildeOperator.enabled = false; + ProhibitUsingUndeclaredVariable.enabled = false; + ProhibitAbbreviationOption.enabled = false; + ProhibitImplicitScopeVariable.enabled = false; + ProhibitSetNoCompatible.enabled = false; + }; + }; + }; + + nmt.script = '' + assertFileContent home-files/.config/.vintrc.yaml ${ + ./basic-configuration.yaml + } + ''; +} diff --git a/tests/modules/programs/vim-vint/basic-configuration.yaml b/tests/modules/programs/vim-vint/basic-configuration.yaml new file mode 100644 index 00000000..1273b14e --- /dev/null +++ b/tests/modules/programs/vim-vint/basic-configuration.yaml @@ -0,0 +1,16 @@ +cmdargs: + color: true + env: + neovim: true + severity: error +policies: + ProhibitAbbreviationOption: + enabled: false + ProhibitEqualTildeOperator: + enabled: false + ProhibitImplicitScopeVariable: + enabled: false + ProhibitSetNoCompatible: + enabled: false + ProhibitUsingUndeclaredVariable: + enabled: false diff --git a/tests/modules/programs/vim-vint/default.nix b/tests/modules/programs/vim-vint/default.nix new file mode 100644 index 00000000..0066eaf8 --- /dev/null +++ b/tests/modules/programs/vim-vint/default.nix @@ -0,0 +1 @@ +{ vim-vint-basic-configuration = ./basic-configuration.nix; } diff --git a/tests/modules/programs/vscode/default.nix b/tests/modules/programs/vscode/default.nix index 70f6d2e7..4015121d 100644 --- a/tests/modules/programs/vscode/default.nix +++ b/tests/modules/programs/vscode/default.nix @@ -1 +1,5 @@ -{ vscode-keybindings = ./keybindings.nix; } +{ + vscode-keybindings = ./keybindings.nix; + vscode-tasks = ./tasks.nix; + vscode-update-checks = ./update-checks.nix; +} diff --git a/tests/modules/programs/vscode/keybindings.nix b/tests/modules/programs/vscode/keybindings.nix index 57931c43..ed457a9b 100644 --- a/tests/modules/programs/vscode/keybindings.nix +++ b/tests/modules/programs/vscode/keybindings.nix @@ -27,12 +27,17 @@ let } ]; - targetPath = if pkgs.stdenv.hostPlatform.isDarwin then + keybindingsPath = if pkgs.stdenv.hostPlatform.isDarwin then "Library/Application Support/Code/User/keybindings.json" else ".config/Code/User/keybindings.json"; - expectedJson = pkgs.writeText "expected.json" '' + settingsPath = if pkgs.stdenv.hostPlatform.isDarwin then + "Library/Application Support/Code/User/settings.json" + else + ".config/Code/User/settings.json"; + + expectedKeybindings = pkgs.writeText "expected.json" '' [ { "command": "editor.action.clipboardCopyAction", @@ -58,6 +63,7 @@ let } ] ''; + in { config = { programs.vscode = { @@ -67,8 +73,10 @@ in { }; nmt.script = '' - assertFileExists "home-files/${targetPath}" - assertFileContent "home-files/${targetPath}" "${expectedJson}" + assertFileExists "home-files/${keybindingsPath}" + assertFileContent "home-files/${keybindingsPath}" "${expectedKeybindings}" + + assertPathNotExists "home-files/${settingsPath}" ''; }; } diff --git a/tests/modules/programs/vscode/tasks.nix b/tests/modules/programs/vscode/tasks.nix new file mode 100644 index 00000000..f0d28380 --- /dev/null +++ b/tests/modules/programs/vscode/tasks.nix @@ -0,0 +1,43 @@ +{ pkgs, config, ... }: + +let + + tasksFilePath = if pkgs.stdenv.hostPlatform.isDarwin then + "Library/Application Support/Code/User/tasks.json" + else + ".config/Code/User/tasks.json"; + + tasks = { + version = "2.0.0"; + tasks = [{ + type = "shell"; + label = "Hello task"; + command = "hello"; + }]; + }; + + expectedTasks = pkgs.writeText "tasks-expected.json" '' + { + "tasks": [ + { + "command": "hello", + "label": "Hello task", + "type": "shell" + } + ], + "version": "2.0.0" + } + ''; + +in { + programs.vscode = { + enable = true; + package = pkgs.writeScriptBin "vscode" "" // { pname = "vscode"; }; + userTasks = tasks; + }; + + nmt.script = '' + assertFileExists "home-files/${tasksFilePath}" + assertFileContent "home-files/${tasksFilePath}" "${expectedTasks}" + ''; +} diff --git a/tests/modules/programs/vscode/update-checks.nix b/tests/modules/programs/vscode/update-checks.nix new file mode 100644 index 00000000..1547bd36 --- /dev/null +++ b/tests/modules/programs/vscode/update-checks.nix @@ -0,0 +1,29 @@ +{ pkgs, ... }: + +let + + settingsPath = if pkgs.stdenv.hostPlatform.isDarwin then + "Library/Application Support/Code/User/settings.json" + else + ".config/Code/User/settings.json"; + + expectedSettings = pkgs.writeText "settings-expected.json" '' + { + "extensions.autoCheckUpdates": false, + "update.mode": "none" + } + ''; + +in { + programs.vscode = { + enable = true; + package = pkgs.writeScriptBin "vscode" "" // { pname = "vscode"; }; + enableUpdateCheck = false; + enableExtensionUpdateCheck = false; + }; + + nmt.script = '' + assertFileExists "home-files/${settingsPath}" + assertFileContent "home-files/${settingsPath}" "${expectedSettings}" + ''; +} diff --git a/tests/modules/programs/wlogout/default.nix b/tests/modules/programs/wlogout/default.nix new file mode 100644 index 00000000..294772e7 --- /dev/null +++ b/tests/modules/programs/wlogout/default.nix @@ -0,0 +1,5 @@ +{ + wlogout-styling = ./styling.nix; + wlogout-layout-single = ./layout-single.nix; + wlogout-layout-multiple = ./layout-multiple.nix; +} diff --git a/tests/modules/programs/wlogout/layout-multiple-expected.json b/tests/modules/programs/wlogout/layout-multiple-expected.json new file mode 100644 index 00000000..9e69d4e9 --- /dev/null +++ b/tests/modules/programs/wlogout/layout-multiple-expected.json @@ -0,0 +1,6 @@ +{"action":"systemctl poweroff","keybind":"s","label":"shutdown","text":"Shutdown"} +{"action":"systemctl hibernate","height":0.5,"keybind":"h","label":"hibernate","text":"Hibernate","width":0.5} +{"action":"systemctl suspend","circular":true,"keybind":"u","label":"suspend","text":"Suspend"} +{"action":"swaymsg exit","keybind":"e","label":"exit","text":"Exit"} +{"action":"systemctl reboot","keybind":"r","label":"reboot","text":"Reboot"} +{"action":"gtklock","keybind":"l","label":"lock","text":"Lock"} diff --git a/tests/modules/programs/wlogout/layout-multiple.nix b/tests/modules/programs/wlogout/layout-multiple.nix new file mode 100644 index 00000000..108961aa --- /dev/null +++ b/tests/modules/programs/wlogout/layout-multiple.nix @@ -0,0 +1,62 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "22.11"; + + programs.wlogout = { + package = config.lib.test.mkStubPackage { outPath = "@wlogout@"; }; + enable = true; + layout = [ + { + label = "shutdown"; + action = "systemctl poweroff"; + text = "Shutdown"; + keybind = "s"; + } + { + label = "hibernate"; + action = "systemctl hibernate"; + text = "Hibernate"; + keybind = "h"; + height = 0.5; + width = 0.5; + } + { + label = "suspend"; + action = "systemctl suspend"; + text = "Suspend"; + keybind = "u"; + circular = true; + } + { + label = "exit"; + action = "swaymsg exit"; + text = "Exit"; + keybind = "e"; + } + { + label = "reboot"; + action = "systemctl reboot"; + text = "Reboot"; + keybind = "r"; + } + { + label = "lock"; + action = "gtklock"; + text = "Lock"; + keybind = "l"; + } + ]; + }; + + nmt.script = '' + assertPathNotExists home-files/.config/wlogout/style.css + assertFileContent \ + home-files/.config/wlogout/layout \ + ${./layout-multiple-expected.json} + ''; + }; +} diff --git a/tests/modules/programs/wlogout/layout-single-expected.json b/tests/modules/programs/wlogout/layout-single-expected.json new file mode 100644 index 00000000..d4d43dde --- /dev/null +++ b/tests/modules/programs/wlogout/layout-single-expected.json @@ -0,0 +1 @@ +{"action":"systemctl poweroff","keybind":"s","label":"shutdown","text":"Shutdown"} diff --git a/tests/modules/programs/wlogout/layout-single.nix b/tests/modules/programs/wlogout/layout-single.nix new file mode 100644 index 00000000..bbb5d61e --- /dev/null +++ b/tests/modules/programs/wlogout/layout-single.nix @@ -0,0 +1,27 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "22.11"; + + programs.wlogout = { + package = config.lib.test.mkStubPackage { outPath = "@wlogout@"; }; + enable = true; + layout = [{ + label = "shutdown"; + action = "systemctl poweroff"; + text = "Shutdown"; + keybind = "s"; + }]; + }; + + nmt.script = '' + assertPathNotExists home-files/.config/wlogout/style.css + assertFileContent \ + home-files/.config/wlogout/layout \ + ${./layout-single-expected.json} + ''; + }; +} diff --git a/tests/modules/programs/wlogout/styling-expected.css b/tests/modules/programs/wlogout/styling-expected.css new file mode 100644 index 00000000..49050beb --- /dev/null +++ b/tests/modules/programs/wlogout/styling-expected.css @@ -0,0 +1,16 @@ +* { + border: none; + border-radius: 0; + font-family: Source Code Pro; + font-weight: bold; + color: #abb2bf; + font-size: 18px; + min-height: 0px; +} +window { + background: #16191C; + color: #aab2bf; +} +#window { + padding: 0 0px; +} diff --git a/tests/modules/programs/wlogout/styling.nix b/tests/modules/programs/wlogout/styling.nix new file mode 100644 index 00000000..6df6290f --- /dev/null +++ b/tests/modules/programs/wlogout/styling.nix @@ -0,0 +1,39 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "22.11"; + + programs.wlogout = { + package = config.lib.test.mkStubPackage { outPath = "@wlogout@"; }; + enable = true; + style = '' + * { + border: none; + border-radius: 0; + font-family: Source Code Pro; + font-weight: bold; + color: #abb2bf; + font-size: 18px; + min-height: 0px; + } + window { + background: #16191C; + color: #aab2bf; + } + #window { + padding: 0 0px; + } + ''; + }; + + nmt.script = '' + assertPathNotExists home-files/.config/wlogout/layout + assertFileContent \ + home-files/.config/wlogout/style.css \ + ${./styling-expected.css} + ''; + }; +} diff --git a/tests/modules/programs/yt-dlp/default.nix b/tests/modules/programs/yt-dlp/default.nix new file mode 100644 index 00000000..4b09a9c5 --- /dev/null +++ b/tests/modules/programs/yt-dlp/default.nix @@ -0,0 +1 @@ +{ yt-dlp-simple-config = ./yt-dlp-simple-config.nix; } diff --git a/tests/modules/programs/yt-dlp/yt-dlp-simple-config-expected b/tests/modules/programs/yt-dlp/yt-dlp-simple-config-expected new file mode 100644 index 00000000..f5062dde --- /dev/null +++ b/tests/modules/programs/yt-dlp/yt-dlp-simple-config-expected @@ -0,0 +1,8 @@ +--downloader aria2c +--downloader-args aria2c:'-c -x8 -s8 -k1M' +--no-embed-subs +--embed-thumbnail +--sub-langs all +--trim-filenames 30 +--config-locations /home/user/.yt-dlp.conf + diff --git a/tests/modules/programs/yt-dlp/yt-dlp-simple-config.nix b/tests/modules/programs/yt-dlp/yt-dlp-simple-config.nix new file mode 100644 index 00000000..229f0438 --- /dev/null +++ b/tests/modules/programs/yt-dlp/yt-dlp-simple-config.nix @@ -0,0 +1,27 @@ +{ ... }: + +{ + programs.yt-dlp = { + enable = true; + settings = { + embed-thumbnail = true; + embed-subs = false; + sub-langs = "all"; + downloader = "aria2c"; + downloader-args = "aria2c:'-c -x8 -s8 -k1M'"; + trim-filenames = 30; + }; + extraConfig = '' + --config-locations /home/user/.yt-dlp.conf + ''; + }; + + test.stubs.yt-dlp = { }; + + nmt.script = '' + assertFileExists home-files/.config/yt-dlp/config + assertFileContent home-files/.config/yt-dlp/config ${ + ./yt-dlp-simple-config-expected + } + ''; +} diff --git a/tests/modules/programs/zplug/modules.nix b/tests/modules/programs/zplug/modules.nix index 7c4abbc4..9f4d4332 100644 --- a/tests/modules/programs/zplug/modules.nix +++ b/tests/modules/programs/zplug/modules.nix @@ -8,7 +8,7 @@ with lib; enable = true; zplug = { enable = true; - zplugHome = ~/.customZplugHome; + zplugHome = pkgs.emptyDirectory; plugins = [ { name = "plugins/git"; diff --git a/tests/modules/services/borgmatic/basic-configuration.nix b/tests/modules/services/borgmatic/basic-configuration.nix new file mode 100644 index 00000000..3763b98f --- /dev/null +++ b/tests/modules/services/borgmatic/basic-configuration.nix @@ -0,0 +1,22 @@ +{ config, pkgs, ... }: + +{ + config = { + services.borgmatic = { + enable = true; + frequency = "weekly"; + }; + + test.stubs.borgmatic = { }; + + nmt.script = '' + assertFileContent \ + $(normalizeStorePaths home-files/.config/systemd/user/borgmatic.service) \ + ${./basic-configuration.service} + + assertFileContent \ + home-files/.config/systemd/user/borgmatic.timer \ + ${./basic-configuration.timer} + ''; + }; +} diff --git a/tests/modules/services/borgmatic/basic-configuration.service b/tests/modules/services/borgmatic/basic-configuration.service new file mode 100644 index 00000000..80713fd9 --- /dev/null +++ b/tests/modules/services/borgmatic/basic-configuration.service @@ -0,0 +1,24 @@ +[Service] +CPUSchedulingPolicy=batch +ExecStart=/nix/store/00000000000000000000000000000000-systemd/bin/systemd-inhibit \ + --who="borgmatic" \ + --what="sleep:shutdown" \ + --why="Prevent interrupting scheduled backup" \ + @borgmatic@/bin/borgmatic \ + --stats \ + --verbosity -1 \ + --list \ + --syslog-verbosity 1 + +ExecStartPre=/nix/store/00000000000000000000000000000000-coreutils/bin/sleep 3m +IOSchedulingClass=best-effort +IOSchedulingPriority=7 +IOWeight=100 +LogRateLimitIntervalSec=0 +Nice=19 +Restart=no +Type=oneshot + +[Unit] +ConditionACPower=true +Description=borgmatic backup diff --git a/tests/modules/services/borgmatic/basic-configuration.timer b/tests/modules/services/borgmatic/basic-configuration.timer new file mode 100644 index 00000000..1427925f --- /dev/null +++ b/tests/modules/services/borgmatic/basic-configuration.timer @@ -0,0 +1,10 @@ +[Install] +WantedBy=timers.target + +[Timer] +OnCalendar=weekly +Persistent=true +RandomizedDelaySec=10m + +[Unit] +Description=Run borgmatic backup diff --git a/tests/modules/services/borgmatic/default.nix b/tests/modules/services/borgmatic/default.nix new file mode 100644 index 00000000..802e7d0c --- /dev/null +++ b/tests/modules/services/borgmatic/default.nix @@ -0,0 +1 @@ +{ borgmatic-service-basic-configuration = ./basic-configuration.nix; } diff --git a/tests/modules/services/cachix-agent/basic-setup.nix b/tests/modules/services/cachix-agent/basic-setup.nix new file mode 100644 index 00000000..0f84ae35 --- /dev/null +++ b/tests/modules/services/cachix-agent/basic-setup.nix @@ -0,0 +1,32 @@ +{ config, ... }: + +{ + services.cachix-agent = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@cachix-agent@"; }; + name = "test-agent"; + }; + + test.stubs.nix = { }; + + nmt.script = '' + assertFileContent \ + home-files/.config/systemd/user/cachix-agent.service \ + ${ + builtins.toFile "cachix-agent.service" '' + [Install] + WantedBy=default.target + + [Service] + Environment=PATH=@nix@/bin + EnvironmentFile=/home/hm-user/.config/cachix-agent.token + ExecStart='@cachix-agent@/bin/cachix' 'deploy' 'agent' 'test-agent' 'home-manager' + KillMode=process + Restart=on-failure + + [Unit] + Description=Cachix Deploy Agent + '' + } + ''; +} diff --git a/tests/modules/services/cachix-agent/default.nix b/tests/modules/services/cachix-agent/default.nix new file mode 100644 index 00000000..48f88e0a --- /dev/null +++ b/tests/modules/services/cachix-agent/default.nix @@ -0,0 +1 @@ +{ cachix = ./basic-setup.nix; } diff --git a/tests/modules/services/clipman/clipman-sway-session-target.nix b/tests/modules/services/clipman/clipman-sway-session-target.nix new file mode 100644 index 00000000..129ab554 --- /dev/null +++ b/tests/modules/services/clipman/clipman-sway-session-target.nix @@ -0,0 +1,20 @@ +{ ... }: + +{ + home.stateVersion = "21.11"; + + services.clipman = { + enable = true; + systemdTarget = "sway-session.target"; + }; + + test.stubs = { + clipman = { }; + wl-clipboard = { }; + }; + + nmt.script = '' + serviceFile=$(normalizeStorePaths home-files/.config/systemd/user/clipman.service) + assertFileContent "$serviceFile" ${./clipman-sway-session-target.service} + ''; +} diff --git a/tests/modules/services/clipman/clipman-sway-session-target.service b/tests/modules/services/clipman/clipman-sway-session-target.service new file mode 100644 index 00000000..0d0478cc --- /dev/null +++ b/tests/modules/services/clipman/clipman-sway-session-target.service @@ -0,0 +1,13 @@ +[Install] +WantedBy=sway-session.target + +[Service] +ExecReload=/nix/store/00000000000000000000000000000000-coreutils/bin/kill -SIGUSR2 $MAINPID +ExecStart=@wl-clipboard@/bin/wl-paste -t text --watch @clipman@/bin/clipman store +KillMode=mixed +Restart=on-failure + +[Unit] +After=graphical-session.target +Description=Clipboard management daemon +PartOf=graphical-session.target diff --git a/tests/modules/services/clipman/default.nix b/tests/modules/services/clipman/default.nix new file mode 100644 index 00000000..abca59c0 --- /dev/null +++ b/tests/modules/services/clipman/default.nix @@ -0,0 +1 @@ +{ clipman-sway-session-target = ./clipman-sway-session-target.nix; } diff --git a/tests/modules/services/lieer/lieer-service-expected.service b/tests/modules/services/lieer/lieer-service-expected.service index 89859f82..f532bff2 100644 --- a/tests/modules/services/lieer/lieer-service-expected.service +++ b/tests/modules/services/lieer/lieer-service-expected.service @@ -1,6 +1,6 @@ [Service] Environment=NOTMUCH_CONFIG=/home/hm-user/.config/notmuch/default/config -ExecStart=@gmailieer@/bin/gmi sync +ExecStart=@lieer@/bin/gmi sync Type=oneshot WorkingDirectory=/home/hm-user/Mail/hm@example.com diff --git a/tests/modules/services/lieer/lieer-service.nix b/tests/modules/services/lieer/lieer-service.nix index f624ae82..f11f1f6e 100644 --- a/tests/modules/services/lieer/lieer-service.nix +++ b/tests/modules/services/lieer/lieer-service.nix @@ -19,7 +19,7 @@ with lib; }; }; - test.stubs.gmailieer = { }; + test.stubs.lieer = { }; nmt.script = '' assertFileExists home-files/.config/systemd/user/lieer-hm-example-com.service diff --git a/tests/modules/services/mpd/basic-configuration.conf b/tests/modules/services/mpd/basic-configuration.conf index 54d6059f..59b3568b 100644 --- a/tests/modules/services/mpd/basic-configuration.conf +++ b/tests/modules/services/mpd/basic-configuration.conf @@ -1,4 +1,4 @@ -music_directory "/home/hm-user/music" +music_directory "/my/music/dir" playlist_directory "/home/hm-user/.local/share/mpd/playlists" db_file "/home/hm-user/.local/share/mpd/tag_cache" diff --git a/tests/modules/services/mpd/basic-configuration.nix b/tests/modules/services/mpd/basic-configuration.nix index c1f28898..6d6250d9 100644 --- a/tests/modules/services/mpd/basic-configuration.nix +++ b/tests/modules/services/mpd/basic-configuration.nix @@ -3,7 +3,12 @@ with lib; { - services.mpd.enable = true; + services.mpd = { + enable = true; + musicDirectory = "/my/music/dir"; + }; + + home.stateVersion = "22.11"; test.stubs.mpd = { }; diff --git a/tests/modules/services/mpd/before-state-version-22_11.nix b/tests/modules/services/mpd/before-state-version-22_11.nix new file mode 100644 index 00000000..6e044b36 --- /dev/null +++ b/tests/modules/services/mpd/before-state-version-22_11.nix @@ -0,0 +1,24 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + services.mpd.enable = true; + + home.stateVersion = "18.09"; + + test.stubs.mpd = { }; + + nmt.script = '' + serviceFile=$(normalizeStorePaths home-files/.config/systemd/user/mpd.service) + assertFileContent "$serviceFile" ${./basic-configuration.service} + + confFile=$(grep -o \ + '/nix/store/.*-mpd.conf' \ + $TESTED/home-files/.config/systemd/user/mpd.service) + + assertFileContains \ + "$confFile" \ + 'music_directory "/home/hm-user/music"' + ''; +} diff --git a/tests/modules/services/mpd/default.nix b/tests/modules/services/mpd/default.nix index 22d1638e..d2fd2a29 100644 --- a/tests/modules/services/mpd/default.nix +++ b/tests/modules/services/mpd/default.nix @@ -1 +1,5 @@ -{ mpd-basic-configuration = ./basic-configuration.nix; } +{ + mpd-basic-configuration = ./basic-configuration.nix; + mpd-before-state-version-22_11 = ./before-state-version-22_11.nix; + mpd-xdg-music-dir = ./xdg-music-dir.nix; +} diff --git a/tests/modules/services/mpd/xdg-music-dir.conf b/tests/modules/services/mpd/xdg-music-dir.conf new file mode 100644 index 00000000..56fe71b4 --- /dev/null +++ b/tests/modules/services/mpd/xdg-music-dir.conf @@ -0,0 +1,11 @@ +music_directory "/home/hm-user/Music" +playlist_directory "/home/hm-user/.local/share/mpd/playlists" +db_file "/home/hm-user/.local/share/mpd/tag_cache" + +state_file "/home/hm-user/.local/share/mpd/state" +sticker_file "/home/hm-user/.local/share/mpd/sticker.sql" + +bind_to_address "127.0.0.1" + + + diff --git a/tests/modules/services/mpd/xdg-music-dir.nix b/tests/modules/services/mpd/xdg-music-dir.nix new file mode 100644 index 00000000..775043c1 --- /dev/null +++ b/tests/modules/services/mpd/xdg-music-dir.nix @@ -0,0 +1,22 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + services.mpd.enable = true; + xdg.userDirs.enable = true; + + home.stateVersion = "22.11"; + + test.stubs.mpd = { }; + + nmt.script = '' + serviceFile=$(normalizeStorePaths home-files/.config/systemd/user/mpd.service) + assertFileContent "$serviceFile" ${./basic-configuration.service} + + confFile=$(grep -o \ + '/nix/store/.*-mpd.conf' \ + $TESTED/home-files/.config/systemd/user/mpd.service) + assertFileContent "$confFile" ${./xdg-music-dir.conf} + ''; +} diff --git a/tests/modules/services/mpdris2/basic-configuration.nix b/tests/modules/services/mpdris2/basic-configuration.nix index 5e809df3..b8c595be 100644 --- a/tests/modules/services/mpdris2/basic-configuration.nix +++ b/tests/modules/services/mpdris2/basic-configuration.nix @@ -7,6 +7,8 @@ multimediaKeys = true; }; + services.mpd.musicDirectory = "/home/hm-user/music"; + test.stubs.mpdris2 = { }; nmt.script = '' diff --git a/tests/modules/services/mpdris2/with-password.nix b/tests/modules/services/mpdris2/with-password.nix index fcfe1531..af4ef33c 100644 --- a/tests/modules/services/mpdris2/with-password.nix +++ b/tests/modules/services/mpdris2/with-password.nix @@ -10,6 +10,8 @@ }; }; + services.mpd.musicDirectory = "/home/hm-user/music"; + test.stubs.mpdris2 = { }; nmt.script = '' diff --git a/tests/modules/services/parcellite/default.nix b/tests/modules/services/parcellite/default.nix new file mode 100644 index 00000000..5cf326b1 --- /dev/null +++ b/tests/modules/services/parcellite/default.nix @@ -0,0 +1 @@ +{ parcellite = ./parcellite.nix; } diff --git a/tests/modules/services/parcellite/parcellite-expected.service b/tests/modules/services/parcellite/parcellite-expected.service new file mode 100644 index 00000000..02d8243a --- /dev/null +++ b/tests/modules/services/parcellite/parcellite-expected.service @@ -0,0 +1,13 @@ +[Install] +WantedBy=graphical-session.target + +[Service] +ExecStart=@parcellite@/bin/parcellite '--no-icon' +Restart=on-abort + +[Unit] +After=graphical-session-pre.target +After=tray.target +Description=Lightweight GTK+ clipboard manager +PartOf=graphical-session.target +Requires=tray.target diff --git a/tests/modules/services/parcellite/parcellite.nix b/tests/modules/services/parcellite/parcellite.nix new file mode 100644 index 00000000..25e553bc --- /dev/null +++ b/tests/modules/services/parcellite/parcellite.nix @@ -0,0 +1,18 @@ +{ config, pkgs, ... }: + +{ + services.parcellite = { + enable = true; + package = config.lib.test.mkStubPackage { + name = "parcellite"; + outPath = "@parcellite@"; + }; + extraOptions = [ "--no-icon" ]; + }; + + nmt.script = '' + assertFileContent \ + "home-files/.config/systemd/user/parcellite.service" \ + ${./parcellite-expected.service} + ''; +} diff --git a/tests/modules/services/pass-secret-service/basic-configuration.nix b/tests/modules/services/pass-secret-service/basic-configuration.nix new file mode 100644 index 00000000..f5568df7 --- /dev/null +++ b/tests/modules/services/pass-secret-service/basic-configuration.nix @@ -0,0 +1,17 @@ +{ config, pkgs, ... }: + +{ + services.pass-secret-service = { + enable = true; + package = config.lib.test.mkStubPackage { }; + storePath = "/mnt/password-store"; + }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/pass-secret-service.service + + assertFileExists $serviceFile + assertFileRegex $serviceFile 'ExecStart=.*/bin/pass_secret_service' + assertFileRegex $serviceFile '/mnt/password-store' + ''; +} diff --git a/tests/modules/services/pass-secret-service/default-configuration.nix b/tests/modules/services/pass-secret-service/default-configuration.nix new file mode 100644 index 00000000..d418d823 --- /dev/null +++ b/tests/modules/services/pass-secret-service/default-configuration.nix @@ -0,0 +1,15 @@ +{ config, pkgs, ... }: + +{ + services.pass-secret-service = { + enable = true; + package = config.lib.test.mkStubPackage { }; + }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/pass-secret-service.service + + assertFileExists $serviceFile + assertFileRegex $serviceFile 'ExecStart=.*/bin/pass_secret_service' + ''; +} diff --git a/tests/modules/services/pass-secret-service/default.nix b/tests/modules/services/pass-secret-service/default.nix new file mode 100644 index 00000000..d841c97e --- /dev/null +++ b/tests/modules/services/pass-secret-service/default.nix @@ -0,0 +1,4 @@ +{ + pass-secret-service-default-configuration = ./default-configuration.nix; + pass-secret-service-basic-configuration = ./basic-configuration.nix; +} diff --git a/tests/modules/services/picom/picom-basic-configuration-expected.service b/tests/modules/services/picom/picom-basic-configuration-expected.service index 62620502..6aeef224 100644 --- a/tests/modules/services/picom/picom-basic-configuration-expected.service +++ b/tests/modules/services/picom/picom-basic-configuration-expected.service @@ -2,7 +2,7 @@ WantedBy=graphical-session.target [Service] -ExecStart=@picom@/bin/picom --config /nix/store/00000000000000000000000000000000-hm_picompicom.conf --experimental-backends +ExecStart=@picom@/bin/picom --config /nix/store/00000000000000000000000000000000-hm_picompicom.conf --legacy-backends Restart=always RestartSec=3 diff --git a/tests/modules/services/picom/picom-basic-configuration.nix b/tests/modules/services/picom/picom-basic-configuration.nix index 67848f52..1c268979 100644 --- a/tests/modules/services/picom/picom-basic-configuration.nix +++ b/tests/modules/services/picom/picom-basic-configuration.nix @@ -19,7 +19,7 @@ "unredir-if-possible" = true; "dbe" = true; }; - experimentalBackends = true; + extraArgs = [ "--legacy-backends" ]; }; test.stubs.picom = { }; diff --git a/tests/modules/services/polybar/basic-configuration.nix b/tests/modules/services/polybar/basic-configuration.nix index e5bb3f38..5d9c8df5 100644 --- a/tests/modules/services/polybar/basic-configuration.nix +++ b/tests/modules/services/polybar/basic-configuration.nix @@ -47,7 +47,7 @@ serviceFile=home-files/.config/systemd/user/polybar.service assertFileExists $serviceFile - assertFileRegex $serviceFile 'X-Restart-Triggers=.*polybar\.conf' + assertFileRegex $serviceFile 'X-Restart-Triggers=/nix/store/.*-polybar.conf$' assertFileRegex $serviceFile 'ExecStart=.*/bin/polybar-start' assertFileExists home-files/.config/polybar/config.ini diff --git a/tests/modules/services/polybar/default.nix b/tests/modules/services/polybar/default.nix index 94d5d3cd..b5594d24 100644 --- a/tests/modules/services/polybar/default.nix +++ b/tests/modules/services/polybar/default.nix @@ -1 +1,4 @@ -{ polybar-basic-configuration = ./basic-configuration.nix; } +{ + polybar-basic-configuration = ./basic-configuration.nix; + polybar-empty-configuration = ./empty-configuration.nix; +} diff --git a/tests/modules/services/polybar/empty-configuration.nix b/tests/modules/services/polybar/empty-configuration.nix new file mode 100644 index 00000000..26350967 --- /dev/null +++ b/tests/modules/services/polybar/empty-configuration.nix @@ -0,0 +1,21 @@ +{ config, pkgs, ... }: + +{ + config = { + services.polybar = { + enable = true; + package = config.lib.test.mkStubPackage { }; + script = "polybar bar &"; + }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/polybar.service + + assertFileExists $serviceFile + assertFileNotRegex $serviceFile 'X-Restart-Triggers=/nix/store/.*-polybar.conf$' + assertFileRegex $serviceFile 'ExecStart=.*/bin/polybar-start' + + assertPathNotExists home-files/.config/polybar/config.ini + ''; + }; +} diff --git a/tests/modules/services/redshift-gammastep/gammastep-basic-configuration-expected.service b/tests/modules/services/redshift-gammastep/gammastep-basic-configuration-expected.service index 8d0e7a5f..d172e3a8 100644 --- a/tests/modules/services/redshift-gammastep/gammastep-basic-configuration-expected.service +++ b/tests/modules/services/redshift-gammastep/gammastep-basic-configuration-expected.service @@ -2,7 +2,7 @@ WantedBy=graphical-session.target [Service] -ExecStart=@gammastep@/bin/gammastep -v -c /home/hm-user/.config/gammastep/config.ini +ExecStart=@gammastep@/bin/gammastep '-c' '/home/hm-user/.config/gammastep/config.ini' Restart=on-failure RestartSec=3 diff --git a/tests/modules/services/redshift-gammastep/redshift-basic-configuration-expected.service b/tests/modules/services/redshift-gammastep/redshift-basic-configuration-expected.service index 07ffbf06..6ee4cdda 100644 --- a/tests/modules/services/redshift-gammastep/redshift-basic-configuration-expected.service +++ b/tests/modules/services/redshift-gammastep/redshift-basic-configuration-expected.service @@ -2,7 +2,7 @@ WantedBy=graphical-session.target [Service] -ExecStart=@redshift@/bin/redshift -v -c /home/hm-user/.config/redshift/redshift.conf +ExecStart=@redshift@/bin/redshift '-c' '/home/hm-user/.config/redshift/redshift.conf' Restart=on-failure RestartSec=3 diff --git a/tests/modules/services/window-managers/herbstluftwm/default.nix b/tests/modules/services/window-managers/herbstluftwm/default.nix index 04b9f89c..31e73365 100644 --- a/tests/modules/services/window-managers/herbstluftwm/default.nix +++ b/tests/modules/services/window-managers/herbstluftwm/default.nix @@ -1 +1,4 @@ -{ herbstluftwm-simple-config = ./herbstluftwm-simple-config.nix; } +{ + herbstluftwm-simple-config = ./herbstluftwm-simple-config.nix; + herbstluftwm-no-tags = ./herbstluftwm-no-tags.nix; +} diff --git a/tests/modules/services/window-managers/herbstluftwm/herbstluftwm-no-tags-autostart b/tests/modules/services/window-managers/herbstluftwm/herbstluftwm-no-tags-autostart new file mode 100644 index 00000000..9e8cd78a --- /dev/null +++ b/tests/modules/services/window-managers/herbstluftwm/herbstluftwm-no-tags-autostart @@ -0,0 +1,32 @@ +#!/nix/store/00000000000000000000000000000000-bash/bin/bash +shopt -s expand_aliases + +# shellcheck disable=SC2142 +alias herbstclient='set -- "$@" ";"' +set -- + +herbstclient emit_hook reload + +# Reset everything. +herbstclient attr theme.tiling.reset 1 +herbstclient attr theme.floating.reset 1 +herbstclient keyunbind --all +herbstclient mouseunbind --all +herbstclient unrule --all + + + + + + + + + + + + + +herbstclient unlock + +@herbstluftwm@/bin/herbstclient chain ";" "$@" + diff --git a/tests/modules/services/window-managers/herbstluftwm/herbstluftwm-no-tags.nix b/tests/modules/services/window-managers/herbstluftwm/herbstluftwm-no-tags.nix new file mode 100644 index 00000000..bd7fb488 --- /dev/null +++ b/tests/modules/services/window-managers/herbstluftwm/herbstluftwm-no-tags.nix @@ -0,0 +1,16 @@ +{ lib, pkgs, ... }: + +{ + xsession.windowManager.herbstluftwm = { enable = true; }; + + test.stubs.herbstluftwm = { }; + + nmt.script = '' + autostart=home-files/.config/herbstluftwm/autostart + assertFileExists "$autostart" + assertFileIsExecutable "$autostart" + + normalizedAutostart=$(normalizeStorePaths "$autostart") + assertFileContent "$normalizedAutostart" ${./herbstluftwm-no-tags-autostart} + ''; +} diff --git a/tests/modules/services/window-managers/herbstluftwm/autostart b/tests/modules/services/window-managers/herbstluftwm/herbstluftwm-simple-config-autostart old mode 100755 new mode 100644 similarity index 89% rename from tests/modules/services/window-managers/herbstluftwm/autostart rename to tests/modules/services/window-managers/herbstluftwm/herbstluftwm-simple-config-autostart index d59da4ba..5f101e0b --- a/tests/modules/services/window-managers/herbstluftwm/autostart +++ b/tests/modules/services/window-managers/herbstluftwm/herbstluftwm-simple-config-autostart @@ -11,6 +11,7 @@ herbstclient emit_hook reload herbstclient attr theme.tiling.reset 1 herbstclient attr theme.floating.reset 1 herbstclient keyunbind --all +herbstclient mouseunbind --all herbstclient unrule --all herbstclient set always_show_frame true @@ -19,7 +20,7 @@ herbstclient set frame_bg_active_color '#000000' herbstclient set frame_gap '12' herbstclient set frame_padding '-12' -if @herbstluftwm@/bin/herbstclient object_tree tags.by-name | /nix/store/00000000000000000000000000000000-gnugrep/bin/grep default; then +if @herbstluftwm@/bin/herbstclient object_tree tags.default &>/dev/null; then herbstclient rename default '1' fi @@ -27,6 +28,7 @@ for tag in '1' 'with space' 'wə1rd#ch@rs'\'''; do herbstclient add "$tag" done + herbstclient keybind Mod4-1 use 1 herbstclient keybind Mod4-2 use 2 herbstclient keybind Mod4-Alt-Tab cycle -1 diff --git a/tests/modules/services/window-managers/herbstluftwm/herbstluftwm-simple-config.nix b/tests/modules/services/window-managers/herbstluftwm/herbstluftwm-simple-config.nix index 27e87150..e351e78f 100644 --- a/tests/modules/services/window-managers/herbstluftwm/herbstluftwm-simple-config.nix +++ b/tests/modules/services/window-managers/herbstluftwm/herbstluftwm-simple-config.nix @@ -39,6 +39,8 @@ assertFileIsExecutable "$autostart" normalizedAutostart=$(normalizeStorePaths "$autostart") - assertFileContent "$normalizedAutostart" ${./autostart} + assertFileContent "$normalizedAutostart" ${ + ./herbstluftwm-simple-config-autostart + } ''; } diff --git a/tests/modules/services/window-managers/i3/i3-bar-focused-colors-expected.conf b/tests/modules/services/window-managers/i3/i3-bar-focused-colors-expected.conf index 92f23a92..3b8fca8a 100644 --- a/tests/modules/services/window-managers/i3/i3-bar-focused-colors-expected.conf +++ b/tests/modules/services/window-managers/i3/i3-bar-focused-colors-expected.conf @@ -3,7 +3,7 @@ floating_modifier Mod1 default_border normal 2 default_floating_border normal 2 hide_edge_borders none -force_focus_wrapping no +focus_wrapping yes focus_follows_mouse yes focus_on_window_activation smart mouse_warping output diff --git a/tests/modules/services/window-managers/i3/i3-followmouse-expected.conf b/tests/modules/services/window-managers/i3/i3-followmouse-expected.conf index 27234b96..dccf535a 100644 --- a/tests/modules/services/window-managers/i3/i3-followmouse-expected.conf +++ b/tests/modules/services/window-managers/i3/i3-followmouse-expected.conf @@ -3,7 +3,7 @@ floating_modifier Mod1 default_border normal 2 default_floating_border normal 2 hide_edge_borders none -force_focus_wrapping no +focus_wrapping yes focus_follows_mouse no focus_on_window_activation smart mouse_warping output 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 d85d978e..8e8cb9da 100644 --- a/tests/modules/services/window-managers/i3/i3-fonts-expected.conf +++ b/tests/modules/services/window-managers/i3/i3-fonts-expected.conf @@ -3,7 +3,7 @@ floating_modifier Mod1 default_border normal 2 default_floating_border normal 2 hide_edge_borders none -force_focus_wrapping no +focus_wrapping yes focus_follows_mouse yes focus_on_window_activation smart mouse_warping output diff --git a/tests/modules/services/window-managers/i3/i3-keybindings-expected.conf b/tests/modules/services/window-managers/i3/i3-keybindings-expected.conf index b3b4c33d..2b7251d2 100644 --- a/tests/modules/services/window-managers/i3/i3-keybindings-expected.conf +++ b/tests/modules/services/window-managers/i3/i3-keybindings-expected.conf @@ -3,7 +3,7 @@ floating_modifier Mod1 default_border normal 2 default_floating_border normal 2 hide_edge_borders none -force_focus_wrapping no +focus_wrapping yes focus_follows_mouse yes focus_on_window_activation smart mouse_warping output diff --git a/tests/modules/services/window-managers/i3/i3-workspace-default-expected.conf b/tests/modules/services/window-managers/i3/i3-workspace-default-expected.conf index d7fe4b61..baca1411 100644 --- a/tests/modules/services/window-managers/i3/i3-workspace-default-expected.conf +++ b/tests/modules/services/window-managers/i3/i3-workspace-default-expected.conf @@ -3,7 +3,7 @@ floating_modifier Mod1 default_border normal 2 default_floating_border normal 2 hide_edge_borders none -force_focus_wrapping no +focus_wrapping yes focus_follows_mouse yes focus_on_window_activation smart mouse_warping output diff --git a/tests/modules/services/window-managers/i3/i3-workspace-output-expected.conf b/tests/modules/services/window-managers/i3/i3-workspace-output-expected.conf index dedad29e..a51edb9a 100644 --- a/tests/modules/services/window-managers/i3/i3-workspace-output-expected.conf +++ b/tests/modules/services/window-managers/i3/i3-workspace-output-expected.conf @@ -3,7 +3,7 @@ floating_modifier Mod1 default_border normal 2 default_floating_border normal 2 hide_edge_borders none -force_focus_wrapping no +focus_wrapping yes focus_follows_mouse yes focus_on_window_activation smart mouse_warping output 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 7f44a2b5..a3b9905d 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 @@ -27,7 +27,7 @@ bindsym Mod1+8 workspace number 8 bindsym Mod1+9 workspace number 9 bindsym Mod1+Down focus down bindsym Mod1+Left focus left -bindsym Mod1+Return exec @rxvt-unicode-unwrapped@/bin/urxvt +bindsym Mod1+Return exec @foot@/bin/foot bindsym Mod1+Right focus right bindsym Mod1+Shift+1 move container to workspace number 1 bindsym Mod1+Shift+2 move container to workspace number 2 @@ -106,4 +106,4 @@ bar { } } -exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP; 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; systemctl --user start 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 9029febf..65780062 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 @@ -29,7 +29,7 @@ bindsym --to-code Mod1+8 workspace number 8 bindsym --to-code Mod1+9 workspace number 9 bindsym --to-code Mod1+Down focus down bindsym --to-code Mod1+Left focus left -bindsym --to-code Mod1+Return exec @rxvt-unicode-unwrapped@/bin/urxvt +bindsym --to-code Mod1+Return exec @foot@/bin/foot bindsym --to-code Mod1+Right focus right bindsym --to-code Mod1+Shift+1 move container to workspace number 1 bindsym --to-code Mod1+Shift+2 move container to workspace number 2 @@ -105,5 +105,5 @@ bar { } } -exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP; 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; systemctl --user start 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 0ca82f99..e1fa6626 100644 --- a/tests/modules/services/window-managers/sway/sway-default.conf +++ b/tests/modules/services/window-managers/sway/sway-default.conf @@ -27,7 +27,7 @@ bindsym Mod1+8 workspace number 8 bindsym Mod1+9 workspace number 9 bindsym Mod1+Down focus down bindsym Mod1+Left focus left -bindsym Mod1+Return exec @rxvt-unicode-unwrapped@/bin/urxvt +bindsym Mod1+Return exec @foot@/bin/foot bindsym Mod1+Right focus right bindsym Mod1+Shift+1 move container to workspace number 1 bindsym Mod1+Shift+2 move container to workspace number 2 @@ -103,4 +103,4 @@ bar { } } -exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP; 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; systemctl --user start 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 e8afc19d..bf996637 100644 --- a/tests/modules/services/window-managers/sway/sway-followmouse-expected.conf +++ b/tests/modules/services/window-managers/sway/sway-followmouse-expected.conf @@ -27,7 +27,7 @@ bindsym Mod1+8 workspace number 8 bindsym Mod1+9 workspace number 9 bindsym Mod1+Down focus down bindsym Mod1+Left focus left -bindsym Mod1+Return exec @rxvt-unicode-unwrapped@/bin/urxvt +bindsym Mod1+Return exec @foot@/bin/foot bindsym Mod1+Right focus right bindsym Mod1+Shift+1 move container to workspace number 1 bindsym Mod1+Shift+2 move container to workspace number 2 @@ -81,4 +81,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; 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; systemctl --user start 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 bba46942..d93031c9 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 @@ -27,7 +27,7 @@ bindsym Mod1+8 workspace number 8 bindsym Mod1+9 workspace number 9 bindsym Mod1+Down focus down bindsym Mod1+Left focus left -bindsym Mod1+Return exec @rxvt-unicode-unwrapped@/bin/urxvt +bindsym Mod1+Return exec @foot@/bin/foot bindsym Mod1+Right focus right bindsym Mod1+Shift+1 move container to workspace number 1 bindsym Mod1+Shift+2 move container to workspace number 2 @@ -81,4 +81,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; 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; systemctl --user start 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 8753b24a..b217f884 100644 --- a/tests/modules/services/window-managers/sway/sway-modules.conf +++ b/tests/modules/services/window-managers/sway/sway-modules.conf @@ -27,7 +27,7 @@ bindsym Mod1+8 workspace number 8 bindsym Mod1+9 workspace number 9 bindsym Mod1+Down focus down bindsym Mod1+Left focus left -bindsym Mod1+Return exec @rxvt-unicode-unwrapped@/bin/urxvt +bindsym Mod1+Return exec @foot@/bin/foot bindsym Mod1+Right focus right bindsym Mod1+Shift+1 move container to workspace number 1 bindsym Mod1+Shift+2 move container to workspace number 2 @@ -115,4 +115,4 @@ bar { } } -exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP; 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; systemctl --user start 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 0ca82f99..e1fa6626 100644 --- a/tests/modules/services/window-managers/sway/sway-null-package.conf +++ b/tests/modules/services/window-managers/sway/sway-null-package.conf @@ -27,7 +27,7 @@ bindsym Mod1+8 workspace number 8 bindsym Mod1+9 workspace number 9 bindsym Mod1+Down focus down bindsym Mod1+Left focus left -bindsym Mod1+Return exec @rxvt-unicode-unwrapped@/bin/urxvt +bindsym Mod1+Return exec @foot@/bin/foot bindsym Mod1+Right focus right bindsym Mod1+Shift+1 move container to workspace number 1 bindsym Mod1+Shift+2 move container to workspace number 2 @@ -103,4 +103,4 @@ bar { } } -exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP; 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; systemctl --user start sway-session.target" diff --git a/tests/modules/services/window-managers/sway/sway-stubs.nix b/tests/modules/services/window-managers/sway/sway-stubs.nix index 55a74e1c..2ae673c7 100644 --- a/tests/modules/services/window-managers/sway/sway-stubs.nix +++ b/tests/modules/services/window-managers/sway/sway-stubs.nix @@ -3,7 +3,7 @@ # not containing hashes, version numbers etc. test.stubs = { dmenu = { }; - rxvt-unicode-unwrapped = { }; + foot = { }; i3status = { }; sway = { }; sway-unwrapped = { version = "1"; }; 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 2f2dd125..b783d4c2 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 @@ -26,7 +26,7 @@ bindsym Mod1+7 workspace number 7 bindsym Mod1+8 workspace number 8 bindsym Mod1+Down focus down bindsym Mod1+Left focus left -bindsym Mod1+Return exec @rxvt-unicode-unwrapped@/bin/urxvt +bindsym Mod1+Return exec @foot@/bin/foot bindsym Mod1+Right focus right bindsym Mod1+Shift+1 move container to workspace number 1 bindsym Mod1+Shift+2 move container to workspace number 2 @@ -102,4 +102,4 @@ bar { } } -exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP; 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; systemctl --user start 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 4ec1e7ce..94ba5e27 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 @@ -27,7 +27,7 @@ bindsym Mod1+8 workspace number 8 bindsym Mod1+9 workspace number 9 bindsym Mod1+Down focus down bindsym Mod1+Left focus left -bindsym Mod1+Return exec @rxvt-unicode-unwrapped@/bin/urxvt +bindsym Mod1+Return exec @foot@/bin/foot bindsym Mod1+Right focus right bindsym Mod1+Shift+1 move container to workspace number 1 bindsym Mod1+Shift+2 move container to workspace number 2 @@ -107,4 +107,4 @@ workspace "1" output eDP workspace "ABC" output DP workspace "3: Test" output HDMI workspace "!"§$%&/(){}[]=?\*#<>-_.:,;²³" output DVI -exec "/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP; 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; systemctl --user start sway-session.target" diff --git a/tests/modules/systemd/default.nix b/tests/modules/systemd/default.nix index c949edd9..a0271b47 100644 --- a/tests/modules/systemd/default.nix +++ b/tests/modules/systemd/default.nix @@ -2,5 +2,6 @@ systemd-services = ./services.nix; systemd-services-disabled-for-root = ./services-disabled-for-root.nix; systemd-session-variables = ./session-variables.nix; + systemd-slices = ./slices.nix; systemd-timers = ./timers.nix; } diff --git a/tests/modules/systemd/slices.nix b/tests/modules/systemd/slices.nix new file mode 100644 index 00000000..0bb90504 --- /dev/null +++ b/tests/modules/systemd/slices.nix @@ -0,0 +1,31 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + systemd.user.slices.app-test = { + Unit = { Description = "Slice for a test app"; }; + + Slice = { + MemoryHigh = "30%"; + MemoryMax = "40%"; + }; + }; + + nmt.script = '' + sliceFile=home-files/.config/systemd/user/app-test.slice + assertFileExists $sliceFile + assertFileContent $sliceFile ${ + builtins.toFile "app-test-expected.conf" '' + [Slice] + MemoryHigh=30% + MemoryMax=40% + + [Unit] + Description=Slice for a test app + '' + } + ''; + }; +} diff --git a/tests/modules/targets-darwin/user-defaults.nix b/tests/modules/targets-darwin/user-defaults.nix index 26e0656e..bb23f718 100644 --- a/tests/modules/targets-darwin/user-defaults.nix +++ b/tests/modules/targets-darwin/user-defaults.nix @@ -10,9 +10,9 @@ nmt.script = '' assertFileRegex activate \ - "defaults import 'com.apple.desktopservices' /nix/store/[a-z0-9]\\{32\\}-com\\.apple\\.desktopservices\\.plist" + "/usr/bin/defaults import 'com.apple.desktopservices' /nix/store/[a-z0-9]\\{32\\}-com\\.apple\\.desktopservices\\.plist" assertFileRegex activate \ - "defaults -currentHost import 'com.apple.controlcenter' /nix/store/[a-z0-9]\\{32\\}-com\\.apple\\.controlcenter\\.plist" + "/usr/bin/defaults -currentHost import 'com.apple.controlcenter' /nix/store/[a-z0-9]\\{32\\}-com\\.apple\\.controlcenter\\.plist" ''; }; }