diff options
author | Katharina Fey <kookie@spacekookie.de> | 2020-02-03 10:05:30 +0100 |
---|---|---|
committer | Katharina Fey <kookie@spacekookie.de> | 2020-02-03 10:05:30 +0100 |
commit | c488527c95c874d3b8743c915173ad7bfb05d5af (patch) | |
tree | 2b874dc5606a9dff44096a5e8557f00dc52ac2b6 | |
parent | 899a451e08f7d6d2c8214d119c2a0316849a0ed4 (diff) | |
parent | 6cc4fd6ede4909226cb81d3475834251ed1b7210 (diff) |
Merge commit '6cc4fd6ede4909226cb81d3475834251ed1b7210'
239 files changed, 5470 insertions, 3446 deletions
diff --git a/home-manager/.gitlab-ci.yml b/home-manager/.gitlab-ci.yml index 73c00f30510..f7c14abb69e 100644 --- a/home-manager/.gitlab-ci.yml +++ b/home-manager/.gitlab-ci.yml @@ -1,5 +1,9 @@ image: nixos/nix:latest +variables: + # Pinned 2020-01-01. + NIX_PATH: "nixpkgs=https://github.com/NixOS/nixpkgs/archive/b0bbacb52134a7e731e549f4c0a7a2a39ca6b481.tar.gz" + stages: - test - deploy diff --git a/home-manager/.travis.yml b/home-manager/.travis.yml index df9c468be64..e0712e1e41f 100644 --- a/home-manager/.travis.yml +++ b/home-manager/.travis.yml @@ -8,5 +8,6 @@ before_script: - mkdir -m 0755 -p /nix/var/nix/{profiles,gcroots}/per-user/$USER script: + - ./format -c - nix-shell . -A install - nix-shell tests -A run.all diff --git a/home-manager/CONTRIBUTING.md b/home-manager/CONTRIBUTING.md index 156d0c9daf6..8e64b3b45f9 100644 --- a/home-manager/CONTRIBUTING.md +++ b/home-manager/CONTRIBUTING.md @@ -91,12 +91,15 @@ In addition to the above commit message guidelines, try to follow the ### Style guidelines ### -The code in Home Manager should follow the [Nixpkgs syntax -guidelines][]. Note, we prefer `lowerCamelCase` for variable and -attribute names with the accepted exception of variables directly -referencing packages in Nixpkgs which use a hyphenated style. For -example, the Home Manager option `services.gpg-agent.enableSshSupport` -references the `gpg-agent` package in Nixpkgs. +The code in Home Manager is formatted by the [nixfmt][] tool and the +formatting is checked in the pull request tests. Run the `format` tool +inside the project repository before submitting your pull request. + +Note, we prefer `lowerCamelCase` for variable and attribute names with +the accepted exception of variables directly referencing packages in +Nixpkgs which use a hyphenated style. For example, the Home Manager +option `services.gpg-agent.enableSshSupport` references the +`gpg-agent` package in Nixpkgs. ### News ### @@ -139,15 +142,18 @@ If you do have a change worthy of a news entry then please add one in > use 'services.myservice.bar' instead. - A new module, say `foo.nix`, should always include a news entry - (without any condition) that has a message along the lines of + that has a message along the lines of - > A new service is available: 'services.foo'. + > A new module is available: 'services.foo'. - or + If the module is platform specific, e.g., a service module using + systemd, then a condition like - > A new program configuration is available: 'program.foo'. + ``` + condition = hostPlatform.isLinux; + ``` - depending on the type of module. + should be added. [open issues]: https://github.com/rycee/home-manager/issues [new issue]: https://github.com/rycee/home-manager/issues/new @@ -155,4 +161,4 @@ If you do have a change worthy of a news entry then please add one in [create a pull request]: https://help.github.com/articles/creating-a-pull-request/ [seven rules]: https://chris.beams.io/posts/git-commit/#seven-rules [`news.nix`]: https://github.com/rycee/home-manager/blob/master/modules/misc/news.nix -[Nixpkgs syntax guidelines]: https://nixos.org/nixpkgs/manual/#sec-syntax +[nixfmt]: https://github.com/serokell/nixfmt/ diff --git a/home-manager/FAQ.md b/home-manager/FAQ.md index 141ecc6ea6b..a83a90f6cab 100644 --- a/home-manager/FAQ.md +++ b/home-manager/FAQ.md @@ -119,3 +119,33 @@ The solution on NixOS is to add services.dbus.packages = with pkgs; [ gnome3.dconf ]; to your system configuration. + +How do I install packages from Nixpkgs unstable? +------------------------------------------------ + +If you are using a stable version of Nixpkgs but would like to install +some particular packages from Nixpkgs unstable then you can import the +unstable Nixpkgs and refer to its packages within your configuration. +Something like + +```nix +{ pkgs, config, ... }: + +let + + pkgsUnstable = import <nixpkgs-unstable> {}; + +in + +{ + home.packages = [ + pkgsUnstable.foo + ]; + + # … +} +``` + +should work provided you have a Nix channel called `nixpkgs-unstable`. +Note, the package will not be affected by any package overrides, +overlays, etc. diff --git a/home-manager/README.md b/home-manager/README.md index 58593f7b374..5171ff657f8 100644 --- a/home-manager/README.md +++ b/home-manager/README.md @@ -6,6 +6,9 @@ using the [Nix][] package manager together with the Nix libraries found in [Nixpkgs][]. Before attempting to use Home Manager please read the warning below. +For a more systematic overview of all the options Home Manager +provides please see the [Home Manager manual][configuration options]. + Words of warning ---------------- @@ -19,7 +22,7 @@ will write to your dconf store and cannot tell whether a configuration that it is about to be overwrite was from a previous Home Manager generation or from manual configuration. -Home Manager targets [NixOS][] unstable and NixOS version 19.03 (the +Home Manager targets [NixOS][] unstable and NixOS version 19.09 (the current stable version), it may or may not work on other Linux distributions and NixOS versions. @@ -72,11 +75,11 @@ Currently the easiest way to install Home Manager is as follows: if you are following Nixpkgs master or an unstable channel and ```console - $ nix-channel --add https://github.com/rycee/home-manager/archive/release-19.03.tar.gz home-manager + $ nix-channel --add https://github.com/rycee/home-manager/archive/release-19.09.tar.gz home-manager $ nix-channel --update ``` - if you follow a Nixpkgs version 19.03 channel. + if you follow a Nixpkgs version 19.09 channel. On NixOS you may need to log out and back in for the channel to become available. On non-NixOS you may have to add diff --git a/home-manager/default.nix b/home-manager/default.nix index 1e3ff09e0bc..545b0114191 100644 --- a/home-manager/default.nix +++ b/home-manager/default.nix @@ -1,13 +1,10 @@ -{ pkgs ? import <nixpkgs> {} }: +{ pkgs ? import <nixpkgs> { } }: rec { - home-manager = pkgs.callPackage ./home-manager { - path = toString ./.; - }; + home-manager = pkgs.callPackage ./home-manager { path = toString ./.; }; - install = pkgs.callPackage ./home-manager/install.nix { - inherit home-manager; - }; + install = + pkgs.callPackage ./home-manager/install.nix { inherit home-manager; }; nixos = import ./nixos; } diff --git a/home-manager/doc/default.nix b/home-manager/doc/default.nix index acfa1f1e49c..638027b0a78 100644 --- a/home-manager/doc/default.nix +++ b/home-manager/doc/default.nix @@ -1,36 +1,35 @@ -{ pkgs }: +{ +# Note, this should be "the standard library" + HM extensions. +lib, pkgs }: let - lib = pkgs.lib; - nmdSrc = pkgs.fetchFromGitLab { name = "nmd"; owner = "rycee"; repo = "nmd"; - rev = "9751ca5ef6eb2ef27470010208d4c0a20e89443d"; - sha256 = "0rbx10n8kk0bvp1nl5c8q79lz1w0p1b8103asbvwps3gmqd070hi"; + rev = "b437898c2b137c39d9c5f9a1cf62ec630f14d9fc"; + sha256 = "18j1nh53cfpjpdiwn99x9kqpvr0s7hwngyc0a93xf4sg88ww93lq"; }; - nmd = import nmdSrc { inherit pkgs; }; + nmd = import nmdSrc { inherit lib pkgs; }; # Make sure the used package is scrubbed to avoid actually # instantiating derivations. scrubbedPkgsModule = { - imports = [ - { - _module.args = { - pkgs = lib.mkForce (nmd.scrubDerivations "pkgs" pkgs); - pkgs_i686 = lib.mkForce { }; - }; - } - ]; + imports = [{ + _module.args = { + pkgs = lib.mkForce (nmd.scrubDerivations "pkgs" pkgs); + pkgs_i686 = lib.mkForce { }; + }; + }]; }; hmModulesDocs = nmd.buildModulesDocs { - modules = - import ../modules/modules.nix { inherit lib pkgs; } - ++ [ scrubbedPkgsModule ]; + modules = import ../modules/modules.nix { + inherit lib pkgs; + check = false; + } ++ [ scrubbedPkgsModule ]; moduleRootPaths = [ ./.. ]; mkModuleUrl = path: "https://github.com/rycee/home-manager/blob/master/${path}#blob-path"; @@ -53,9 +52,7 @@ let ''; }; -in - -{ +in { inherit nmdSrc; options = { @@ -66,7 +63,5 @@ in manPages = docs.manPages; - manual = { - inherit (docs) html htmlOpenTool; - }; + manual = { inherit (docs) html htmlOpenTool; }; } diff --git a/home-manager/doc/installation.xml b/home-manager/doc/installation.xml index 0e4c904e570..52119886800 100644 --- a/home-manager/doc/installation.xml +++ b/home-manager/doc/installation.xml @@ -79,11 +79,11 @@ if you are following Nixpkgs master or an unstable channel and </para> <screen> -<prompt>$</prompt> <userinput>nix-channel --add https://github.com/rycee/home-manager/archive/release-19.03.tar.gz home-manager</userinput> +<prompt>$</prompt> <userinput>nix-channel --add https://github.com/rycee/home-manager/archive/release-19.09.tar.gz home-manager</userinput> <prompt>$</prompt> <userinput>nix-channel --update</userinput> </screen> <para> - if you follow a Nixpkgs version 19.03 channel. + if you follow a Nixpkgs version 19.09 channel. </para> <para> On NixOS you may need to log out and back in for the channel to become @@ -169,12 +169,12 @@ $HOME/.nix-profile/etc/profile.d/hm-session-vars.sh </para> <screen> -<prompt>#</prompt> <userinput>nix-channel --add https://github.com/rycee/home-manager/archive/release-19.03.tar.gz home-manager</userinput> +<prompt>#</prompt> <userinput>nix-channel --add https://github.com/rycee/home-manager/archive/release-19.09.tar.gz home-manager</userinput> <prompt>#</prompt> <userinput>nix-channel --update</userinput> </screen> <para> - if you follow a Nixpkgs version 19.03 channel. + if you follow a Nixpkgs version 19.09 channel. </para> <para> @@ -251,12 +251,12 @@ home-manager.useUserPackages = true; </para> <screen> -<prompt>#</prompt> <userinput>nix-channel --add https://github.com/rycee/home-manager/archive/release-19.03.tar.gz home-manager</userinput> +<prompt>#</prompt> <userinput>nix-channel --add https://github.com/rycee/home-manager/archive/release-19.09.tar.gz home-manager</userinput> <prompt>#</prompt> <userinput>nix-channel --update</userinput> </screen> <para> - if you follow a Nixpkgs version 19.03 channel. + if you follow a Nixpkgs version 19.09 channel. </para> <para> diff --git a/home-manager/doc/man-home-manager.xml b/home-manager/doc/man-home-manager.xml index a0f55d1106a..117bc494687 100644 --- a/home-manager/doc/man-home-manager.xml +++ b/home-manager/doc/man-home-manager.xml @@ -127,6 +127,10 @@ </arg> <arg> + --(no-)substitute + </arg> + + <arg> <group choice="req"> <arg choice="plain"> -v @@ -448,6 +452,18 @@ </varlistentry> <varlistentry> <term> + <option>--(no-)substitute</option> + </term> + <listitem> + <para> + Passed on to <citerefentry> + <refentrytitle>nix-build</refentrytitle> + <manvolnum>1</manvolnum> </citerefentry>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> <option>-v</option> </term> <term> diff --git a/home-manager/doc/release-notes/rl-2003.adoc b/home-manager/doc/release-notes/rl-2003.adoc index ff6d9325bd7..fc1dcd7cfe2 100644 --- a/home-manager/doc/release-notes/rl-2003.adoc +++ b/home-manager/doc/release-notes/rl-2003.adoc @@ -9,7 +9,65 @@ section is therefore not final. This release has the following notable changes: -* Nothing has happened. +* Assigning a list to the <<opt-home.file>>, <<opt-xdg.configFile>>, +and <<opt-xdg.dataFile>> options is now deprecated and will produce a +warning message if used. Specifically, if your configuration currently +contains something like ++ +[source,nix] +---- +home.file = [ + { + target = ".config/foo.txt"; + text = "bar"; + } +] +---- ++ +then it should be updated to instead use the equivalent attribute set form ++ +[source,nix] +---- +home.file = { + ".config/foo.txt".text = "bar"; +} +---- ++ +Support for the list form will be removed in Home Manager version +20.09. + +* The `lib` function attribute given to modules is now enriched with +an attribute `hm` containing extra library functions specific for Home +Manager. More specifically, `lib.hm` is now the same as `config.lib` +and should be the preferred choice since it is more robust. ++ +Therefore, if your configuration makes use of, for example, +`config.lib.dag` to create activation script blocks, it is recommended +to change to `lib.hm.dag`. ++ +Note, in the unlikely case that you are ++ +** using Home Manager's NixOS or nix-darwin module, +** have made your own Home Manager module containing an top-level + option named `config` or `options`, and +** assign to this option in your system configuration inside a plain + attribute set, i.e., without a function argument, + ++ +then you must update your configuration to perform the option +assignment inside a `config` attribute. For example, instead of ++ +[source,nix] +---- +home-manager.users.jane = { config = "foo"; }; +---- ++ +use ++ +[source,nix] +---- +home-manager.users.jane = { config.config = "foo"; }; +---- [[sec-release-20.03-state-version-changes]] === State Version Changes @@ -18,4 +76,8 @@ The state version in this release includes the changes below. These changes are only active if the `home.stateVersion` option is set to "20.03" or later. -* Nothing has happened. +* The <<opt-programs.zsh.history.path>> option is no longer prepended + by `$HOME`, which allows specifying absolute paths, for example, + using the xdg module. Also, the default value is fixed to + `$HOME/.zsh_history` and `dotDir` path is not prepended to it + anymore. diff --git a/home-manager/format b/home-manager/format new file mode 100755 index 00000000000..539ae60de22 --- /dev/null +++ b/home-manager/format @@ -0,0 +1,70 @@ +#! /usr/bin/env nix-shell +#! nix-shell -i bash -p findutils nixfmt + +CHECK_ARG= + +case $1 in + -h) + echo "$0 [-c]" + ;; + -c) + CHECK_ARG=-c + ;; +esac + +# The first block of excludes are files where nixfmt does a poor job, +# IMHO. The second block of excludes are files touched by open pull +# requests and we want to avoid merge conflicts. +find . -name '*.nix' \ + ! -path ./modules/programs/irssi.nix \ + \ + ! -path ./home-manager/default.nix \ + ! -path ./home-manager/home-manager.nix \ + ! -path ./modules/accounts/email.nix \ + ! -path ./modules/default.nix \ + ! -path ./modules/files.nix \ + ! -path ./modules/home-environment.nix \ + ! -path ./modules/lib/default.nix \ + ! -path ./modules/lib/file-type.nix \ + ! -path ./modules/lib/types.nix \ + ! -path ./modules/manual.nix \ + ! -path ./modules/misc/dconf.nix \ + ! -path ./modules/misc/gtk.nix \ + ! -path ./modules/misc/news.nix \ + ! -path ./modules/misc/nixpkgs.nix \ + ! -path ./modules/misc/xdg.nix \ + ! -path ./modules/modules.nix \ + ! -path ./modules/programs/afew.nix \ + ! -path ./modules/programs/alot.nix \ + ! -path ./modules/programs/bash.nix \ + ! -path ./modules/programs/emacs.nix \ + ! -path ./modules/programs/firefox.nix \ + ! -path ./modules/programs/fish.nix \ + ! -path ./modules/programs/gpg.nix \ + ! -path ./modules/programs/lesspipe.nix \ + ! -path ./modules/programs/neovim.nix \ + ! -path ./modules/programs/ssh.nix \ + ! -path ./modules/programs/tmux.nix \ + ! -path ./modules/programs/vscode.nix \ + ! -path ./modules/programs/zsh.nix \ + ! -path ./modules/services/gpg-agent.nix \ + ! -path ./modules/services/kbfs.nix \ + ! -path ./modules/services/keybase.nix \ + ! -path ./modules/services/mpd.nix \ + ! -path ./modules/services/sxhkd.nix \ + ! -path ./modules/services/window-managers/i3.nix \ + ! -path ./modules/systemd.nix \ + ! -path ./nix-darwin/default.nix \ + ! -path ./tests/default.nix \ + ! -path ./tests/modules/home-environment/default.nix \ + ! -path ./tests/modules/home-environment/session-variables.nix \ + ! -path ./tests/modules/programs/gpg/override-defaults.nix \ + ! -path ./tests/modules/programs/tmux/default.nix \ + ! -path ./tests/modules/programs/tmux/disable-confirmation-prompt.nix \ + ! -path ./tests/modules/programs/tmux/secure-socket-enabled.nix \ + ! -path ./tests/modules/programs/zsh/session-variables.nix \ + ! -path ./tests/modules/services/sxhkd/service.nix \ + ! -path ./tests/modules/systemd/default.nix \ + ! -path ./tests/modules/systemd/services.nix \ + ! -path ./tests/modules/systemd/session-variables.nix \ + -exec nixfmt $CHECK_ARG {} + diff --git a/home-manager/home-manager/home-manager b/home-manager/home-manager/home-manager index 6fe4f13c7f0..d5a4c4f41a1 100644 --- a/home-manager/home-manager/home-manager +++ b/home-manager/home-manager/home-manager @@ -93,14 +93,14 @@ function doBuildAttr() { nix build \ -f "<home-manager/home-manager/home-manager.nix>" \ $extraArgs \ - ${PASSTHROUGH_OPTS[*]} \ + "${PASSTHROUGH_OPTS[@]}" \ --argstr confPath "$HOME_MANAGER_CONFIG" \ --argstr confAttr "$HOME_MANAGER_CONFIG_ATTRIBUTE" else nix-build \ "<home-manager/home-manager/home-manager.nix>" \ $extraArgs \ - ${PASSTHROUGH_OPTS[*]} \ + "${PASSTHROUGH_OPTS[@]}" \ --argstr confPath "$HOME_MANAGER_CONFIG" \ --argstr confAttr "$HOME_MANAGER_CONFIG_ATTRIBUTE" fi @@ -431,6 +431,7 @@ function doHelp() { echo " --max-jobs NUM" echo " --option NAME VALUE" echo " --show-trace" + echo " --(no-)substitute" echo echo "Commands" echo @@ -507,7 +508,8 @@ while [[ $# -gt 0 ]]; do PASSTHROUGH_OPTS+=("$opt" "$1") shift ;; - --keep-failed|--keep-going|--show-trace) + --keep-failed|--keep-going|--show-trace\ + |--substitute|--no-substitute) PASSTHROUGH_OPTS+=("$opt") ;; -v|--verbose) diff --git a/home-manager/home-manager/install.nix b/home-manager/home-manager/install.nix index c58c0ba7478..87aae50470e 100644 --- a/home-manager/home-manager/install.nix +++ b/home-manager/home-manager/install.nix @@ -1,60 +1,67 @@ { home-manager, runCommand }: -runCommand - "home-manager-install" - { - propagatedBuildInputs = [ home-manager ]; - preferLocalBuild = true; - allowSubstitutes = false; - shellHookOnly = true; - shellHook = '' - confFile="''${XDG_CONFIG_HOME:-$HOME/.config}/nixpkgs/home.nix" - - if [[ ! -e $confFile ]]; then - echo - echo "Creating initial Home Manager configuration..." - - mkdir -p "$(dirname "$confFile")" - cat > $confFile <<EOF - { config, pkgs, ... }: - - { - # Let Home Manager install and manage itself. - programs.home-manager.enable = true; - } - EOF - fi +runCommand "home-manager-install" { + propagatedBuildInputs = [ home-manager ]; + preferLocalBuild = true; + allowSubstitutes = false; + shellHookOnly = true; + shellHook = '' + confFile="''${XDG_CONFIG_HOME:-$HOME/.config}/nixpkgs/home.nix" + if [[ ! -e $confFile ]]; then echo - echo "Creating initial Home Manager generation..." - echo + echo "Creating initial Home Manager configuration..." + + mkdir -p "$(dirname "$confFile")" + cat > $confFile <<EOF + { config, pkgs, ... }: + + { + # Let Home Manager install and manage itself. + programs.home-manager.enable = true; + + # This value determines the Home Manager release that your + # configuration is compatible with. This helps avoid breakage + # when a new Home Manager release introduces backwards + # incompatible changes. + # + # 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 = "19.09"; + } + EOF + fi + + echo + echo "Creating initial Home Manager generation..." + echo - if home-manager switch; then - cat <<EOF + if home-manager switch; then + cat <<EOF - All done! The home-manager tool should now be installed and you - can edit + All done! The home-manager tool should now be installed and you + can edit - $confFile + $confFile - to configure Home Manager. Run 'man home-configuration.nix' to - see all available options. - EOF - exit 0 - else - cat <<EOF + to configure Home Manager. Run 'man home-configuration.nix' to + see all available options. + EOF + exit 0 + else + cat <<EOF - Uh oh, the installation failed! Please create an issue at + Uh oh, the installation failed! Please create an issue at - https://github.com/rycee/home-manager/issues + https://github.com/rycee/home-manager/issues - if the error seems to be the fault of Home Manager. - EOF - exit 1 - fi - ''; - } - '' - echo This derivation is not buildable, instead run it using nix-shell. - exit 1 - '' + if the error seems to be the fault of Home Manager. + EOF + exit 1 + fi + ''; +} '' + echo This derivation is not buildable, instead run it using nix-shell. + exit 1 +'' diff --git a/home-manager/modules/accounts/email.nix b/home-manager/modules/accounts/email.nix index cc9d0dc2813..b3a9db947a9 100644 --- a/home-manager/modules/accounts/email.nix +++ b/home-manager/modules/accounts/email.nix @@ -391,6 +391,7 @@ in (import ../programs/getmail-accounts.nix) (import ../programs/mbsync-accounts.nix) (import ../programs/msmtp-accounts.nix) + (import ../programs/neomutt-accounts.nix) (import ../programs/notmuch-accounts.nix) (import ../programs/offlineimap-accounts.nix) ]); diff --git a/home-manager/modules/default.nix b/home-manager/modules/default.nix index 9f6404ff9cc..7f3494e4dea 100644 --- a/home-manager/modules/default.nix +++ b/home-manager/modules/default.nix @@ -19,10 +19,16 @@ let in fold f res res.config.warnings; - rawModule = lib.evalModules { - modules = - [ configuration ] - ++ (import ./modules.nix { inherit check lib pkgs; }); + extendedLib = import ./lib/stdlib-extended.nix pkgs.lib; + + hmModules = + import ./modules.nix { + inherit check pkgs; + lib = extendedLib; + }; + + rawModule = extendedLib.evalModules { + modules = [ configuration ] ++ hmModules; specialArgs = { modulesPath = builtins.toString ./.; }; diff --git a/home-manager/modules/files.nix b/home-manager/modules/files.nix index ac946976faf..94b3aa565a8 100644 --- a/home-manager/modules/files.nix +++ b/home-manager/modules/files.nix @@ -6,8 +6,6 @@ let cfg = config.home.file; - dag = config.lib.dag; - homeDirectory = config.home.homeDirectory; fileType = (import lib/file-type.nix { @@ -23,10 +21,6 @@ let then file.source else builtins.path { path = file.source; name = sourceName; }; - # A symbolic link whose target path matches this pattern will be - # considered part of a Home Manager generation. - homeFilePattern = "${builtins.storeDir}/*-home-manager-files/*"; - in { @@ -47,18 +41,22 @@ in config = { # This verifies that the links we are about to create will not # overwrite an existing file. - home.activation.checkLinkTargets = dag.entryBefore ["writeBoundary"] ( + home.activation.checkLinkTargets = hm.dag.entryBefore ["writeBoundary"] ( let check = pkgs.writeText "check" '' . ${./lib-bash/color-echo.sh} + # A symbolic link whose target path matches this pattern will be + # considered part of a Home Manager generation. + homeFilePattern="$(readlink -e "${builtins.storeDir}")/*-home-manager-files/*" + newGenFiles="$1" shift for sourcePath in "$@" ; do relativePath="''${sourcePath#$newGenFiles/}" targetPath="$HOME/$relativePath" if [[ -e "$targetPath" \ - && ! "$(readlink "$targetPath")" == ${homeFilePattern} ]] ; then + && ! "$(readlink "$targetPath")" == $homeFilePattern ]] ; then if [[ ! -L "$targetPath" && -n "$HOME_MANAGER_BACKUP_EXT" ]] ; then backup="$targetPath.$HOME_MANAGER_BACKUP_EXT" if [[ -e "$backup" ]]; then @@ -113,7 +111,7 @@ in # and a failure during the intermediate state FA ∩ FB will not # result in lost links because this set of links are in both the # source and target generation. - home.activation.linkGeneration = dag.entryAfter ["writeBoundary"] ( + home.activation.linkGeneration = hm.dag.entryAfter ["writeBoundary"] ( let link = pkgs.writeText "link" '' newGenFiles="$1" @@ -133,13 +131,17 @@ in cleanup = pkgs.writeText "cleanup" '' . ${./lib-bash/color-echo.sh} + # A symbolic link whose target path matches this pattern will be + # considered part of a Home Manager generation. + homeFilePattern="$(readlink -e "${builtins.storeDir}")/*-home-manager-files/*" + newGenFiles="$1" shift 1 for relativePath in "$@" ; do targetPath="$HOME/$relativePath" if [[ -e "$newGenFiles/$relativePath" ]] ; then $VERBOSE_ECHO "Checking $targetPath: exists" - elif [[ ! "$(readlink "$targetPath")" == ${homeFilePattern} ]] ; then + elif [[ ! "$(readlink "$targetPath")" == $homeFilePattern ]] ; then warnEcho "Path '$targetPath' not link into Home Manager generation. Skipping delete." else $VERBOSE_ECHO "Checking $targetPath: gone (deleting)" @@ -206,7 +208,7 @@ in '' ); - home.activation.checkFilesChanged = dag.entryBefore ["linkGeneration"] ( + home.activation.checkFilesChanged = hm.dag.entryBefore ["linkGeneration"] ( '' declare -A changedFiles '' + concatMapStrings (v: '' @@ -216,7 +218,7 @@ in '') (filter (v: v.onChange != "") (attrValues cfg)) ); - home.activation.onFilesChange = dag.entryAfter ["linkGeneration"] ( + home.activation.onFilesChange = hm.dag.entryAfter ["linkGeneration"] ( concatMapStrings (v: '' if [[ ${"$\{changedFiles"}["${v.target}"]} -eq 1 ]]; then ${v.onChange} @@ -236,6 +238,9 @@ in ('' mkdir -p $out + # Needed in case /nix is a symbolic link. + realOut="$(realpath -m "$out")" + function insertFile() { local source="$1" local relTarget="$2" @@ -244,10 +249,10 @@ in # Figure out the real absolute path to the target. local target - target="$(realpath -m "$out/$relTarget")" + target="$(realpath -m "$realOut/$relTarget")" # Target path must be within $HOME. - if [[ ! $target == $out* ]] ; then + if [[ ! $target == $realOut* ]] ; then echo "Error installing file '$relTarget' outside \$HOME" >&2 exit 1 fi diff --git a/home-manager/modules/home-environment.nix b/home-manager/modules/home-environment.nix index f12e86d4104..0b2fb8f4ef9 100644 --- a/home-manager/modules/home-environment.nix +++ b/home-manager/modules/home-environment.nix @@ -6,8 +6,6 @@ let cfg = config.home; - dag = config.lib.dag; - languageSubModule = types.submodule { options = { base = mkOption { @@ -234,17 +232,51 @@ in }; home.activation = mkOption { - internal = true; + type = hm.types.dagOf types.str; default = {}; - type = types.attrs; + example = literalExample '' + { + myActivationAction = lib.hm.dag.entryAfter ["writeBoundary"] ''' + $DRY_RUN_CMD ln -s $VERBOSE_ARG \ + ''${builtins.toPath ./link-me-directly} $HOME + '''; + } + ''; description = '' - Activation scripts for the home environment. + The activation scripts blocks to run when activating a Home + Manager generation. Any entry here should be idempotent, + meaning running twice or more times produces the same result + as running it once. + </para><para> - Any script should respect the <varname>DRY_RUN</varname> - variable, if it is set then no actual action should be taken. + + If the script block produces any observable side effect, such + as writing or deleting files, then it + <emphasis>must</emphasis> be placed after the special + <literal>writeBoundary</literal> script block. Prior to the + write boundary one can place script blocks that verifies, but + does not modify, the state of the system and exits if an + unexpected state is found. For example, the + <literal>checkLinkTargets</literal> script block checks for + collisions between non-managed files and files defined in + <varname><link linkend="opt-home.file">home.file</link></varname>. + + </para><para> + + A script block should respect the <varname>DRY_RUN</varname> + variable, if it is set then the actions taken by the script + should be logged to standard out and not actually performed. The variable <varname>DRY_RUN_CMD</varname> is set to - <code>echo</code> if dry run is enabled. Thus, many cases you - can use the idiom <code>$DRY_RUN_CMD rm -rf /</code>. + <command>echo</command> if dry run is enabled. + + </para><para> + + A script block should also respect the + <varname>VERBOSE</varname> variable, and if set print + information on standard out that may be useful for debugging + any issue that may arise. The variable + <varname>VERBOSE_ARG</varname> is set to + <option>--verbose</option> if verbose output is enabled. ''; }; @@ -327,7 +359,7 @@ in # A dummy entry acting as a boundary between the activation # script's "check" and the "write" phases. - home.activation.writeBoundary = dag.entryAnywhere ""; + home.activation.writeBoundary = hm.dag.entryAnywhere ""; # Install packages to the user environment. # @@ -344,7 +376,7 @@ in # In case the user has moved from a user-install of Home Manager # to a submodule managed one we attempt to uninstall the # `home-manager-path` package if it is installed. - home.activation.installPackages = dag.entryAfter ["writeBoundary"] ( + home.activation.installPackages = hm.dag.entryAfter ["writeBoundary"] ( if config.submoduleSupport.externalPackageInstall then '' @@ -364,7 +396,7 @@ in noteEcho Activating ${res.name} ${res.data} ''; - sortedCommands = dag.topoSort cfg.activation; + sortedCommands = hm.dag.topoSort cfg.activation; activationCmds = if sortedCommands ? result then concatStringsSep "\n" (map mkCmd sortedCommands.result) diff --git a/home-manager/modules/lib/dag.nix b/home-manager/modules/lib/dag.nix index 535dec35ad4..cbe34129652 100644 --- a/home-manager/modules/lib/dag.nix +++ b/home-manager/modules/lib/dag.nix @@ -13,13 +13,11 @@ with lib; rec { - emptyDag = {}; + emptyDag = { }; isDag = dag: - let - isEntry = e: (e ? data) && (e ? after) && (e ? before); - in - builtins.isAttrs dag && all (x: x) (mapAttrsToList (n: isEntry) dag); + let isEntry = e: (e ? data) && (e ? after) && (e ? before); + in builtins.isAttrs dag && all (x: x) (mapAttrsToList (n: isEntry) dag); # Takes an attribute set containing entries built by # dagEntryAnywhere, dagEntryAfter, and dagEntryBefore to a @@ -80,22 +78,19 @@ rec { dagTopoSort = dag: let dagBefore = dag: name: - mapAttrsToList (n: v: n) ( - filterAttrs (n: v: any (a: a == name) v.before) dag - ); - normalizedDag = - mapAttrs (n: v: { - name = n; - data = v.data; - after = v.after ++ dagBefore dag n; - }) dag; + mapAttrsToList (n: v: n) + (filterAttrs (n: v: any (a: a == name) v.before) dag); + normalizedDag = mapAttrs (n: v: { + name = n; + data = v.data; + after = v.after ++ dagBefore dag n; + }) dag; before = a: b: any (c: a.name == c) b.after; sorted = toposort before (mapAttrsToList (n: v: v) normalizedDag); - in - if sorted ? result then - { result = map (v: { inherit (v) name data; }) sorted.result; } - else - sorted; + in if sorted ? result then { + result = map (v: { inherit (v) name data; }) sorted.result; + } else + sorted; # Applies a function to each element of the given DAG. dagMap = f: dag: mapAttrs (n: v: v // { data = f n v.data; }) dag; @@ -103,22 +98,20 @@ rec { # Create a DAG entry with no particular dependency information. dagEntryAnywhere = data: { inherit data; - before = []; - after = []; + before = [ ]; + after = [ ]; }; - dagEntryBetween = before: after: data: { - inherit data before after; - }; + dagEntryBetween = before: after: data: { inherit data before after; }; dagEntryAfter = after: data: { inherit data after; - before = []; + before = [ ]; }; dagEntryBefore = before: data: { inherit data before; - after = []; + after = [ ]; }; } diff --git a/home-manager/modules/lib/default.nix b/home-manager/modules/lib/default.nix index 754713cab5d..6b2bbacc249 100644 --- a/home-manager/modules/lib/default.nix +++ b/home-manager/modules/lib/default.nix @@ -1,6 +1,6 @@ { lib }: -{ +rec { dag = let d = import ./dag.nix { inherit lib; }; @@ -17,6 +17,7 @@ }; strings = import ./strings.nix { inherit lib; }; + types = import ./types.nix { inherit dag lib; }; shell = import ./shell.nix { inherit lib; }; zsh = import ./zsh.nix { inherit lib; }; diff --git a/home-manager/modules/lib/file-type.nix b/home-manager/modules/lib/file-type.nix index efbb33b231d..3096a6d37bb 100644 --- a/home-manager/modules/lib/file-type.nix +++ b/home-manager/modules/lib/file-type.nix @@ -2,12 +2,6 @@ with lib; -let - - stringsExtra = import ./strings.nix { inherit lib; }; - -in - { # Constructs a type suitable for a `home.file` like option. The # target path may be either absolute or relative, in which case it @@ -93,7 +87,7 @@ in source = mkIf (config.text != null) ( mkDefault (pkgs.writeTextFile { inherit (config) executable text; - name = stringsExtra.storeFileName name; + name = hm.strings.storeFileName name; }) ); }; diff --git a/home-manager/modules/lib/shell.nix b/home-manager/modules/lib/shell.nix index f1443c5466a..5e5743f51ea 100644 --- a/home-manager/modules/lib/shell.nix +++ b/home-manager/modules/lib/shell.nix @@ -2,7 +2,7 @@ rec { # Produces a Bourne shell like variable export statement. - export = n: v: "export ${n}=\"${toString v}\""; + export = n: v: ''export ${n}="${toString v}"''; # Given an attribute set containing shell variable names and their # assignment, this function produces a string containing an export diff --git a/home-manager/modules/lib/stdlib-extended.nix b/home-manager/modules/lib/stdlib-extended.nix new file mode 100644 index 00000000000..93f2397cee8 --- /dev/null +++ b/home-manager/modules/lib/stdlib-extended.nix @@ -0,0 +1,7 @@ +# Just a convenience function that returns the given Nixpkgs standard +# library extended with the HM library. + +nixpkgsLib: + +let mkHmLib = import ./.; +in nixpkgsLib.extend (self: super: { hm = mkHmLib { lib = super; }; }) diff --git a/home-manager/modules/lib/strings.nix b/home-manager/modules/lib/strings.nix index 13d6bb03be6..fe7b2fa3061 100644 --- a/home-manager/modules/lib/strings.nix +++ b/home-manager/modules/lib/strings.nix @@ -9,19 +9,14 @@ with lib; # All characters that are considered safe. Note "-" is not # included to avoid "-" followed by digit being interpreted as a # version. - safeChars = - [ "+" "." "_" "?" "=" ] - ++ lowerChars - ++ upperChars + safeChars = [ "+" "." "_" "?" "=" ] ++ lowerChars ++ upperChars ++ stringToCharacters "0123456789"; empties = l: genList (x: "") (length l); - unsafeInName = stringToCharacters ( - replaceStrings safeChars (empties safeChars) path - ); + unsafeInName = + stringToCharacters (replaceStrings safeChars (empties safeChars) path); safeName = replaceStrings unsafeInName (empties unsafeInName) path; - in - "hm_" + safeName; + in "hm_" + safeName; } diff --git a/home-manager/modules/lib/types-dag.nix b/home-manager/modules/lib/types-dag.nix new file mode 100644 index 00000000000..4dbdb907b0e --- /dev/null +++ b/home-manager/modules/lib/types-dag.nix @@ -0,0 +1,84 @@ +{ dag, lib }: + +with lib; + +let + + isDagEntry = e: isAttrs e && (e ? data) && (e ? after) && (e ? before); + + dagContentType = elemType: + types.submodule { + options = { + data = mkOption { type = elemType; }; + after = mkOption { type = with types; uniq (listOf str); }; + before = mkOption { type = with types; uniq (listOf str); }; + }; + }; + +in { + # A directed acyclic graph of some inner type. + dagOf = elemType: + let + convertAllToDags = let + maybeConvert = n: v: if isDagEntry v then v else dag.entryAnywhere v; + in map (def: def // { value = mapAttrs maybeConvert def.value; }); + + attrEquivalent = types.attrsOf (dagContentType elemType); + in mkOptionType rec { + name = "dagOf"; + description = "DAG of ${elemType.description}s"; + check = isAttrs; + merge = loc: defs: attrEquivalent.merge loc (convertAllToDags defs); + getSubOptions = prefix: elemType.getSubOptions (prefix ++ [ "<name>" ]); + getSubModules = elemType.getSubModules; + substSubModules = m: dagOf (elemType.substSubModules m); + functor = (defaultFunctor name) // { wrapped = elemType; }; + }; + + # A directed acyclic graph of some inner type OR a list of that + # inner type. This is a temporary hack for use by the + # `programs.ssh.matchBlocks` and is only guaranteed to be vaguely + # correct! + # + # In particular, adding a dependency on one of the "unnamed-N-M" + # entries generated by a list value is almost guaranteed to destroy + # the list's order. + # + # This function will be removed in version 20.09. + listOrDagOf = elemType: + let + paddedIndexStr = list: i: + let padWidth = stringLength (toString (length list)); + in fixedWidthNumber padWidth i; + + convertAllToDags = defs: + let + convertAttrValue = n: v: + if isDagEntry v then v else dag.entryAnywhere v; + + convertListValue = namePrefix: vs: + let + pad = paddedIndexStr vs; + makeEntry = i: v: + nameValuePair "${namePrefix}.${pad i}" (dag.entryAnywhere v); + in listToAttrs (imap1 makeEntry vs); + + convertValue = i: value: + if isList value then + convertListValue "unnamed-${paddedIndexStr defs i}" value + else + mapAttrs convertAttrValue value; + in imap1 (i: def: def // { value = convertValue i def.value; }) defs; + + attrEquivalent = types.attrsOf (dagContentType elemType); + in mkOptionType rec { + name = "dagOf"; + description = "DAG of ${elemType.description}s"; + check = x: isAttrs x || isList x; + merge = loc: defs: attrEquivalent.merge loc (convertAllToDags defs); + getSubOptions = prefix: elemType.getSubOptions (prefix ++ [ "<name>" ]); + getSubModules = elemType.getSubModules; + substSubModules = m: dagOf (elemType.substSubModules m); + functor = (defaultFunctor name) // { wrapped = elemType; }; + }; +} diff --git a/home-manager/modules/lib/types.nix b/home-manager/modules/lib/types.nix index 1b514d20a82..78a875f519e 100644 --- a/home-manager/modules/lib/types.nix +++ b/home-manager/modules/lib/types.nix @@ -1,9 +1,17 @@ -{ lib }: +{ lib, dag ? import ./dag.nix { inherit lib; } }: with lib; +let + + typesDag = import ./types-dag.nix { inherit dag lib; }; + +in + { + inherit (typesDag) dagOf listOrDagOf; + selectorFunction = mkOptionType { name = "selectorFunction"; description = diff --git a/home-manager/modules/lib/zsh.nix b/home-manager/modules/lib/zsh.nix index 1d3e96b54bb..c6901350f50 100644 --- a/home-manager/modules/lib/zsh.nix +++ b/home-manager/modules/lib/zsh.nix @@ -2,13 +2,15 @@ rec { # Produces a Zsh shell like value - toZshValue = v: if builtins.isBool v then - if v then "true" else "false" - else if builtins.isString v then - "\"${v}\"" - else if builtins.isList v then - "(${lib.concatStringsSep " " (map toZshValue v)})" - else "\"${toString v}\""; + toZshValue = v: + if builtins.isBool v then + if v then "true" else "false" + else if builtins.isString v then + ''"${v}"'' + else if builtins.isList v then + "(${lib.concatStringsSep " " (map toZshValue v)})" + else + ''"${toString v}"''; # Produces a Zsh shell like definition statement define = n: v: "${n}=${toZshValue v}"; diff --git a/home-manager/modules/manual.nix b/home-manager/modules/manual.nix index e4c127c0d47..ab01c45003e 100644 --- a/home-manager/modules/manual.nix +++ b/home-manager/modules/manual.nix @@ -6,7 +6,7 @@ let cfg = config.manual; - docs = import ../doc { inherit pkgs; }; + docs = import ../doc { inherit lib pkgs; }; in diff --git a/home-manager/modules/misc/dconf.nix b/home-manager/modules/misc/dconf.nix index ef87f8972ff..f5c9bf71456 100644 --- a/home-manager/modules/misc/dconf.nix +++ b/home-manager/modules/misc/dconf.nix @@ -5,7 +5,6 @@ with lib; let cfg = config.dconf; - dag = config.lib.dag; toDconfIni = generators.toINI { mkKeyValue = mkIniKeyValue; }; @@ -65,7 +64,7 @@ in }; config = mkIf (cfg.enable && cfg.settings != {}) { - home.activation.dconfSettings = dag.entryAfter ["installPackages"] ( + home.activation.dconfSettings = hm.dag.entryAfter ["installPackages"] ( let iniFile = pkgs.writeText "hm-dconf.ini" (toDconfIni cfg.settings); in diff --git a/home-manager/modules/misc/fontconfig.nix b/home-manager/modules/misc/fontconfig.nix index 8dbcce53c22..795ab3a74f6 100644 --- a/home-manager/modules/misc/fontconfig.nix +++ b/home-manager/modules/misc/fontconfig.nix @@ -8,15 +8,15 @@ let profileDirectory = config.home.profileDirectory; -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; imports = [ - (mkRenamedOptionModule - [ "fonts" "fontconfig" "enableProfileFonts" ] - [ "fonts" "fontconfig" "enable" ]) + (mkRenamedOptionModule [ "fonts" "fontconfig" "enableProfileFonts" ] [ + "fonts" + "fontconfig" + "enable" + ]) ]; options = { diff --git a/home-manager/modules/misc/lib.nix b/home-manager/modules/misc/lib.nix index a0907545314..13c00dc59a6 100644 --- a/home-manager/modules/misc/lib.nix +++ b/home-manager/modules/misc/lib.nix @@ -4,7 +4,7 @@ options = { lib = lib.mkOption { type = lib.types.attrsOf lib.types.attrs; - default = {}; + default = { }; description = '' This option allows modules to define helper functions, constants, etc. diff --git a/home-manager/modules/misc/news.nix b/home-manager/modules/misc/news.nix index 4949b757fff..6b01617fc55 100644 --- a/home-manager/modules/misc/news.nix +++ b/home-manager/modules/misc/news.nix @@ -1207,6 +1207,117 @@ in A new module is available: 'programs.rtorrent'. ''; } + + { + time = "2019-11-04T20:56:29+00:00"; + message = '' + A new module is available: 'programs.pazi'. + ''; + } + + { + time = "2019-11-05T21:54:04+00:00"; + condition = config.programs.zsh.enable; + message = '' + The 'programs.zsh.history.path' option behavior and the + default value has changed for state version 20.03 and above. + + Specifically, '$HOME' will no longer be prepended to the + option value, which allows specifying absolute paths (e.g. + using the xdg module). Also, the default value is fixed to + '$HOME/.zsh_history' and 'dotDir' path is not prepended to + it anymore. + ''; + } + + { + time = "2019-11-17T18:47:40+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.lorri'. + ''; + } + + { + time = "2019-11-24T17:46:57+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.spotifyd'. + ''; + } + + { + time = "2019-11-29T21:18:48+00:00"; + message = '' + A new module is available: 'programs.password-store'. + ''; + } + + { + time = "2019-11-29T21:18:48+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.password-store-sync'. + ''; + } + + { + time = "2019-11-29T22:46:49+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.unison'. + ''; + } + + { + time = "2019-12-01T22:10:23+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'xdg.mime'. + + If enabled, which it is by default, this module will create + the XDG mime database and desktop file database caches from + programs installed via Home Manager. + ''; + } + + { + time = "2019-12-08T19:48:26+00:00"; + message = '' + A new module is available: 'programs.readline'. + ''; + } + + { + time = "2020-01-11T11:49:51+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.cbatticon'. + ''; + } + + { + time = "2020-01-26T12:42:33+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'xsession.windowManager.bspwm'. + ''; + } + + { + time = "2020-01-26T12:49:40+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.grobi'. + ''; + } + + { + time = "2020-01-26T19:37:57+00:00"; + message = '' + A new module is available: 'programs.neomutt'. + ''; + } ]; }; } diff --git a/home-manager/modules/misc/nixpkgs.nix b/home-manager/modules/misc/nixpkgs.nix index e7c0d8f25ea..7b0904a5f20 100644 --- a/home-manager/modules/misc/nixpkgs.nix +++ b/home-manager/modules/misc/nixpkgs.nix @@ -142,7 +142,7 @@ in config = { _module.args = { - pkgs = _pkgs; + pkgs = mkOverride modules.defaultPriority _pkgs; pkgs_i686 = if _pkgs.stdenv.isLinux && _pkgs.stdenv.hostPlatform.isx86 then _pkgs.pkgsi686Linux diff --git a/home-manager/modules/misc/numlock.nix b/home-manager/modules/misc/numlock.nix index 77149d123ec..199dd317daa 100644 --- a/home-manager/modules/misc/numlock.nix +++ b/home-manager/modules/misc/numlock.nix @@ -6,12 +6,8 @@ let cfg = config.xsession.numlock; -in - -{ - options = { - xsession.numlock.enable = mkEnableOption "Num Lock"; - }; +in { + options = { xsession.numlock.enable = mkEnableOption "Num Lock"; }; config = mkIf cfg.enable { systemd.user.services.numlockx = { @@ -27,9 +23,7 @@ in ExecStart = "${pkgs.numlockx}/bin/numlockx"; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; }; }; } diff --git a/home-manager/modules/misc/pam.nix b/home-manager/modules/misc/pam.nix index 6ace2bfdaac..f54f4b95089 100644 --- a/home-manager/modules/misc/pam.nix +++ b/home-manager/modules/misc/pam.nix @@ -6,14 +6,12 @@ let vars = config.pam.sessionVariables; -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; options = { pam.sessionVariables = mkOption { - default = {}; + default = { }; type = types.attrs; example = { EDITOR = "vim"; }; description = '' @@ -27,10 +25,8 @@ in }; }; - config = mkIf (vars != {}) { - home.file.".pam_environment".text = - concatStringsSep "\n" ( - mapAttrsToList (n: v: "${n} OVERRIDE=\"${toString v}\"") vars - ) + "\n"; + config = mkIf (vars != { }) { + home.file.".pam_environment".text = concatStringsSep "\n" + (mapAttrsToList (n: v: ''${n} OVERRIDE="${toString v}"'') vars) + "\n"; }; } diff --git a/home-manager/modules/misc/qt.nix b/home-manager/modules/misc/qt.nix index 60de8774231..ff38f842c81 100644 --- a/home-manager/modules/misc/qt.nix +++ b/home-manager/modules/misc/qt.nix @@ -5,21 +5,14 @@ with lib; let cfg = config.qt; - dag = config.lib.dag; -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; imports = [ - (mkChangedOptionModule - [ "qt" "useGtkTheme" ] - [ "qt" "platformTheme" ] + (mkChangedOptionModule [ "qt" "useGtkTheme" ] [ "qt" "platformTheme" ] (config: - if getAttrFromPath [ "qt" "useGtkTheme" ] config - then "gtk" - else null)) + if getAttrFromPath [ "qt" "useGtkTheme" ] config then "gtk" else null)) ]; options = { @@ -30,10 +23,8 @@ in type = types.nullOr (types.enum [ "gtk" "gnome" ]); default = null; example = "gnome"; - relatedPackages = [ - "qgnomeplatform" - ["libsForQt5" "qtstyleplugins"] - ]; + relatedPackages = + [ "qgnomeplatform" [ "libsForQt5" "qtstyleplugins" ] ]; description = '' Selects the platform theme to use for Qt applications.</para> <para>The options are @@ -60,16 +51,16 @@ in home.sessionVariables.QT_QPA_PLATFORMTHEME = if cfg.platformTheme == "gnome" then "gnome" else "gtk2"; - home.packages = - if cfg.platformTheme == "gnome" - then [ pkgs.qgnomeplatform ] - else [ pkgs.libsForQt5.qtstyleplugins ]; + home.packages = if cfg.platformTheme == "gnome" then + [ pkgs.qgnomeplatform ] + else + [ pkgs.libsForQt5.qtstyleplugins ]; xsession.importedVariables = [ "QT_QPA_PLATFORMTHEME" ]; # Enable GTK+ style for Qt4 in either case. # It doesn’t support the platform theme packages. - home.activation.useGtkThemeInQt4 = dag.entryAfter ["writeBoundary"] '' + home.activation.useGtkThemeInQt4 = hm.dag.entryAfter [ "writeBoundary" ] '' $DRY_RUN_CMD ${pkgs.crudini}/bin/crudini $VERBOSE_ARG \ --set "${config.xdg.configHome}/Trolltech.conf" Qt style GTK+ ''; diff --git a/home-manager/modules/misc/version.nix b/home-manager/modules/misc/version.nix index 18bb28f7603..1352aadc614 100644 --- a/home-manager/modules/misc/version.nix +++ b/home-manager/modules/misc/version.nix @@ -5,7 +5,7 @@ with lib; { options = { home.stateVersion = mkOption { - type = types.enum [ "18.09" "19.03" "19.09" ]; + type = types.enum [ "18.09" "19.03" "19.09" "20.03" ]; default = "18.09"; description = '' It is occasionally necessary for Home Manager to change diff --git a/home-manager/modules/misc/xdg-mime-apps.nix b/home-manager/modules/misc/xdg-mime-apps.nix index 979c7ea48be..7ba4083b3c0 100644 --- a/home-manager/modules/misc/xdg-mime-apps.nix +++ b/home-manager/modules/misc/xdg-mime-apps.nix @@ -9,9 +9,7 @@ let strListOrSingleton = with types; coercedTo (either (listOf str) str) toList (listOf str); -in - -{ +in { meta.maintainers = with maintainers; [ pacien ]; options.xdg.mimeApps = { @@ -80,13 +78,11 @@ in config.xdg.configFile."mimeapps.list".source; xdg.configFile."mimeapps.list".text = - let - joinValues = mapAttrs (n: concatStringsSep ";"); - in - generators.toINI {} { - "Added Associations" = joinValues cfg.associations.added; - "Removed Associations" = joinValues cfg.associations.removed; - "Default Applications" = joinValues cfg.defaultApplications; - }; + let joinValues = mapAttrs (n: concatStringsSep ";"); + in generators.toINI { } { + "Added Associations" = joinValues cfg.associations.added; + "Removed Associations" = joinValues cfg.associations.removed; + "Default Applications" = joinValues cfg.defaultApplications; + }; }; } diff --git a/home-manager/modules/misc/xdg-mime.nix b/home-manager/modules/misc/xdg-mime.nix new file mode 100644 index 00000000000..32006e025ff --- /dev/null +++ b/home-manager/modules/misc/xdg-mime.nix @@ -0,0 +1,47 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.xdg.mime; + +in { + options = { + xdg.mime.enable = mkOption { + type = types.bool; + default = true; + description = '' + Whether to install programs and files to support the + XDG Shared MIME-info specification and XDG MIME Applications + specification at + <link xlink:href="https://specifications.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html"/> + and + <link xlink:href="https://specifications.freedesktop.org/mime-apps-spec/mime-apps-spec-latest.html"/>, + respectively. + ''; + }; + }; + + config = mkIf config.xdg.mime.enable { + home.packages = [ + # Explicitly install package to provide basic mime types. + pkgs.shared-mime-info + ]; + + home.extraProfileCommands = '' + if [[ -w $out/share/mime && -d $out/share/mime/packages ]]; then + XDG_DATA_DIRS=$out/share \ + PKGSYSTEM_ENABLE_FSYNC=0 \ + ${pkgs.buildPackages.shared-mime-info}/bin/update-mime-database \ + -V $out/share/mime > /dev/null + fi + + if [[ -w $out/share/applications ]]; then + ${pkgs.buildPackages.desktop-file-utils}/bin/update-desktop-database \ + $out/share/applications + fi + ''; + }; + +} diff --git a/home-manager/modules/misc/xdg-user-dirs.nix b/home-manager/modules/misc/xdg-user-dirs.nix index 4d034d7fe43..da9d3c43ad9 100644 --- a/home-manager/modules/misc/xdg-user-dirs.nix +++ b/home-manager/modules/misc/xdg-user-dirs.nix @@ -6,11 +6,17 @@ let cfg = config.xdg.userDirs; -in - -{ +in { meta.maintainers = with maintainers; [ pacien ]; + imports = [ + (mkRenamedOptionModule [ "xdg" "userDirs" "publishShare" ] [ + "xdg" + "userDirs" + "publicShare" + ]) + ]; + options.xdg.userDirs = { enable = mkOption { type = types.bool; @@ -56,7 +62,7 @@ in description = "The Pictures directory."; }; - publishShare = mkOption { + publicShare = mkOption { type = types.str; default = "$HOME/Public"; description = "The Public share directory."; @@ -83,18 +89,15 @@ in }; config = mkIf cfg.enable { - xdg.configFile."user-dirs.dirs".text = generators.toKeyValue {} ( - { - XDG_DESKTOP_DIR = cfg.desktop; - XDG_DOCUMENTS_DIR = cfg.documents; - XDG_DOWNLOAD_DIR = cfg.download; - XDG_MUSIC_DIR = cfg.music; - XDG_PICTURES_DIR = cfg.pictures; - XDG_PUBLICSHARE_DIR = cfg.publishShare; - XDG_TEMPLATES_DIR = cfg.templates; - XDG_VIDEOS_DIR = cfg.videos; - } - // cfg.extraConfig - ); + xdg.configFile."user-dirs.dirs".text = generators.toKeyValue { } ({ + XDG_DESKTOP_DIR = cfg.desktop; + XDG_DOCUMENTS_DIR = cfg.documents; + XDG_DOWNLOAD_DIR = cfg.download; + XDG_MUSIC_DIR = cfg.music; + XDG_PICTURES_DIR = cfg.pictures; + XDG_PUBLICSHARE_DIR = cfg.publicShare; + XDG_TEMPLATES_DIR = cfg.templates; + XDG_VIDEOS_DIR = cfg.videos; + } // cfg.extraConfig); }; } diff --git a/home-manager/modules/modules.nix b/home-manager/modules/modules.nix index 2dc89ebc012..64418dbae11 100644 --- a/home-manager/modules/modules.nix +++ b/home-manager/modules/modules.nix @@ -1,4 +1,6 @@ { pkgs + + # Note, this should be "the standard library" + HM extensions. , lib # Whether to enable module type checking. @@ -33,6 +35,7 @@ let (loadModule ./misc/qt.nix { }) (loadModule ./misc/submodule-support.nix { }) (loadModule ./misc/version.nix { }) + (loadModule ./misc/xdg-mime.nix { condition = hostPlatform.isLinux; }) (loadModule ./misc/xdg-mime-apps.nix { condition = hostPlatform.isLinux; }) (loadModule ./misc/xdg-user-dirs.nix { condition = hostPlatform.isLinux; }) (loadModule ./misc/xdg.nix { }) @@ -75,6 +78,7 @@ let (loadModule ./programs/mercurial.nix { }) (loadModule ./programs/mpv.nix { }) (loadModule ./programs/msmtp.nix { }) + (loadModule ./programs/neomutt.nix { }) (loadModule ./programs/neovim.nix { }) (loadModule ./programs/newsboat.nix { }) (loadModule ./programs/noti.nix { }) @@ -82,7 +86,10 @@ let (loadModule ./programs/obs-studio.nix { }) (loadModule ./programs/offlineimap.nix { }) (loadModule ./programs/opam.nix { }) + (loadModule ./programs/password-store.nix { }) + (loadModule ./programs/pazi.nix { }) (loadModule ./programs/pidgin.nix { }) + (loadModule ./programs/readline.nix { }) (loadModule ./programs/rofi.nix { }) (loadModule ./programs/rtorrent.nix { }) (loadModule ./programs/skim.nix { }) @@ -100,6 +107,7 @@ let (loadModule ./programs/zathura.nix { }) (loadModule ./programs/zsh.nix { }) (loadModule ./services/blueman-applet.nix { }) + (loadModule ./services/cbatticon.nix { condition = hostPlatform.isLinux; }) (loadModule ./services/compton.nix { }) (loadModule ./services/dunst.nix { }) (loadModule ./services/dwm-status.nix { condition = hostPlatform.isLinux; }) @@ -108,12 +116,14 @@ let (loadModule ./services/getmail.nix { condition = hostPlatform.isLinux; }) (loadModule ./services/gnome-keyring.nix { }) (loadModule ./services/gpg-agent.nix { }) + (loadModule ./services/grobi.nix { condition = hostPlatform.isLinux; }) (loadModule ./services/hound.nix { condition = hostPlatform.isLinux; }) (loadModule ./services/imapnotify.nix { condition = hostPlatform.isLinux; }) (loadModule ./services/kbfs.nix { }) (loadModule ./services/kdeconnect.nix { }) (loadModule ./services/keepassx.nix { }) (loadModule ./services/keybase.nix { }) + (loadModule ./services/lorri.nix { condition = hostPlatform.isLinux; }) (loadModule ./services/mbsync.nix { }) (loadModule ./services/mpd.nix { }) (loadModule ./services/mpdris2.nix { condition = hostPlatform.isLinux; }) @@ -122,6 +132,7 @@ let (loadModule ./services/nextcloud-client.nix { }) (loadModule ./services/owncloud-client.nix { }) (loadModule ./services/parcellite.nix { }) + (loadModule ./services/password-store-sync.nix { condition = hostPlatform.isLinux; }) (loadModule ./services/pasystray.nix { }) (loadModule ./services/polybar.nix { }) (loadModule ./services/random-background.nix { }) @@ -130,6 +141,7 @@ let (loadModule ./services/screen-locker.nix { }) (loadModule ./services/stalonetray.nix { }) (loadModule ./services/status-notifier-watcher.nix { }) + (loadModule ./services/spotifyd.nix { condition = hostPlatform.isLinux; }) (loadModule ./services/sxhkd.nix { condition = hostPlatform.isLinux; }) (loadModule ./services/syncthing.nix { }) (loadModule ./services/taffybar.nix { }) @@ -137,7 +149,9 @@ let (loadModule ./services/taskwarrior-sync.nix { condition = hostPlatform.isLinux; }) (loadModule ./services/udiskie.nix { }) (loadModule ./services/unclutter.nix { }) + (loadModule ./services/unison.nix { condition = hostPlatform.isLinux; }) (loadModule ./services/window-managers/awesome.nix { }) + (loadModule ./services/window-managers/bspwm/default.nix { condition = hostPlatform.isLinux; }) (loadModule ./services/window-managers/i3.nix { }) (loadModule ./services/window-managers/xmonad.nix { }) (loadModule ./services/xcape.nix { condition = hostPlatform.isLinux; }) @@ -148,8 +162,8 @@ let (loadModule ./xcursor.nix { }) (loadModule ./xresources.nix { }) (loadModule ./xsession.nix { }) - (loadModule <nixpkgs/nixos/modules/misc/assertions.nix> { }) - (loadModule <nixpkgs/nixos/modules/misc/meta.nix> { }) + (loadModule (pkgs.path + "/nixos/modules/misc/assertions.nix") { }) + (loadModule (pkgs.path + "/nixos/modules/misc/meta.nix") { }) ]; modules = map (getAttr "file") (filter (getAttr "condition") allModules); @@ -158,7 +172,7 @@ let config._module.args.baseModules = modules; config._module.args.pkgs = lib.mkDefault pkgs; config._module.check = check; - config.lib = import ./lib { inherit lib; }; + config.lib = lib.hm; config.nixpkgs.system = mkDefault pkgs.system; }; diff --git a/home-manager/modules/programs/alacritty.nix b/home-manager/modules/programs/alacritty.nix index 84675cb1c8a..69b9ea9673d 100644 --- a/home-manager/modules/programs/alacritty.nix +++ b/home-manager/modules/programs/alacritty.nix @@ -6,16 +6,14 @@ let cfg = config.programs.alacritty; -in - -{ +in { options = { programs.alacritty = { enable = mkEnableOption "Alacritty"; settings = mkOption { type = types.attrs; - default = {}; + default = { }; example = literalExample '' { window.dimensions = { @@ -45,8 +43,9 @@ in (mkIf cfg.enable { home.packages = [ pkgs.alacritty ]; - xdg.configFile."alacritty/alacritty.yml" = mkIf (cfg.settings != {}) { - text = replaceStrings ["\\\\"] ["\\"] (builtins.toJSON cfg.settings); + xdg.configFile."alacritty/alacritty.yml" = mkIf (cfg.settings != { }) { + text = + replaceStrings [ "\\\\" ] [ "\\" ] (builtins.toJSON cfg.settings); }; }) ]; diff --git a/home-manager/modules/programs/alot-accounts.nix b/home-manager/modules/programs/alot-accounts.nix index 8f3ffdfb31e..89ae28f9c8e 100644 --- a/home-manager/modules/programs/alot-accounts.nix +++ b/home-manager/modules/programs/alot-accounts.nix @@ -18,12 +18,10 @@ with lib; type = types.attrsOf types.str; default = { type = "shellcommand"; - command = "'${pkgs.notmuch}/bin/notmuch address --format=json --output=recipients date:6M..'"; - regexp = - "'\\[?{" - + ''"name": "(?P<name>.*)", '' - + ''"address": "(?P<email>.+)", '' - + ''"name-addr": ".*"'' + command = + "'${pkgs.notmuch}/bin/notmuch address --format=json --output=recipients date:6M..'"; + regexp = "'\\[?{" + '' + "name": "(?P<name>.*)", "address": "(?P<email>.+)", "name-addr": ".*"'' + "}[,\\]]?'"; shellcommand_external_filtering = "False"; }; @@ -36,9 +34,9 @@ with lib; } ''; description = '' - Contact completion configuration as expected per alot. - See <link xlink:href="http://alot.readthedocs.io/en/latest/configuration/contacts_completion.html">alot's wiki</link> for - explanation about possible values. + Contact completion configuration as expected per alot. + See <link xlink:href="http://alot.readthedocs.io/en/latest/configuration/contacts_completion.html">alot's wiki</link> for + explanation about possible values. ''; }; @@ -52,10 +50,9 @@ with lib; }; config = mkIf config.notmuch.enable { - alot.sendMailCommand = mkOptionDefault ( - if config.msmtp.enable - then "msmtpq --read-envelope-from --read-recipients" - else null - ); + alot.sendMailCommand = mkOptionDefault (if config.msmtp.enable then + "msmtpq --read-envelope-from --read-recipients" + else + null); }; } diff --git a/home-manager/modules/programs/astroid-accounts.nix b/home-manager/modules/programs/astroid-accounts.nix index bc94a301db0..17544ff7899 100644 --- a/home-manager/modules/programs/astroid-accounts.nix +++ b/home-manager/modules/programs/astroid-accounts.nix @@ -17,7 +17,7 @@ with lib; extraConfig = mkOption { type = types.attrs; - default = {}; + default = { }; example = { select_query = ""; }; description = '' Extra settings to add to this astroid account configuration. @@ -26,8 +26,7 @@ with lib; }; config = mkIf config.notmuch.enable { - astroid.sendMailCommand = mkIf config.msmtp.enable ( - mkOptionDefault "msmtpq --read-envelope-from --read-recipients" - ); + astroid.sendMailCommand = mkIf config.msmtp.enable + (mkOptionDefault "msmtpq --read-envelope-from --read-recipients"); }; } diff --git a/home-manager/modules/programs/astroid.nix b/home-manager/modules/programs/astroid.nix index 0463cd15528..8b3762fac0b 100644 --- a/home-manager/modules/programs/astroid.nix +++ b/home-manager/modules/programs/astroid.nix @@ -8,35 +8,32 @@ let cfg = config.programs.astroid; astroidAccounts = - filterAttrs - (n: v: v.astroid.enable) - config.accounts.email.accounts; + filterAttrs (n: v: v.astroid.enable) config.accounts.email.accounts; boolOpt = b: if b then "true" else "false"; - accountAttr = account: with account; { - email = address; - name = realName; - sendmail = astroid.sendMailCommand; - additional_sent_tags = ""; - default = boolOpt primary; - save_drafts_to = folders.drafts; - save_sent = "true"; - save_sent_to = folders.sent; - select_query = ""; - } - // optionalAttrs (signature.showSignature != "none") { - signature_attach = boolOpt (signature.showSignature == "attach"); - signature_default_on = boolOpt (signature.showSignature != "none"); - signature_file = pkgs.writeText "signature.txt" signature.text; - signature_file_markdown = "false"; - signature_separate = "true"; # prepends '--\n' to the signature - } - // optionalAttrs (gpg != null) { - always_gpg_sign = boolOpt gpg.signByDefault; - gpgkey = gpg.key; - } - // astroid.extraConfig; + accountAttr = account: + with account; + { + email = address; + name = realName; + sendmail = astroid.sendMailCommand; + additional_sent_tags = ""; + default = boolOpt primary; + save_drafts_to = "${maildir.absPath}/${folders.drafts}"; + save_sent = "true"; + save_sent_to = "${maildir.absPath}/${folders.sent}"; + select_query = ""; + } // optionalAttrs (signature.showSignature != "none") { + signature_attach = boolOpt (signature.showSignature == "attach"); + signature_default_on = boolOpt (signature.showSignature != "none"); + signature_file = pkgs.writeText "signature.txt" signature.text; + signature_file_markdown = "false"; + signature_separate = "true"; # prepends '--\n' to the signature + } // optionalAttrs (gpg != null) { + always_gpg_sign = boolOpt gpg.signByDefault; + gpgkey = gpg.key; + } // astroid.extraConfig; # See https://github.com/astroidmail/astroid/wiki/Configuration-Reference configFile = mailAccounts: @@ -51,12 +48,9 @@ let cfg.extraConfig cfg.externalEditor ]; - in - builtins.toJSON astroidConfig; + in builtins.toJSON astroidConfig; -in - -{ +in { options = { programs.astroid = { enable = mkEnableOption "Astroid"; @@ -81,7 +75,8 @@ in "cmd" = cmd; }; }; - example = "nvim-qt -- -c 'set ft=mail' '+set fileencoding=utf-8' '+set ff=unix' '+set enc=utf-8' '+set fo+=w' %1"; + example = + "nvim-qt -- -c 'set ft=mail' '+set fileencoding=utf-8' '+set ff=unix' '+set enc=utf-8' '+set fo+=w' %1"; description = '' You can use <code>%1</code>, <code>%2</code>, and <code>%3</code> to refer respectively to: @@ -96,7 +91,7 @@ in extraConfig = mkOption { type = types.attrs; - default = {}; + default = { }; example = { poll.interval = 0; }; description = '' JSON config that will override the default Astroid configuration. @@ -106,26 +101,15 @@ in }; config = mkIf cfg.enable { - assertions = [ - { - assertion = config.programs.notmuch.maildir.synchronizeFlags; - message = "The astroid module requires" - + " 'programs.notmuch.maildir.synchronizeFlags = true'."; - } - ]; - - home.packages = [ pkgs.astroid ]; - - xdg.configFile."astroid/config".source = - pkgs.runCommand "out.json" - { - json = configFile astroidAccounts; - preferLocalBuild = true; - allowSubstitutes = false; - } - '' - echo -n "$json" | ${pkgs.jq}/bin/jq . > $out - ''; + home.packages = [ pkgs.astroid ]; + + xdg.configFile."astroid/config".source = pkgs.runCommand "out.json" { + json = configFile astroidAccounts; + preferLocalBuild = true; + allowSubstitutes = false; + } '' + echo -n "$json" | ${pkgs.jq}/bin/jq . > $out + ''; xdg.configFile."astroid/poll.sh" = { executable = true; diff --git a/home-manager/modules/programs/autorandr.nix b/home-manager/modules/programs/autorandr.nix index 4514a5b5d58..02fc77c1e58 100644 --- a/home-manager/modules/programs/autorandr.nix +++ b/home-manager/modules/programs/autorandr.nix @@ -6,20 +6,21 @@ let cfg = config.programs.autorandr; - matrixOf = n: m: elemType: mkOptionType rec { - name = "matrixOf"; - description = "${toString n}×${toString m} matrix of ${elemType.description}s"; - check = xss: - let - listOfSize = l: xs: isList xs && length xs == l; - in - listOfSize n xss && all (xs: listOfSize m xs && all elemType.check xs) xss; - merge = mergeOneOption; - getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["*" "*"]); - getSubModules = elemType.getSubModules; - substSubModules = mod: matrixOf n m (elemType.substSubModules mod); - functor = (defaultFunctor name) // { wrapped = elemType; }; - }; + matrixOf = n: m: elemType: + mkOptionType rec { + name = "matrixOf"; + description = + "${toString n}×${toString m} matrix of ${elemType.description}s"; + check = xss: + let listOfSize = l: xs: isList xs && length xs == l; + in listOfSize n xss + && all (xs: listOfSize m xs && all elemType.check xs) xss; + merge = mergeOneOption; + getSubOptions = prefix: elemType.getSubOptions (prefix ++ [ "*" "*" ]); + getSubModules = elemType.getSubModules; + substSubModules = mod: matrixOf n m (elemType.substSubModules mod); + functor = (defaultFunctor name) // { wrapped = elemType; }; + }; profileModule = types.submodule { options = { @@ -29,19 +30,19 @@ let Output name to EDID mapping. Use <code>autorandr --fingerprint</code> to get current setup values. ''; - default = {}; + default = { }; }; config = mkOption { type = types.attrsOf configModule; description = "Per output profile configuration."; - default = {}; + default = { }; }; hooks = mkOption { type = profileHooksModule; description = "Profile hook scripts."; - default = {}; + default = { }; }; }; }; @@ -89,7 +90,7 @@ let }; rotate = mkOption { - type = types.nullOr (types.enum ["normal" "left" "right" "inverted"]); + type = types.nullOr (types.enum [ "normal" "left" "right" "inverted" ]); description = "Output rotate configuration."; default = null; example = "left"; @@ -126,7 +127,7 @@ let type = types.nullOr (types.submodule { options = { method = mkOption { - type = types.enum ["factor" "pixel" ]; + type = types.enum [ "factor" "pixel" ]; description = "Output scaling method."; default = "factor"; example = "pixel"; @@ -178,19 +179,21 @@ let postswitch = mkOption { type = types.attrsOf hookType; description = "Postswitch hook executed after mode switch."; - default = {}; + default = { }; }; preswitch = mkOption { type = types.attrsOf hookType; description = "Preswitch hook executed before mode switch."; - default = {}; + default = { }; }; predetect = mkOption { type = types.attrsOf hookType; - description = "Predetect hook executed before autorandr attempts to run xrandr."; - default = {}; + description = '' + Predetect hook executed before autorandr attempts to run xrandr. + ''; + default = { }; }; }; }; @@ -211,50 +214,56 @@ let predetect = mkOption { type = hookType; - description = "Predetect hook executed before autorandr attempts to run xrandr."; + description = '' + Predetect hook executed before autorandr attempts to run xrandr. + ''; default = ""; }; }; }; hookToFile = folder: name: hook: - nameValuePair - "autorandr/${folder}/${name}" - { source = "${pkgs.writeShellScriptBin "hook" hook}/bin/hook"; }; - profileToFiles = name: profile: with profile; mkMerge ([ - { - "autorandr/${name}/setup".text = concatStringsSep "\n" (mapAttrsToList fingerprintToString fingerprint); - "autorandr/${name}/config".text = concatStringsSep "\n" (mapAttrsToList configToString profile.config); - } - (mkIf (hooks.postswitch != "") (listToAttrs [ (hookToFile name "postswitch" hooks.postswitch) ])) - (mkIf (hooks.preswitch != "") (listToAttrs [ (hookToFile name "preswitch" hooks.preswitch) ])) - (mkIf (hooks.predetect != "") (listToAttrs [ (hookToFile name "predetect" hooks.predetect) ])) - ]); + nameValuePair "autorandr/${folder}/${name}" { + source = "${pkgs.writeShellScriptBin "hook" hook}/bin/hook"; + }; + profileToFiles = name: profile: + with profile; + mkMerge ([ + { + "autorandr/${name}/setup".text = concatStringsSep "\n" + (mapAttrsToList fingerprintToString fingerprint); + "autorandr/${name}/config".text = + concatStringsSep "\n" (mapAttrsToList configToString profile.config); + } + (mkIf (hooks.postswitch != "") + (listToAttrs [ (hookToFile name "postswitch" hooks.postswitch) ])) + (mkIf (hooks.preswitch != "") + (listToAttrs [ (hookToFile name "preswitch" hooks.preswitch) ])) + (mkIf (hooks.predetect != "") + (listToAttrs [ (hookToFile name "predetect" hooks.predetect) ])) + ]); fingerprintToString = name: edid: "${name} ${edid}"; - configToString = name: config: if config.enable then '' - output ${name} - ${optionalString (config.position != "") "pos ${config.position}"} - ${optionalString config.primary "primary"} - ${optionalString (config.dpi != null) "dpi ${toString config.dpi}"} - ${optionalString (config.gamma != "") "gamma ${config.gamma}"} - ${optionalString (config.mode != "") "mode ${config.mode}"} - ${optionalString (config.rate != "") "rate ${config.rate}"} - ${optionalString (config.rotate != null) "rotate ${config.rotate}"} - ${optionalString (config.scale != null) ( - (if config.scale.method == "factor" then "scale" else "scale-from") - + " ${toString config.scale.x}x${toString config.scale.y}" - )} - ${optionalString (config.transform != null) ( - "transform " + concatMapStringsSep "," toString (flatten config.transform) - )} - '' else '' - output ${name} - off - ''; - -in - -{ + configToString = name: config: + if config.enable then '' + output ${name} + ${optionalString (config.position != "") "pos ${config.position}"} + ${optionalString config.primary "primary"} + ${optionalString (config.dpi != null) "dpi ${toString config.dpi}"} + ${optionalString (config.gamma != "") "gamma ${config.gamma}"} + ${optionalString (config.mode != "") "mode ${config.mode}"} + ${optionalString (config.rate != "") "rate ${config.rate}"} + ${optionalString (config.rotate != null) "rotate ${config.rotate}"} + ${optionalString (config.scale != null) + ((if config.scale.method == "factor" then "scale" else "scale-from") + + " ${toString config.scale.x}x${toString config.scale.y}")} + ${optionalString (config.transform != null) ("transform " + + concatMapStringsSep "," toString (flatten config.transform))} + '' else '' + output ${name} + off + ''; + +in { options = { programs.autorandr = { enable = mkEnableOption "Autorandr"; @@ -262,39 +271,39 @@ in hooks = mkOption { type = globalHooksModule; description = "Global hook scripts"; - default = {}; + default = { }; example = literalExample '' - { - postswitch = { - "notify-i3" = "''${pkgs.i3}/bin/i3-msg restart"; - "change-background" = readFile ./change-background.sh; - "change-dpi" = ''' - case "$AUTORANDR_CURRENT_PROFILE" in - default) - DPI=120 - ;; - home) - DPI=192 - ;; - work) - DPI=144 - ;; - *) - echo "Unknown profle: $AUTORANDR_CURRENT_PROFILE" - exit 1 - esac - - echo "Xft.dpi: $DPI" | ''${pkgs.xorg.xrdb}/bin/xrdb -merge - ''' - }; - } + { + postswitch = { + "notify-i3" = "''${pkgs.i3}/bin/i3-msg restart"; + "change-background" = readFile ./change-background.sh; + "change-dpi" = ''' + case "$AUTORANDR_CURRENT_PROFILE" in + default) + DPI=120 + ;; + home) + DPI=192 + ;; + work) + DPI=144 + ;; + *) + echo "Unknown profle: $AUTORANDR_CURRENT_PROFILE" + exit 1 + esac + + echo "Xft.dpi: $DPI" | ''${pkgs.xorg.xrdb}/bin/xrdb -merge + ''' + }; + } ''; }; profiles = mkOption { type = types.attrsOf profileModule; description = "Autorandr profiles specification."; - default = {}; + default = { }; example = literalExample '' { "work" = { @@ -323,24 +332,21 @@ in }; config = mkIf cfg.enable { - assertions = flatten (mapAttrsToList ( - profile: { config, ... }: mapAttrsToList ( - output: opts: { - assertion = opts.scale == null || opts.transform == null; - message = '' - Cannot use the profile output options 'scale' and 'transform' simultaneously. - Check configuration for: programs.autorandr.profiles.${profile}.config.${output} - ''; - }) - config - ) - cfg.profiles); + assertions = flatten (mapAttrsToList (profile: + { config, ... }: + mapAttrsToList (output: opts: { + assertion = opts.scale == null || opts.transform == null; + message = '' + Cannot use the profile output options 'scale' and 'transform' simultaneously. + Check configuration for: programs.autorandr.profiles.${profile}.config.${output} + ''; + }) config) cfg.profiles); home.packages = [ pkgs.autorandr ]; xdg.configFile = mkMerge ([ (mapAttrs' (hookToFile "postswitch.d") cfg.hooks.postswitch) - (mapAttrs' (hookToFile "preswitch.d") cfg.hooks.preswitch) - (mapAttrs' (hookToFile "predetect.d") cfg.hooks.predetect) + (mapAttrs' (hookToFile "preswitch.d") cfg.hooks.preswitch) + (mapAttrs' (hookToFile "predetect.d") cfg.hooks.predetect) (mkMerge (mapAttrsToList profileToFiles cfg.profiles)) ]); }; diff --git a/home-manager/modules/programs/bat.nix b/home-manager/modules/programs/bat.nix index 860c5e82f54..aa0df9abd45 100644 --- a/home-manager/modules/programs/bat.nix +++ b/home-manager/modules/programs/bat.nix @@ -6,9 +6,7 @@ let cfg = config.programs.bat; -in - -{ +in { meta.maintainers = [ maintainers.marsam ]; options.programs.bat = { @@ -16,7 +14,7 @@ in config = mkOption { type = types.attrsOf types.str; - default = {}; + default = { }; example = { theme = "TwoDark"; pager = "less -FR"; @@ -31,10 +29,9 @@ in config = mkIf cfg.enable { home.packages = [ pkgs.bat ]; - xdg.configFile."bat/config" = mkIf (cfg.config != {}) { - text = concatStringsSep "\n" ( - mapAttrsToList (n: v: ''--${n}="${v}"'') cfg.config - ); + xdg.configFile."bat/config" = mkIf (cfg.config != { }) { + text = concatStringsSep "\n" + (mapAttrsToList (n: v: ''--${n}="${v}"'') cfg.config); }; }; } diff --git a/home-manager/modules/programs/beets.nix b/home-manager/modules/programs/beets.nix index 152bfd304a4..1a45bbea1c7 100644 --- a/home-manager/modules/programs/beets.nix +++ b/home-manager/modules/programs/beets.nix @@ -6,19 +6,17 @@ let cfg = config.programs.beets; -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; options = { programs.beets = { enable = mkOption { type = types.bool; - default = - if versionAtLeast config.home.stateVersion "19.03" - then false - else cfg.settings != {}; + default = if versionAtLeast config.home.stateVersion "19.03" then + false + else + cfg.settings != { }; defaultText = "false"; description = '' Whether to enable the beets music library manager. This @@ -28,9 +26,21 @@ in ''; }; + package = mkOption { + type = types.package; + default = pkgs.beets; + defaultText = literalExample "pkgs.beets"; + example = + literalExample "(pkgs.beets.override { enableCheck = true; })"; + description = '' + The <literal>beets</literal> package to use. + Can be used to specify extensions. + ''; + }; + settings = mkOption { type = types.attrs; - default = {}; + default = { }; description = '' Configuration written to <filename>~/.config/beets/config.yaml</filename> @@ -40,9 +50,9 @@ in }; config = mkIf cfg.enable { - home.packages = [ pkgs.beets ]; + home.packages = [ cfg.package ]; xdg.configFile."beets/config.yaml".text = - builtins.toJSON config.programs.beets.settings; + builtins.toJSON config.programs.beets.settings; }; } diff --git a/home-manager/modules/programs/broot.nix b/home-manager/modules/programs/broot.nix index f6d3cd7f920..eac31b56801 100644 --- a/home-manager/modules/programs/broot.nix +++ b/home-manager/modules/programs/broot.nix @@ -7,29 +7,23 @@ let cfg = config.programs.broot; configFile = config: - pkgs.runCommand "conf.toml" - { - buildInputs = [ pkgs.remarshal ]; - preferLocalBuild = true; - allowSubstitutes = false; - } - '' - remarshal -if json -of toml \ - < ${pkgs.writeText "verbs.json" (builtins.toJSON config)} \ - > $out - ''; + pkgs.runCommand "conf.toml" { + buildInputs = [ pkgs.remarshal ]; + preferLocalBuild = true; + allowSubstitutes = false; + } '' + remarshal -if json -of toml \ + < ${pkgs.writeText "verbs.json" (builtins.toJSON config)} \ + > $out + ''; brootConf = { verbs = - mapAttrsToList - (name: value: value // { invocation = name; }) - cfg.verbs; + mapAttrsToList (name: value: value // { invocation = name; }) cfg.verbs; skin = cfg.skin; }; -in - -{ +in { meta.maintainers = [ maintainers.aheaume ]; options.programs.broot = { @@ -63,7 +57,10 @@ in type = with types; attrsOf (attrsOf (either bool str)); default = { "p" = { execution = ":parent"; }; - "edit" = { shortcut = "e"; execution = "$EDITOR {file}" ; }; + "edit" = { + shortcut = "e"; + execution = "$EDITOR {file}"; + }; "create {subpath}" = { execution = "$EDITOR {directory}/{subpath}"; }; "view" = { execution = "less {file}"; }; }; @@ -114,7 +111,7 @@ in skin = mkOption { type = types.attrsOf types.str; - default = {}; + default = { }; example = literalExample '' { status_normal_fg = "grayscale(18)"; @@ -177,38 +174,36 @@ in # Dummy file to prevent broot from trying to reinstall itself xdg.configFile."broot/launcher/installed".text = ""; - 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" - } - '' - ); + 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" + } + ''); programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' # This script was automatically generated by the broot function diff --git a/home-manager/modules/programs/browserpass.nix b/home-manager/modules/programs/browserpass.nix index 7af5e8f8756..10a2883c871 100644 --- a/home-manager/modules/programs/browserpass.nix +++ b/home-manager/modules/programs/browserpass.nix @@ -2,13 +2,7 @@ with lib; -let - browsers = [ - "chrome" - "chromium" - "firefox" - "vivaldi" - ]; +let browsers = [ "chrome" "chromium" "firefox" "vivaldi" ]; in { options = { programs.browserpass = { @@ -24,57 +18,59 @@ in { }; config = mkIf config.programs.browserpass.enable { - home.file = builtins.concatLists (with pkgs.stdenv; map (x: + home.file = foldl' (a: b: a // b) { } (concatMap (x: + with pkgs.stdenv; if x == "chrome" then - let dir = if isDarwin - then "Library/Application Support/Google/Chrome/NativeMessagingHosts" - else ".config/google-chrome/NativeMessagingHosts"; - in [ - { - target = "${dir}/com.github.browserpass.native.json"; - source = "${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json"; - } - { - target = "${dir}/../policies/managed/com.github.browserpass.native.json"; - source = "${pkgs.browserpass}/lib/browserpass/policies/chromium/com.github.browserpass.native.json"; - } - ] + let + dir = if isDarwin then + "Library/Application Support/Google/Chrome/NativeMessagingHosts" + else + ".config/google-chrome/NativeMessagingHosts"; + in [{ + "${dir}/com.github.browserpass.native.json".source = + "${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json"; + "${dir}/../policies/managed/com.github.browserpass.native.json".source = + "${pkgs.browserpass}/lib/browserpass/policies/chromium/com.github.browserpass.native.json"; + }] else if x == "chromium" then - let dir = if isDarwin - then "Library/Application Support/Chromium/NativeMessagingHosts" - else ".config/chromium/NativeMessagingHosts"; + let + dir = if isDarwin then + "Library/Application Support/Chromium/NativeMessagingHosts" + else + ".config/chromium/NativeMessagingHosts"; in [ { - target = "${dir}/com.github.browserpass.native.json"; - source = "${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json"; + "${dir}/com.github.browserpass.native.json".source = + "${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json"; } { - target = "${dir}/../policies/managed/com.github.browserpass.native.json"; - source = "${pkgs.browserpass}/lib/browserpass/policies/chromium/com.github.browserpass.native.json"; + "${dir}/../policies/managed/com.github.browserpass.native.json".source = + "${pkgs.browserpass}/lib/browserpass/policies/chromium/com.github.browserpass.native.json"; } ] else if x == "firefox" then - [ { - target = (if isDarwin - then "Library/Application Support/Mozilla/NativeMessagingHosts" - else ".mozilla/native-messaging-hosts") - + "/com.github.browserpass.native.json"; - source = "${pkgs.browserpass}/lib/browserpass/hosts/firefox/com.github.browserpass.native.json"; - } ] + let + dir = if isDarwin then + "Library/Application Support/Mozilla/NativeMessagingHosts" + else + ".mozilla/native-messaging-hosts"; + in [{ + "${dir}/com.github.browserpass.native.json".source = + "${pkgs.browserpass}/lib/browserpass/hosts/firefox/com.github.browserpass.native.json"; + }] else if x == "vivaldi" then - let dir = if isDarwin - then "Library/Application Support/Vivaldi/NativeMessagingHosts" - else ".config/vivaldi/NativeMessagingHosts"; - in [ - { - target = "${dir}/com.github.browserpass.native.json"; - source = "${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json"; - } - { - target = "${dir}/../policies/managed/com.github.browserpass.native.json"; - source = "${pkgs.browserpass}/lib/browserpass/policies/chromium/com.github.browserpass.native.json"; - } - ] - else throw "unknown browser ${x}") config.programs.browserpass.browsers); + let + dir = if isDarwin then + "Library/Application Support/Vivaldi/NativeMessagingHosts" + else + ".config/vivaldi/NativeMessagingHosts"; + in [{ + "${dir}/com.github.browserpass.native.json".source = + "${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json"; + "${dir}/../policies/managed/com.github.browserpass.native.json".source = + "${pkgs.browserpass}/lib/browserpass/policies/chromium/com.github.browserpass.native.json"; + }] + else + throw "unknown browser ${x}") config.programs.browserpass.browsers); }; } diff --git a/home-manager/modules/programs/chromium.nix b/home-manager/modules/programs/chromium.nix index 83a827a0ed0..4e35c07b90c 100644 --- a/home-manager/modules/programs/chromium.nix +++ b/home-manager/modules/programs/chromium.nix @@ -5,45 +5,43 @@ with lib; let browserModule = defaultPkg: name: visible: - let - browser = (builtins.parseDrvName defaultPkg.name).name; - in - { - enable = mkOption { - inherit visible; - default = false; - example = true; - description = "Whether to enable ${name}."; - type = lib.types.bool; - }; + let browser = (builtins.parseDrvName defaultPkg.name).name; + in { + enable = mkOption { + inherit visible; + default = false; + example = true; + description = "Whether to enable ${name}."; + type = lib.types.bool; + }; - package = mkOption { - inherit visible; - type = types.package; - default = defaultPkg; - defaultText = literalExample "pkgs.${browser}"; - description = "The ${name} package to use."; - }; + package = mkOption { + inherit visible; + type = types.package; + default = defaultPkg; + defaultText = literalExample "pkgs.${browser}"; + description = "The ${name} package to use."; + }; - extensions = mkOption { - inherit visible; - type = types.listOf types.str; - default = []; - example = literalExample '' - [ - "chlffgpmiacpedhhbkiomidkjlcfhogd" # pushbullet - "mbniclmhobmnbdlbpiphghaielnnpgdp" # lightshot - "gcbommkclmclpchllfjekcdonpmejbdp" # https everywhere - "cjpalhdlnbpafiamejdnhcphjbkeiagm" # ublock origin - ] - ''; - description = '' - List of ${name} extensions to install. - To find the extension ID, check its URL on the - <link xlink:href="https://chrome.google.com/webstore/category/extensions">Chrome Web Store</link>. - ''; - }; + extensions = mkOption { + inherit visible; + type = types.listOf types.str; + default = [ ]; + example = literalExample '' + [ + "chlffgpmiacpedhhbkiomidkjlcfhogd" # pushbullet + "mbniclmhobmnbdlbpiphghaielnnpgdp" # lightshot + "gcbommkclmclpchllfjekcdonpmejbdp" # https everywhere + "cjpalhdlnbpafiamejdnhcphjbkeiagm" # ublock origin + ] + ''; + description = '' + List of ${name} extensions to install. + To find the extension ID, check its URL on the + <link xlink:href="https://chrome.google.com/webstore/category/extensions">Chrome Web Store</link>. + ''; }; + }; browserConfig = cfg: let @@ -57,31 +55,32 @@ let google-chrome-dev = "Google/Chrome Dev"; }; - configDir = if pkgs.stdenv.isDarwin - then "Library/Application Support/${getAttr browser darwinDirs}" - else "${config.xdg.configHome}/${browser}"; + configDir = if pkgs.stdenv.isDarwin then + "Library/Application Support/${getAttr browser darwinDirs}" + else + "${config.xdg.configHome}/${browser}"; extensionJson = ext: { - target = "${configDir}/External Extensions/${ext}.json"; - text = builtins.toJSON { - external_update_url = "https://clients2.google.com/service/update2/crx"; + name = "${configDir}/External Extensions/${ext}.json"; + value.text = builtins.toJSON { + external_update_url = + "https://clients2.google.com/service/update2/crx"; }; }; - in - mkIf cfg.enable { - home.packages = [ cfg.package ]; - home.file = map extensionJson cfg.extensions; - }; - -in + in mkIf cfg.enable { + home.packages = [ cfg.package ]; + home.file = listToAttrs (map extensionJson cfg.extensions); + }; -{ +in { options.programs = { chromium = browserModule pkgs.chromium "Chromium" true; google-chrome = browserModule pkgs.google-chrome "Google Chrome" false; - google-chrome-beta = browserModule pkgs.google-chrome-beta "Google Chrome Beta" false; - google-chrome-dev = browserModule pkgs.google-chrome-dev "Google Chrome Dev" false; + google-chrome-beta = + browserModule pkgs.google-chrome-beta "Google Chrome Beta" false; + google-chrome-dev = + browserModule pkgs.google-chrome-dev "Google Chrome Dev" false; }; config = mkMerge [ diff --git a/home-manager/modules/programs/command-not-found/command-not-found.nix b/home-manager/modules/programs/command-not-found/command-not-found.nix index 0053fe36ad7..b79fde0f619 100644 --- a/home-manager/modules/programs/command-not-found/command-not-found.nix +++ b/home-manager/modules/programs/command-not-found/command-not-found.nix @@ -13,8 +13,11 @@ let isExecutable = true; inherit (pkgs) perl; inherit (cfg) dbPath; - perlFlags = concatStrings (map (path: "-I ${path}/lib/perl5/site_perl ") - [ pkgs.perlPackages.DBI pkgs.perlPackages.DBDSQLite pkgs.perlPackages.StringShellQuote ]); + perlFlags = concatStrings (map (path: "-I ${path}/lib/perl5/site_perl ") [ + pkgs.perlPackages.DBI + pkgs.perlPackages.DBDSQLite + pkgs.perlPackages.StringShellQuote + ]); }; shInit = commandNotFoundHandlerName: '' @@ -31,14 +34,13 @@ let } ''; -in - -{ +in { options.programs.command-not-found = { enable = mkEnableOption "command-not-found hook for interactive shell"; dbPath = mkOption { - default = "/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite" ; + default = + "/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite"; description = '' Absolute path to <filename>programs.sqlite</filename>. By default this file will be provided by your channel diff --git a/home-manager/modules/programs/direnv.nix b/home-manager/modules/programs/direnv.nix index e4c17239c58..beb40a96261 100644 --- a/home-manager/modules/programs/direnv.nix +++ b/home-manager/modules/programs/direnv.nix @@ -6,21 +6,17 @@ let cfg = config.programs.direnv; configFile = config: - pkgs.runCommand "config.toml" - { - buildInputs = [ pkgs.remarshal ]; - preferLocalBuild = true; - allowSubstitutes = false; - } - '' - remarshal -if json -of toml \ - < ${pkgs.writeText "config.json" (builtins.toJSON config)} \ - > $out - ''; - -in + pkgs.runCommand "config.toml" { + buildInputs = [ pkgs.remarshal ]; + preferLocalBuild = true; + allowSubstitutes = false; + } '' + remarshal -if json -of toml \ + < ${pkgs.writeText "config.json" (builtins.toJSON config)} \ + > $out + ''; -{ +in { meta.maintainers = [ maintainers.rycee ]; options.programs.direnv = { @@ -28,7 +24,7 @@ in config = mkOption { type = types.attrs; - default = {}; + default = { }; description = '' Configuration written to <filename>~/.config/direnv/config.toml</filename>. @@ -79,22 +75,18 @@ in config = mkIf cfg.enable { home.packages = [ pkgs.direnv ]; - xdg.configFile."direnv/config.toml" = mkIf (cfg.config != {}) { - source = configFile cfg.config; - }; + xdg.configFile."direnv/config.toml" = + mkIf (cfg.config != { }) { source = configFile cfg.config; }; - xdg.configFile."direnv/direnvrc" = mkIf (cfg.stdlib != "") { - text = cfg.stdlib; - }; + xdg.configFile."direnv/direnvrc" = + mkIf (cfg.stdlib != "") { text = cfg.stdlib; }; - programs.bash.initExtra = - mkIf cfg.enableBashIntegration ( - # Using mkAfter to make it more likely to appear after other - # manipulations of the prompt. - mkAfter '' - eval "$(${pkgs.direnv}/bin/direnv hook bash)" - '' - ); + programs.bash.initExtra = mkIf cfg.enableBashIntegration ( + # Using mkAfter to make it more likely to appear after other + # manipulations of the prompt. + mkAfter '' + eval "$(${pkgs.direnv}/bin/direnv hook bash)" + ''); programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' eval "$(${pkgs.direnv}/bin/direnv hook zsh)" diff --git a/home-manager/modules/programs/eclipse.nix b/home-manager/modules/programs/eclipse.nix index 4a432c9fe1a..8ce605b106a 100644 --- a/home-manager/modules/programs/eclipse.nix +++ b/home-manager/modules/programs/eclipse.nix @@ -6,9 +6,7 @@ let cfg = config.programs.eclipse; -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; options = { @@ -27,13 +25,13 @@ in jvmArgs = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; description = "JVM arguments to use for the Eclipse process."; }; plugins = mkOption { type = types.listOf types.package; - default = []; + default = [ ]; description = "Plugins that should be added to Eclipse."; }; }; @@ -43,10 +41,8 @@ in home.packages = [ (pkgs.eclipses.eclipseWithPlugins { eclipse = pkgs.eclipses.eclipse-platform; - jvmArgs = - cfg.jvmArgs - ++ optional cfg.enableLombok - "-javaagent:${pkgs.lombok}/share/java/lombok.jar"; + jvmArgs = cfg.jvmArgs ++ optional cfg.enableLombok + "-javaagent:${pkgs.lombok}/share/java/lombok.jar"; plugins = cfg.plugins; }) ]; diff --git a/home-manager/modules/programs/emacs.nix b/home-manager/modules/programs/emacs.nix index 78c136c9868..987a9f2431e 100644 --- a/home-manager/modules/programs/emacs.nix +++ b/home-manager/modules/programs/emacs.nix @@ -4,15 +4,13 @@ with lib; let - hmTypes = import ../lib/types.nix { inherit lib; }; - cfg = config.programs.emacs; # Copied from all-packages.nix, with modifications to support # overrides. emacsPackages = let - epkgs = pkgs.emacsPackagesNgGen cfg.package; + epkgs = pkgs.emacsPackagesGen cfg.package; in epkgs.overrideScope' cfg.overrides; emacsWithPackages = emacsPackages.emacsWithPackages; @@ -36,19 +34,19 @@ in extraPackages = mkOption { default = self: []; - type = hmTypes.selectorFunction; + type = hm.types.selectorFunction; defaultText = "epkgs: []"; example = literalExample "epkgs: [ epkgs.emms epkgs.magit ]"; description = '' Extra packages available to Emacs. To get a list of available packages run: - <command>nix-env -f '<nixpkgs>' -qaP -A emacsPackagesNg</command>. + <command>nix-env -f '<nixpkgs>' -qaP -A emacsPackages</command>. ''; }; overrides = mkOption { default = self: super: {}; - type = hmTypes.overlayFunction; + type = hm.types.overlayFunction; defaultText = "self: super: {}"; example = literalExample '' self: super: rec { diff --git a/home-manager/modules/programs/feh.nix b/home-manager/modules/programs/feh.nix index 4342181fa4a..b1b33697e95 100644 --- a/home-manager/modules/programs/feh.nix +++ b/home-manager/modules/programs/feh.nix @@ -7,20 +7,37 @@ let cfg = config.programs.feh; disableBinding = func: key: func; - enableBinding = func: key: "${func} ${key}"; + enableBinding = func: key: "${func} ${toString key}"; -in - -{ +in { options.programs.feh = { enable = mkEnableOption "feh - a fast and light image viewer"; + buttons = mkOption { + default = { }; + type = with types; attrsOf (nullOr (either str int)); + example = { + zoom_in = 4; + zoom_out = "C-4"; + }; + description = '' + Override feh's default mouse button mapping. If you want to disable an + action, set its value to null. + See <link xlink:href="https://man.finalrewind.org/1/feh/#x425554544f4e53"/> for + default bindings and available commands. + ''; + }; + keybindings = mkOption { - default = {}; - type = types.attrsOf types.str; - example = { zoom_in = "plus"; zoom_out = "minus"; }; + default = { }; + type = types.attrsOf (types.nullOr types.str); + example = { + zoom_in = "plus"; + zoom_out = "minus"; + }; description = '' - Set keybindings. + Override feh's default keybindings. If you want to disable a keybinding + set its value to null. See <link xlink:href="https://man.finalrewind.org/1/feh/#x4b455953"/> for default bindings and available commands. ''; @@ -28,14 +45,26 @@ in }; config = mkIf cfg.enable { + assertions = [{ + assertion = ((filterAttrs (n: v: v == "") cfg.keybindings) == { }); + message = + "To disable a keybinding, use `null` instead of an empty string."; + }]; + home.packages = [ pkgs.feh ]; - xdg.configFile."feh/keys".text = '' - # Disable default keybindings - ${concatStringsSep "\n" (mapAttrsToList disableBinding cfg.keybindings)} + xdg.configFile."feh/buttons".text = '' + ${concatStringsSep "\n" (mapAttrsToList disableBinding + (filterAttrs (n: v: v == null) cfg.buttons))} + ${concatStringsSep "\n" (mapAttrsToList enableBinding + (filterAttrs (n: v: v != null) cfg.buttons))} + ''; - # Enable new keybindings - ${concatStringsSep "\n" (mapAttrsToList enableBinding cfg.keybindings)} + xdg.configFile."feh/keys".text = '' + ${concatStringsSep "\n" (mapAttrsToList disableBinding + (filterAttrs (n: v: v == null) cfg.keybindings))} + ${concatStringsSep "\n" (mapAttrsToList enableBinding + (filterAttrs (n: v: v != null) cfg.keybindings))} ''; }; } diff --git a/home-manager/modules/programs/firefox.nix b/home-manager/modules/programs/firefox.nix index 708b05417d6..17c64752d66 100644 --- a/home-manager/modules/programs/firefox.nix +++ b/home-manager/modules/programs/firefox.nix @@ -4,15 +4,35 @@ with lib; let + inherit (pkgs.stdenv.hostPlatform) isDarwin; + cfg = config.programs.firefox; + mozillaConfigPath = + if isDarwin + then "Library/Application Support/Mozilla" + else ".mozilla"; + + firefoxConfigPath = + if isDarwin + then "Library/Application Support/Firefox" + else "${mozillaConfigPath}/firefox"; + + profilesPath = + if isDarwin + then "${firefoxConfigPath}/Profiles" + else firefoxConfigPath; + extensionPath = "extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"; profiles = flip mapAttrs' cfg.profiles (_: profile: nameValuePair "Profile${toString profile.id}" { Name = profile.name; - Path = profile.path; + Path = + if isDarwin + then "Profiles/${profile.path}" + else profile.path; IsRelative = 1; Default = if profile.isDefault then 1 else 0; } @@ -242,15 +262,18 @@ in bcfg = setAttrByPath [browserName] fcfg; package = - if versionAtLeast config.home.stateVersion "19.09" - then cfg.package.override { cfg = fcfg; } - else (pkgs.wrapFirefox.override { config = bcfg; }) cfg.package { }; + if isDarwin then + cfg.package + else if versionAtLeast config.home.stateVersion "19.09" then + cfg.package.override { cfg = fcfg; } + else + (pkgs.wrapFirefox.override { config = bcfg; }) cfg.package { }; in [ package ]; home.file = mkMerge ( [{ - ".mozilla/${extensionPath}" = mkIf (cfg.extensions != []) ( + "${mozillaConfigPath}/${extensionPath}" = mkIf (cfg.extensions != []) ( let extensionsEnv = pkgs.buildEnv { name = "hm-firefox-extensions"; @@ -262,17 +285,17 @@ in } ); - ".mozilla/firefox/profiles.ini" = mkIf (cfg.profiles != {}) { + "${firefoxConfigPath}/profiles.ini" = mkIf (cfg.profiles != {}) { text = profilesIni; }; }] ++ flip mapAttrsToList cfg.profiles (_: profile: { - ".mozilla/firefox/${profile.path}/chrome/userChrome.css" = + "${profilesPath}/${profile.path}/chrome/userChrome.css" = mkIf (profile.userChrome != "") { text = profile.userChrome; }; - ".mozilla/firefox/${profile.path}/user.js" = + "${profilesPath}/${profile.path}/user.js" = mkIf (profile.settings != {} || profile.extraConfig != "") { text = mkUserJs profile.settings profile.extraConfig; }; diff --git a/home-manager/modules/programs/fzf.nix b/home-manager/modules/programs/fzf.nix index 832c0bfa3e4..36eb3a1cdba 100644 --- a/home-manager/modules/programs/fzf.nix +++ b/home-manager/modules/programs/fzf.nix @@ -6,9 +6,7 @@ let cfg = config.programs.fzf; -in - -{ +in { options.programs.fzf = { enable = mkEnableOption "fzf - a command-line fuzzy finder"; @@ -24,7 +22,7 @@ in defaultOptions = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; example = [ "--height 40%" "--border" ]; description = '' Extra command line options given to fzf by default. @@ -43,7 +41,7 @@ in fileWidgetOptions = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; example = [ "--preview 'head {}'" ]; description = '' Command line options for the CTRL-T keybinding. @@ -53,7 +51,7 @@ in changeDirWidgetCommand = mkOption { type = types.nullOr types.str; default = null; - example = "fd --type d" ; + example = "fd --type d"; description = '' The command that gets executed as the source for fzf for the ALT-C keybinding. @@ -62,7 +60,7 @@ in changeDirWidgetOptions = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; example = [ "--preview 'tree -C {} | head -200'" ]; description = '' Command line options for the ALT-C keybinding. @@ -80,7 +78,7 @@ in historyWidgetOptions = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; example = [ "--sort" "--exact" ]; description = '' Command line options for the CTRL-R keybinding. @@ -107,19 +105,17 @@ in config = mkIf cfg.enable { home.packages = [ pkgs.fzf ]; - home.sessionVariables = - mapAttrs (n: v: toString v) ( - filterAttrs (n: v: v != [] && v != null) { - FZF_ALT_C_COMMAND = cfg.changeDirWidgetCommand; - FZF_ALT_C_OPTS = cfg.changeDirWidgetOptions; - FZF_CTRL_R_COMMAND = cfg.historyWidgetCommand; - FZF_CTRL_R_OPTS = cfg.historyWidgetOptions; - FZF_CTRL_T_COMMAND = cfg.fileWidgetCommand; - FZF_CTRL_T_OPTS = cfg.fileWidgetOptions; - FZF_DEFAULT_COMMAND = cfg.defaultCommand; - FZF_DEFAULT_OPTS = cfg.defaultOptions; - } - ); + home.sessionVariables = mapAttrs (n: v: toString v) + (filterAttrs (n: v: v != [ ] && v != null) { + FZF_ALT_C_COMMAND = cfg.changeDirWidgetCommand; + FZF_ALT_C_OPTS = cfg.changeDirWidgetOptions; + FZF_CTRL_R_COMMAND = cfg.historyWidgetCommand; + FZF_CTRL_R_OPTS = cfg.historyWidgetOptions; + FZF_CTRL_T_COMMAND = cfg.fileWidgetCommand; + FZF_CTRL_T_OPTS = cfg.fileWidgetOptions; + FZF_DEFAULT_COMMAND = cfg.defaultCommand; + FZF_DEFAULT_OPTS = cfg.defaultOptions; + }); programs.bash.initExtra = mkIf cfg.enableBashIntegration '' if [[ :$SHELLOPTS: =~ :(vi|emacs): ]]; then diff --git a/home-manager/modules/programs/getmail-accounts.nix b/home-manager/modules/programs/getmail-accounts.nix index 32e1312dc8f..24eb4fb588a 100644 --- a/home-manager/modules/programs/getmail-accounts.nix +++ b/home-manager/modules/programs/getmail-accounts.nix @@ -17,8 +17,8 @@ with lib; mailboxes = mkOption { type = types.nonEmptyListOf types.str; - default = []; - example = ["INBOX" "INBOX.spam"]; + default = [ ]; + example = [ "INBOX" "INBOX.spam" ]; description = '' A non-empty list of mailboxes. To download all mail you can use the <literal>ALL</literal> mailbox. diff --git a/home-manager/modules/programs/getmail.nix b/home-manager/modules/programs/getmail.nix index 04a958d6cda..2c3919dcf2f 100644 --- a/home-manager/modules/programs/getmail.nix +++ b/home-manager/modules/programs/getmail.nix @@ -4,34 +4,33 @@ with lib; let - accounts = filter (a: a.getmail.enable) - (attrValues config.accounts.email.accounts); + accounts = + filter (a: a.getmail.enable) (attrValues config.accounts.email.accounts); - renderAccountConfig = account: with account; + renderAccountConfig = account: + with account; let passCmd = concatMapStringsSep ", " (x: "'${x}'") passwordCommand; - renderedMailboxes = concatMapStringsSep ", " (x: "'${x}'") getmail.mailboxes; - retrieverType = if imap.tls.enable - then "SimpleIMAPSSLRetriever" - else "SimpleIMAPRetriever"; - destination = if getmail.destinationCommand != null - then - { - destinationType = "MDA_external"; - destinationPath = getmail.destinationCommand; - } - else - { - destinationType = "Maildir"; - destinationPath = "${maildir.absPath}/"; - }; + renderedMailboxes = + concatMapStringsSep ", " (x: "'${x}'") getmail.mailboxes; + retrieverType = if imap.tls.enable then + "SimpleIMAPSSLRetriever" + else + "SimpleIMAPRetriever"; + destination = if getmail.destinationCommand != null then { + destinationType = "MDA_external"; + destinationPath = getmail.destinationCommand; + } else { + destinationType = "Maildir"; + destinationPath = "${maildir.absPath}/"; + }; renderGetmailBoolean = v: if v then "true" else "false"; in '' # Generated by Home-Manager. [retriever] type = ${retrieverType} server = ${imap.host} - ${optionalString (imap.port != null) "port = ${imap.port}"} + ${optionalString (imap.port != null) "port = ${toString imap.port}"} username = ${userName} password_command = (${passCmd}) mailboxes = ( ${renderedMailboxes} ) @@ -46,15 +45,13 @@ let ''; getmailEnabled = length (filter (a: a.getmail.enable) accounts) > 0; # Watch out! This is used by the getmail.service too! - renderConfigFilepath = a: ".getmail/getmail${if a.primary then "rc" else a.name}"; -in - - { - config = mkIf getmailEnabled { - home.file = map (a: - { target = renderConfigFilepath a; - text = renderAccountConfig a; - }) accounts; - - }; - } + renderConfigFilepath = a: + ".getmail/getmail${if a.primary then "rc" else a.name}"; + +in { + config = mkIf getmailEnabled { + home.file = foldl' (a: b: a // b) { } + (map (a: { "${renderConfigFilepath a}".text = renderAccountConfig a; }) + accounts); + }; +} diff --git a/home-manager/modules/programs/git.nix b/home-manager/modules/programs/git.nix index 913f86f71ce..a56aa10d50e 100644 --- a/home-manager/modules/programs/git.nix +++ b/home-manager/modules/programs/git.nix @@ -14,36 +14,31 @@ let section = head sections; subsections = tail sections; subsection = concatStringsSep "." subsections; - in - if containsQuote || subsections == [] - then name - else "${section} \"${subsection}\""; + in if containsQuote || subsections == [ ] then + name + else + ''${section} "${subsection}"''; # generation for multiple ini values mkKeyValue = k: v: - let - mkKeyValue = generators.mkKeyValueDefault {} "=" k; - in - concatStringsSep "\n" (map mkKeyValue (toList v)); + let mkKeyValue = generators.mkKeyValueDefault { } "=" k; + in concatStringsSep "\n" (map mkKeyValue (toList v)); # converts { a.b.c = 5; } to { "a.b".c = 5; } for toINI - gitFlattenAttrs = - let - recurse = path: value: - if isAttrs value then - mapAttrsToList (name: value: recurse ([name] ++ path) value) value - else if length path > 1 then - { ${concatStringsSep "." (reverseList (tail path))}.${head path} = value; } - else - { ${head path} = value; }; - in - attrs: foldl recursiveUpdate {} (flatten (recurse [] attrs)); + gitFlattenAttrs = let + recurse = path: value: + if isAttrs value then + mapAttrsToList (name: value: recurse ([ name ] ++ path) value) value + else if length path > 1 then { + ${concatStringsSep "." (reverseList (tail path))}.${head path} = value; + } else { + ${head path} = value; + }; + in attrs: foldl recursiveUpdate { } (flatten (recurse [ ] attrs)); gitToIni = attrs: - let - toIni = generators.toINI { inherit mkKeyValue mkSectionName; }; - in - toIni (gitFlattenAttrs attrs); + let toIni = generators.toINI { inherit mkKeyValue mkSectionName; }; + in toIni (gitFlattenAttrs attrs); gitIniType = with types; let @@ -51,8 +46,7 @@ let multipleType = either primitiveType (listOf primitiveType); sectionType = attrsOf multipleType; supersectionType = attrsOf (either multipleType sectionType); - in - attrsOf supersectionType; + in attrsOf supersectionType; signModule = types.submodule { options = { @@ -98,21 +92,18 @@ let contents = mkOption { type = types.attrs; - default = {}; + default = { }; description = '' Configuration to include. If empty then a path must be given. ''; }; }; - config.path = mkIf (config.contents != {}) ( - mkDefault (pkgs.writeText "contents" (gitToIni config.contents)) - ); + config.path = mkIf (config.contents != { }) + (mkDefault (pkgs.writeText "contents" (gitToIni config.contents))); }); -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; options = { @@ -143,7 +134,7 @@ in aliases = mkOption { type = types.attrsOf types.str; - default = {}; + default = { }; example = { co = "checkout"; }; description = "Git aliases to define."; }; @@ -156,7 +147,7 @@ in extraConfig = mkOption { type = types.either types.lines gitIniType; - default = {}; + default = { }; example = { core = { whitespace = "trailing-space,space-before-tab"; }; url."ssh://git@host".insteadOf = "otherhost"; @@ -174,21 +165,21 @@ in ignores = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; example = [ "*~" "*.swp" ]; description = "List of paths that should be globally ignored."; }; attributes = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; example = [ "*.pdf diff=pdf" ]; description = "List of defining attributes set globally."; }; includes = mkOption { type = types.listOf includeModule; - default = []; + default = [ ]; example = literalExample '' [ { path = "~/path/to/config.inc"; } @@ -217,109 +208,96 @@ in }; }; - config = mkIf cfg.enable ( - mkMerge [ - { - home.packages = [ cfg.package ]; + config = mkIf cfg.enable (mkMerge [ + { + home.packages = [ cfg.package ]; - programs.git.iniContent.user = { - name = mkIf (cfg.userName != null) cfg.userName; - email = mkIf (cfg.userEmail != null) cfg.userEmail; - }; + programs.git.iniContent.user = { + name = mkIf (cfg.userName != null) cfg.userName; + email = mkIf (cfg.userEmail != null) cfg.userEmail; + }; - xdg.configFile = { - "git/config".text = gitToIni cfg.iniContent; + xdg.configFile = { + "git/config".text = gitToIni cfg.iniContent; - "git/ignore" = mkIf (cfg.ignores != []) { - text = concatStringsSep "\n" cfg.ignores + "\n"; - }; + "git/ignore" = mkIf (cfg.ignores != [ ]) { + text = concatStringsSep "\n" cfg.ignores + "\n"; + }; - "git/attributes" = mkIf (cfg.attributes != []) { - text = concatStringsSep "\n" cfg.attributes + "\n"; - }; + "git/attributes" = mkIf (cfg.attributes != [ ]) { + text = concatStringsSep "\n" cfg.attributes + "\n"; }; - } - - { - programs.git.iniContent = - let - hasSmtp = name: account: account.smtp != null; - - genIdentity = name: account: with account; - nameValuePair "sendemail.${name}" ({ - smtpEncryption = if smtp.tls.enable then "tls" else ""; - smtpServer = smtp.host; - smtpUser = userName; - from = address; - } - // optionalAttrs (smtp.port != null) { - smtpServerPort = smtp.port; - }); - in - mapAttrs' genIdentity - (filterAttrs hasSmtp config.accounts.email.accounts); - } - - (mkIf (cfg.signing != null) { - programs.git.iniContent = { - user.signingKey = cfg.signing.key; - commit.gpgSign = cfg.signing.signByDefault; - gpg.program = cfg.signing.gpgPath; + }; + } + + { + programs.git.iniContent = let + hasSmtp = name: account: account.smtp != null; + + genIdentity = name: account: + with account; + nameValuePair "sendemail.${name}" ({ + smtpEncryption = if smtp.tls.enable then "tls" else ""; + smtpServer = smtp.host; + smtpUser = userName; + from = address; + } // optionalAttrs (smtp.port != null) { + smtpServerPort = smtp.port; + }); + in mapAttrs' genIdentity + (filterAttrs hasSmtp config.accounts.email.accounts); + } + + (mkIf (cfg.signing != null) { + programs.git.iniContent = { + user.signingKey = cfg.signing.key; + commit.gpgSign = cfg.signing.signByDefault; + gpg.program = cfg.signing.gpgPath; + }; + }) + + (mkIf (cfg.aliases != { }) { programs.git.iniContent.alias = cfg.aliases; }) + + (mkIf (lib.isAttrs cfg.extraConfig) { + programs.git.iniContent = cfg.extraConfig; + }) + + (mkIf (lib.isString cfg.extraConfig) { + warnings = ['' + Using programs.git.extraConfig as a string option is + deprecated and will be removed in the future. Please + change to using it as an attribute set instead. + '']; + + xdg.configFile."git/config".text = cfg.extraConfig; + }) + + (mkIf (cfg.includes != [ ]) { + xdg.configFile."git/config".text = let + include = i: + with i; + if condition != null then { + includeIf.${condition}.path = "${path}"; + } else { + include.path = "${path}"; + }; + in mkAfter + (concatStringsSep "\n" (map gitToIni (map include cfg.includes))); + }) + + (mkIf cfg.lfs.enable { + home.packages = [ pkgs.git-lfs ]; + + programs.git.iniContent.filter.lfs = + let skipArg = optional cfg.lfs.skipSmudge "--skip"; + in { + clean = "git-lfs clean -- %f"; + process = + concatStringsSep " " ([ "git-lfs" "filter-process" ] ++ skipArg); + required = true; + smudge = concatStringsSep " " + ([ "git-lfs" "smudge" ] ++ skipArg ++ [ "--" "%f" ]); }; - }) - - (mkIf (cfg.aliases != {}) { - programs.git.iniContent.alias = cfg.aliases; - }) - - (mkIf (lib.isAttrs cfg.extraConfig) { - programs.git.iniContent = cfg.extraConfig; - }) - - (mkIf (lib.isString cfg.extraConfig) { - warnings = [ - '' - Using programs.git.extraConfig as a string option is - deprecated and will be removed in the future. Please - change to using it as an attribute set instead. - '' - ]; - - xdg.configFile."git/config".text = cfg.extraConfig; - }) - - (mkIf (cfg.includes != []) { - xdg.configFile."git/config".text = - let - include = i: with i; - if condition != null - then { includeIf.${condition}.path = "${path}"; } - else { include.path = "${path}"; }; - in - mkAfter - (concatStringsSep "\n" - (map gitToIni - (map include cfg.includes))); - }) - - (mkIf cfg.lfs.enable { - home.packages = [ pkgs.git-lfs ]; - - programs.git.iniContent.filter.lfs = - let - skipArg = optional cfg.lfs.skipSmudge "--skip"; - in - { - clean = "git-lfs clean -- %f"; - process = concatStringsSep " " ( - [ "git-lfs" "filter-process" ] ++ skipArg - ); - required = true; - smudge = concatStringsSep " " ( - [ "git-lfs" "smudge" ] ++ skipArg ++ [ "--" "%f" ] - ); - }; - }) - ] - ); + }) + ]); } diff --git a/home-manager/modules/programs/gnome-terminal.nix b/home-manager/modules/programs/gnome-terminal.nix index 9a44364491d..570a1fc7df0 100644 --- a/home-manager/modules/programs/gnome-terminal.nix +++ b/home-manager/modules/programs/gnome-terminal.nix @@ -11,125 +11,118 @@ let . ${pkgs.gnome3.vte}/etc/profile.d/vte.sh ''; - backForeSubModule = types.submodule ( - { ... }: { - options = { - foreground = mkOption { - type = types.str; - description = "The foreground color."; - }; - - background = mkOption { - type = types.str; - description = "The background color."; - }; - }; - } - ); - - profileColorsSubModule = types.submodule ( - { ... }: { - options = { - foregroundColor = mkOption { - type = types.str; - description = "The foreground color."; - }; - - backgroundColor = mkOption { - type = types.str; - description = "The background color."; - }; - - boldColor = mkOption { - default = null; - type = types.nullOr types.str; - description = "The bold color, null to use same as foreground."; - }; - - palette = mkOption { - type = types.listOf types.str; - description = "The terminal palette."; - }; - - cursor = mkOption { - default = null; - type = types.nullOr backForeSubModule; - description = "The color for the terminal cursor."; - }; - - highlight = mkOption { - default = null; - type = types.nullOr backForeSubModule; - description = "The colors for the terminal’s highlighted area."; - }; - }; - } - ); - - profileSubModule = types.submodule ( - { name, config, ... }: { - options = { - default = mkOption { - default = false; - type = types.bool; - description = "Whether this should be the default profile."; - }; - - visibleName = mkOption { - type = types.str; - description = "The profile name."; - }; - - colors = mkOption { - default = null; - type = types.nullOr profileColorsSubModule; - description = "The terminal colors, null to use system default."; - }; - - cursorShape = mkOption { - default = "block"; - type = types.enum [ "block" "ibeam" "underline" ]; - description = "The cursor shape."; - }; - - font = mkOption { - default = null; - type = types.nullOr types.str; - description = "The font name, null to use system default."; - }; - - allowBold = mkOption { - default = null; - type = types.nullOr types.bool; - description = '' - If <literal>true</literal>, allow applications in the - terminal to make text boldface. - ''; - }; - - scrollOnOutput = mkOption { - default = true; - type = types.bool; - description = "Whether to scroll when output is written."; - }; - - showScrollbar = mkOption { - default = true; - type = types.bool; - description = "Whether the scroll bar should be visible."; - }; - - scrollbackLines = mkOption { - default = 10000; - type = types.nullOr types.int; - description = - '' - The number of scrollback lines to keep, null for infinite. - ''; - }; - }; - } - ); + backForeSubModule = types.submodule ({ ... }: { + options = { + foreground = mkOption { + type = types.str; + description = "The foreground color."; + }; + + background = mkOption { + type = types.str; + description = "The background color."; + }; + }; + }); + + profileColorsSubModule = types.submodule ({ ... }: { + options = { + foregroundColor = mkOption { + type = types.str; + description = "The foreground color."; + }; + + backgroundColor = mkOption { + type = types.str; + description = "The background color."; + }; + + boldColor = mkOption { + default = null; + type = types.nullOr types.str; + description = "The bold color, null to use same as foreground."; + }; + + palette = mkOption { + type = types.listOf types.str; + description = "The terminal palette."; + }; + + cursor = mkOption { + default = null; + type = types.nullOr backForeSubModule; + description = "The color for the terminal cursor."; + }; + + highlight = mkOption { + default = null; + type = types.nullOr backForeSubModule; + description = "The colors for the terminal’s highlighted area."; + }; + }; + }); + + profileSubModule = types.submodule ({ name, config, ... }: { + options = { + default = mkOption { + default = false; + type = types.bool; + description = "Whether this should be the default profile."; + }; + + visibleName = mkOption { + type = types.str; + description = "The profile name."; + }; + + colors = mkOption { + default = null; + type = types.nullOr profileColorsSubModule; + description = "The terminal colors, null to use system default."; + }; + + cursorShape = mkOption { + default = "block"; + type = types.enum [ "block" "ibeam" "underline" ]; + description = "The cursor shape."; + }; + + font = mkOption { + default = null; + type = types.nullOr types.str; + description = "The font name, null to use system default."; + }; + + allowBold = mkOption { + default = null; + type = types.nullOr types.bool; + description = '' + If <literal>true</literal>, allow applications in the + terminal to make text boldface. + ''; + }; + + scrollOnOutput = mkOption { + default = true; + type = types.bool; + description = "Whether to scroll when output is written."; + }; + + showScrollbar = mkOption { + default = true; + type = types.bool; + description = "Whether the scroll bar should be visible."; + }; + + scrollbackLines = mkOption { + default = 10000; + type = types.nullOr types.int; + description = '' + The number of scrollback lines to keep, null for infinite. + ''; + }; + }; + }); buildProfileSet = pcfg: { @@ -137,56 +130,41 @@ let scrollbar-policy = if pcfg.showScrollbar then "always" else "never"; scrollback-lines = pcfg.scrollbackLines; cursor-shape = pcfg.cursorShape; - } - // ( - if (pcfg.font == null) - then { use-system-font = true; } - else { use-system-font = false; font = pcfg.font; } - ) // ( - if (pcfg.colors == null) - then { use-theme-colors = true; } - else ( - { - use-theme-colors = false; - foreground-color = pcfg.colors.foregroundColor; - background-color = pcfg.colors.backgroundColor; - palette = pcfg.colors.palette; - } - // optionalAttrs (pcfg.allowBold != null) { - allow-bold = pcfg.allowBold; - } - // ( - if (pcfg.colors.boldColor == null) - then { bold-color-same-as-fg = true; } - else { - bold-color-same-as-fg = false; - bold-color = pcfg.colors.boldColor; - } - ) - // ( - if (pcfg.colors.cursor != null) - then { - cursor-colors-set = true; - cursor-foreground-color = pcfg.colors.cursor.foreground; - cursor-background-color = pcfg.colors.cursor.background; - } - else { cursor-colors-set = false; } - ) - // ( - if (pcfg.colors.highlight != null) - then { - highlight-colors-set = true; - highlight-foreground-color = pcfg.colors.highlight.foreground; - highlight-background-color = pcfg.colors.highlight.background; - } - else { highlight-colors-set = false; } - ) - ) - ); - -in - -{ + } // (if (pcfg.font == null) then { + use-system-font = true; + } else { + use-system-font = false; + font = pcfg.font; + }) // (if (pcfg.colors == null) then { + use-theme-colors = true; + } else + ({ + use-theme-colors = false; + foreground-color = pcfg.colors.foregroundColor; + background-color = pcfg.colors.backgroundColor; + palette = pcfg.colors.palette; + } // optionalAttrs (pcfg.allowBold != null) { + allow-bold = pcfg.allowBold; + } // (if (pcfg.colors.boldColor == null) then { + bold-color-same-as-fg = true; + } else { + bold-color-same-as-fg = false; + bold-color = pcfg.colors.boldColor; + }) // (if (pcfg.colors.cursor != null) then { + cursor-colors-set = true; + cursor-foreground-color = pcfg.colors.cursor.foreground; + cursor-background-color = pcfg.colors.cursor.background; + } else { + cursor-colors-set = false; + }) // (if (pcfg.colors.highlight != null) then { + highlight-colors-set = true; + highlight-foreground-color = pcfg.colors.highlight.foreground; + highlight-background-color = pcfg.colors.highlight.background; + } else { + highlight-colors-set = false; + }))); + +in { meta.maintainers = [ maintainers.rycee ]; options = { @@ -206,7 +184,7 @@ in }; profile = mkOption { - default = {}; + default = { }; type = types.attrsOf profileSubModule; description = "A set of Gnome Terminal profiles."; }; @@ -216,25 +194,21 @@ in config = mkIf cfg.enable { home.packages = [ pkgs.gnome3.gnome_terminal ]; - dconf.settings = - let - dconfPath = "org/gnome/terminal/legacy"; - in - { - "${dconfPath}" = { - default-show-menubar = cfg.showMenubar; - theme-variant = cfg.themeVariant; - schema-version = 3; - }; - - "${dconfPath}/profiles:" = { - default = head (attrNames (filterAttrs (n: v: v.default) cfg.profile)); - list = attrNames cfg.profile; - }; - } - // mapAttrs' (n: v: - nameValuePair ("${dconfPath}/profiles:/:${n}") (buildProfileSet v) - ) cfg.profile; + dconf.settings = let dconfPath = "org/gnome/terminal/legacy"; + in { + "${dconfPath}" = { + default-show-menubar = cfg.showMenubar; + theme-variant = cfg.themeVariant; + schema-version = 3; + }; + + "${dconfPath}/profiles:" = { + default = head (attrNames (filterAttrs (n: v: v.default) cfg.profile)); + list = attrNames cfg.profile; + }; + } // mapAttrs' + (n: v: nameValuePair ("${dconfPath}/profiles:/:${n}") (buildProfileSet v)) + cfg.profile; programs.bash.initExtra = mkBefore vteInitStr; programs.zsh.initExtra = vteInitStr; diff --git a/home-manager/modules/programs/go.nix b/home-manager/modules/programs/go.nix index 06c25c9b82a..983769d26af 100644 --- a/home-manager/modules/programs/go.nix +++ b/home-manager/modules/programs/go.nix @@ -6,9 +6,7 @@ let cfg = config.programs.go; -in - -{ +in { meta.maintainers = [ maintainers.rvolosatovs ]; options = { @@ -24,7 +22,7 @@ in packages = mkOption { type = with types; attrsOf path; - default = {}; + default = { }; example = literalExample '' { "golang.org/x/text" = builtins.fetchGit "https://go.googlesource.com/text"; @@ -38,7 +36,24 @@ in type = with types; nullOr str; default = null; example = "go"; - description = "GOPATH relative to HOME"; + description = '' + Primary <envar>GOPATH</envar> relative to + <envar>HOME</envar>. It will be exported first and therefore + used by default by the Go tooling. + ''; + }; + + extraGoPaths = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "extraGoPath1" "extraGoPath2" ]; + description = let goPathOpt = "programs.go.goPath"; + in '' + Extra <envar>GOPATH</envar>s relative to <envar>HOME</envar> appended + after + <varname><link linkend="opt-${goPathOpt}">${goPathOpt}</link></varname>, + if that option is set. + ''; }; goBin = mkOption { @@ -54,22 +69,21 @@ in { home.packages = [ cfg.package ]; - home.file = - let - goPath = if cfg.goPath != null then cfg.goPath else "go"; - - mkSrc = n: v: { - target = "${goPath}/src/${n}"; - source = v; - }; - in - mapAttrsToList mkSrc cfg.packages; + home.file = let + goPath = if cfg.goPath != null then cfg.goPath else "go"; + mkSrc = n: v: { "${goPath}/src/${n}".source = v; }; + in foldl' (a: b: a // b) { } (mapAttrsToList mkSrc cfg.packages); } + (mkIf (cfg.goPath != null) { - home.sessionVariables.GOPATH = builtins.toPath "${config.home.homeDirectory}/${cfg.goPath}"; + home.sessionVariables.GOPATH = concatStringsSep ":" (map builtins.toPath + (map (path: "${config.home.homeDirectory}/${path}") + ([ cfg.goPath ] ++ cfg.extraGoPaths))); }) + (mkIf (cfg.goBin != null) { - home.sessionVariables.GOBIN = builtins.toPath "${config.home.homeDirectory}/${cfg.goBin}"; + home.sessionVariables.GOBIN = + builtins.toPath "${config.home.homeDirectory}/${cfg.goBin}"; }) ]); } diff --git a/home-manager/modules/programs/home-manager.nix b/home-manager/modules/programs/home-manager.nix index 42e3c8a384f..9039a59d7c5 100644 --- a/home-manager/modules/programs/home-manager.nix +++ b/home-manager/modules/programs/home-manager.nix @@ -8,9 +8,7 @@ let dag = config.lib.dag; -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; options = { @@ -33,10 +31,7 @@ in }; config = mkIf (cfg.enable && !config.submoduleSupport.enable) { - home.packages = [ - (pkgs.callPackage ../../home-manager { - inherit (cfg) path; - }) - ]; + home.packages = + [ (pkgs.callPackage ../../home-manager { inherit (cfg) path; }) ]; }; } diff --git a/home-manager/modules/programs/htop.nix b/home-manager/modules/programs/htop.nix index d700c4855fe..84966040534 100644 --- a/home-manager/modules/programs/htop.nix +++ b/home-manager/modules/programs/htop.nix @@ -3,6 +3,7 @@ with lib; let + cfg = config.programs.htop; list = xs: concatMapStrings (x: "${toString x} ") xs; @@ -81,16 +82,15 @@ let RightCPUs2 = 1; Blank = 2; CPU = 1; - "CPU(1)"= 1; + "CPU(1)" = 1; "CPU(2)" = 1; "CPU(3)" = 1; "CPU(4)" = 1; }; - singleMeterType = types.coercedTo - (types.enum (attrNames meters)) - (m: { kind = m; mode = meters.${m}; }) - (types.submodule { + singleMeterType = let + meterEnum = types.enum (attrNames meters); + meterSubmodule = types.submodule { options = { kind = mkOption { type = types.enum (attrNames meters); @@ -101,10 +101,15 @@ let mode = mkOption { type = types.enum [ 1 2 3 4 ]; example = 2; - description = "Which mode the meter should use, one of 1(Bar) 2(Text) 3(Graph) 4(LED)."; + description = + "Which mode the meter should use, one of 1(Bar) 2(Text) 3(Graph) 4(LED)."; }; }; - }); + }; + in types.coercedTo meterEnum (m: { + kind = m; + mode = meters.${m}; + }) meterSubmodule; meterType = types.submodule { options = { @@ -115,7 +120,10 @@ let "Memory" "LeftCPUs2" "RightCPUs2" - { kind = "CPU"; mode = 3; } + { + kind = "CPU"; + mode = 3; + } ]; type = types.listOf singleMeterType; }; @@ -123,7 +131,10 @@ let description = "Meters shown in the right header."; default = [ "Tasks" "LoadAverage" "Uptime" ]; example = [ - { kind = "Clock"; mode = 4; } + { + kind = "Clock"; + mode = 4; + } "Uptime" "Tasks" ]; @@ -131,15 +142,37 @@ let }; }; }; -in -{ + +in { options.programs.htop = { enable = mkEnableOption "htop"; fields = mkOption { type = types.listOf (types.enum (attrNames fields)); - default = [ "PID" "USER" "PRIORITY" "NICE" "M_SIZE" "M_RESIDENT" "M_SHARE" "STATE" "PERCENT_CPU" "PERCENT_MEM" "TIME" "COMM" ]; - example = [ "PID" "USER" "PRIORITY" "PERCENT_CPU" "M_RESIDENT" "PERCENT_MEM" "TIME" "COMM" ]; + default = [ + "PID" + "USER" + "PRIORITY" + "NICE" + "M_SIZE" + "M_RESIDENT" + "M_SHARE" + "STATE" + "PERCENT_CPU" + "PERCENT_MEM" + "TIME" + "COMM" + ]; + example = [ + "PID" + "USER" + "PRIORITY" + "PERCENT_CPU" + "M_RESIDENT" + "PERCENT_MEM" + "TIME" + "COMM" + ]; description = "Active fields shown in the table."; }; @@ -209,7 +242,7 @@ in default = true; description = "Display threads in a different color."; }; - + treeView = mkOption { type = types.bool; default = false; @@ -225,7 +258,8 @@ in detailedCpuTime = mkOption { type = types.bool; default = false; - description = "Detailed CPU time (System/IO-Wait/Hard-IRQ/Soft-IRQ/Steal/Guest)."; + description = + "Detailed CPU time (System/IO-Wait/Hard-IRQ/Soft-IRQ/Steal/Guest)."; }; cpuCountFromZero = mkOption { @@ -272,14 +306,23 @@ in "CPU" "LeftCPUs2" "RightCPUs2" - { kind = "CPU"; mode = 3; } + { + kind = "CPU"; + mode = 3; + } ]; right = [ - { kind = "Clock"; mode = 4; } + { + kind = "Clock"; + mode = 4; + } "Uptime" "Tasks" "LoadAverage" - { kind = "Battery"; mode = 1; } + { + kind = "Battery"; + mode = 1; + } ]; }; type = meterType; diff --git a/home-manager/modules/programs/info.nix b/home-manager/modules/programs/info.nix index 93dcaf474af..9e4a5d4aaff 100644 --- a/home-manager/modules/programs/info.nix +++ b/home-manager/modules/programs/info.nix @@ -26,8 +26,6 @@ let cfg = config.programs.info; - dag = config.lib.dag; - # Indexes info files found in this location homeInfoPath = "${config.home.profileDirectory}/share/info"; @@ -36,9 +34,7 @@ let # from this package in the activation script. infoPkg = pkgs.texinfoInteractive; -in - -{ +in { options = { programs.info = { enable = mkEnableOption "GNU Info"; @@ -57,19 +53,20 @@ in home.sessionVariables.INFOPATH = "${cfg.homeInfoDirLocation}\${INFOPATH:+:}\${INFOPATH}"; - home.activation.createHomeInfoDir = dag.entryAfter ["installPackages"] '' - oPATH=$PATH - export PATH="${lib.makeBinPath [ pkgs.gzip ]}''${PATH:+:}$PATH" - $DRY_RUN_CMD mkdir -p "${cfg.homeInfoDirLocation}" - $DRY_RUN_CMD rm -f "${cfg.homeInfoDirLocation}/dir" - if [[ -d "${homeInfoPath}" ]]; then - find -L "${homeInfoPath}" \( -name '*.info' -o -name '*.info.gz' \) \ - -exec $DRY_RUN_CMD ${infoPkg}/bin/install-info '{}' \ - "${cfg.homeInfoDirLocation}/dir" \; - fi - export PATH="$oPATH" - unset oPATH - ''; + home.activation.createHomeInfoDir = + hm.dag.entryAfter [ "installPackages" ] '' + oPATH=$PATH + export PATH="${lib.makeBinPath [ pkgs.gzip ]}''${PATH:+:}$PATH" + $DRY_RUN_CMD mkdir -p "${cfg.homeInfoDirLocation}" + $DRY_RUN_CMD rm -f "${cfg.homeInfoDirLocation}/dir" + if [[ -d "${homeInfoPath}" ]]; then + find -L "${homeInfoPath}" \( -name '*.info' -o -name '*.info.gz' \) \ + -exec $DRY_RUN_CMD ${infoPkg}/bin/install-info '{}' \ + "${cfg.homeInfoDirLocation}/dir" \; + fi + export PATH="$oPATH" + unset oPATH + ''; home.packages = [ infoPkg ]; diff --git a/home-manager/modules/programs/jq.nix b/home-manager/modules/programs/jq.nix index 56c3adf0654..6c89df0df93 100644 --- a/home-manager/modules/programs/jq.nix +++ b/home-manager/modules/programs/jq.nix @@ -15,19 +15,17 @@ let colorsType = types.submodule { options = { - null = colorType; - false = colorType; - true = colorType; + null = colorType; + false = colorType; + true = colorType; numbers = colorType; strings = colorType; - arrays = colorType; + arrays = colorType; objects = colorType; }; }; -in - -{ +in { options = { programs.jq = { enable = mkEnableOption "the jq command-line JSON processor"; @@ -52,12 +50,12 @@ in ''; default = { - null = "1;30"; - false = "0;39"; - true = "0;39"; + null = "1;30"; + false = "0;39"; + true = "0;39"; numbers = "0;39"; strings = "0;32"; - arrays = "1;39"; + arrays = "1;39"; objects = "1;39"; }; @@ -69,8 +67,10 @@ in config = mkIf cfg.enable { home.packages = [ pkgs.jq ]; - home.sessionVariables = let c = cfg.colors; in { - JQ_COLORS = "${c.null}:${c.false}:${c.true}:${c.numbers}:${c.strings}:${c.arrays}:${c.objects}"; + home.sessionVariables = let c = cfg.colors; + in { + JQ_COLORS = + "${c.null}:${c.false}:${c.true}:${c.numbers}:${c.strings}:${c.arrays}:${c.objects}"; }; }; } diff --git a/home-manager/modules/programs/kakoune.nix b/home-manager/modules/programs/kakoune.nix index dbaa764a212..faf2542dc70 100644 --- a/home-manager/modules/programs/kakoune.nix +++ b/home-manager/modules/programs/kakoune.nix @@ -10,16 +10,44 @@ let options = { name = mkOption { type = types.enum [ - "NormalBegin" "NormalIdle" "NormalEnd" "NormalKey" - "InsertBegin" "InsertIdle" "InsertEnd" "InsertKey" - "InsertChar" "InsertDelete" "InsertMove" "WinCreate" - "WinClose" "WinResize" "WinDisplay" "WinSetOption" - "BufSetOption" "BufNewFile" "BufOpenFile" "BufCreate" - "BufWritePre" "BufWritePost" "BufReload" "BufClose" - "BufOpenFifo" "BufReadFifo" "BufCloseFifo" "RuntimeError" - "ModeChange" "PromptIdle" "GlobalSetOption" "KakBegin" - "KakEnd" "FocusIn" "FocusOut" "RawKey" - "InsertCompletionShow" "InsertCompletionHide" + "NormalBegin" + "NormalIdle" + "NormalEnd" + "NormalKey" + "InsertBegin" + "InsertIdle" + "InsertEnd" + "InsertKey" + "InsertChar" + "InsertDelete" + "InsertMove" + "WinCreate" + "WinClose" + "WinResize" + "WinDisplay" + "WinSetOption" + "BufSetOption" + "BufNewFile" + "BufOpenFile" + "BufCreate" + "BufWritePre" + "BufWritePost" + "BufReload" + "BufClose" + "BufOpenFifo" + "BufReadFifo" + "BufCloseFifo" + "RuntimeError" + "ModeChange" + "PromptIdle" + "GlobalSetOption" + "KakBegin" + "KakEnd" + "FocusIn" + "FocusOut" + "RawKey" + "InsertCompletionShow" + "InsertCompletionHide" "InsertCompletionSelect" ]; example = "SetOption"; @@ -159,7 +187,8 @@ let }; autoInfo = mkOption { - type = types.nullOr (types.listOf (types.enum [ "command" "onkey" "normal" ])); + type = types.nullOr + (types.listOf (types.enum [ "command" "onkey" "normal" ])); default = null; example = [ "command" "normal" ]; description = '' @@ -169,7 +198,7 @@ let }; autoComplete = mkOption { - type = types.nullOr(types.listOf (types.enum [ "insert" "prompt" ])); + type = types.nullOr (types.listOf (types.enum [ "insert" "prompt" ])); default = null; description = '' Modes in which to display possible completions. @@ -450,7 +479,7 @@ let keyMappings = mkOption { type = types.listOf keyMapping; - default = []; + default = [ ]; description = '' User-defined key mappings. For documentation, see <link xlink:href="https://github.com/mawww/kakoune/blob/master/doc/pages/mapping.asciidoc"/>. @@ -459,7 +488,7 @@ let hooks = mkOption { type = types.listOf hook; - default = []; + default = [ ]; description = '' Global hooks. For documentation, see <link xlink:href="https://github.com/mawww/kakoune/blob/master/doc/pages/hooks.asciidoc"/>. @@ -468,92 +497,103 @@ let }; }; - configFile = - let - wrapOptions = with cfg.config.wrapLines; concatStrings [ + configFile = let + wrapOptions = with cfg.config.wrapLines; + concatStrings [ "${optionalString word " -word"}" "${optionalString indent " -indent"}" "${optionalString (marker != null) " -marker ${marker}"}" "${optionalString (maxWidth != null) " -width ${toString maxWidth}"}" ]; - numberLinesOptions = with cfg.config.numberLines; concatStrings [ + numberLinesOptions = with cfg.config.numberLines; + concatStrings [ "${optionalString relative " -relative "}" "${optionalString highlightCursor " -hlcursor"}" "${optionalString (separator != null) " -separator ${separator}"}" ]; - uiOptions = with cfg.config.ui; concatStringsSep " " [ + uiOptions = with cfg.config.ui; + concatStringsSep " " [ "ncurses_set_title=${if setTitle then "true" else "false"}" - "ncurses_status_on_top=${if (statusLine == "top") then "true" else "false"}" + "ncurses_status_on_top=${ + if (statusLine == "top") then "true" else "false" + }" "ncurses_assistant=${assistant}" "ncurses_enable_mouse=${if enableMouse then "true" else "false"}" "ncurses_change_colors=${if changeColors then "true" else "false"}" "${optionalString (wheelDownButton != null) - "ncurses_wheel_down_button=${wheelDownButton}"}" + "ncurses_wheel_down_button=${wheelDownButton}"}" "${optionalString (wheelUpButton != null) - "ncurses_wheel_up_button=${wheelUpButton}"}" + "ncurses_wheel_up_button=${wheelUpButton}"}" "${optionalString (shiftFunctionKeys != null) - "ncurses_shift_function_key=${toString shiftFunctionKeys}"}" - "ncurses_builtin_key_parser=${if useBuiltinKeyParser then "true" else "false"}" + "ncurses_shift_function_key=${toString shiftFunctionKeys}"}" + "ncurses_builtin_key_parser=${ + if useBuiltinKeyParser then "true" else "false" + }" ]; - keyMappingString = km: concatStringsSep " " [ + keyMappingString = km: + concatStringsSep " " [ "map global" "${km.mode} ${km.key} '${km.effect}'" - "${optionalString (km.docstring != null) "-docstring '${km.docstring}'"}" + "${optionalString (km.docstring != null) + "-docstring '${km.docstring}'"}" ]; - hookString = h: concatStringsSep " " [ - "hook" "${optionalString (h.group != null) "-group ${group}"}" - "${optionalString (h.once) "-once"}" "global" - "${h.name}" "${optionalString (h.option != null) h.option}" + hookString = h: + concatStringsSep " " [ + "hook" + "${optionalString (h.group != null) "-group ${group}"}" + "${optionalString (h.once) "-once"}" + "global" + "${h.name}" + "${optionalString (h.option != null) h.option}" "%{ ${h.commands} }" ]; - cfgStr = with cfg.config; concatStringsSep "\n" ( - [ "# Generated by home-manager" ] + cfgStr = with cfg.config; + concatStringsSep "\n" ([ "# Generated by home-manager" ] ++ optional (colorScheme != null) "colorscheme ${colorScheme}" - ++ optional (tabStop != null) "set-option global tabstop ${toString tabStop}" - ++ optional (indentWidth != null) "set-option global indentwidth ${toString indentWidth}" + ++ optional (tabStop != null) + "set-option global tabstop ${toString tabStop}" + ++ optional (indentWidth != null) + "set-option global indentwidth ${toString indentWidth}" ++ optional (!incrementalSearch) "set-option global incsearch false" ++ optional (alignWithTabs) "set-option global aligntab true" - ++ optional (autoInfo != null) "set-option global autoinfo ${concatStringsSep "|" autoInfo}" - ++ optional (autoComplete != null) "set-option global autocomplete ${concatStringsSep "|" autoComplete}" - ++ optional (autoReload != null) "set-option global/ autoreload ${autoReload}" - ++ optional (wrapLines != null && wrapLines.enable) "add-highlighter global/ wrap${wrapOptions}" + ++ optional (autoInfo != null) + "set-option global autoinfo ${concatStringsSep "|" autoInfo}" + ++ optional (autoComplete != null) + "set-option global autocomplete ${concatStringsSep "|" autoComplete}" + ++ optional (autoReload != null) + "set-option global/ autoreload ${autoReload}" + ++ optional (wrapLines != null && wrapLines.enable) + "add-highlighter global/ wrap${wrapOptions}" ++ optional (numberLines != null && numberLines.enable) - "add-highlighter global/ number-lines${numberLinesOptions}" + "add-highlighter global/ number-lines${numberLinesOptions}" ++ optional showMatching "add-highlighter global/ show-matching" ++ optional (scrollOff != null) - "set-option global scrolloff ${toString scrollOff.lines},${toString scrollOff.columns}" + "set-option global scrolloff ${toString scrollOff.lines},${ + toString scrollOff.columns + }" ++ [ "# UI options" ] ++ optional (ui != null) "set-option global ui_options ${uiOptions}" - ++ [ "# Key mappings" ] - ++ map keyMappingString keyMappings + ++ [ "# Key mappings" ] ++ map keyMappingString keyMappings - ++ [ "# Hooks" ] - ++ map hookString hooks - ); - in - pkgs.writeText "kakrc" ( - optionalString (cfg.config != null) cfgStr - + "\n" - + cfg.extraConfig - ); + ++ [ "# Hooks" ] ++ map hookString hooks); + in pkgs.writeText "kakrc" + (optionalString (cfg.config != null) cfgStr + "\n" + cfg.extraConfig); -in - -{ +in { options = { programs.kakoune = { enable = mkEnableOption "the kakoune text editor"; config = mkOption { type = types.nullOr configModule; - default = {}; + default = { }; description = "kakoune configuration options."; }; diff --git a/home-manager/modules/programs/keychain.nix b/home-manager/modules/programs/keychain.nix index 6dbf83a872e..6e26bd232ce 100644 --- a/home-manager/modules/programs/keychain.nix +++ b/home-manager/modules/programs/keychain.nix @@ -6,17 +6,16 @@ let cfg = config.programs.keychain; - flags = cfg.extraFlags - ++ optional (cfg.agents != []) "--agents ${concatStringsSep "," cfg.agents}" + flags = cfg.extraFlags ++ optional (cfg.agents != [ ]) + "--agents ${concatStringsSep "," cfg.agents}" ++ optional (cfg.inheritType != null) "--inherit ${cfg.inheritType}"; - shellCommand = '' - eval "$(${cfg.package}/bin/keychain --eval ${concatStringsSep " " flags} ${concatStringsSep " " cfg.keys})" - ''; + shellCommand = + "${cfg.package}/bin/keychain --eval ${concatStringsSep " " flags} ${ + concatStringsSep " " cfg.keys + }"; -in - -{ +in { meta.maintainers = [ maintainers.marsam ]; options.programs.keychain = { @@ -41,14 +40,15 @@ in agents = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; description = '' Agents to add. ''; }; inheritType = mkOption { - type = types.nullOr (types.enum ["local" "any" "local-once" "any-once"]); + type = + types.nullOr (types.enum [ "local" "any" "local-once" "any-once" ]); default = null; description = '' Inherit type to attempt from agent variables from the environment. @@ -71,6 +71,14 @@ in ''; }; + enableFishIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Fish integration. + ''; + }; + enableZshIntegration = mkOption { default = true; type = types.bool; @@ -78,11 +86,30 @@ in Whether to enable Zsh integration. ''; }; + + enableXsessionIntegration = mkOption { + default = true; + type = types.bool; + visible = pkgs.stdenv.hostPlatform.isLinux; + description = '' + Whether to run keychain from your <filename>~/.xsession</filename>. + ''; + }; }; config = mkIf cfg.enable { home.packages = [ cfg.package ]; - programs.bash.initExtra = mkIf cfg.enableBashIntegration shellCommand; - programs.zsh.initExtra = mkIf cfg.enableZshIntegration shellCommand; + programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + eval "$(${shellCommand})" + ''; + programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration '' + eval (${shellCommand}) + ''; + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + eval "$(${shellCommand})" + ''; + xsession.initExtra = mkIf cfg.enableXsessionIntegration '' + eval "$(${shellCommand})" + ''; }; } diff --git a/home-manager/modules/programs/lsd.nix b/home-manager/modules/programs/lsd.nix index 5e145e8c69b..ab1880ff828 100644 --- a/home-manager/modules/programs/lsd.nix +++ b/home-manager/modules/programs/lsd.nix @@ -11,12 +11,10 @@ let ll = "ls -l"; la = "ls -a"; lt = "ls --tree"; - lla ="ls -la"; + lla = "ls -la"; }; -in - -{ +in { meta.maintainers = [ maintainers.marsam ]; options.programs.lsd = { @@ -37,5 +35,7 @@ in programs.bash.shellAliases = mkIf cfg.enableAliases aliases; programs.zsh.shellAliases = mkIf cfg.enableAliases aliases; + + programs.fish.shellAliases = mkIf cfg.enableAliases aliases; }; } diff --git a/home-manager/modules/programs/matplotlib.nix b/home-manager/modules/programs/matplotlib.nix index 48ff6e60d68..da80c116770 100644 --- a/home-manager/modules/programs/matplotlib.nix +++ b/home-manager/modules/programs/matplotlib.nix @@ -9,16 +9,13 @@ let formatLine = o: n: v: let formatValue = v: - if isBool v then (if v then "True" else "False") - else toString v; - in - if isAttrs v - then concatStringsSep "\n" (mapAttrsToList (formatLine "${o}${n}.") v) - else (if v == "" then "" else "${o}${n}: ${formatValue v}"); + if isBool v then (if v then "True" else "False") else toString v; + in if isAttrs v then + concatStringsSep "\n" (mapAttrsToList (formatLine "${o}${n}.") v) + else + (if v == "" then "" else "${o}${n}: ${formatValue v}"); -in - -{ +in { meta.maintainers = [ maintainers.rprospero ]; options.programs.matplotlib = { @@ -31,7 +28,7 @@ in Add terms to the <filename>matplotlibrc</filename> file to control the default matplotlib behavior. ''; - example = literalExample '' + example = literalExample '' { backend = "Qt5Agg"; axes = { @@ -55,10 +52,8 @@ in }; config = mkIf cfg.enable { - xdg.configFile."matplotlib/matplotlibrc".text = - concatStringsSep "\n" ([] - ++ mapAttrsToList (formatLine "") cfg.config - ++ optional (cfg.extraConfig != "") cfg.extraConfig - ) + "\n"; + xdg.configFile."matplotlib/matplotlibrc".text = concatStringsSep "\n" ([ ] + ++ mapAttrsToList (formatLine "") cfg.config + ++ optional (cfg.extraConfig != "") cfg.extraConfig) + "\n"; }; } diff --git a/home-manager/modules/programs/mbsync-accounts.nix b/home-manager/modules/programs/mbsync-accounts.nix index c586481df4d..4de1965fe3f 100644 --- a/home-manager/modules/programs/mbsync-accounts.nix +++ b/home-manager/modules/programs/mbsync-accounts.nix @@ -6,9 +6,7 @@ let extraConfigType = with lib.types; attrsOf (either (either str int) bool); -in - -{ +in { options.mbsync = { enable = mkEnableOption "synchronization using mbsync"; @@ -62,7 +60,7 @@ in extraConfig.channel = mkOption { type = extraConfigType; - default = {}; + default = { }; example = literalExample '' { MaxMessages = 10000; @@ -76,7 +74,7 @@ in extraConfig.local = mkOption { type = extraConfigType; - default = {}; + default = { }; description = '' Local store extra configuration. ''; @@ -84,7 +82,7 @@ in extraConfig.remote = mkOption { type = extraConfigType; - default = {}; + default = { }; description = '' Remote store extra configuration. ''; @@ -92,7 +90,7 @@ in extraConfig.account = mkOption { type = extraConfigType; - default = {}; + default = { }; example = literalExample '' { PipelineDepth = 10; diff --git a/home-manager/modules/programs/mbsync.nix b/home-manager/modules/programs/mbsync.nix index 908a1add715..6ade10986fe 100644 --- a/home-manager/modules/programs/mbsync.nix +++ b/home-manager/modules/programs/mbsync.nix @@ -4,22 +4,21 @@ with lib; let - dag = config.lib.dag; - cfg = config.programs.mbsync; # Accounts for which mbsync is enabled. mbsyncAccounts = filter (a: a.mbsync.enable) (attrValues config.accounts.email.accounts); - genTlsConfig = tls: { - SSLType = - if !tls.enable then "None" - else if tls.useStartTls then "STARTTLS" - else "IMAPS"; - } - // - optionalAttrs (tls.enable && tls.certificatesFile != null) { + genTlsConfig = tls: + { + SSLType = if !tls.enable then + "None" + else if tls.useStartTls then + "STARTTLS" + else + "IMAPS"; + } // optionalAttrs (tls.enable && tls.certificatesFile != null) { CertificateFile = toString tls.certificatesFile; }; @@ -32,79 +31,61 @@ let genSection = header: entries: let - escapeValue = escape [ "\"" ]; + escapeValue = escape [ ''"'' ]; hasSpace = v: builtins.match ".* .*" v != null; genValue = n: v: - if isList v - then concatMapStringsSep " " (genValue n) v - else if isBool v then (if v then "yes" else "no") - else if isInt v then toString v - else if isString v && hasSpace v then "\"${escapeValue v}\"" - else if isString v then v + if isList v then + concatMapStringsSep " " (genValue n) v + else if isBool v then + (if v then "yes" else "no") + else if isInt v then + toString v + else if isString v && hasSpace v then + ''"${escapeValue v}"'' + else if isString v then + v else - let prettyV = lib.generators.toPretty {} v; - in throw "mbsync: unexpected value for option ${n}: '${prettyV}'"; - in - '' - ${header} - ${concatStringsSep "\n" - (mapAttrsToList (n: v: "${n} ${genValue n v}") entries)} - ''; - - genAccountConfig = account: with account; - genSection "IMAPAccount ${name}" ( - { - Host = imap.host; - User = userName; - PassCmd = toString passwordCommand; - } - // genTlsConfig imap.tls - // optionalAttrs (imap.port != null) { Port = toString imap.port; } - // mbsync.extraConfig.account - ) - + "\n" - + genSection "IMAPStore ${name}-remote" ( - { - Account = name; - } - // mbsync.extraConfig.remote - ) - + "\n" - + genSection "MaildirStore ${name}-local" ( - { - Path = "${maildir.absPath}/"; - Inbox = "${maildir.absPath}/${folders.inbox}"; - SubFolders = "Verbatim"; - } - // optionalAttrs (mbsync.flatten != null) { Flatten = mbsync.flatten; } - // mbsync.extraConfig.local - ) - + "\n" - + genSection "Channel ${name}" ( - { - Master = ":${name}-remote:"; - Slave = ":${name}-local:"; - Patterns = mbsync.patterns; - Create = masterSlaveMapping.${mbsync.create}; - Remove = masterSlaveMapping.${mbsync.remove}; - Expunge = masterSlaveMapping.${mbsync.expunge}; - SyncState = "*"; - } - // mbsync.extraConfig.channel - ) - + "\n"; + let prettyV = lib.generators.toPretty { } v; + in throw "mbsync: unexpected value for option ${n}: '${prettyV}'"; + in '' + ${header} + ${concatStringsSep "\n" + (mapAttrsToList (n: v: "${n} ${genValue n v}") entries)} + ''; + + genAccountConfig = account: + with account; + genSection "IMAPAccount ${name}" ({ + Host = imap.host; + User = userName; + PassCmd = toString passwordCommand; + } // genTlsConfig imap.tls + // optionalAttrs (imap.port != null) { Port = toString imap.port; } + // mbsync.extraConfig.account) + "\n" + + genSection "IMAPStore ${name}-remote" + ({ Account = name; } // mbsync.extraConfig.remote) + "\n" + + genSection "MaildirStore ${name}-local" ({ + Path = "${maildir.absPath}/"; + Inbox = "${maildir.absPath}/${folders.inbox}"; + SubFolders = "Verbatim"; + } // optionalAttrs (mbsync.flatten != null) { Flatten = mbsync.flatten; } + // mbsync.extraConfig.local) + "\n" + genSection "Channel ${name}" ({ + Master = ":${name}-remote:"; + Slave = ":${name}-local:"; + Patterns = mbsync.patterns; + Create = masterSlaveMapping.${mbsync.create}; + Remove = masterSlaveMapping.${mbsync.remove}; + Expunge = masterSlaveMapping.${mbsync.expunge}; + SyncState = "*"; + } // mbsync.extraConfig.channel) + "\n"; genGroupConfig = name: channels: let genGroupChannel = n: boxes: "Channel ${n}:${concatStringsSep "," boxes}"; - in - concatStringsSep "\n" ( - [ "Group ${name}" ] ++ mapAttrsToList genGroupChannel channels - ); - -in + in concatStringsSep "\n" + ([ "Group ${name}" ] ++ mapAttrsToList genGroupChannel channels); -{ +in { options = { programs.mbsync = { enable = mkEnableOption "mbsync IMAP4 and Maildir mailbox synchronizer"; @@ -119,7 +100,7 @@ in groups = mkOption { type = types.attrsOf (types.attrsOf (types.listOf types.str)); - default = {}; + default = { }; example = literalExample '' { inboxes = { @@ -144,45 +125,40 @@ in }; config = mkIf cfg.enable { - assertions = - let - checkAccounts = pred: msg: - let - badAccounts = filter pred mbsyncAccounts; - in { - assertion = badAccounts == []; - message = "mbsync: ${msg} for accounts: " - + concatMapStringsSep ", " (a: a.name) badAccounts; - }; - in - [ - (checkAccounts (a: a.maildir == null) "Missing maildir configuration") - (checkAccounts (a: a.imap == null) "Missing IMAP configuration") - (checkAccounts (a: a.passwordCommand == null) "Missing passwordCommand") - (checkAccounts (a: a.userName == null) "Missing username") - ]; + assertions = let + checkAccounts = pred: msg: + let badAccounts = filter pred mbsyncAccounts; + in { + assertion = badAccounts == [ ]; + message = "mbsync: ${msg} for accounts: " + + concatMapStringsSep ", " (a: a.name) badAccounts; + }; + in [ + (checkAccounts (a: a.maildir == null) "Missing maildir configuration") + (checkAccounts (a: a.imap == null) "Missing IMAP configuration") + (checkAccounts (a: a.passwordCommand == null) "Missing passwordCommand") + (checkAccounts (a: a.userName == null) "Missing username") + ]; home.packages = [ cfg.package ]; programs.notmuch.new.ignore = [ ".uidvalidity" ".mbsyncstate" ]; - home.file.".mbsyncrc".text = - let - accountsConfig = map genAccountConfig mbsyncAccounts; - groupsConfig = mapAttrsToList genGroupConfig cfg.groups; - in - concatStringsSep "\n" ( - [ "# Generated by Home Manager.\n" ] - ++ optional (cfg.extraConfig != "") cfg.extraConfig - ++ accountsConfig - ++ groupsConfig - ) + "\n"; - - home.activation.createMaildir = - dag.entryBetween [ "linkGeneration" ] [ "writeBoundary" ] '' - $DRY_RUN_CMD mkdir -m700 -p $VERBOSE_ARG ${ - concatMapStringsSep " " (a: a.maildir.absPath) mbsyncAccounts - } - ''; + home.file.".mbsyncrc".text = let + accountsConfig = map genAccountConfig mbsyncAccounts; + groupsConfig = mapAttrsToList genGroupConfig cfg.groups; + in concatStringsSep "\n" (['' + # Generated by Home Manager. + ''] ++ optional (cfg.extraConfig != "") cfg.extraConfig ++ accountsConfig + ++ groupsConfig) + "\n"; + + home.activation = mkIf (mbsyncAccounts != [ ]) { + createMaildir = + hm.dag.entryBetween [ "linkGeneration" ] [ "writeBoundary" ] '' + $DRY_RUN_CMD mkdir -m700 -p $VERBOSE_ARG ${ + concatMapStringsSep " " (a: a.maildir.absPath) mbsyncAccounts + } + ''; + }; }; } diff --git a/home-manager/modules/programs/mercurial.nix b/home-manager/modules/programs/mercurial.nix index fa6e7b3e5ba..8e9a3befbaf 100644 --- a/home-manager/modules/programs/mercurial.nix +++ b/home-manager/modules/programs/mercurial.nix @@ -6,9 +6,7 @@ let cfg = config.programs.mercurial; -in - -{ +in { options = { programs.mercurial = { @@ -33,13 +31,13 @@ in aliases = mkOption { type = types.attrs; - default = {}; + default = { }; description = "Mercurial aliases to define."; }; extraConfig = mkOption { type = types.either types.attrs types.lines; - default = {}; + default = { }; description = "Additional configuration to add."; }; @@ -50,53 +48,53 @@ in ignores = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; example = [ "*~" "*.swp" ]; description = "List of globs for files to be globally ignored."; }; ignoresRegexp = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; example = [ "^.*~$" "^.*\\.swp$" ]; description = - "List of regular expressions for files to be globally ignored."; + "List of regular expressions for files to be globally ignored."; }; }; }; - config = mkIf cfg.enable ( - mkMerge [ - { - home.packages = [ cfg.package ]; + config = mkIf cfg.enable (mkMerge [ + { + home.packages = [ cfg.package ]; - programs.mercurial.iniContent.ui = { - username = cfg.userName + " <" + cfg.userEmail + ">"; - }; + programs.mercurial.iniContent.ui = { + username = cfg.userName + " <" + cfg.userEmail + ">"; + }; - xdg.configFile."hg/hgrc".text = generators.toINI {} cfg.iniContent; - } + xdg.configFile."hg/hgrc".text = generators.toINI { } cfg.iniContent; + } - (mkIf (cfg.ignores != [] || cfg.ignoresRegexp != []) { - programs.mercurial.iniContent.ui.ignore = - "${config.xdg.configHome}/hg/hgignore_global"; + (mkIf (cfg.ignores != [ ] || cfg.ignoresRegexp != [ ]) { + programs.mercurial.iniContent.ui.ignore = + "${config.xdg.configHome}/hg/hgignore_global"; - xdg.configFile."hg/hgignore_global".text = - "syntax: glob\n" + concatStringsSep "\n" cfg.ignores + "\n" + - "syntax: regexp\n" + concatStringsSep "\n" cfg.ignoresRegexp + "\n"; - }) + xdg.configFile."hg/hgignore_global".text = '' + syntax: glob + '' + concatStringsSep "\n" cfg.ignores + "\n" + '' + syntax: regexp + '' + concatStringsSep "\n" cfg.ignoresRegexp + "\n"; + }) - (mkIf (cfg.aliases != {}) { - programs.mercurial.iniContent.alias = cfg.aliases; - }) + (mkIf (cfg.aliases != { }) { + programs.mercurial.iniContent.alias = cfg.aliases; + }) - (mkIf (lib.isAttrs cfg.extraConfig) { - programs.mercurial.iniContent = cfg.extraConfig; - }) + (mkIf (lib.isAttrs cfg.extraConfig) { + programs.mercurial.iniContent = cfg.extraConfig; + }) - (mkIf (lib.isString cfg.extraConfig) { - xdg.configFile."hg/hgrc".text = cfg.extraConfig; - }) - ] - ); + (mkIf (lib.isString cfg.extraConfig) { + xdg.configFile."hg/hgrc".text = cfg.extraConfig; + }) + ]); } diff --git a/home-manager/modules/programs/mpv.nix b/home-manager/modules/programs/mpv.nix index 1051f71ccd6..3a4e5092f9a 100644 --- a/home-manager/modules/programs/mpv.nix +++ b/home-manager/modules/programs/mpv.nix @@ -23,31 +23,21 @@ let }.${typeOf option}; renderOptions = options: - concatStringsSep "\n" - (mapAttrsToList - (name: value: - let - rendered = renderOption value; - length = toString (stringLength rendered); - in - "${name}=%${length}%${rendered}") - options); + concatStringsSep "\n" (mapAttrsToList (name: value: + let + rendered = renderOption value; + length = toString (stringLength rendered); + in "${name}=%${length}%${rendered}") options); renderProfiles = profiles: - concatStringsSep "\n" - (mapAttrsToList - (name: value: '' - [${name}] - ${renderOptions value} - '') - profiles); + concatStringsSep "\n" (mapAttrsToList (name: value: '' + [${name}] + ${renderOptions value} + '') profiles); renderBindings = bindings: concatStringsSep "\n" - (mapAttrsToList - (name: value: - "${name} ${value}") - bindings); + (mapAttrsToList (name: value: "${name} ${value}") bindings); in { options = { @@ -55,8 +45,8 @@ in { enable = mkEnableOption "mpv"; scripts = mkOption { - type = types.listOf types.package; - default = []; + type = with types; listOf (either package str); + default = [ ]; example = literalExample "[ pkgs.mpvScripts.mpris ]"; description = '' List of scripts to use with mpv. @@ -74,7 +64,7 @@ in { for the full list of options. ''; type = mpvOptions; - default = {}; + default = { }; example = literalExample '' { profile = "gpu-hq"; @@ -92,7 +82,7 @@ in { <option>programs.mpv.config</option> for more information. ''; type = mpvProfiles; - default = {}; + default = { }; example = literalExample '' { fast = { @@ -117,7 +107,7 @@ in { for the full list of options. ''; type = mpvBindings; - default = {}; + default = { }; example = literalExample '' { WHEEL_UP = "seek 10"; @@ -131,19 +121,20 @@ in { config = mkIf cfg.enable (mkMerge [ { - home.packages = [( - if cfg.scripts == [] - then pkgs.mpv - else pkgs.mpv-with-scripts.override { scripts = cfg.scripts; } - )]; + home.packages = [ + (if cfg.scripts == [ ] then + pkgs.mpv + else + pkgs.mpv-with-scripts.override { scripts = cfg.scripts; }) + ]; } - (mkIf (cfg.config != {} || cfg.profiles != {}) { + (mkIf (cfg.config != { } || cfg.profiles != { }) { xdg.configFile."mpv/mpv.conf".text = '' - ${optionalString (cfg.config != {}) (renderOptions cfg.config)} - ${optionalString (cfg.profiles != {}) (renderProfiles cfg.profiles)} + ${optionalString (cfg.config != { }) (renderOptions cfg.config)} + ${optionalString (cfg.profiles != { }) (renderProfiles cfg.profiles)} ''; }) - (mkIf (cfg.bindings != {}) { + (mkIf (cfg.bindings != { }) { xdg.configFile."mpv/input.conf".text = renderBindings cfg.bindings; }) ]); diff --git a/home-manager/modules/programs/msmtp-accounts.nix b/home-manager/modules/programs/msmtp-accounts.nix index 277710f4cba..894cef51742 100644 --- a/home-manager/modules/programs/msmtp-accounts.nix +++ b/home-manager/modules/programs/msmtp-accounts.nix @@ -23,7 +23,8 @@ with lib; }; tls.fingerprint = mkOption { - type = types.nullOr (types.strMatching "([[:alnum:]]{2}\:)+[[:alnum:]]{2}"); + type = + types.nullOr (types.strMatching "([[:alnum:]]{2}:)+[[:alnum:]]{2}"); default = null; example = "my:SH:a2:56:ha:sh"; description = '' diff --git a/home-manager/modules/programs/msmtp.nix b/home-manager/modules/programs/msmtp.nix index 1ff3139ef36..f34fd72f8b1 100644 --- a/home-manager/modules/programs/msmtp.nix +++ b/home-manager/modules/programs/msmtp.nix @@ -6,38 +6,32 @@ let cfg = config.programs.msmtp; - msmtpAccounts = filter (a: a.msmtp.enable) - (attrValues config.accounts.email.accounts); + msmtpAccounts = + filter (a: a.msmtp.enable) (attrValues config.accounts.email.accounts); onOff = p: if p then "on" else "off"; - accountStr = account: with account; - concatStringsSep "\n" ( - [ "account ${name}" ] - ++ mapAttrsToList (n: v: n + " " + v) ( - { - host = smtp.host; - from = address; - auth = "on"; - user = userName; - tls = onOff smtp.tls.enable; - tls_starttls = onOff smtp.tls.useStartTls; - tls_trust_file = smtp.tls.certificatesFile; - } - // optionalAttrs (msmtp.tls.fingerprint != null) { - tls_fingerprint = msmtp.tls.fingerprint; - } - // optionalAttrs (smtp.port != null) { - port = toString smtp.port; - } + accountStr = account: + with account; + concatStringsSep "\n" ([ "account ${name}" ] + ++ mapAttrsToList (n: v: n + " " + v) ({ + host = smtp.host; + from = address; + auth = "on"; + user = userName; + tls = onOff smtp.tls.enable; + tls_starttls = onOff smtp.tls.useStartTls; + tls_trust_file = smtp.tls.certificatesFile; + } // optionalAttrs (msmtp.tls.fingerprint != null) { + tls_fingerprint = msmtp.tls.fingerprint; + } // optionalAttrs (smtp.port != null) { port = toString smtp.port; } // optionalAttrs (passwordCommand != null) { # msmtp requires the password to finish with a newline. - passwordeval = ''${pkgs.bash}/bin/bash -c "${toString passwordCommand}; echo"''; - } - // msmtp.extraConfig - ) - ++ optional primary "\naccount default : ${name}" - ); + passwordeval = + ''${pkgs.bash}/bin/bash -c "${toString passwordCommand}; echo"''; + } // msmtp.extraConfig) ++ optional primary '' + + account default : ${name}''); configFile = mailAccounts: '' # Generated by Home Manager. @@ -47,9 +41,7 @@ let ${concatStringsSep "\n\n" (map accountStr mailAccounts)} ''; -in - -{ +in { options = { programs.msmtp = { @@ -71,7 +63,7 @@ in xdg.configFile."msmtp/config".text = configFile msmtpAccounts; - home.sessionVariables = { + home.sessionVariables = { MSMTP_QUEUE = "${config.xdg.dataHome}/msmtp/queue"; MSMTP_LOG = "${config.xdg.dataHome}/msmtp/queue.log"; }; diff --git a/home-manager/modules/programs/neomutt-accounts.nix b/home-manager/modules/programs/neomutt-accounts.nix new file mode 100644 index 00000000000..033db38eb0a --- /dev/null +++ b/home-manager/modules/programs/neomutt-accounts.nix @@ -0,0 +1,34 @@ +{ config, lib, ... }: + +with lib; + +{ + options.neomutt = { + enable = mkEnableOption "NeoMutt"; + + sendMailCommand = mkOption { + type = types.nullOr types.str; + default = null; + example = "msmtpq --read-envelope-from --read-recipients"; + description = '' + Command to send a mail. If not set, neomutt will be in charge of sending mails. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = "color status cyan default"; + description = '' + Extra lines to add to the folder hook for this account. + ''; + }; + }; + + config = mkIf config.neomutt.enable { + neomutt.sendMailCommand = mkOptionDefault (if config.msmtp.enable then + "msmtpq --read-envelope-from --read-recipients" + else + null); + }; +} diff --git a/home-manager/modules/programs/neomutt.nix b/home-manager/modules/programs/neomutt.nix new file mode 100644 index 00000000000..85af0353b6c --- /dev/null +++ b/home-manager/modules/programs/neomutt.nix @@ -0,0 +1,302 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.neomutt; + + neomuttAccounts = + filter (a: a.neomutt.enable) (attrValues config.accounts.email.accounts); + + sidebarModule = types.submodule { + options = { + enable = mkEnableOption "sidebar support"; + + width = mkOption { + type = types.int; + default = 22; + description = "Width of the sidebar"; + }; + + shortPath = mkOption { + type = types.bool; + default = true; + description = '' + By default sidebar shows the full path of the mailbox, but + with this enabled only the relative name is shown. + ''; + }; + + format = mkOption { + type = types.str; + default = "%B%?F? [%F]?%* %?N?%N/?%S"; + description = '' + Sidebar format. Check neomutt documentation for details. + ''; + }; + }; + }; + + bindModule = types.submodule { + options = { + map = mkOption { + type = types.enum [ + "alias" + "attach" + "browser" + "compose" + "editor" + "generic" + "index" + "mix" + "pager" + "pgp" + "postpone" + "query" + "smime" + ]; + default = "index"; + description = "Select the menu to bind the command to."; + }; + + key = mkOption { + type = types.str; + example = "<left>"; + description = "The key to bind."; + }; + + action = mkOption { + type = types.str; + example = "<enter-command>toggle sidebar_visible<enter><refresh>"; + description = "Specify the action to take."; + }; + }; + }; + + yesno = x: if x then "yes" else "no"; + setOption = n: v: if v == null then "unset ${n}" else "set ${n}=${v}"; + escape = replaceStrings [ "%" ] [ "%25" ]; + + accountFilename = account: config.xdg.configHome + "/neomutt/" + account.name; + + genCommonFolderHooks = account: + with account; { + from = "'${address}'"; + realname = "'${realName}'"; + spoolfile = "'+${folders.inbox}'"; + record = if folders.sent == null then null else "'+${folders.sent}'"; + postponed = "'+${folders.drafts}'"; + trash = "'+${folders.trash}'"; + }; + + mtaSection = account: + with account; + let passCmd = concatStringsSep " " passwordCommand; + in if neomutt.sendMailCommand != null then { + sendmail = "'${neomutt.sendMailCommand}'"; + } else + let + smtpProto = if smtp.tls.enable then "smtps" else "smtp"; + smtpBaseUrl = "${smtpProto}://${escape userName}@${smtp.host}"; + in { + smtp_url = "'${smtpBaseUrl}'"; + smtp_pass = "'`${passCmd}`'"; + }; + + genMaildirAccountConfig = account: + with account; + let + folderHook = mapAttrsToList setOption (genCommonFolderHooks account // { + folder = "'${account.maildir.absPath}'"; + }) ++ optional (neomutt.extraConfig != "") neomutt.extraConfig; + in '' + ${concatStringsSep "\n" folderHook} + ''; + + registerAccount = account: + with account; '' + # register account ${name} + mailboxes "${account.maildir.absPath}/${folders.inbox}" + folder-hook ${account.maildir.absPath}/ " \ + source ${accountFilename account} " + ''; + + mraSection = account: + with account; + if account.maildir != null then + genMaildirAccountConfig account + else + throw "Only maildir is supported at the moment"; + + optionsStr = attrs: concatStringsSep "\n" (mapAttrsToList setOption attrs); + + sidebarSection = '' + # Sidebar + set sidebar_visible = yes + set sidebar_short_path = ${yesno cfg.sidebar.shortPath} + set sidebar_width = ${toString cfg.sidebar.width} + set sidebar_format = '${cfg.sidebar.format}' + ''; + + bindSection = concatMapStringsSep "\n" + (bind: ''bind ${bind.map} ${bind.key} "${bind.action}"'') cfg.binds; + + macroSection = concatMapStringsSep "\n" + (bind: ''macro ${bind.map} ${bind.key} "${bind.action}"'') cfg.macros; + + mailCheckSection = '' + set mail_check_stats + set mail_check_stats_interval = ${toString cfg.checkStatsInterval} + ''; + + notmuchSection = account: + with account; '' + # notmuch section + set nm_default_uri = "notmuch://${config.accounts.email.maildirBasePath}" + virtual-mailboxes "My INBOX" "notmuch://?query=tag:inbox" + ''; + + accountStr = account: + with account; + '' + # Generated by Home Manager. + set ssl_force_tls = yes + set certificate_file=${config.accounts.email.certificatesFile} + + # GPG section + set crypt_use_gpgme = yes + set crypt_autosign = ${yesno (gpg.signByDefault or false)} + set pgp_use_gpg_agent = yes + set mbox_type = ${if maildir != null then "Maildir" else "mbox"} + set sort = "${cfg.sort}" + + # MTA section + ${optionsStr (mtaSection account)} + + ${optionalString (cfg.checkStatsInterval != null) mailCheckSection} + + ${optionalString cfg.sidebar.enable sidebarSection} + + # MRA section + ${mraSection account} + + # Extra configuration + ${account.neomutt.extraConfig} + '' + optionalString (account.signature.showSignature != "none") '' + set signature = ${pkgs.writeText "signature.txt" account.signature.text} + '' + optionalString account.notmuch.enable (notmuchSection account); + +in { + options = { + programs.neomutt = { + enable = mkEnableOption "the NeoMutt mail client"; + + sidebar = mkOption { + type = sidebarModule; + default = { }; + description = "Options related to the sidebar."; + }; + + binds = mkOption { + type = types.listOf bindModule; + default = [ ]; + description = "List of keybindings."; + }; + + macros = mkOption { + type = types.listOf bindModule; + default = [ ]; + description = "List of macros."; + }; + + sort = mkOption { + type = types.enum [ + "date" + "date-received" + "from" + "mailbox-order" + "score" + "size" + "spam" + "subject" + "threads" + "to" + ]; + default = "threads"; + description = "Sorting method on messages."; + }; + + vimKeys = mkOption { + type = types.bool; + default = false; + description = "Enable vim-like bindings."; + }; + + checkStatsInterval = mkOption { + type = types.nullOr types.int; + default = null; + example = 60; + description = "Enable and set the interval of automatic mail check."; + }; + + editor = mkOption { + type = types.str; + default = "$EDITOR"; + description = "Select the editor used for writing mail."; + }; + + settings = mkOption { + type = types.attrsOf types.str; + default = { }; + description = "Extra configuration appended to the end."; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = "Extra configuration appended to the end."; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.neomutt ]; + home.file = let + rcFile = account: { + "${accountFilename account}".text = accountStr account; + }; + in foldl' (a: b: a // b) { } (map rcFile neomuttAccounts); + + xdg.configFile."neomutt/neomuttrc" = mkIf (neomuttAccounts != [ ]) { + text = let primary = filter (a: a.primary) neomuttAccounts; + in '' + # Generated by Home Manager. + set header_cache = "${config.xdg.cacheHome}/neomutt/headers/" + set message_cachedir = "${config.xdg.cacheHome}/neomutt/messages/" + set editor = "${cfg.editor}" + set implicit_autoview = yes + + alternative_order text/enriched text/plain text + + set delete = yes + + # Binds + ${bindSection} + + # Macros + ${macroSection} + + ${optionalString cfg.vimKeys + "source ${pkgs.neomutt}/share/doc/neomutt/vim-keys/vim-keys.rc"} + + # Extra configuration + ${optionsStr cfg.settings} + + ${cfg.extraConfig} + '' + concatMapStringsSep "\n" registerAccount neomuttAccounts + + # source primary account + "source ${accountFilename (builtins.head primary)}"; + }; + }; +} diff --git a/home-manager/modules/programs/neovim.nix b/home-manager/modules/programs/neovim.nix index dadda2c7118..4101dc0f4e7 100644 --- a/home-manager/modules/programs/neovim.nix +++ b/home-manager/modules/programs/neovim.nix @@ -148,8 +148,8 @@ in </para><para> - This option is deprecated. Please use the options <varname>extraConfig</varname> - and <varname>plugins</varname> which are mutually exclusive with this option. + This option is mutually exclusive with <varname>extraConfig</varname> + and <varname>plugins</varname>. ''; }; @@ -193,11 +193,6 @@ in } ]; - warnings = optional (cfg.configure != {}) '' - The programs.neovim.configure option is deprecated. Please use - extraConfig and package option. - ''; - home.packages = [ cfg.finalPackage ]; programs.neovim.finalPackage = pkgs.wrapNeovim cfg.package { diff --git a/home-manager/modules/programs/newsboat.nix b/home-manager/modules/programs/newsboat.nix index 19fec642d21..6b59ed713d8 100644 --- a/home-manager/modules/programs/newsboat.nix +++ b/home-manager/modules/programs/newsboat.nix @@ -4,11 +4,9 @@ with lib; let cfg = config.programs.newsboat; - wrapQuote = x: "\"${x}\""; + wrapQuote = x: ''"${x}"''; -in - -{ +in { options = { programs.newsboat = { enable = mkEnableOption "the Newsboat feed reader"; @@ -24,8 +22,8 @@ in tags = mkOption { type = types.listOf types.str; - default = []; - example = ["foo" "bar"]; + default = [ ]; + example = [ "foo" "bar" ]; description = "Feed tags."; }; @@ -37,8 +35,11 @@ in }; }; }); - default = []; - example = [{url = "http://example.com"; tags = ["foo" "bar"];}]; + default = [ ]; + example = [{ + url = "http://example.com"; + tags = [ "foo" "bar" ]; + }]; description = "List of news feeds."; }; @@ -57,7 +58,9 @@ in autoReload = mkOption { type = types.bool; default = false; - description = "Whether to enable automatic reloading while newsboat is running."; + description = '' + Whether to enable automatic reloading while newsboat is running. + ''; }; reloadTime = mkOption { @@ -74,43 +77,40 @@ in queries = mkOption { type = types.attrsOf types.str; - default = {}; - example = { - "foo" = "rssurl =~ \"example.com\""; - }; + default = { }; + example = { "foo" = ''rssurl =~ "example.com"''; }; description = "A list of queries to use."; }; extraConfig = mkOption { type = types.lines; default = ""; - description = "Extra configuration values that will be appended to the end."; + description = '' + Extra configuration values that will be appended to the end. + ''; }; }; }; config = mkIf cfg.enable { home.packages = [ pkgs.newsboat ]; - home.file.".newsboat/urls".text = - let - mkUrlEntry = u: concatStringsSep " " ( - [u.url] - ++ map wrapQuote u.tags - ++ optional (u.title != null) (wrapQuote "~${u.title}") - ); - urls = map mkUrlEntry cfg.urls; - - mkQueryEntry = n: v: "\"query:${n}:${escape ["\""] v}\""; - queries = mapAttrsToList mkQueryEntry cfg.queries; - in - concatStringsSep "\n" (urls ++ queries) + "\n"; + home.file.".newsboat/urls".text = let + mkUrlEntry = u: + concatStringsSep " " ([ u.url ] ++ map wrapQuote u.tags + ++ optional (u.title != null) (wrapQuote "~${u.title}")); + urls = map mkUrlEntry cfg.urls; + + mkQueryEntry = n: v: ''"query:${n}:${escape [ ''"'' ] v}"''; + queries = mapAttrsToList mkQueryEntry cfg.queries; + in concatStringsSep "\n" (urls ++ queries) + "\n"; home.file.".newsboat/config".text = '' max-items ${toString cfg.maxItems} browser ${cfg.browser} reload-threads ${toString cfg.reloadThreads} auto-reload ${if cfg.autoReload then "yes" else "no"} - ${optionalString (cfg.reloadTime != null) (toString "reload-time ${toString cfg.reloadTime}")} + ${optionalString (cfg.reloadTime != null) + (toString "reload-time ${toString cfg.reloadTime}")} prepopulate-query-feeds yes ${cfg.extraConfig} diff --git a/home-manager/modules/programs/noti.nix b/home-manager/modules/programs/noti.nix index 476c2eb1978..348555eef51 100644 --- a/home-manager/modules/programs/noti.nix +++ b/home-manager/modules/programs/noti.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, ...}: +{ config, lib, pkgs, ... }: with lib; @@ -6,9 +6,7 @@ let cfg = config.programs.noti; -in - -{ +in { meta.maintainers = [ maintainers.marsam ]; options.programs.noti = { @@ -16,7 +14,7 @@ in settings = mkOption { type = types.attrsOf (types.attrsOf types.str); - default = {}; + default = { }; description = '' Configuration written to <filename>~/.config/noti/noti.yaml</filename>. @@ -45,9 +43,8 @@ in config = mkIf cfg.enable { home.packages = [ pkgs.noti ]; - xdg.configFile."noti/noti.yaml" = mkIf (cfg.settings != {}) { - text = generators.toYAML {} cfg.settings; - }; + xdg.configFile."noti/noti.yaml" = + mkIf (cfg.settings != { }) { text = generators.toYAML { } cfg.settings; }; }; } diff --git a/home-manager/modules/programs/notmuch-accounts.nix b/home-manager/modules/programs/notmuch-accounts.nix index 7c9c93d3f95..fd4a811d73d 100644 --- a/home-manager/modules/programs/notmuch-accounts.nix +++ b/home-manager/modules/programs/notmuch-accounts.nix @@ -1,7 +1,5 @@ { lib, ... }: { - options.notmuch = { - enable = lib.mkEnableOption "notmuch indexing"; - }; + options.notmuch = { enable = lib.mkEnableOption "notmuch indexing"; }; } diff --git a/home-manager/modules/programs/notmuch.nix b/home-manager/modules/programs/notmuch.nix index cd0b1384ad9..7e7a140b20c 100644 --- a/home-manager/modules/programs/notmuch.nix +++ b/home-manager/modules/programs/notmuch.nix @@ -9,53 +9,42 @@ let mkIniKeyValue = key: value: let tweakVal = v: - if isString v then v - else if isList v then concatMapStringsSep ";" tweakVal v - else if isBool v then (if v then "true" else "false") - else toString v; - in - "${key}=${tweakVal value}"; - - notmuchIni = - recursiveUpdate - { - database = { - path = config.accounts.email.maildirBasePath; - }; - - maildir = { - synchronize_flags = cfg.maildir.synchronizeFlags; - }; - - new = { - ignore = cfg.new.ignore; - tags = cfg.new.tags; - }; - - user = - let - accounts = - filter (a: a.notmuch.enable) - (attrValues config.accounts.email.accounts); - primary = filter (a: a.primary) accounts; - secondaries = filter (a: !a.primary) accounts; - in { - name = catAttrs "realName" primary; - primary_email = catAttrs "address" primary; - other_email = catAttrs "aliases" primary - ++ catAttrs "address" secondaries - ++ catAttrs "aliases" secondaries; - }; + if isString v then + v + else if isList v then + concatMapStringsSep ";" tweakVal v + else if isBool v then + (if v then "true" else "false") + else + toString v; + in "${key}=${tweakVal value}"; + + notmuchIni = recursiveUpdate { + database = { path = config.accounts.email.maildirBasePath; }; + + maildir = { synchronize_flags = cfg.maildir.synchronizeFlags; }; + + new = { + ignore = cfg.new.ignore; + tags = cfg.new.tags; + }; - search = { - exclude_tags = cfg.search.excludeTags; - }; - } - cfg.extraConfig; + user = let + accounts = filter (a: a.notmuch.enable) + (attrValues config.accounts.email.accounts); + primary = filter (a: a.primary) accounts; + secondaries = filter (a: !a.primary) accounts; + in { + name = catAttrs "realName" primary; + primary_email = catAttrs "address" primary; + other_email = catAttrs "aliases" primary ++ catAttrs "address" secondaries + ++ catAttrs "aliases" secondaries; + }; -in + search = { exclude_tags = cfg.search.excludeTags; }; + } cfg.extraConfig; -{ +in { options = { programs.notmuch = { enable = mkEnableOption "Notmuch mail indexer"; @@ -65,7 +54,7 @@ in options = { ignore = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; description = '' A list to specify files and directories that will not be searched for messages by <command>notmuch new</command>. @@ -83,7 +72,7 @@ in }; }; }; - default = {}; + default = { }; description = '' Options related to email processing performed by <command>notmuch new</command>. @@ -92,7 +81,7 @@ in extraConfig = mkOption { type = types.attrsOf (types.attrsOf types.str); - default = {}; + default = { }; description = '' Options that should be appended to the notmuch configuration file. ''; @@ -159,11 +148,11 @@ in config = mkIf cfg.enable { assertions = [ { - assertion = notmuchIni.user.name != []; + assertion = notmuchIni.user.name != [ ]; message = "notmuch: Must have a user name set."; } { - assertion = notmuchIni.user.primary_email != []; + assertion = notmuchIni.user.primary_email != [ ]; message = "notmuch: Must have a user primary email address set."; } ]; @@ -176,36 +165,27 @@ in }; xdg.configFile."notmuch/notmuchrc".text = - let - toIni = generators.toINI { mkKeyValue = mkIniKeyValue; }; - in - "# Generated by Home Manager.\n\n" - + toIni notmuchIni; - - home.file = - let - hook = name: cmds: - { - target = "${notmuchIni.database.path}/.notmuch/hooks/${name}"; - source = pkgs.writeScript name '' - #!${pkgs.runtimeShell} - - export PATH="${pkgs.notmuch}/bin''${PATH:+:}$PATH" - export NOTMUCH_CONFIG="${config.xdg.configHome}/notmuch/notmuchrc" - export NMBGIT="${config.xdg.dataHome}/notmuch/nmbug" - - ${cmds} - ''; - executable = true; - }; - in - optional (cfg.hooks.preNew != "") - (hook "pre-new" cfg.hooks.preNew) - ++ - optional (cfg.hooks.postNew != "") - (hook "post-new" cfg.hooks.postNew) - ++ - optional (cfg.hooks.postInsert != "") - (hook "post-insert" cfg.hooks.postInsert); + let toIni = generators.toINI { mkKeyValue = mkIniKeyValue; }; + in '' + # Generated by Home Manager. + + '' + toIni notmuchIni; + + home.file = let + hook = name: cmds: { + "${notmuchIni.database.path}/.notmuch/hooks/${name}".source = + pkgs.writeShellScript name '' + export PATH="${pkgs.notmuch}/bin''${PATH:+:}$PATH" + export NOTMUCH_CONFIG="${config.xdg.configHome}/notmuch/notmuchrc" + export NMBGIT="${config.xdg.dataHome}/notmuch/nmbug" + + ${cmds} + ''; + }; + in optionalAttrs (cfg.hooks.preNew != "") (hook "pre-new" cfg.hooks.preNew) + // optionalAttrs (cfg.hooks.postNew != "") + (hook "post-new" cfg.hooks.postNew) + // optionalAttrs (cfg.hooks.postInsert != "") + (hook "post-insert" cfg.hooks.postInsert); }; } diff --git a/home-manager/modules/programs/obs-studio.nix b/home-manager/modules/programs/obs-studio.nix index f0dfecb63cc..6df5978384c 100644 --- a/home-manager/modules/programs/obs-studio.nix +++ b/home-manager/modules/programs/obs-studio.nix @@ -11,23 +11,18 @@ let let pluginDirs = map (pkg: "${pkg}/share/obs/obs-plugins") packages; plugins = concatMapStringsSep " " (p: "${p}/*") pluginDirs; - in - pkgs.runCommand "obs-studio-plugins" - { - preferLocalBuild = true; - allowSubstitutes = false; - } - '' - mkdir $out - [[ '${plugins}' ]] || exit 0 - for plugin in ${plugins}; do - ln -s "$plugin" $out/ - done - ''; - -in - -{ + in pkgs.runCommand "obs-studio-plugins" { + preferLocalBuild = true; + allowSubstitutes = false; + } '' + mkdir $out + [[ '${plugins}' ]] || exit 0 + for plugin in ${plugins}; do + ln -s "$plugin" $out/ + done + ''; + +in { meta.maintainers = [ maintainers.adisbladis ]; options = { @@ -35,7 +30,7 @@ in enable = mkEnableOption "obs-studio"; plugins = mkOption { - default = []; + default = [ ]; example = literalExample "[ pkgs.obs-linuxbrowser ]"; description = "Optional OBS plugins."; type = types.listOf types.package; @@ -46,8 +41,7 @@ in config = mkIf cfg.enable { home.packages = [ package ]; - xdg.configFile."obs-studio/plugins" = mkIf (cfg.plugins != []) { - source = mkPluginEnv cfg.plugins; - }; + xdg.configFile."obs-studio/plugins" = + mkIf (cfg.plugins != [ ]) { source = mkPluginEnv cfg.plugins; }; }; } diff --git a/home-manager/modules/programs/offlineimap-accounts.nix b/home-manager/modules/programs/offlineimap-accounts.nix index 015a5974ab3..afc7a019972 100644 --- a/home-manager/modules/programs/offlineimap-accounts.nix +++ b/home-manager/modules/programs/offlineimap-accounts.nix @@ -6,18 +6,14 @@ let extraConfigType = with types; attrsOf (either (either str int) bool); -in - -{ +in { options.offlineimap = { enable = mkEnableOption "OfflineIMAP"; extraConfig.account = mkOption { type = extraConfigType; - default = {}; - example = { - autorefresh = 20; - }; + default = { }; + example = { autorefresh = 20; }; description = '' Extra configuration options to add to the account section. ''; @@ -25,10 +21,8 @@ in extraConfig.local = mkOption { type = extraConfigType; - default = {}; - example = { - sync_deletes = true; - }; + default = { }; + example = { sync_deletes = true; }; description = '' Extra configuration options to add to the local account section. @@ -37,7 +31,7 @@ in extraConfig.remote = mkOption { type = extraConfigType; - default = {}; + default = { }; example = { maxconnections = 2; expunge = false; diff --git a/home-manager/modules/programs/offlineimap.nix b/home-manager/modules/programs/offlineimap.nix index 82143b630ad..4ce12ec0a61 100644 --- a/home-manager/modules/programs/offlineimap.nix +++ b/home-manager/modules/programs/offlineimap.nix @@ -12,11 +12,11 @@ let toIni = generators.toINI { mkKeyValue = key: value: let - value' = - if isBool value then (if value then "yes" else "no") - else toString value; - in - "${key} = ${value'}"; + value' = if isBool value then + (if value then "yes" else "no") + else + toString value; + in "${key} = ${value'}"; }; # Generates a script to fetch only a specific account. @@ -29,90 +29,65 @@ let # Something like # # $ email <account name> <program name> <program args> - genOfflineImapScript = account: with account; + genOfflineImapScript = account: + with account; pkgs.writeShellScriptBin "offlineimap-${name}" '' exec ${pkgs.offlineimap}/bin/offlineimap -a${account.name} "$@" ''; - accountStr = account: with account; + accountStr = account: + with account; let postSyncHook = optionalAttrs (offlineimap.postSyncHookCommand != "") { - postsynchook = - pkgs.writeShellScriptBin - "postsynchook" - offlineimap.postSyncHookCommand - + "/bin/postsynchook"; + postsynchook = pkgs.writeShellScriptBin "postsynchook" + offlineimap.postSyncHookCommand + "/bin/postsynchook"; }; localType = - if account.flavor == "gmail.com" - then "GmailMaildir" - else "Maildir"; + if account.flavor == "gmail.com" then "GmailMaildir" else "Maildir"; - remoteType = - if account.flavor == "gmail.com" - then "Gmail" - else "IMAP"; + remoteType = if account.flavor == "gmail.com" then "Gmail" else "IMAP"; - remoteHost = optionalAttrs (imap.host != null) { - remotehost = imap.host; - }; + remoteHost = + optionalAttrs (imap.host != null) { remotehost = imap.host; }; - remotePort = optionalAttrs ((imap.port or null) != null) { - remoteport = imap.port; - }; + remotePort = + optionalAttrs ((imap.port or null) != null) { remoteport = imap.port; }; - ssl = - if imap.tls.enable - then - { - ssl = true; - sslcacertfile = imap.tls.certificatesFile; - starttls = imap.tls.useStartTls; - } - else - { - ssl = false; - }; + ssl = if imap.tls.enable then { + ssl = true; + sslcacertfile = imap.tls.certificatesFile; + starttls = imap.tls.useStartTls; + } else { + ssl = false; + }; remotePassEval = - let - arglist = concatMapStringsSep "," (x: "'${x}'") passwordCommand; - in - optionalAttrs (passwordCommand != null) { - remotepasseval = ''get_pass("${name}", [${arglist}])''; - }; - in - toIni { - "Account ${name}" = { - localrepository = "${name}-local"; - remoterepository = "${name}-remote"; - } - // postSyncHook - // offlineimap.extraConfig.account; - - "Repository ${name}-local" = { - type = localType; - localfolders = maildir.absPath; - } - // offlineimap.extraConfig.local; - - "Repository ${name}-remote" = { - type = remoteType; - remoteuser = userName; - } - // remoteHost - // remotePort - // remotePassEval - // ssl + let arglist = concatMapStringsSep "," (x: "'${x}'") passwordCommand; + in optionalAttrs (passwordCommand != null) { + remotepasseval = ''get_pass("${name}", [${arglist}])''; + }; + in toIni { + "Account ${name}" = { + localrepository = "${name}-local"; + remoterepository = "${name}-remote"; + } // postSyncHook // offlineimap.extraConfig.account; + + "Repository ${name}-local" = { + type = localType; + localfolders = maildir.absPath; + } // offlineimap.extraConfig.local; + + "Repository ${name}-remote" = { + type = remoteType; + remoteuser = userName; + } // remoteHost // remotePort // remotePassEval // ssl // offlineimap.extraConfig.remote; - }; + }; extraConfigType = with types; attrsOf (either (either str int) bool); -in - -{ +in { options = { programs.offlineimap = { enable = mkEnableOption "OfflineIMAP"; @@ -133,7 +108,7 @@ in extraConfig.general = mkOption { type = extraConfigType; - default = {}; + default = { }; example = { maxage = 30; ui = "blinkenlights"; @@ -146,10 +121,8 @@ in extraConfig.default = mkOption { type = extraConfigType; - default = {}; - example = { - gmailtrashfolder = "[Gmail]/Papierkorb"; - }; + default = { }; + example = { gmailtrashfolder = "[Gmail]/Papierkorb"; }; description = '' Extra configuration options added to the <option>DEFAULT</option> section. @@ -158,7 +131,7 @@ in extraConfig.mbnames = mkOption { type = extraConfigType; - default = {}; + default = { }; example = literalExample '' { filename = "~/.config/mutt/mailboxes"; @@ -181,27 +154,20 @@ in xdg.configFile."offlineimap/get_settings.py".text = cfg.pythonFile; - xdg.configFile."offlineimap/config".text = - '' - # Generated by Home Manager. - # See https://github.com/OfflineIMAP/offlineimap/blob/master/offlineimap.conf - # for an exhaustive list of options. - '' - + toIni ({ - general = { - accounts = concatMapStringsSep "," (a: a.name) accounts; - pythonfile = "${config.xdg.configHome}/offlineimap/get_settings.py"; - metadata = "${config.xdg.dataHome}/offlineimap"; - } - // cfg.extraConfig.general; - } - // optionalAttrs (cfg.extraConfig.mbnames != {}) { - mbnames = { enabled = true; } // cfg.extraConfig.mbnames; - } - // optionalAttrs (cfg.extraConfig.default != {}) { - DEFAULT = cfg.extraConfig.default; - }) - + "\n" - + concatStringsSep "\n" (map accountStr accounts); + xdg.configFile."offlineimap/config".text = '' + # Generated by Home Manager. + # See https://github.com/OfflineIMAP/offlineimap/blob/master/offlineimap.conf + # for an exhaustive list of options. + '' + toIni ({ + general = { + accounts = concatMapStringsSep "," (a: a.name) accounts; + pythonfile = "${config.xdg.configHome}/offlineimap/get_settings.py"; + metadata = "${config.xdg.dataHome}/offlineimap"; + } // cfg.extraConfig.general; + } // optionalAttrs (cfg.extraConfig.mbnames != { }) { + mbnames = { enabled = true; } // cfg.extraConfig.mbnames; + } // optionalAttrs (cfg.extraConfig.default != { }) { + DEFAULT = cfg.extraConfig.default; + }) + "\n" + concatStringsSep "\n" (map accountStr accounts); }; } diff --git a/home-manager/modules/programs/opam.nix b/home-manager/modules/programs/opam.nix index 4de2e82da55..a61ff7878df 100644 --- a/home-manager/modules/programs/opam.nix +++ b/home-manager/modules/programs/opam.nix @@ -6,9 +6,7 @@ let cfg = config.programs.opam; -in - -{ +in { meta.maintainers = [ maintainers.marsam ]; options.programs.opam = { diff --git a/home-manager/modules/programs/password-store.nix b/home-manager/modules/programs/password-store.nix new file mode 100644 index 00000000000..db31146a1ba --- /dev/null +++ b/home-manager/modules/programs/password-store.nix @@ -0,0 +1,62 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.password-store; + +in { + meta.maintainers = with maintainers; [ pacien ]; + + options.programs.password-store = { + enable = mkEnableOption "Password store"; + + package = mkOption { + type = types.package; + default = pkgs.pass; + defaultText = literalExample "pkgs.pass"; + example = literalExample '' + pkgs.pass.withExtensions (exts: [ exts.pass-otp ]) + ''; + description = '' + The <literal>pass</literal> package to use. + Can be used to specify extensions. + ''; + }; + + settings = mkOption rec { + type = with types; attrsOf str; + apply = mergeAttrs default; + default = { + PASSWORD_STORE_DIR = "${config.xdg.dataHome}/password-store"; + }; + defaultText = literalExample '' + { PASSWORD_STORE_DIR = "$XDG_DATA_HOME/password-store"; } + ''; + example = literalExample '' + { + PASSWORD_STORE_DIR = "/some/directory"; + PASSWORD_STORE_KEY = "12345678"; + PASSWORD_STORE_CLIP_TIME = "60"; + } + ''; + description = '' + The <literal>pass</literal> environment variables dictionary. + </para><para> + See the "Environment variables" section of + <citerefentry> + <refentrytitle>pass</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry> + and the extension man pages for more information about the + available keys. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + home.sessionVariables = cfg.settings; + }; +} diff --git a/home-manager/modules/programs/pazi.nix b/home-manager/modules/programs/pazi.nix new file mode 100644 index 00000000000..e1a08eb615a --- /dev/null +++ b/home-manager/modules/programs/pazi.nix @@ -0,0 +1,55 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.pazi; + +in { + meta.maintainers = [ maintainers.marsam ]; + + options.programs.pazi = { + enable = mkEnableOption "pazi"; + + enableBashIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Bash integration. + ''; + }; + + enableZshIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Zsh integration. + ''; + }; + + enableFishIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Fish integration. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.pazi ]; + + programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + eval "$(${pkgs.pazi}/bin/pazi init bash)" + ''; + + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + eval "$(${pkgs.pazi}/bin/pazi init zsh)" + ''; + + programs.fish.shellInit = mkIf cfg.enableFishIntegration '' + ${pkgs.pazi}/bin/pazi init fish | source + ''; + }; +} diff --git a/home-manager/modules/programs/pidgin.nix b/home-manager/modules/programs/pidgin.nix index 8dcb2122172..a375fd1b2bd 100644 --- a/home-manager/modules/programs/pidgin.nix +++ b/home-manager/modules/programs/pidgin.nix @@ -6,9 +6,7 @@ let cfg = config.programs.pidgin; -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; options = { @@ -23,7 +21,7 @@ in }; plugins = mkOption { - default = []; + default = [ ]; example = literalExample "[ pkgs.pidgin-otr pkgs.pidgin-osd ]"; description = "Plugins that should be available to Pidgin."; }; diff --git a/home-manager/modules/programs/readline.nix b/home-manager/modules/programs/readline.nix new file mode 100644 index 00000000000..2f79df6e103 --- /dev/null +++ b/home-manager/modules/programs/readline.nix @@ -0,0 +1,77 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.readline; + + mkSetVariableStr = n: v: + let + mkValueStr = v: + if v == true then + "on" + else if v == false then + "off" + else if isInt v then + toString v + else if isString v then + v + else + abort ("values ${toPretty v} is of unsupported type"); + in "set ${n} ${mkValueStr v}"; + + mkBindingStr = k: v: ''"${k}": ${v}''; + +in { + options.programs.readline = { + enable = mkEnableOption "readline"; + + bindings = mkOption { + default = { }; + type = types.attrsOf types.str; + example = literalExample '' + { "\\C-h" = "backward-kill-word"; } + ''; + description = "Readline bindings."; + }; + + variables = mkOption { + type = with types; attrsOf (either str (either int bool)); + default = { }; + example = { expand-tilde = true; }; + description = '' + Readline customization variable assignments. + ''; + }; + + includeSystemConfig = mkOption { + type = types.bool; + default = true; + description = "Whether to include the system-wide configuration."; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Configuration lines appended unchanged to the end of the + <filename>~/.inputrc</filename> file. + ''; + }; + }; + + config = mkIf cfg.enable { + home.file.".inputrc".text = let + configStr = concatStringsSep "\n" + (optional cfg.includeSystemConfig "$include /etc/inputrc" + ++ mapAttrsToList mkSetVariableStr cfg.variables + ++ mapAttrsToList mkBindingStr cfg.bindings); + in '' + # Generated by Home Manager. + + ${configStr} + ${cfg.extraConfig} + ''; + }; +} diff --git a/home-manager/modules/programs/rofi.nix b/home-manager/modules/programs/rofi.nix index e64e5d4782e..f344e88e2ff 100644 --- a/home-manager/modules/programs/rofi.nix +++ b/home-manager/modules/programs/rofi.nix @@ -7,10 +7,11 @@ let cfg = config.programs.rofi; - colorOption = description: mkOption { - type = types.str; - description = description; - }; + colorOption = description: + mkOption { + type = types.str; + description = description; + }; rowColorSubmodule = types.submodule { options = { @@ -71,72 +72,64 @@ let }; valueToString = value: - if isBool value - then (if value then "true" else "else") - else toString value; + if isBool value then (if value then "true" else "else") else toString value; - windowColorsToString = window: concatStringsSep ", " (with window; [ - background - border - separator - ]); + windowColorsToString = window: + concatStringsSep ", " (with window; [ background border separator ]); rowsColorsToString = rows: '' - ${optionalString - (rows.normal != null) - (setOption "color-normal" (rowColorsToString rows.normal))} - ${optionalString - (rows.active != null) - (setOption "color-active" (rowColorsToString rows.active))} - ${optionalString - (rows.urgent != null) - (setOption "color-urgent" (rowColorsToString rows.urgent))} + ${optionalString (rows.normal != null) + (setOption "color-normal" (rowColorsToString rows.normal))} + ${optionalString (rows.active != null) + (setOption "color-active" (rowColorsToString rows.active))} + ${optionalString (rows.urgent != null) + (setOption "color-urgent" (rowColorsToString rows.urgent))} ''; - rowColorsToString = row: concatStringsSep ", " (with row; [ - background - foreground - backgroundAlt - highlight.background - highlight.foreground - ]); + rowColorsToString = row: + concatStringsSep ", " (with row; [ + background + foreground + backgroundAlt + highlight.background + highlight.foreground + ]); setOption = name: value: optionalString (value != null) "rofi.${name}: ${valueToString value}"; - setColorScheme = colors: optionalString (colors != null) '' - ${optionalString - (colors.window != null) - setOption "color-window" (windowColorsToString colors.window)} - ${optionalString - (colors.rows != null) - (rowsColorsToString colors.rows)} - ''; + setColorScheme = colors: + optionalString (colors != null) '' + ${optionalString (colors.window != null) setOption "color-window" + (windowColorsToString colors.window)} + ${optionalString (colors.rows != null) (rowsColorsToString colors.rows)} + ''; locationsMap = { - center = 0; - top-left = 1; - top = 2; - top-right = 3; - right = 4; + center = 0; + top-left = 1; + top = 2; + top-right = 3; + right = 4; bottom-right = 5; - bottom = 6; - bottom-left = 7; - left = 8; + bottom = 6; + bottom-left = 7; + left = 8; }; - themeName = - if (cfg.theme == null) then null - else if (lib.isString cfg.theme) then cfg.theme - else lib.removeSuffix ".rasi" (baseNameOf cfg.theme); + themeName = if (cfg.theme == null) then + null + else if (lib.isString cfg.theme) then + cfg.theme + else + lib.removeSuffix ".rasi" (baseNameOf cfg.theme); themePath = if (lib.isString cfg.theme) then null else cfg.theme; -in - -{ +in { options.programs.rofi = { - enable = mkEnableOption "Rofi: A window switcher, application launcher and dmenu replacement"; + enable = mkEnableOption + "Rofi: A window switcher, application launcher and dmenu replacement"; width = mkOption { default = null; @@ -295,14 +288,12 @@ in }; config = mkIf cfg.enable { - assertions = [ - { - assertion = cfg.theme == null || cfg.colors == null; - message = '' - Cannot use the rofi options 'theme' and 'colors' simultaneously. - ''; - } - ]; + assertions = [{ + assertion = cfg.theme == null || cfg.colors == null; + message = '' + Cannot use the rofi options 'theme' and 'colors' simultaneously. + ''; + }]; home.packages = [ pkgs.rofi ]; @@ -314,11 +305,8 @@ in ${setOption "eh" cfg.rowHeight} ${setOption "padding" cfg.padding} ${setOption "separator-style" cfg.separator} - ${setOption "hide-scrollbar" ( - if (cfg.scrollbar != null) - then (! cfg.scrollbar) - else cfg.scrollbar - )} + ${setOption "hide-scrollbar" + (if (cfg.scrollbar != null) then (!cfg.scrollbar) else cfg.scrollbar)} ${setOption "terminal" cfg.terminal} ${setOption "cycle" cfg.cycle} ${setOption "fullscreen" cfg.fullscreen} @@ -333,7 +321,7 @@ in ''; xdg.dataFile = mkIf (themePath != null) { - "rofi/themes/${themeName}.rasi".source = themePath; + "rofi/themes/${themeName}.rasi".source = themePath; }; }; } diff --git a/home-manager/modules/programs/rtorrent.nix b/home-manager/modules/programs/rtorrent.nix index 6300969a519..7beeb2e4221 100644 --- a/home-manager/modules/programs/rtorrent.nix +++ b/home-manager/modules/programs/rtorrent.nix @@ -6,9 +6,7 @@ let cfg = config.programs.rtorrent; -in - -{ +in { meta.maintainers = [ maintainers.marsam ]; options.programs.rtorrent = { @@ -30,8 +28,7 @@ in config = mkIf cfg.enable { home.packages = [ pkgs.rtorrent ]; - xdg.configFile."rtorrent/rtorrent.rc" = mkIf (cfg.settings != "") { - text = cfg.settings; - }; + xdg.configFile."rtorrent/rtorrent.rc" = + mkIf (cfg.settings != "") { text = cfg.settings; }; }; } diff --git a/home-manager/modules/programs/skim.nix b/home-manager/modules/programs/skim.nix index de1bff30fce..c90fe1b1a35 100644 --- a/home-manager/modules/programs/skim.nix +++ b/home-manager/modules/programs/skim.nix @@ -6,9 +6,7 @@ let cfg = config.programs.skim; -in - -{ +in { options.programs.skim = { enable = mkEnableOption "skim - a command-line fuzzy finder"; @@ -24,7 +22,7 @@ in defaultOptions = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; example = [ "--height 40%" "--prompt ⟫" ]; description = '' Extra command line options given to skim by default. @@ -43,7 +41,7 @@ in fileWidgetOptions = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; example = [ "--preview 'head {}'" ]; description = '' Command line options for the CTRL-T keybinding. @@ -53,7 +51,7 @@ in changeDirWidgetCommand = mkOption { type = types.nullOr types.str; default = null; - example = "fd --type d" ; + example = "fd --type d"; description = '' The command that gets executed as the source for skim for the ALT-C keybinding. @@ -62,7 +60,7 @@ in changeDirWidgetOptions = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; example = [ "--preview 'tree -C {} | head -200'" ]; description = '' Command line options for the ALT-C keybinding. @@ -71,7 +69,7 @@ in historyWidgetOptions = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; example = [ "--tac" "--exact" ]; description = '' Command line options for the CTRL-R keybinding. @@ -98,18 +96,16 @@ in config = mkIf cfg.enable { home.packages = [ pkgs.skim ]; - home.sessionVariables = - mapAttrs (n: v: toString v) ( - filterAttrs (n: v: v != [] && v != null) { - SKIM_ALT_C_COMMAND = cfg.changeDirWidgetCommand; - SKIM_ALT_C_OPTS = cfg.changeDirWidgetOptions; - SKIM_CTRL_R_OPTS = cfg.historyWidgetOptions; - SKIM_CTRL_T_COMMAND = cfg.fileWidgetCommand; - SKIM_CTRL_T_OPTS = cfg.fileWidgetOptions; - SKIM_DEFAULT_COMMAND = cfg.defaultCommand; - SKIM_DEFAULT_OPTIONS = cfg.defaultOptions; - } - ); + home.sessionVariables = mapAttrs (n: v: toString v) + (filterAttrs (n: v: v != [ ] && v != null) { + SKIM_ALT_C_COMMAND = cfg.changeDirWidgetCommand; + SKIM_ALT_C_OPTS = cfg.changeDirWidgetOptions; + SKIM_CTRL_R_OPTS = cfg.historyWidgetOptions; + SKIM_CTRL_T_COMMAND = cfg.fileWidgetCommand; + SKIM_CTRL_T_OPTS = cfg.fileWidgetOptions; + SKIM_DEFAULT_COMMAND = cfg.defaultCommand; + SKIM_DEFAULT_OPTIONS = cfg.defaultOptions; + }); programs.bash.initExtra = mkIf cfg.enableBashIntegration '' if [[ :$SHELLOPTS: =~ :(vi|emacs): ]]; then diff --git a/home-manager/modules/programs/ssh.nix b/home-manager/modules/programs/ssh.nix index ab61c0dcbc4..6b0747dd9b1 100644 --- a/home-manager/modules/programs/ssh.nix +++ b/home-manager/modules/programs/ssh.nix @@ -183,10 +183,14 @@ let }; certificateFile = mkOption { - type = types.nullOr types.path; - default = null; + type = with types; either (listOf str) (nullOr str); + default = []; + apply = p: + if p == null then [] + else if isString p then [p] + else p; description = '' - Specifies a file from which the user certificate is read. + Specifies files from which the user certificate is read. ''; }; @@ -273,7 +277,6 @@ let ++ optional cf.forwardX11Trusted " ForwardX11Trusted yes" ++ optional cf.identitiesOnly " IdentitiesOnly yes" ++ optional (cf.user != null) " User ${cf.user}" - ++ optional (cf.certificateFile != null) " CertificateFile ${cf.certificateFile}" ++ optional (cf.hostname != null) " HostName ${cf.hostname}" ++ optional (cf.addressFamily != null) " AddressFamily ${cf.addressFamily}" ++ optional (cf.sendEnv != []) " SendEnv ${unwords cf.sendEnv}" @@ -284,6 +287,7 @@ let ++ optional (cf.proxyCommand != null) " ProxyCommand ${cf.proxyCommand}" ++ optional (cf.proxyJump != null) " ProxyJump ${cf.proxyJump}" ++ map (file: " IdentityFile ${file}") cf.identityFile + ++ map (file: " CertificateFile ${file}") cf.certificateFile ++ map (f: " LocalForward" + addressPort f.bind + addressPort f.host) cf.localForwards ++ map (f: " RemoteForward" + addressPort f.bind + addressPort f.host) cf.remoteForwards ++ map (f: " DynamicForward" + addressPort f) cf.dynamicForwards diff --git a/home-manager/modules/programs/starship.nix b/home-manager/modules/programs/starship.nix index 81793c7a6f6..7c7819865f7 100644 --- a/home-manager/modules/programs/starship.nix +++ b/home-manager/modules/programs/starship.nix @@ -7,28 +7,32 @@ let cfg = config.programs.starship; configFile = config: - pkgs.runCommand "config.toml" - { - buildInputs = [ pkgs.remarshal ]; - preferLocalBuild = true; - allowSubstitutes = false; - } - '' - remarshal -if json -of toml \ - < ${pkgs.writeText "config.json" (builtins.toJSON config)} \ - > $out - ''; -in + pkgs.runCommand "config.toml" { + buildInputs = [ pkgs.remarshal ]; + preferLocalBuild = true; + allowSubstitutes = false; + } '' + remarshal -if json -of toml \ + < ${pkgs.writeText "config.json" (builtins.toJSON config)} \ + > $out + ''; -{ +in { meta.maintainers = [ maintainers.marsam ]; options.programs.starship = { enable = mkEnableOption "starship"; + package = mkOption { + type = types.package; + default = pkgs.starship; + defaultText = literalExample "pkgs.starship"; + description = "The package to use for the starship binary."; + }; + settings = mkOption { type = types.attrs; - default = {}; + default = { }; description = '' Configuration written to <filename>~/.config/starship.toml</filename>. @@ -64,27 +68,26 @@ in }; config = mkIf cfg.enable { - home.packages = [ pkgs.starship ]; + home.packages = [ cfg.package ]; - xdg.configFile."starship.toml" = mkIf (cfg.settings != {}) { - source = configFile cfg.settings; - }; + xdg.configFile."starship.toml" = + mkIf (cfg.settings != { }) { source = configFile cfg.settings; }; programs.bash.initExtra = mkIf cfg.enableBashIntegration '' if [[ -z $INSIDE_EMACS ]]; then - eval "$(${pkgs.starship}/bin/starship init bash)" + eval "$(${cfg.package}/bin/starship init bash)" fi ''; programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' if [ -z "$INSIDE_EMACS" ]; then - eval "$(${pkgs.starship}/bin/starship init zsh)" + eval "$(${cfg.package}/bin/starship init zsh)" fi ''; programs.fish.shellInit = mkIf cfg.enableFishIntegration '' if test -z "$INSIDE_EMACS" - eval (${pkgs.starship}/bin/starship init fish) + eval (${cfg.package}/bin/starship init fish) end ''; }; diff --git a/home-manager/modules/programs/taskwarrior.nix b/home-manager/modules/programs/taskwarrior.nix index eeacc77da29..cf95511f8ef 100644 --- a/home-manager/modules/programs/taskwarrior.nix +++ b/home-manager/modules/programs/taskwarrior.nix @@ -9,38 +9,39 @@ let themePath = theme: "${pkgs.taskwarrior}/share/doc/task/rc/${theme}.theme"; includeTheme = location: - if location == null then "" - else if isString location then "include ${themePath location}" - else "include ${location}"; + if location == null then + "" + else if isString location then + "include ${themePath location}" + else + "include ${location}"; formatValue = value: - if isBool value then if value then "true" else "false" - else if isList value then concatMapStringsSep "," formatValue value - else toString value; + if isBool value then + if value then "true" else "false" + else if isList value then + concatMapStringsSep "," formatValue value + else + toString value; - formatLine = key: value: - "${key}=${formatValue value}"; + formatLine = key: value: "${key}=${formatValue value}"; formatSet = key: values: (concatStringsSep "\n" - (mapAttrsToList - (subKey: subValue: formatPair "${key}.${subKey}" subValue) + (mapAttrsToList (subKey: subValue: formatPair "${key}.${subKey}" subValue) values)); formatPair = key: value: - if isAttrs value then formatSet key value - else formatLine key value; + if isAttrs value then formatSet key value else formatLine key value; -in - -{ +in { options = { programs.taskwarrior = { enable = mkEnableOption "Task Warrior"; config = mkOption { type = types.attrs; - default = {}; + default = { }; example = literalExample '' { confirmation = false; @@ -103,8 +104,7 @@ in data.location=${cfg.dataLocation} ${includeTheme cfg.colorTheme} - ${concatStringsSep "\n" ( - mapAttrsToList formatPair cfg.config)} + ${concatStringsSep "\n" (mapAttrsToList formatPair cfg.config)} ${cfg.extraConfig} ''; diff --git a/home-manager/modules/programs/termite.nix b/home-manager/modules/programs/termite.nix index a5b1cebe775..8a05db03558 100644 --- a/home-manager/modules/programs/termite.nix +++ b/home-manager/modules/programs/termite.nix @@ -13,9 +13,7 @@ let fi ''; -in - -{ +in { options = { programs.termite = { enable = mkEnableOption "Termite VTE-based terminal"; @@ -61,7 +59,9 @@ in mouseAutohide = mkOption { default = null; type = types.nullOr types.bool; - description = "Automatically hide the mouse pointer when you start typing."; + description = '' + Automatically hide the mouse pointer when you start typing. + ''; }; scrollOnOutput = mkOption { @@ -73,7 +73,9 @@ in scrollOnKeystroke = mkOption { default = null; type = types.nullOr types.bool; - description = "Scroll to the bottom automatically when a key is pressed."; + description = '' + Scroll to the bottom automatically when a key is pressed. + ''; }; searchWrap = mkOption { @@ -106,14 +108,16 @@ in default = null; example = "terminal"; type = types.nullOr types.str; - description = "The name of the icon to be used for the terminal process."; + description = + "The name of the icon to be used for the terminal process."; }; scrollbackLines = mkOption { default = null; example = 10000; type = types.nullOr types.int; - description = "Set the number of lines to limit the terminal's scrollback."; + description = + "Set the number of lines to limit the terminal's scrollback."; }; browser = mkOption { @@ -149,7 +153,8 @@ in filterUnmatchedUrls = mkOption { default = null; type = types.nullOr types.bool; - description = "Whether to hide url hints not matching input in url hints mode."; + description = + "Whether to hide url hints not matching input in url hints mode."; }; modifyOtherKeys = mkOption { @@ -178,7 +183,7 @@ in scrollbar = mkOption { default = null; type = types.nullOr (types.enum [ "off" "left" "right" ]); - description = "Scroll to the bottom when the shell generates output."; + description = "Scrollbar position."; }; backgroundColor = mkOption { @@ -290,7 +295,8 @@ in default = ""; example = "fullscreen = true"; type = types.lines; - description = "Extra options that should be added to [options] section."; + description = + "Extra options that should be added to [options] section."; }; colorsExtra = mkOption { @@ -301,78 +307,81 @@ in color2 = #60b48a ''; type = types.lines; - description = "Extra colors options that should be added to [colors] section."; + description = + "Extra colors options that should be added to [colors] section."; }; hintsExtra = mkOption { default = ""; example = "border = #3f3f3f"; type = types.lines; - description = "Extra hints options that should be added to [hints] section."; + description = + "Extra hints options that should be added to [hints] section."; }; }; }; - config = ( - let - boolToString = v: if v then "true" else "false"; - optionalBoolean = name: val: lib.optionalString (val != null) "${name} = ${boolToString val}"; - optionalInteger = name: val: lib.optionalString (val != null) "${name} = ${toString val}"; - optionalString = name: val: lib.optionalString (val != null) "${name} = ${val}"; - in mkIf cfg.enable { - home.packages = [ pkgs.termite ]; - xdg.configFile."termite/config".text = '' - [options] - ${optionalBoolean "allow_bold" cfg.allowBold} - ${optionalBoolean "audible_bell" cfg.audibleBell} - ${optionalString "browser" cfg.browser} - ${optionalBoolean "clickable_url" cfg.clickableUrl} - ${optionalString "cursor_blink" cfg.cursorBlink} - ${optionalString "cursor_shape" cfg.cursorShape} - ${optionalBoolean "dynamic_title" cfg.dynamicTitle} - ${optionalBoolean "filter_unmatched_urls" cfg.filterUnmatchedUrls} - ${optionalString "font" cfg.font} - ${optionalBoolean "fullscreen" cfg.fullscreen} - ${optionalString "geometry" cfg.geometry} - ${optionalString "icon_name" cfg.iconName} - ${optionalBoolean "modify_other_keys" cfg.modifyOtherKeys} - ${optionalBoolean "mouse_autohide" cfg.mouseAutohide} - ${optionalBoolean "scroll_on_keystroke" cfg.scrollOnKeystroke} - ${optionalBoolean "scroll_on_output" cfg.scrollOnOutput} - ${optionalInteger "scrollback_lines" cfg.scrollbackLines} - ${optionalString "scrollbar" cfg.scrollbar} - ${optionalBoolean "search_wrap" cfg.searchWrap} - ${optionalBoolean "size_hints" cfg.sizeHints} - ${optionalBoolean "urgent_on_bell" cfg.urgentOnBell} - - ${cfg.optionsExtra} - - [colors] - ${optionalString "background" cfg.backgroundColor} - ${optionalString "cursor" cfg.cursorColor} - ${optionalString "cursor_foreground" cfg.cursorForegroundColor} - ${optionalString "foreground" cfg.foregroundColor} - ${optionalString "foregroundBold" cfg.foregroundBoldColor} - ${optionalString "highlight" cfg.highlightColor} - - ${cfg.colorsExtra} - - [hints] - ${optionalString "active_background" cfg.hintsActiveBackgroundColor} - ${optionalString "active_foreground" cfg.hintsActiveForegroundColor} - ${optionalString "background" cfg.hintsBackgroundColor} - ${optionalString "border" cfg.hintsBorderColor} - ${optionalInteger "border_width" cfg.hintsBorderWidth} - ${optionalString "font" cfg.hintsFont} - ${optionalString "foreground" cfg.hintsForegroundColor} - ${optionalInteger "padding" cfg.hintsPadding} - ${optionalInteger "roundness" cfg.hintsRoundness} - - ${cfg.hintsExtra} - ''; - - programs.bash.initExtra = vteInitStr; - programs.zsh.initExtra = vteInitStr; - } - ); + config = (let + boolToString = v: if v then "true" else "false"; + optionalBoolean = name: val: + lib.optionalString (val != null) "${name} = ${boolToString val}"; + optionalInteger = name: val: + lib.optionalString (val != null) "${name} = ${toString val}"; + optionalString = name: val: + lib.optionalString (val != null) "${name} = ${val}"; + in mkIf cfg.enable { + home.packages = [ pkgs.termite ]; + xdg.configFile."termite/config".text = '' + [options] + ${optionalBoolean "allow_bold" cfg.allowBold} + ${optionalBoolean "audible_bell" cfg.audibleBell} + ${optionalString "browser" cfg.browser} + ${optionalBoolean "clickable_url" cfg.clickableUrl} + ${optionalString "cursor_blink" cfg.cursorBlink} + ${optionalString "cursor_shape" cfg.cursorShape} + ${optionalBoolean "dynamic_title" cfg.dynamicTitle} + ${optionalBoolean "filter_unmatched_urls" cfg.filterUnmatchedUrls} + ${optionalString "font" cfg.font} + ${optionalBoolean "fullscreen" cfg.fullscreen} + ${optionalString "geometry" cfg.geometry} + ${optionalString "icon_name" cfg.iconName} + ${optionalBoolean "modify_other_keys" cfg.modifyOtherKeys} + ${optionalBoolean "mouse_autohide" cfg.mouseAutohide} + ${optionalBoolean "scroll_on_keystroke" cfg.scrollOnKeystroke} + ${optionalBoolean "scroll_on_output" cfg.scrollOnOutput} + ${optionalInteger "scrollback_lines" cfg.scrollbackLines} + ${optionalString "scrollbar" cfg.scrollbar} + ${optionalBoolean "search_wrap" cfg.searchWrap} + ${optionalBoolean "size_hints" cfg.sizeHints} + ${optionalBoolean "urgent_on_bell" cfg.urgentOnBell} + + ${cfg.optionsExtra} + + [colors] + ${optionalString "background" cfg.backgroundColor} + ${optionalString "cursor" cfg.cursorColor} + ${optionalString "cursor_foreground" cfg.cursorForegroundColor} + ${optionalString "foreground" cfg.foregroundColor} + ${optionalString "foregroundBold" cfg.foregroundBoldColor} + ${optionalString "highlight" cfg.highlightColor} + + ${cfg.colorsExtra} + + [hints] + ${optionalString "active_background" cfg.hintsActiveBackgroundColor} + ${optionalString "active_foreground" cfg.hintsActiveForegroundColor} + ${optionalString "background" cfg.hintsBackgroundColor} + ${optionalString "border" cfg.hintsBorderColor} + ${optionalInteger "border_width" cfg.hintsBorderWidth} + ${optionalString "font" cfg.hintsFont} + ${optionalString "foreground" cfg.hintsForegroundColor} + ${optionalInteger "padding" cfg.hintsPadding} + ${optionalInteger "roundness" cfg.hintsRoundness} + + ${cfg.hintsExtra} + ''; + + programs.bash.initExtra = vteInitStr; + programs.zsh.initExtra = vteInitStr; + }); } diff --git a/home-manager/modules/programs/texlive.nix b/home-manager/modules/programs/texlive.nix index 0f8953e9f91..08a376d654a 100644 --- a/home-manager/modules/programs/texlive.nix +++ b/home-manager/modules/programs/texlive.nix @@ -8,9 +8,7 @@ let texlivePkgs = cfg.extraPackages pkgs.texlive; -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; options = { @@ -35,13 +33,11 @@ in }; config = mkIf cfg.enable { - assertions = [ - { - assertion = texlivePkgs != {}; - message = "Must provide at least one extra package in" - + " 'programs.texlive.extraPackages'."; - } - ]; + assertions = [{ + assertion = texlivePkgs != { }; + message = "Must provide at least one extra package in" + + " 'programs.texlive.extraPackages'."; + }]; home.packages = [ cfg.package ]; diff --git a/home-manager/modules/programs/urxvt.nix b/home-manager/modules/programs/urxvt.nix index 6f4eb3ff7ba..e4c72bfe272 100644 --- a/home-manager/modules/programs/urxvt.nix +++ b/home-manager/modules/programs/urxvt.nix @@ -6,9 +6,7 @@ let cfg = config.programs.urxvt; -in - -{ +in { options.programs.urxvt = { enable = mkEnableOption "rxvt-unicode terminal emulator"; @@ -21,14 +19,14 @@ in fonts = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; description = "List of fonts to be used."; example = [ "xft:Droid Sans Mono Nerd Font:size=9" ]; }; keybindings = mkOption { type = types.attrsOf types.str; - default = {}; + default = { }; description = "Mapping of keybindings to actions"; example = literalExample '' { @@ -41,7 +39,8 @@ in iso14755 = mkOption { type = types.bool; default = true; - description = "ISO14755 support for viewing and entering unicode characters."; + description = + "ISO14755 support for viewing and entering unicode characters."; }; scroll = { @@ -75,11 +74,12 @@ in floating = mkOption { type = types.bool; default = true; - description = "Whether to display an rxvt scrollbar without a trough."; + description = + "Whether to display an rxvt scrollbar without a trough."; }; }; }; - default = {}; + default = { }; description = "Scrollbar settings."; }; @@ -92,7 +92,8 @@ in keepPosition = mkOption { type = types.bool; default = true; - description = "Whether to keep a scroll position when TTY receives new lines."; + description = + "Whether to keep a scroll position when TTY receives new lines."; }; scrollOnKeystroke = mkOption { @@ -117,11 +118,12 @@ in shading = mkOption { type = types.ints.between 0 200; default = 100; - description = "Darken (0 .. 99) or lighten (101 .. 200) the transparent background."; + description = + "Darken (0 .. 99) or lighten (101 .. 200) the transparent background."; }; extraConfig = mkOption { - default = {}; + default = { }; type = types.attrs; description = "Additional configuration to add."; example = { "shading" = 15; }; @@ -145,12 +147,10 @@ in "URxvt.transparent" = cfg.transparent; "URxvt.shading" = cfg.shading; "URxvt.iso14755" = cfg.iso14755; - } // flip mapAttrs' cfg.keybindings (kb: action: - nameValuePair "URxvt.keysym.${kb}" action - ) // optionalAttrs (cfg.fonts != []) { - "URxvt.font" = concatStringsSep "," cfg.fonts; - } // flip mapAttrs' cfg.extraConfig (k: v: - nameValuePair "URxvt.${k}" v - ); + } // flip mapAttrs' cfg.keybindings + (kb: action: nameValuePair "URxvt.keysym.${kb}" action) + // optionalAttrs (cfg.fonts != [ ]) { + "URxvt.font" = concatStringsSep "," cfg.fonts; + } // flip mapAttrs' cfg.extraConfig (k: v: nameValuePair "URxvt.${k}" v); }; } diff --git a/home-manager/modules/programs/vim.nix b/home-manager/modules/programs/vim.nix index a14a9562ac1..39826a9a5d6 100644 --- a/home-manager/modules/programs/vim.nix +++ b/home-manager/modules/programs/vim.nix @@ -31,43 +31,36 @@ let }; vimSettingsType = types.submodule { - options = - let - opt = name: type: mkOption { + options = let + opt = name: type: + mkOption { type = types.nullOr type; default = null; visible = false; }; - in - mapAttrs opt knownSettings; + in mapAttrs opt knownSettings; }; setExpr = name: value: let - v = - if isBool value then (if value then "" else "no") + name - else - "${name}=${ - if isList value - then concatStringsSep "," value - else toString value - }"; - in - optionalString (value != null) ("set " + v); - - plugins = - let - vpkgs = pkgs.vimPlugins; - getPkg = p: - if isDerivation p - then [ p ] - else optional (isString p && hasAttr p vpkgs) vpkgs.${p}; - in - concatMap getPkg cfg.plugins; - -in - -{ + v = if isBool value then + (if value then "" else "no") + name + else + "${name}=${ + if isList value then concatStringsSep "," value else toString value + }"; + in optionalString (value != null) ("set " + v); + + plugins = let + vpkgs = pkgs.vimPlugins; + getPkg = p: + if isDerivation p then + [ p ] + else + optional (isString p && hasAttr p vpkgs) vpkgs.${p}; + in concatMap getPkg cfg.plugins; + +in { options = { programs.vim = { enable = mkEnableOption "Vim"; @@ -75,7 +68,7 @@ in plugins = mkOption { type = with types; listOf (either str package); default = defaultPlugins; - example = literalExample ''[ pkgs.vimPlugins.YankRing ]''; + example = literalExample "[ pkgs.vimPlugins.YankRing ]"; description = '' List of vim plugins to install. To get a list of supported plugins run: <command>nix-env -f '<nixpkgs>' -qaP -A vimPlugins</command>. @@ -88,7 +81,7 @@ in settings = mkOption { type = vimSettingsType; - default = {}; + default = { }; example = literalExample '' { expandtab = true; @@ -102,14 +95,12 @@ in options. <informaltable frame="none"><tgroup cols="1"><tbody> - ${concatStringsSep "\n" ( - mapAttrsToList (n: v: '' - <row> - <entry><varname>${n}</varname></entry> - <entry>${v.description}</entry> - </row> - '') knownSettings - )} + ${concatStringsSep "\n" (mapAttrsToList (n: v: '' + <row> + <entry><varname>${n}</varname></entry> + <entry>${v.description}</entry> + </row> + '') knownSettings)} </tbody></tgroup></informaltable> See the Vim documentation for detailed descriptions of these @@ -136,56 +127,45 @@ in }; }; - config = ( - let - customRC = '' - ${concatStringsSep "\n" ( - filter (v: v != "") ( - mapAttrsToList setExpr ( - builtins.intersectAttrs knownSettings cfg.settings)))} + config = (let + customRC = '' + ${concatStringsSep "\n" (filter (v: v != "") (mapAttrsToList setExpr + (builtins.intersectAttrs knownSettings cfg.settings)))} - ${cfg.extraConfig} - ''; + ${cfg.extraConfig} + ''; - vim = pkgs.vim_configurable.customize { - name = "vim"; - vimrcConfig = { - inherit customRC; + vim = pkgs.vim_configurable.customize { + name = "vim"; + vimrcConfig = { + inherit customRC; - packages.home-manager.start = plugins; - }; + packages.home-manager.start = plugins; }; - in - mkIf cfg.enable { - assertions = - let - packagesNotFound = filter (p: isString p && (!hasAttr p pkgs.vimPlugins)) cfg.plugins; - in - [ - { - assertion = packagesNotFound == []; - message = "Following VIM plugin not found in pkgs.vimPlugins: ${ - concatMapStringsSep ", " (p: ''"${p}"'') packagesNotFound - }"; - } - ]; - - warnings = - let - stringPlugins = filter isString cfg.plugins; - in - optional (stringPlugins != []) '' - Specifying VIM plugins using strings is deprecated, found ${ - concatMapStringsSep ", " (p: ''"${p}"'') stringPlugins - } as strings. - ''; - - home.packages = [ cfg.package ]; - - programs.vim = { - package = vim; - plugins = defaultPlugins; - }; - } - ); + }; + in mkIf cfg.enable { + assertions = let + packagesNotFound = + filter (p: isString p && (!hasAttr p pkgs.vimPlugins)) cfg.plugins; + in [{ + assertion = packagesNotFound == [ ]; + message = "Following VIM plugin not found in pkgs.vimPlugins: ${ + concatMapStringsSep ", " (p: ''"${p}"'') packagesNotFound + }"; + }]; + + warnings = let stringPlugins = filter isString cfg.plugins; + in optional (stringPlugins != [ ]) '' + Specifying VIM plugins using strings is deprecated, found ${ + concatMapStringsSep ", " (p: ''"${p}"'') stringPlugins + } as strings. + ''; + + home.packages = [ cfg.package ]; + + programs.vim = { + package = vim; + plugins = defaultPlugins; + }; + }); } diff --git a/home-manager/modules/programs/vscode.nix b/home-manager/modules/programs/vscode.nix index fdaea0ba4fe..cf7ac722210 100644 --- a/home-manager/modules/programs/vscode.nix +++ b/home-manager/modules/programs/vscode.nix @@ -11,7 +11,13 @@ let configDir = { "vscode" = "Code"; "vscode-insiders" = "Code - Insiders"; - "vscodium" = "Codium"; + "vscodium" = "VSCodium"; + }.${vscodePname}; + + extensionDir = { + "vscode" = "vscode"; + "vscode-insiders" = "vscode-insiders"; + "vscodium" = "vscode-oss"; }.${vscodePname}; configFilePath = @@ -21,7 +27,7 @@ let "${config.xdg.configHome}/${configDir}/User/settings.json"; # TODO: On Darwin where are the extensions? - extensionPath = ".${vscodePname}/extensions"; + extensionPath = ".${extensionDir}/extensions"; in { @@ -71,18 +77,24 @@ in # Adapted from https://discourse.nixos.org/t/vscode-extensions-setup/1801/2 home.file = let - toPaths = p: - # Links every dir in p to the extension path. - mapAttrsToList (k: v: - { - "${extensionPath}/${k}".source = "${p}/${k}"; - }) (builtins.readDir p); + toPaths = path: + let + p = "${path}/share/vscode/extensions"; + in + # Links every dir in p to the extension path. + mapAttrsToList (k: v: + { + "${extensionPath}/${k}".source = "${p}/${k}"; + }) (builtins.readDir p); toSymlink = concatMap toPaths cfg.extensions; in foldr (a: b: a // b) { - "${configFilePath}".text = builtins.toJSON cfg.userSettings; + "${configFilePath}" = + mkIf (cfg.userSettings != {}) { + text = builtins.toJSON cfg.userSettings; + }; } toSymlink; }; diff --git a/home-manager/modules/programs/vscode/haskell.nix b/home-manager/modules/programs/vscode/haskell.nix index c8ea10d473e..ee84e707102 100644 --- a/home-manager/modules/programs/vscode/haskell.nix +++ b/home-manager/modules/programs/vscode/haskell.nix @@ -7,8 +7,8 @@ let cfg = config.programs.vscode.haskell; defaultHieNixExe = hie-nix.hies + "/bin/hie-wrapper"; - defaultHieNixExeText = literalExample - "\"\${pkgs.hie-nix.hies}/bin/hie-wrapper\""; + defaultHieNixExeText = + literalExample ''"''${pkgs.hie-nix.hies}/bin/hie-wrapper"''; hie-nix = pkgs.hie-nix or (abort '' vscode.haskell: pkgs.hie-nix missing. Please add an overlay such as: @@ -21,9 +21,7 @@ let ] ''; -in - -{ +in { options.programs.vscode.haskell = { enable = mkEnableOption "Haskell integration for Visual Studio Code"; @@ -57,10 +55,8 @@ in }; programs.vscode.extensions = - [ - pkgs.vscode-extensions.justusadam.language-haskell - ] + [ pkgs.vscode-extensions.justusadam.language-haskell ] ++ lib.optional cfg.hie.enable - pkgs.vscode-extensions.alanz.vscode-hie-server; + pkgs.vscode-extensions.alanz.vscode-hie-server; }; } diff --git a/home-manager/modules/programs/z-lua.nix b/home-manager/modules/programs/z-lua.nix index 245eff6a51e..d722ac6a2f0 100644 --- a/home-manager/modules/programs/z-lua.nix +++ b/home-manager/modules/programs/z-lua.nix @@ -7,16 +7,14 @@ let cfg = config.programs.z-lua; aliases = { - zz = "z -c"; # restrict matches to subdirs of $PWD - zi = "z -i"; # cd with interactive selection - zf = "z -I"; # use fzf to select in multiple matches - zb = "z -b"; # quickly cd to the parent directory - zh = "z -I -t ."; # fzf + zz = "z -c"; # restrict matches to subdirs of $PWD + zi = "z -i"; # cd with interactive selection + zf = "z -I"; # use fzf to select in multiple matches + zb = "z -b"; # quickly cd to the parent directory + zh = "z -I -t ."; # fzf }; -in - -{ +in { meta.maintainers = [ maintainers.marsam ]; options.programs.z-lua = { @@ -24,7 +22,7 @@ in options = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; example = [ "enhanced" "once" "fzf" ]; description = '' List of options to pass to z.lua. @@ -68,15 +66,21 @@ in home.packages = [ pkgs.z-lua ]; programs.bash.initExtra = mkIf cfg.enableBashIntegration '' - eval "$(${pkgs.z-lua}/bin/z --init bash ${concatStringsSep " " cfg.options})" + eval "$(${pkgs.z-lua}/bin/z --init bash ${ + concatStringsSep " " cfg.options + })" ''; programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' - eval "$(${pkgs.z-lua}/bin/z --init zsh ${concatStringsSep " " cfg.options})" + eval "$(${pkgs.z-lua}/bin/z --init zsh ${ + concatStringsSep " " cfg.options + })" ''; programs.fish.shellInit = mkIf cfg.enableFishIntegration '' - source (${pkgs.z-lua}/bin/z --init fish ${concatStringsSep " " cfg.options} | psub) + source (${pkgs.z-lua}/bin/z --init fish ${ + concatStringsSep " " cfg.options + } | psub) ''; programs.bash.shellAliases = mkIf cfg.enableAliases aliases; diff --git a/home-manager/modules/programs/zathura.nix b/home-manager/modules/programs/zathura.nix index f01bd501c39..d9f3c1af1fd 100644 --- a/home-manager/modules/programs/zathura.nix +++ b/home-manager/modules/programs/zathura.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, ...}: +{ config, lib, pkgs, ... }: with lib; @@ -9,14 +9,10 @@ let formatLine = n: v: let formatValue = v: - if isBool v then (if v then "true" else "false") - else toString v; - in - "set ${n}\t\"${formatValue v}\""; + if isBool v then (if v then "true" else "false") else toString v; + in ''set ${n} "${formatValue v}"''; -in - -{ +in { meta.maintainers = [ maintainers.rprospero ]; options.programs.zathura = { @@ -25,7 +21,7 @@ in focused on keyboard interaction''; options = mkOption { - default = {}; + default = { }; type = with types; attrsOf (either str (either bool int)); description = '' Add <option>:set</option> command options to zathura and make @@ -36,7 +32,10 @@ in </citerefentry> for the full list of options. ''; - example = { default-bg = "#000000"; default-fg = "#FFFFFF"; }; + example = { + default-bg = "#000000"; + default-fg = "#FFFFFF"; + }; }; extraConfig = mkOption { @@ -52,10 +51,8 @@ in config = mkIf cfg.enable { home.packages = [ pkgs.zathura ]; - xdg.configFile."zathura/zathurarc".text = - concatStringsSep "\n" ([] - ++ optional (cfg.extraConfig != "") cfg.extraConfig - ++ mapAttrsToList formatLine cfg.options - ) + "\n"; + xdg.configFile."zathura/zathurarc".text = concatStringsSep "\n" ([ ] + ++ optional (cfg.extraConfig != "") cfg.extraConfig + ++ mapAttrsToList formatLine cfg.options) + "\n"; }; } diff --git a/home-manager/modules/programs/zsh.nix b/home-manager/modules/programs/zsh.nix index ffe5f4960b6..c5694e1f704 100644 --- a/home-manager/modules/programs/zsh.nix +++ b/home-manager/modules/programs/zsh.nix @@ -26,6 +26,8 @@ let vicmd = "bindkey -a"; }; + stateVersion = config.home.stateVersion; + historyModule = types.submodule ({ config, ... }: { options = { size = mkOption { @@ -43,8 +45,10 @@ let path = mkOption { type = types.str; - default = relToDotDir ".zsh_history"; - defaultText = ".zsh_history"; + default = if versionAtLeast stateVersion "20.03" + then "$HOME/.zsh_history" + else relToDotDir ".zsh_history"; + example = literalExample ''"''${config.xdg.dataHome}/zsh/zsh_history"''; description = "History file location"; }; @@ -57,6 +61,15 @@ let ''; }; + ignoreSpace = mkOption { + type = types.bool; + default = true; + description = '' + Do not enter command lines into the history list + if the first character is a space. + ''; + }; + expireDuplicatesFirst = mkOption { type = types.bool; default = false; @@ -402,11 +415,15 @@ in # History options should be set in .zshrc and after oh-my-zsh sourcing. # See https://github.com/rycee/home-manager/issues/177. HISTSIZE="${toString cfg.history.size}" - HISTFILE="$HOME/${cfg.history.path}" SAVEHIST="${toString cfg.history.save}" + ${if versionAtLeast config.home.stateVersion "20.03" + then ''HISTFILE="${cfg.history.path}"'' + else ''HISTFILE="$HOME/${cfg.history.path}"''} + mkdir -p "$(dirname "$HISTFILE")" setopt HIST_FCNTL_LOCK ${if cfg.history.ignoreDups then "setopt" else "unsetopt"} HIST_IGNORE_DUPS + ${if cfg.history.ignoreSpace then "setopt" else "unsetopt"} HIST_IGNORE_SPACE ${if cfg.history.expireDuplicatesFirst then "setopt" else "unsetopt"} HIST_EXPIRE_DUPS_FIRST ${if cfg.history.share then "setopt" else "unsetopt"} SHARE_HISTORY ${if cfg.history.extended then "setopt" else "unsetopt"} EXTENDED_HISTORY @@ -430,10 +447,10 @@ in # but allow the user to opt out. programs.zsh.enableCompletion = mkDefault true; - home.file = map (plugin: { - target = "${pluginsDir}/${plugin.name}"; - source = plugin.src; - }) cfg.plugins; + home.file = + foldl' (a: b: a // b) {} + (map (plugin: { "${pluginsDir}/${plugin.name}".source = plugin.src; }) + cfg.plugins); }) ]); } diff --git a/home-manager/modules/services/blueman-applet.nix b/home-manager/modules/services/blueman-applet.nix index 186dc7454f9..5a57acccc27 100644 --- a/home-manager/modules/services/blueman-applet.nix +++ b/home-manager/modules/services/blueman-applet.nix @@ -5,33 +5,32 @@ with lib; { options = { services.blueman-applet = { - enable = mkEnableOption '' - Blueman applet. - - Note, for the applet to work, 'blueman' package should also be installed system-wide - since it requires running 'blueman-mechanism' service activated via dbus. - You can add it to the dbus packages in system configuration: - - services.dbus.packages = [ pkgs.blueman ]; - ''; + enable = mkEnableOption "" // { + description = '' + Whether to enable the Blueman applet. + </para><para> + Note, for the applet to work, the 'blueman' service should + be enabled system-wide. You can enable it in the system + configuration using + <programlisting language="nix"> + services.blueman.enable = true; + </programlisting> + ''; + }; }; }; config = mkIf config.services.blueman-applet.enable { systemd.user.services.blueman-applet = { - Unit = { - Description = "Blueman applet"; - After = [ "graphical-session-pre.target" ]; - PartOf = [ "graphical-session.target" ]; - }; + Unit = { + Description = "Blueman applet"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; - Service = { - ExecStart = "${pkgs.blueman}/bin/blueman-applet"; - }; + Service = { ExecStart = "${pkgs.blueman}/bin/blueman-applet"; }; }; }; } diff --git a/home-manager/modules/services/cbatticon.nix b/home-manager/modules/services/cbatticon.nix new file mode 100644 index 00000000000..0de69c5f9ec --- /dev/null +++ b/home-manager/modules/services/cbatticon.nix @@ -0,0 +1,118 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.cbatticon; + + package = pkgs.cbatticon; + + makeCommand = commandName: commandArg: + optional (commandArg != null) + (let cmd = pkgs.writeShellScript commandName commandArg; + in "--${commandName} ${cmd}"); + + commandLine = concatStringsSep " " ([ "${package}/bin/cbatticon" ] + ++ makeCommand "command-critical-level" cfg.commandCriticalLevel + ++ makeCommand "command-left-click" cfg.commandLeftClick + ++ optional (cfg.iconType != null) "--icon-type ${cfg.iconType}" + ++ optional (cfg.lowLevelPercent != null) + "--low-level ${toString cfg.lowLevelPercent}" + ++ optional (cfg.criticalLevelPercent != null) + "--critical-level ${toString cfg.criticalLevelPercent}" + ++ optional (cfg.updateIntervalSeconds != null) + "--update-interval ${toString cfg.updateIntervalSeconds}" + ++ optional (cfg.hideNotification != null && cfg.hideNotification) + "--hide-notification"); + +in { + meta.maintainers = [ maintainers.pmiddend ]; + + options = { + services.cbatticon = { + enable = mkEnableOption "cbatticon"; + + commandCriticalLevel = mkOption { + type = types.nullOr types.lines; + default = null; + example = '' + notify-send "battery critical!" + ''; + description = '' + Command to execute when the critical battery level is reached. + ''; + }; + + commandLeftClick = mkOption { + type = types.nullOr types.lines; + default = null; + description = '' + Command to execute when left clicking on the tray icon. + ''; + }; + + iconType = mkOption { + type = + types.nullOr (types.enum [ "standard" "notification" "symbolic" ]); + default = null; + example = "symbolic"; + description = "Icon type to display in the system tray."; + }; + + lowLevelPercent = mkOption { + type = types.nullOr (types.ints.between 0 100); + default = null; + example = 20; + description = '' + Low level percentage of the battery in percent (without the + percent symbol). + ''; + }; + + criticalLevelPercent = mkOption { + type = types.nullOr (types.ints.between 0 100); + default = null; + example = 5; + description = '' + Critical level percentage of the battery in percent (without + the percent symbol). + ''; + }; + + updateIntervalSeconds = mkOption { + type = types.nullOr types.ints.positive; + default = null; + example = 5; + description = '' + Number of seconds between updates of the battery information. + ''; + }; + + hideNotification = mkOption { + type = types.nullOr types.bool; + default = null; + description = "Hide the notification popups."; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ package ]; + + systemd.user.services.cbatticon = { + Unit = { + Description = "cbatticon system tray battery icon"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { + ExecStart = commandLine; + Restart = "on-abort"; + }; + }; + }; +} diff --git a/home-manager/modules/services/compton.nix b/home-manager/modules/services/compton.nix index c227f0a8c07..c5b96af34da 100644 --- a/home-manager/modules/services/compton.nix +++ b/home-manager/modules/services/compton.nix @@ -7,44 +7,41 @@ let cfg = config.services.compton; - configFile = pkgs.writeText "compton.conf" - (optionalString cfg.fade '' - # fading - fading = true; - fade-delta = ${toString cfg.fadeDelta}; - fade-in-step = ${elemAt cfg.fadeSteps 0}; - fade-out-step = ${elemAt cfg.fadeSteps 1}; - fade-exclude = ${toJSON cfg.fadeExclude}; - '' + - optionalString cfg.shadow '' - - # shadows - shadow = true; - shadow-offset-x = ${toString (elemAt cfg.shadowOffsets 0)}; - shadow-offset-y = ${toString (elemAt cfg.shadowOffsets 1)}; - shadow-opacity = ${cfg.shadowOpacity}; - shadow-exclude = ${toJSON cfg.shadowExclude}; - no-dock-shadow = ${toJSON cfg.noDockShadow}; - no-dnd-shadow = ${toJSON cfg.noDNDShadow}; - '' + - optionalString cfg.blur '' - - # blur - blur-background = true; - blur-background-exclude = ${toJSON cfg.blurExclude}; - '' + '' - - # opacity - active-opacity = ${cfg.activeOpacity}; - inactive-opacity = ${cfg.inactiveOpacity}; - menu-opacity = ${cfg.menuOpacity}; - opacity-rule = ${toJSON cfg.opacityRule}; - - # other options - backend = ${toJSON cfg.backend}; - vsync = ${toJSON cfg.vSync}; - refresh-rate = ${toString cfg.refreshRate}; - '' + cfg.extraOptions); + configFile = pkgs.writeText "compton.conf" (optionalString cfg.fade '' + # fading + fading = true; + fade-delta = ${toString cfg.fadeDelta}; + fade-in-step = ${elemAt cfg.fadeSteps 0}; + fade-out-step = ${elemAt cfg.fadeSteps 1}; + fade-exclude = ${toJSON cfg.fadeExclude}; + '' + optionalString cfg.shadow '' + + # shadows + shadow = true; + shadow-offset-x = ${toString (elemAt cfg.shadowOffsets 0)}; + shadow-offset-y = ${toString (elemAt cfg.shadowOffsets 1)}; + shadow-opacity = ${cfg.shadowOpacity}; + shadow-exclude = ${toJSON cfg.shadowExclude}; + no-dock-shadow = ${toJSON cfg.noDockShadow}; + no-dnd-shadow = ${toJSON cfg.noDNDShadow}; + '' + optionalString cfg.blur '' + + # blur + blur-background = true; + blur-background-exclude = ${toJSON cfg.blurExclude}; + '' + '' + + # opacity + active-opacity = ${cfg.activeOpacity}; + inactive-opacity = ${cfg.inactiveOpacity}; + menu-opacity = ${cfg.menuOpacity}; + opacity-rule = ${toJSON cfg.opacityRule}; + + # other options + backend = ${toJSON cfg.backend}; + vsync = ${toJSON cfg.vSync}; + refresh-rate = ${toString cfg.refreshRate}; + '' + cfg.extraOptions); in { @@ -61,11 +58,8 @@ in { blurExclude = mkOption { type = types.listOf types.str; - default = []; - example = [ - "class_g = 'slop'" - "class_i = 'polybar'" - ]; + default = [ ]; + example = [ "class_g = 'slop'" "class_i = 'polybar'" ]; description = '' List of windows to exclude background blur. See the @@ -105,12 +99,8 @@ in { fadeExclude = mkOption { type = types.listOf types.str; - default = []; - example = [ - "window_type *= 'menu'" - "name ~= 'Firefox$'" - "focused = 1" - ]; + default = [ ]; + example = [ "window_type *= 'menu'" "name ~= 'Firefox$'" "focused = 1" ]; description = '' List of conditions of windows that should not be faded. See the @@ -150,12 +140,8 @@ in { shadowExclude = mkOption { type = types.listOf types.str; - default = []; - example = [ - "window_type *= 'menu'" - "name ~= 'Firefox$'" - "focused = 1" - ]; + default = [ ]; + example = [ "window_type *= 'menu'" "name ~= 'Firefox$'" "focused = 1" ]; description = '' List of conditions of windows that should have no shadow. See the @@ -212,11 +198,8 @@ in { opacityRule = mkOption { type = types.listOf types.str; - default = []; - example = [ - "87:class_i ?= 'scratchpad'" - "91:class_i ?= 'xterm'" - ]; + default = [ ]; + example = [ "87:class_i ?= 'scratchpad'" "91:class_i ?= 'xterm'" ]; description = '' List of opacity rules. See the @@ -256,7 +239,7 @@ in { default = 0; example = 60; description = '' - Screen refresh rate (0 = automatically detect). + Screen refresh rate (0 = automatically detect). ''; }; @@ -293,16 +276,13 @@ in { PartOf = [ "graphical-session.target" ]; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { ExecStart = "${cfg.package}/bin/compton --config ${configFile}"; Restart = "always"; RestartSec = 3; - } - // optionalAttrs (cfg.backend == "glx") { + } // optionalAttrs (cfg.backend == "glx") { # Temporarily fixes corrupt colours with Mesa 18. Environment = [ "allow_rgb10_configs=false" ]; }; diff --git a/home-manager/modules/services/dunst.nix b/home-manager/modules/services/dunst.nix index 96b1f71a2fa..d32e875137b 100644 --- a/home-manager/modules/services/dunst.nix +++ b/home-manager/modules/services/dunst.nix @@ -6,17 +6,19 @@ let cfg = config.services.dunst; - eitherStrBoolIntList = with types; either str (either bool (either int (listOf str))); + eitherStrBoolIntList = with types; + either str (either bool (either int (listOf str))); toDunstIni = generators.toINI { mkKeyValue = key: value: - let - value' = - if isBool value then (if value then "yes" else "no") - else if isString value then "\"${value}\"" - else toString value; - in - "${key}=${value'}"; + let + value' = if isBool value then + (if value then "yes" else "no") + else if isString value then + ''"${value}"'' + else + toString value; + in "${key}=${value'}"; }; themeType = types.submodule { @@ -48,9 +50,7 @@ let size = "32x32"; }; -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; options = { @@ -65,7 +65,7 @@ in settings = mkOption { type = with types; attrsOf (attrsOf eitherStrBoolIntList); - default = {}; + default = { }; description = "Configuration written to ~/.config/dunstrc"; example = literalExample '' { @@ -87,86 +87,73 @@ in }; }; - config = mkIf cfg.enable ( - mkMerge [ - { - xdg.dataFile."dbus-1/services/org.knopwob.dunst.service".source = - "${pkgs.dunst}/share/dbus-1/services/org.knopwob.dunst.service"; - - services.dunst.settings.global.icon_path = - let - useCustomTheme = - cfg.iconTheme.package != hicolorTheme.package - || cfg.iconTheme.name != hicolorTheme.name - || cfg.iconTheme.size != hicolorTheme.size; - - basePaths = [ - "/run/current-system/sw" - config.home.profileDirectory - cfg.iconTheme.package - ] ++ optional useCustomTheme hicolorTheme.package; - - themes = - [ - cfg.iconTheme - ] ++ optional useCustomTheme ( - hicolorTheme // { size = cfg.iconTheme.size; } - ); - - categories = [ - "actions" - "animations" - "apps" - "categories" - "devices" - "emblems" - "emotes" - "filesystem" - "intl" - "mimetypes" - "places" - "status" - "stock" - ]; - in - concatStringsSep ":" ( - concatMap (theme: - concatMap (basePath: - map (category: - "${basePath}/share/icons/${theme.name}/${theme.size}/${category}" - ) categories - ) basePaths - ) themes - ); - - systemd.user.services.dunst = { - Unit = { - Description = "Dunst notification daemon"; - After = [ "graphical-session-pre.target" ]; - PartOf = [ "graphical-session.target" ]; - }; - - Service = { - Type = "dbus"; - BusName = "org.freedesktop.Notifications"; - ExecStart = "${pkgs.dunst}/bin/dunst"; - }; + config = mkIf cfg.enable (mkMerge [ + { + xdg.dataFile."dbus-1/services/org.knopwob.dunst.service".source = + "${pkgs.dunst}/share/dbus-1/services/org.knopwob.dunst.service"; + + services.dunst.settings.global.icon_path = let + useCustomTheme = cfg.iconTheme.package != hicolorTheme.package + || cfg.iconTheme.name != hicolorTheme.name || cfg.iconTheme.size + != hicolorTheme.size; + + basePaths = [ + "/run/current-system/sw" + config.home.profileDirectory + cfg.iconTheme.package + ] ++ optional useCustomTheme hicolorTheme.package; + + themes = [ cfg.iconTheme ] ++ optional useCustomTheme + (hicolorTheme // { size = cfg.iconTheme.size; }); + + categories = [ + "actions" + "animations" + "apps" + "categories" + "devices" + "emblems" + "emotes" + "filesystem" + "intl" + "mimetypes" + "places" + "status" + "stock" + ]; + in concatStringsSep ":" (concatMap (theme: + concatMap (basePath: + map (category: + "${basePath}/share/icons/${theme.name}/${theme.size}/${category}") + categories) basePaths) themes); + + systemd.user.services.dunst = { + Unit = { + Description = "Dunst notification daemon"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; }; - } - - (mkIf (cfg.settings != {}) { - xdg.configFile."dunst/dunstrc" = { - text = toDunstIni cfg.settings; - onChange = '' - pkillVerbose="" - if [[ -v VERBOSE ]]; then - pkillVerbose="-e" - fi - $DRY_RUN_CMD ${pkgs.procps}/bin/pkill -u $USER $pkillVerbose dunst || true - unset pkillVerbose - ''; + + Service = { + Type = "dbus"; + BusName = "org.freedesktop.Notifications"; + ExecStart = "${pkgs.dunst}/bin/dunst"; }; - }) - ] - ); + }; + } + + (mkIf (cfg.settings != { }) { + xdg.configFile."dunst/dunstrc" = { + text = toDunstIni cfg.settings; + onChange = '' + pkillVerbose="" + if [[ -v VERBOSE ]]; then + pkillVerbose="-e" + fi + $DRY_RUN_CMD ${pkgs.procps}/bin/pkill -u $USER $pkillVerbose dunst || true + unset pkillVerbose + ''; + }; + }) + ]); } diff --git a/home-manager/modules/services/dwm-status.nix b/home-manager/modules/services/dwm-status.nix index 2b010cec1e1..7a19e5e5fc9 100644 --- a/home-manager/modules/services/dwm-status.nix +++ b/home-manager/modules/services/dwm-status.nix @@ -10,9 +10,8 @@ let configText = builtins.toJSON ({ inherit (cfg) order; } // cfg.extraConfig); configFile = pkgs.writeText "dwm-status.json" configText; -in -{ +in { options = { services.dwm-status = { enable = mkEnableOption "dwm-status user service"; @@ -32,7 +31,7 @@ in extraConfig = mkOption { type = types.attrs; - default = {}; + default = { }; example = literalExample '' { separator = "#"; @@ -58,13 +57,9 @@ in PartOf = [ "graphical-session.target" ]; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; - Service = { - ExecStart = "${cfg.package}/bin/dwm-status ${configFile}"; - }; + Service = { ExecStart = "${cfg.package}/bin/dwm-status ${configFile}"; }; }; }; } diff --git a/home-manager/modules/services/emacs.nix b/home-manager/modules/services/emacs.nix index 33d6871c61b..5b0e88db72d 100644 --- a/home-manager/modules/services/emacs.nix +++ b/home-manager/modules/services/emacs.nix @@ -8,26 +8,21 @@ let emacsCfg = config.programs.emacs; emacsBinPath = "${emacsCfg.finalPackage}/bin"; -in - -{ - options.services.emacs = { - enable = mkEnableOption "the Emacs daemon"; - }; +in { + options.services.emacs = { enable = mkEnableOption "the Emacs daemon"; }; config = mkIf cfg.enable { - assertions = [ - { - assertion = emacsCfg.enable; - message = "The Emacs service module requires" - + " 'programs.emacs.enable = true'."; - } - ]; + assertions = [{ + assertion = emacsCfg.enable; + message = "The Emacs service module requires" + + " 'programs.emacs.enable = true'."; + }]; systemd.user.services.emacs = { Unit = { Description = "Emacs: the extensible, self-documenting text editor"; - Documentation = "info:emacs man:emacs(1) https://gnu.org/software/emacs/"; + Documentation = + "info:emacs man:emacs(1) https://gnu.org/software/emacs/"; # Avoid killing the Emacs session, which may be full of # unsaved buffers. @@ -35,14 +30,13 @@ in }; Service = { - ExecStart = "${pkgs.runtimeShell} -l -c 'exec ${emacsBinPath}/emacs --fg-daemon'"; + ExecStart = + "${pkgs.runtimeShell} -l -c 'exec ${emacsBinPath}/emacs --fg-daemon'"; ExecStop = "${emacsBinPath}/emacsclient --eval '(kill-emacs)'"; Restart = "on-failure"; }; - Install = { - WantedBy = [ "default.target" ]; - }; + Install = { WantedBy = [ "default.target" ]; }; }; }; } diff --git a/home-manager/modules/services/flameshot.nix b/home-manager/modules/services/flameshot.nix index 87b494d0fcd..c8659d51d1e 100644 --- a/home-manager/modules/services/flameshot.nix +++ b/home-manager/modules/services/flameshot.nix @@ -7,16 +7,10 @@ let cfg = config.services.flameshot; package = pkgs.flameshot; -in - -{ +in { meta.maintainers = [ maintainers.hamhut1066 ]; - options = { - services.flameshot = { - enable = mkEnableOption "Flameshot"; - }; - }; + options = { services.flameshot = { enable = mkEnableOption "Flameshot"; }; }; config = mkIf cfg.enable { home.packages = [ package ]; @@ -33,9 +27,7 @@ in PartOf = [ "graphical-session.target" ]; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { Environment = "PATH=${config.home.profileDirectory}/bin"; diff --git a/home-manager/modules/services/getmail.nix b/home-manager/modules/services/getmail.nix index 46d4c1752d4..e7a1b1a4627 100644 --- a/home-manager/modules/services/getmail.nix +++ b/home-manager/modules/services/getmail.nix @@ -6,17 +6,19 @@ let cfg = config.services.getmail; - accounts = filter (a: a.getmail.enable) - (attrValues config.accounts.email.accounts); + accounts = + filter (a: a.getmail.enable) (attrValues config.accounts.email.accounts); # Note: The getmail service does not expect a path, but just the filename! - renderConfigFilepath = a: if a.primary then "getmailrc" else "getmail${a.name}"; - configFiles = concatMapStringsSep " " (a: " --rcfile ${renderConfigFilepath a}") accounts; -in -{ + renderConfigFilepath = a: + if a.primary then "getmailrc" else "getmail${a.name}"; + configFiles = + concatMapStringsSep " " (a: " --rcfile ${renderConfigFilepath a}") accounts; +in { options = { services.getmail = { - enable = mkEnableOption "the getmail systemd service to automatically retrieve mail"; + enable = mkEnableOption + "the getmail systemd service to automatically retrieve mail"; frequency = mkOption { type = types.str; @@ -36,25 +38,17 @@ in config = mkIf cfg.enable { systemd.user.services.getmail = { - Unit = { - Description = "getmail email fetcher"; - }; - Service = { - ExecStart = "${pkgs.getmail}/bin/getmail ${configFiles}"; - }; + Unit = { Description = "getmail email fetcher"; }; + Service = { ExecStart = "${pkgs.getmail}/bin/getmail ${configFiles}"; }; }; systemd.user.timers.getmail = { - Unit = { - Description = "getmail email fetcher"; - }; + Unit = { Description = "getmail email fetcher"; }; Timer = { OnCalendar = "${cfg.frequency}"; Unit = "getmail.service"; }; - Install = { - WantedBy = [ "timers.target" ]; - }; + Install = { WantedBy = [ "timers.target" ]; }; }; }; diff --git a/home-manager/modules/services/gnome-keyring.nix b/home-manager/modules/services/gnome-keyring.nix index 4ca6c7cacf2..6d8317dcffc 100644 --- a/home-manager/modules/services/gnome-keyring.nix +++ b/home-manager/modules/services/gnome-keyring.nix @@ -6,9 +6,7 @@ let cfg = config.services.gnome-keyring; -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; options = { @@ -16,8 +14,8 @@ in enable = mkEnableOption "GNOME Keyring"; components = mkOption { - type = types.listOf (types.enum ["pkcs11" "secrets" "ssh"]); - default = []; + type = types.listOf (types.enum [ "pkcs11" "secrets" "ssh" ]); + default = [ ]; description = '' The GNOME keyring components to start. If empty then the default set of components will be started. @@ -34,22 +32,15 @@ in }; Service = { - ExecStart = - let - args = concatStringsSep " " ( - [ "--start" "--foreground" ] - ++ optional (cfg.components != []) ( - "--components=" + concatStringsSep "," cfg.components - ) - ); - in - "${pkgs.gnome3.gnome_keyring}/bin/gnome-keyring-daemon ${args}"; + ExecStart = let + args = concatStringsSep " " ([ "--start" "--foreground" ] + ++ optional (cfg.components != [ ]) + ("--components=" + concatStringsSep "," cfg.components)); + in "${pkgs.gnome3.gnome_keyring}/bin/gnome-keyring-daemon ${args}"; Restart = "on-abort"; }; - Install = { - WantedBy = [ "graphical-session-pre.target" ]; - }; + Install = { WantedBy = [ "graphical-session-pre.target" ]; }; }; }; } diff --git a/home-manager/modules/services/gpg-agent.nix b/home-manager/modules/services/gpg-agent.nix index 5dc942fef63..16a4723fea7 100644 --- a/home-manager/modules/services/gpg-agent.nix +++ b/home-manager/modules/services/gpg-agent.nix @@ -129,6 +129,26 @@ in configuration file. ''; }; + + pinentryFlavor = mkOption { + type = types.nullOr (types.enum pkgs.pinentry.flavors); + example = "gnome3"; + default = "gtk2"; + description = '' + Which pinentry interface to use. If not + <literal>null</literal>, it sets + <option>pinentry-program</option> in + <filename>gpg-agent.conf</filename>. Beware that + <literal>pinentry-gnome3</literal> may not work on non-Gnome + systems. You can fix it by adding the following to your + system configuration: + <programlisting language="nix"> + services.dbus.packages = [ pkgs.gcr ]; + </programlisting> + For this reason, the default is <literal>gtk2</literal> for + now. + ''; + }; }; }; @@ -153,6 +173,9 @@ in optional (cfg.maxCacheTtlSsh != null) "max-cache-ttl-ssh ${toString cfg.maxCacheTtlSsh}" ++ + optional (cfg.pinentryFlavor != null) + "pinentry-program ${pkgs.pinentry.${cfg.pinentryFlavor}}/bin/pinentry" + ++ [ cfg.extraConfig ] ); diff --git a/home-manager/modules/services/grobi.nix b/home-manager/modules/services/grobi.nix new file mode 100644 index 00000000000..4dfc5d6331f --- /dev/null +++ b/home-manager/modules/services/grobi.nix @@ -0,0 +1,97 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.grobi; + + eitherStrBoolIntList = with types; + either str (either bool (either int (listOf str))); + +in { + meta.maintainers = [ maintainers.mbrgm ]; + + options = { + services.grobi = { + enable = mkEnableOption "the grobi display setup daemon"; + + executeAfter = mkOption { + type = with types; listOf str; + default = [ ]; + example = [ "setxkbmap dvorak" ]; + description = '' + Commands to be run after an output configuration was + changed. The Nix value declared here will be translated to + JSON and written to the <option>execute_after</option> key + in <filename>~/.config/grobi.conf</filename>. + ''; + }; + + rules = mkOption { + type = with types; listOf (attrsOf eitherStrBoolIntList); + default = [ ]; + example = literalExample '' + [ + { + name = "Home"; + outputs_connected = [ "DP-2" ]; + configure_single = "DP-2"; + primary = true; + atomic = true; + execute_after = [ + "${pkgs.xorg.xrandr}/bin/xrandr --dpi 96" + "${pkgs.xmonad-with-packages}/bin/xmonad --restart"; + ]; + } + { + name = "Mobile"; + outputs_disconnected = [ "DP-2" ]; + configure_single = "eDP-1"; + primary = true; + atomic = true; + execute_after = [ + "${pkgs.xorg.xrandr}/bin/xrandr --dpi 120" + "${pkgs.xmonad-with-packages}/bin/xmonad --restart"; + ]; + } + ] + ''; + description = '' + These are the rules grobi tries to match to the current + output configuration. The rules are evaluated top to bottom, + the first matching rule is applied and processing stops. See + <link xlink:href="https://github.com/fd0/grobi/blob/master/doc/grobi.conf"/> + for more information. The Nix value declared here will be + translated to JSON and written to the <option>rules</option> + key in <filename>~/.config/grobi.conf</filename>. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + systemd.user.services.grobi = { + Unit = { + Description = "grobi display auto config daemon"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Service = { + Type = "simple"; + ExecStart = "${pkgs.grobi}/bin/grobi watch -v"; + Restart = "always"; + RestartSec = "2s"; + Environment = "PATH=${pkgs.xorg.xrandr}/bin:${pkgs.bash}/bin"; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + + xdg.configFile."grobi.conf".text = builtins.toJSON { + execute_after = cfg.executeAfter; + rules = cfg.rules; + }; + }; +} diff --git a/home-manager/modules/services/hound.nix b/home-manager/modules/services/hound.nix index a252a68d271..00589f3405f 100644 --- a/home-manager/modules/services/hound.nix +++ b/home-manager/modules/services/hound.nix @@ -6,23 +6,16 @@ let cfg = config.services.hound; - configFile = pkgs.writeText "hound-config.json" ( - builtins.toJSON { - max-concurrent-indexers = cfg.maxConcurrentIndexers; - dbpath = cfg.databasePath; - repos = cfg.repositories; - health-check-url = "/healthz"; - } - ); + configFile = pkgs.writeText "hound-config.json" (builtins.toJSON { + max-concurrent-indexers = cfg.maxConcurrentIndexers; + dbpath = cfg.databasePath; + repos = cfg.repositories; + health-check-url = "/healthz"; + }); - houndOptions = [ - "--addr ${cfg.listenAddress}" - "--conf ${configFile}" - ]; + houndOptions = [ "--addr ${cfg.listenAddress}" "--conf ${configFile}" ]; -in - -{ +in { meta.maintainers = [ maintainers.adisbladis ]; options.services.hound = { @@ -37,7 +30,7 @@ in databasePath = mkOption { type = types.path; default = "${config.xdg.dataHome}/hound"; - defaultText = "\$XDG_DATA_HOME/hound"; + defaultText = "$XDG_DATA_HOME/hound"; description = "The Hound database path."; }; @@ -49,7 +42,7 @@ in repositories = mkOption { type = types.attrsOf (types.uniq types.attrs); - default = {}; + default = { }; example = literalExample '' { SomeGitRepo = { @@ -67,17 +60,14 @@ in home.packages = [ pkgs.hound ]; systemd.user.services.hound = { - Unit = { - Description = "Hound source code search engine"; - }; + Unit = { Description = "Hound source code search engine"; }; - Install = { - WantedBy = [ "default.target" ]; - }; + Install = { WantedBy = [ "default.target" ]; }; Service = { Environment = "PATH=${makeBinPath [ pkgs.mercurial pkgs.git ]}"; - ExecStart = "${pkgs.hound}/bin/houndd ${concatStringsSep " " houndOptions}"; + ExecStart = + "${pkgs.hound}/bin/houndd ${concatStringsSep " " houndOptions}"; }; }; }; diff --git a/home-manager/modules/services/imapnotify-accounts.nix b/home-manager/modules/services/imapnotify-accounts.nix index 1c780bf28c3..94bdce5dfb4 100644 --- a/home-manager/modules/services/imapnotify-accounts.nix +++ b/home-manager/modules/services/imapnotify-accounts.nix @@ -16,13 +16,16 @@ with lib; onNotifyPost = mkOption { type = with types; either str (attrsOf str); default = ""; - example = { mail = "\${pkgs.notmuch}/bin/notmuch new && \${pkgs.libnotify}/bin/notify-send 'New mail arrived'"; }; + example = { + mail = + "\${pkgs.notmuch}/bin/notmuch new && \${pkgs.libnotify}/bin/notify-send 'New mail arrived'"; + }; description = "Shell commands to run after onNotify event."; }; boxes = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; example = [ "Inbox" "[Gmail]/MyLabel" ]; description = "IMAP folders to watch."; }; diff --git a/home-manager/modules/services/imapnotify.nix b/home-manager/modules/services/imapnotify.nix index fbb0713e978..b59b006e335 100644 --- a/home-manager/modules/services/imapnotify.nix +++ b/home-manager/modules/services/imapnotify.nix @@ -6,102 +6,85 @@ let cfg = config.services.imapnotify; - safeName = lib.replaceChars ["@" ":" "\\" "[" "]"] ["-" "-" "-" "" ""]; + safeName = lib.replaceChars [ "@" ":" "\\" "[" "]" ] [ "-" "-" "-" "" "" ]; imapnotifyAccounts = - filter (a: a.imapnotify.enable) - (attrValues config.accounts.email.accounts); + filter (a: a.imapnotify.enable) (attrValues config.accounts.email.accounts); genAccountUnit = account: - let - name = safeName account.name; - in - { - name = "imapnotify-${name}"; - value = { - Unit = { - Description = "imapnotify for ${name}"; - }; - - Service = { - ExecStart = "${pkgs.imapnotify}/bin/imapnotify -c ${genAccountConfig account}"; - } // optionalAttrs account.notmuch.enable { - Environment = "NOTMUCH_CONFIG=${config.xdg.configHome}/notmuch/notmuchrc"; - }; - - Install = { - WantedBy = [ "default.target" ]; - }; + let name = safeName account.name; + in { + name = "imapnotify-${name}"; + value = { + Unit = { Description = "imapnotify for ${name}"; }; + + Service = { + ExecStart = + "${pkgs.imapnotify}/bin/imapnotify -c ${genAccountConfig account}"; + } // optionalAttrs account.notmuch.enable { + Environment = + "NOTMUCH_CONFIG=${config.xdg.configHome}/notmuch/notmuchrc"; }; + + Install = { WantedBy = [ "default.target" ]; }; }; + }; genAccountConfig = account: - pkgs.writeText "imapnotify-${safeName account.name}-config.js" ( - let - port = - if account.imap.port != null then account.imap.port - else if account.imap.tls.enable then 993 - else 143; - - toJSON = builtins.toJSON; - in - '' - var child_process = require('child_process'); - - function getStdout(cmd) { - var stdout = child_process.execSync(cmd); - return stdout.toString().trim(); - } - - exports.host = ${toJSON account.imap.host} - exports.port = ${toJSON port}; - exports.tls = ${toJSON account.imap.tls.enable}; - exports.username = ${toJSON account.userName}; - exports.password = getStdout("${toString account.passwordCommand}"); - exports.onNotify = ${toJSON account.imapnotify.onNotify}; - exports.onNotifyPost = ${toJSON account.imapnotify.onNotifyPost}; - exports.boxes = ${toJSON account.imapnotify.boxes}; - '' - ); - -in - -{ + pkgs.writeText "imapnotify-${safeName account.name}-config.js" (let + port = if account.imap.port != null then + account.imap.port + else if account.imap.tls.enable then + 993 + else + 143; + + toJSON = builtins.toJSON; + in '' + var child_process = require('child_process'); + + function getStdout(cmd) { + var stdout = child_process.execSync(cmd); + return stdout.toString().trim(); + } + + exports.host = ${toJSON account.imap.host} + exports.port = ${toJSON port}; + exports.tls = ${toJSON account.imap.tls.enable}; + exports.username = ${toJSON account.userName}; + exports.password = getStdout("${toString account.passwordCommand}"); + exports.onNotify = ${toJSON account.imapnotify.onNotify}; + exports.onNotifyPost = ${toJSON account.imapnotify.onNotifyPost}; + exports.boxes = ${toJSON account.imapnotify.boxes}; + ''); + +in { meta.maintainers = [ maintainers.nickhu ]; options = { - services.imapnotify = { - enable = mkEnableOption "imapnotify"; - }; + services.imapnotify = { enable = mkEnableOption "imapnotify"; }; accounts.email.accounts = mkOption { - type = with types; attrsOf (submodule ( - import ./imapnotify-accounts.nix - )); + type = with types; attrsOf (submodule (import ./imapnotify-accounts.nix)); }; }; config = mkIf cfg.enable { - assertions = - let - checkAccounts = pred: msg: - let - badAccounts = filter pred imapnotifyAccounts; - in - { - assertion = badAccounts == []; - message = "imapnotify: Missing ${msg} for accounts: " - + concatMapStringsSep ", " (a: a.name) badAccounts; - }; - in - [ - (checkAccounts (a: a.maildir == null) "maildir configuration") - (checkAccounts (a: a.imap == null) "IMAP configuration") - (checkAccounts (a: a.passwordCommand == null) "password command") - (checkAccounts (a: a.userName == null) "username") - ]; - - systemd.user.services = - listToAttrs (map genAccountUnit imapnotifyAccounts); + assertions = let + checkAccounts = pred: msg: + let badAccounts = filter pred imapnotifyAccounts; + in { + assertion = badAccounts == [ ]; + message = "imapnotify: Missing ${msg} for accounts: " + + concatMapStringsSep ", " (a: a.name) badAccounts; + }; + in [ + (checkAccounts (a: a.maildir == null) "maildir configuration") + (checkAccounts (a: a.imap == null) "IMAP configuration") + (checkAccounts (a: a.passwordCommand == null) "password command") + (checkAccounts (a: a.userName == null) "username") + ]; + + systemd.user.services = listToAttrs (map genAccountUnit imapnotifyAccounts); }; } diff --git a/home-manager/modules/services/kdeconnect.nix b/home-manager/modules/services/kdeconnect.nix index bd698fcf836..82de1f0eb7c 100644 --- a/home-manager/modules/services/kdeconnect.nix +++ b/home-manager/modules/services/kdeconnect.nix @@ -7,9 +7,7 @@ let cfg = config.services.kdeconnect; package = pkgs.kdeconnect; -in - -{ +in { meta.maintainers = [ maintainers.adisbladis ]; options = { @@ -31,14 +29,13 @@ in systemd.user.services.kdeconnect = { Unit = { - Description = "Adds communication between your desktop and your smartphone"; + Description = + "Adds communication between your desktop and your smartphone"; After = [ "graphical-session-pre.target" ]; PartOf = [ "graphical-session.target" ]; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { Environment = "PATH=${config.home.profileDirectory}/bin"; @@ -52,16 +49,16 @@ in systemd.user.services.kdeconnect-indicator = { Unit = { Description = "kdeconnect-indicator"; - After = [ "graphical-session-pre.target" - "polybar.service" - "taffybar.service" - "stalonetray.service" ]; + After = [ + "graphical-session-pre.target" + "polybar.service" + "taffybar.service" + "stalonetray.service" + ]; PartOf = [ "graphical-session.target" ]; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { Environment = "PATH=${config.home.profileDirectory}/bin"; diff --git a/home-manager/modules/services/keepassx.nix b/home-manager/modules/services/keepassx.nix index ad791786f05..dc37066e20c 100644 --- a/home-manager/modules/services/keepassx.nix +++ b/home-manager/modules/services/keepassx.nix @@ -13,19 +13,15 @@ with lib; config = mkIf config.services.keepassx.enable { systemd.user.services.keepassx = { - Unit = { - Description = "KeePassX password manager"; - After = [ "graphical-session-pre.target" ]; - PartOf = [ "graphical-session.target" ]; - }; + Unit = { + Description = "KeePassX password manager"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; - Service = { - ExecStart = "${pkgs.keepassx}/bin/keepassx -min -lock"; - }; + Service = { ExecStart = "${pkgs.keepassx}/bin/keepassx -min -lock"; }; }; }; } diff --git a/home-manager/modules/services/lorri.nix b/home-manager/modules/services/lorri.nix new file mode 100644 index 00000000000..3b2c244e3c0 --- /dev/null +++ b/home-manager/modules/services/lorri.nix @@ -0,0 +1,51 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.lorri; + +in { + meta.maintainers = [ maintainers.gerschtli ]; + + options = { services.lorri.enable = mkEnableOption "lorri build daemon"; }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.lorri ]; + + systemd.user = { + services.lorri = { + Unit = { + Description = "lorri build daemon"; + Requires = "lorri.socket"; + After = "lorri.socket"; + RefuseManualStart = true; + }; + + Service = { + ExecStart = "${pkgs.lorri}/bin/lorri daemon"; + PrivateTmp = true; + ProtectSystem = "strict"; + ProtectHome = "read-only"; + Restart = "on-failure"; + Environment = let + path = with pkgs; + makeSearchPath "bin" [ nix gitMinimal gnutar gzip ]; + in "PATH=${path}"; + }; + }; + + sockets.lorri = { + Unit = { Description = "Socket for lorri build daemon"; }; + + Socket = { + ListenStream = "%t/lorri/daemon.socket"; + RuntimeDirectory = "lorri"; + }; + + Install = { WantedBy = [ "sockets.target" ]; }; + }; + }; + }; +} diff --git a/home-manager/modules/services/mbsync.nix b/home-manager/modules/services/mbsync.nix index 73c3b326695..ac6ac1ef78a 100644 --- a/home-manager/modules/services/mbsync.nix +++ b/home-manager/modules/services/mbsync.nix @@ -6,14 +6,10 @@ let cfg = config.services.mbsync; - mbsyncOptions = - [ "--all" - ] ++ optional (cfg.verbose) "--verbose" - ++ optional (cfg.configFile != null) "--config ${cfg.configFile}"; + mbsyncOptions = [ "--all" ] ++ optional (cfg.verbose) "--verbose" + ++ optional (cfg.configFile != null) "--config ${cfg.configFile}"; -in - -{ +in { meta.maintainers = [ maintainers.pjones ]; options.services.mbsync = { @@ -81,30 +77,28 @@ in config = mkIf cfg.enable { systemd.user.services.mbsync = { - Unit = { - Description = "mbsync mailbox synchronization"; - }; + Unit = { Description = "mbsync mailbox synchronization"; }; Service = { Type = "oneshot"; - ExecStart = "${cfg.package}/bin/mbsync ${concatStringsSep " " mbsyncOptions}"; - } // (optionalAttrs (cfg.postExec != null) { ExecStartPost = cfg.postExec; }) - // (optionalAttrs (cfg.preExec != null) { ExecStartPre = cfg.preExec; }); + ExecStart = + "${cfg.package}/bin/mbsync ${concatStringsSep " " mbsyncOptions}"; + } // (optionalAttrs (cfg.postExec != null) { + ExecStartPost = cfg.postExec; + }) // (optionalAttrs (cfg.preExec != null) { + ExecStartPre = cfg.preExec; + }); }; systemd.user.timers.mbsync = { - Unit = { - Description = "mbsync mailbox synchronization"; - }; + Unit = { Description = "mbsync mailbox synchronization"; }; Timer = { OnCalendar = cfg.frequency; Unit = "mbsync.service"; }; - Install = { - WantedBy = [ "timers.target" ]; - }; + Install = { WantedBy = [ "timers.target" ]; }; }; }; } diff --git a/home-manager/modules/services/mpdris2.nix b/home-manager/modules/services/mpdris2.nix index 450f84c5912..cb8cefba6bd 100644 --- a/home-manager/modules/services/mpdris2.nix +++ b/home-manager/modules/services/mpdris2.nix @@ -9,11 +9,11 @@ let toIni = generators.toINI { mkKeyValue = key: value: let - value' = - if isBool value then (if value then "True" else "False") - else toString value; - in - "${key} = ${value'}"; + value' = if isBool value then + (if value then "True" else "False") + else + toString value; + in "${key} = ${value'}"; }; mpdris2Conf = { @@ -29,9 +29,7 @@ let }; }; -in - -{ +in { meta.maintainers = [ maintainers.pjones ]; options.services.mpdris2 = { @@ -76,25 +74,27 @@ in }; config = mkIf cfg.enable { - assertions = [ - { - assertion = config.services.mpd.enable; - message = "The mpdris2 module requires 'services.mpd.enable = true'."; - } - ]; + assertions = [{ + assertion = config.services.mpd.enable; + message = "The mpdris2 module requires 'services.mpd.enable = true'."; + }]; xdg.configFile."mpDris2/mpDris2.conf".text = toIni mpdris2Conf; systemd.user.services.mpdris2 = { + Install = { WantedBy = [ "default.target" ]; }; + Unit = { Description = "MPRIS 2 support for MPD"; - After = [ "graphical-session-pre.target" "mpd.service" ]; - PartOf = [ "graphical-session.target" ]; + After = [ "mpd.service" ]; }; Service = { Type = "simple"; + Restart = "on-failure"; + RestartSec = "5s"; ExecStart = "${cfg.package}/bin/mpDris2"; + BusName = "org.mpris.MediaPlayer2.mpd"; }; }; }; diff --git a/home-manager/modules/services/muchsync.nix b/home-manager/modules/services/muchsync.nix index 72bf737c27d..b7004418d35 100644 --- a/home-manager/modules/services/muchsync.nix +++ b/home-manager/modules/services/muchsync.nix @@ -150,23 +150,21 @@ in { }; config = let - mapRemotes = gen: with attrsets; mapAttrs' + mapRemotes = gen: + with attrsets; + mapAttrs' (name: remoteCfg: nameValuePair "muchsync-${name}" (gen name remoteCfg)) cfg.remotes; in mkIf (cfg.remotes != { }) { - assertions = [ - { - assertion = config.programs.notmuch.enable; - message = '' - The muchsync module requires 'programs.notmuch.enable = true'. - ''; - } - ]; + assertions = [{ + assertion = config.programs.notmuch.enable; + message = '' + The muchsync module requires 'programs.notmuch.enable = true'. + ''; + }]; systemd.user.services = mapRemotes (name: remoteCfg: { - Unit = { - Description = "muchsync sync service (${name})"; - }; + Unit = { Description = "muchsync sync service (${name})"; }; Service = { CPUSchedulingPolicy = "idle"; IOSchedulingClass = "idle"; @@ -175,8 +173,7 @@ in { ''"NOTMUCH_CONFIG=${config.home.sessionVariables.NOTMUCH_CONFIG}"'' ''"NMBGIT=${config.home.sessionVariables.NMBGIT}"'' ]; - ExecStart = concatStringsSep " " ( - [ "${pkgs.muchsync}/bin/muchsync" ] + ExecStart = concatStringsSep " " ([ "${pkgs.muchsync}/bin/muchsync" ] ++ [ "-s ${escapeShellArg remoteCfg.sshCommand}" ] ++ optional (!remoteCfg.upload) "--noup" @@ -187,25 +184,20 @@ in { # remote configuration ++ [ (escapeShellArg remoteCfg.remote.host) ] ++ optional (remoteCfg.remote.muchsyncPath != "") - "-r ${escapeShellArg remoteCfg.remote.muchsyncPath}" + "-r ${escapeShellArg remoteCfg.remote.muchsyncPath}" ++ optional remoteCfg.remote.checkForModifiedFiles "-F" - ++ optional (!remoteCfg.remote.importNew) "--nonew" - ); + ++ optional (!remoteCfg.remote.importNew) "--nonew"); }; }); systemd.user.timers = mapRemotes (name: remoteCfg: { - Unit = { - Description = "muchsync periodic sync (${name})"; - }; + Unit = { Description = "muchsync periodic sync (${name})"; }; Timer = { Unit = "muchsync-${name}.service"; OnCalendar = remoteCfg.frequency; Persistent = true; }; - Install = { - WantedBy = [ "timers.target" ]; - }; + Install = { WantedBy = [ "timers.target" ]; }; }); }; } diff --git a/home-manager/modules/services/network-manager-applet.nix b/home-manager/modules/services/network-manager-applet.nix index 72a4711e39a..bf57ed65091 100644 --- a/home-manager/modules/services/network-manager-applet.nix +++ b/home-manager/modules/services/network-manager-applet.nix @@ -6,9 +6,7 @@ let cfg = config.services.network-manager-applet; -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; options = { @@ -25,17 +23,13 @@ in PartOf = [ "graphical-session.target" ]; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { - ExecStart = toString ( - [ - "${pkgs.networkmanagerapplet}/bin/nm-applet" - "--sm-disable" - ] ++ optional config.xsession.preferStatusNotifierItems "--indicator" - ); + ExecStart = toString + ([ "${pkgs.networkmanagerapplet}/bin/nm-applet" "--sm-disable" ] + ++ optional config.xsession.preferStatusNotifierItems + "--indicator"); }; }; }; diff --git a/home-manager/modules/services/nextcloud-client.nix b/home-manager/modules/services/nextcloud-client.nix index 3d8dc0bc80b..555ca11ad64 100644 --- a/home-manager/modules/services/nextcloud-client.nix +++ b/home-manager/modules/services/nextcloud-client.nix @@ -4,9 +4,7 @@ with lib; { options = { - services.nextcloud-client = { - enable = mkEnableOption "Nextcloud Client"; - }; + services.nextcloud-client = { enable = mkEnableOption "Nextcloud Client"; }; }; config = mkIf config.services.nextcloud-client.enable { @@ -22,9 +20,7 @@ with lib; ExecStart = "${pkgs.nextcloud-client}/bin/nextcloud"; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; }; }; } diff --git a/home-manager/modules/services/owncloud-client.nix b/home-manager/modules/services/owncloud-client.nix index d98a508f088..d55d8ffa2a4 100644 --- a/home-manager/modules/services/owncloud-client.nix +++ b/home-manager/modules/services/owncloud-client.nix @@ -4,9 +4,7 @@ with lib; { options = { - services.owncloud-client = { - enable = mkEnableOption "Owncloud Client"; - }; + services.owncloud-client = { enable = mkEnableOption "Owncloud Client"; }; }; config = mkIf config.services.owncloud-client.enable { @@ -22,9 +20,7 @@ with lib; ExecStart = "${pkgs.owncloud-client}/bin/owncloud"; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; }; }; } diff --git a/home-manager/modules/services/parcellite.nix b/home-manager/modules/services/parcellite.nix index 455989ffe07..ce04238613b 100644 --- a/home-manager/modules/services/parcellite.nix +++ b/home-manager/modules/services/parcellite.nix @@ -7,15 +7,11 @@ let cfg = config.services.parcellite; package = pkgs.parcellite; -in - -{ +in { meta.maintainers = [ maintainers.gleber ]; options = { - services.parcellite = { - enable = mkEnableOption "Parcellite"; - }; + services.parcellite = { enable = mkEnableOption "Parcellite"; }; }; config = mkIf cfg.enable { @@ -28,17 +24,9 @@ in PartOf = [ "graphical-session.target" ]; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { - # PATH have been added in nixpkgs.parcellite, keeping it here for - # backward compatibility. XDG_DATA_DIRS is necessary to make it pick up - # icons correctly. - Environment = '' - PATH=${package}/bin:${pkgs.which}/bin:${pkgs.xdotool}/bin XDG_DATA_DIRS=${pkgs.hicolor_icon_theme}/share - ''; ExecStart = "${package}/bin/parcellite"; Restart = "on-abort"; }; diff --git a/home-manager/modules/services/password-store-sync.nix b/home-manager/modules/services/password-store-sync.nix new file mode 100644 index 00000000000..81933914980 --- /dev/null +++ b/home-manager/modules/services/password-store-sync.nix @@ -0,0 +1,71 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + serviceCfg = config.services.password-store-sync; + programCfg = config.programs.password-store; + +in { + meta.maintainers = with maintainers; [ pacien ]; + + options.services.password-store-sync = { + enable = mkEnableOption "Password store periodic sync"; + + frequency = mkOption { + type = types.str; + default = "*:0/5"; + description = '' + How often to synchronise the password store git repository with its + default upstream. + </para><para> + This value is passed to the systemd timer configuration as the + <literal>onCalendar</literal> option. + See + <citerefentry> + <refentrytitle>systemd.time</refentrytitle> + <manvolnum>7</manvolnum> + </citerefentry> + for more information about the format. + ''; + }; + }; + + config = mkIf serviceCfg.enable { + assertions = [{ + assertion = programCfg.enable; + message = "The 'services.password-store-sync' module requires" + + " 'programs.password-store.enable = true'."; + }]; + + systemd.user.services.password-store-sync = { + Unit = { Description = "Password store sync"; }; + + Service = { + CPUSchedulingPolicy = "idle"; + IOSchedulingClass = "idle"; + Environment = let + makeEnvironmentPairs = + mapAttrsToList (key: value: "${key}=${builtins.toJSON value}"); + in makeEnvironmentPairs programCfg.settings; + ExecStart = toString (pkgs.writeShellScript "password-store-sync" '' + ${pkgs.pass}/bin/pass git pull --rebase && \ + ${pkgs.pass}/bin/pass git push + ''); + }; + }; + + systemd.user.timers.password-store-sync = { + Unit = { Description = "Password store periodic sync"; }; + + Timer = { + Unit = "password-store-sync.service"; + OnCalendar = serviceCfg.frequency; + Persistent = true; + }; + + Install = { WantedBy = [ "timers.target" ]; }; + }; + }; +} diff --git a/home-manager/modules/services/pasystray.nix b/home-manager/modules/services/pasystray.nix index 8f92f34c091..7c6651d9499 100644 --- a/home-manager/modules/services/pasystray.nix +++ b/home-manager/modules/services/pasystray.nix @@ -6,31 +6,25 @@ with lib; meta.maintainers = [ maintainers.pltanton ]; options = { - services.pasystray = { - enable = mkEnableOption "PulseAudio system tray"; - }; + services.pasystray = { enable = mkEnableOption "PulseAudio system tray"; }; }; config = mkIf config.services.pasystray.enable { systemd.user.services.pasystray = { - Unit = { - Description = "PulseAudio system tray"; - After = [ "graphical-session-pre.target" ]; - PartOf = [ "graphical-session.target" ]; - }; + Unit = { + Description = "PulseAudio system tray"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; - Service = { - Environment = - let - toolPaths = makeBinPath [ pkgs.paprefs pkgs.pavucontrol ]; - in - [ "PATH=${toolPaths}" ]; - ExecStart = "${pkgs.pasystray}/bin/pasystray"; - }; + Service = { + Environment = + let toolPaths = makeBinPath [ pkgs.paprefs pkgs.pavucontrol ]; + in [ "PATH=${toolPaths}" ]; + ExecStart = "${pkgs.pasystray}/bin/pasystray"; + }; }; }; } diff --git a/home-manager/modules/services/polybar.nix b/home-manager/modules/services/polybar.nix index 4225ed9b38c..934a990638f 100644 --- a/home-manager/modules/services/polybar.nix +++ b/home-manager/modules/services/polybar.nix @@ -6,30 +6,28 @@ let cfg = config.services.polybar; - eitherStrBoolIntList = with types; either str (either bool (either int (listOf str))); + eitherStrBoolIntList = with types; + either str (either bool (either int (listOf str))); toPolybarIni = generators.toINI { mkKeyValue = key: value: let quoted = v: - if hasPrefix " " v || hasSuffix " " v - then ''"${v}"'' - else v; - - value' = - if isBool value then (if value then "true" else "false") - else if (isString value && key != "include-file") then quoted value - else toString value; - in - "${key}=${value'}"; + if hasPrefix " " v || hasSuffix " " v then ''"${v}"'' else v; + + value' = if isBool value then + (if value then "true" else "false") + else if (isString value && key != "include-file") then + quoted value + else + toString value; + in "${key}=${value'}"; }; configFile = pkgs.writeText "polybar.conf" (toPolybarIni cfg.config + "\n" + cfg.extraConfig); -in - -{ +in { options = { services.polybar = { enable = mkEnableOption "Polybar status bar"; @@ -39,7 +37,7 @@ in default = pkgs.polybar; defaultText = literalExample "pkgs.polybar"; description = "Polybar package to install."; - example = literalExample '' + example = literalExample '' pkgs.polybar.override { i3GapsSupport = true; alsaSupport = true; @@ -50,15 +48,14 @@ in }; config = mkOption { - type = types.coercedTo - types.path + type = types.coercedTo types.path (p: { "section/base" = { include-file = "${p}"; }; }) (types.attrsOf (types.attrsOf eitherStrBoolIntList)); description = '' Polybar configuration. Can be either path to a file, or set of attributes that will be used to create the final configuration. ''; - default = {}; + default = { }; example = literalExample '' { "bar/top" = { @@ -118,25 +115,20 @@ in Description = "Polybar status bar"; After = [ "graphical-session-pre.target" ]; PartOf = [ "graphical-session.target" ]; - X-Restart-Triggers = [ - "${config.xdg.configFile."polybar/config".source}" - ]; + X-Restart-Triggers = + [ "${config.xdg.configFile."polybar/config".source}" ]; }; Service = { Type = "forking"; Environment = "PATH=${cfg.package}/bin:/run/wrappers/bin"; ExecStart = - let - scriptPkg = pkgs.writeShellScriptBin "polybar-start" cfg.script; - in - "${scriptPkg}/bin/polybar-start"; + let scriptPkg = pkgs.writeShellScriptBin "polybar-start" cfg.script; + in "${scriptPkg}/bin/polybar-start"; Restart = "on-failure"; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; }; }; diff --git a/home-manager/modules/services/random-background.nix b/home-manager/modules/services/random-background.nix index cbec97ae7cb..9deee8deb5c 100644 --- a/home-manager/modules/services/random-background.nix +++ b/home-manager/modules/services/random-background.nix @@ -6,23 +6,26 @@ let cfg = config.services.random-background; - flags = lib.concatStringsSep " " ( - [ - "--bg-${cfg.display}" - "--no-fehbg" - "--randomize" - ] - ++ lib.optional (!cfg.enableXinerama) "--no-xinerama" - ); + flags = lib.concatStringsSep " " + ([ "--bg-${cfg.display}" "--no-fehbg" "--randomize" ] + ++ lib.optional (!cfg.enableXinerama) "--no-xinerama"); -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; options = { services.random-background = { - enable = mkEnableOption "random desktop background"; + enable = mkEnableOption "" // { + description = '' + Whether to enable random desktop background. + </para><para> + Note, if you are using NixOS and have set up a custom + desktop manager session for Home Manager, then the session + configuration must have the <option>bgSupport</option> + option set to <literal>true</literal> or the background + image set by this module may be overwritten. + ''; + }; imageDirectory = mkOption { type = types.str; @@ -63,41 +66,32 @@ in }; }; - config = mkIf cfg.enable ( - mkMerge ([ - { - systemd.user.services.random-background = { - Unit = { - Description = "Set random desktop background using feh"; - After = [ "graphical-session-pre.target" ]; - PartOf = [ "graphical-session.target" ]; - }; - - Service = { - Type = "oneshot"; - ExecStart = "${pkgs.feh}/bin/feh ${flags} ${cfg.imageDirectory}"; - IOSchedulingClass = "idle"; - }; + config = mkIf cfg.enable (mkMerge ([ + { + systemd.user.services.random-background = { + Unit = { + Description = "Set random desktop background using feh"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Service = { + Type = "oneshot"; + ExecStart = "${pkgs.feh}/bin/feh ${flags} ${cfg.imageDirectory}"; + IOSchedulingClass = "idle"; }; - } - (mkIf (cfg.interval != null) { - systemd.user.timers.random-background = { - Unit = { - Description = "Set random desktop background using feh"; - }; - Timer = { - OnUnitActiveSec = cfg.interval; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + } + (mkIf (cfg.interval != null) { + systemd.user.timers.random-background = { + Unit = { Description = "Set random desktop background using feh"; }; - Install = { - WantedBy = [ "timers.target" ]; - }; - }; - }) - ])); + Timer = { OnUnitActiveSec = cfg.interval; }; + + Install = { WantedBy = [ "timers.target" ]; }; + }; + }) + ])); } diff --git a/home-manager/modules/services/redshift.nix b/home-manager/modules/services/redshift.nix index 1452fcc95ed..86cbab205f6 100644 --- a/home-manager/modules/services/redshift.nix +++ b/home-manager/modules/services/redshift.nix @@ -8,9 +8,7 @@ let cfg = config.services.redshift; -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; options.services.redshift = { @@ -113,7 +111,7 @@ in extraOptions = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; example = [ "-v" "-m randr" ]; description = '' Additional command-line arguments to pass to @@ -123,17 +121,13 @@ in }; config = mkIf cfg.enable { - assertions = [ - { - assertion = - cfg.provider == "manual" - -> cfg.latitude != null && cfg.longitude != null; - message = - "Must provide services.redshift.latitude and" - + " services.redshift.latitude when" - + " services.redshift.provider is set to \"manual\"."; - } - ]; + assertions = [{ + assertion = cfg.provider == "manual" -> cfg.latitude != null + && cfg.longitude != null; + message = "Must provide services.redshift.latitude and" + + " services.redshift.latitude when" + + " services.redshift.provider is set to \"manual\"."; + }]; systemd.user.services.redshift = { Unit = { @@ -142,27 +136,25 @@ in PartOf = [ "graphical-session.target" ]; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { - ExecStart = - let - providerString = - if cfg.provider == "manual" - then "${cfg.latitude}:${cfg.longitude}" - else cfg.provider; - - args = [ - "-l ${providerString}" - "-t ${toString cfg.temperature.day}:${toString cfg.temperature.night}" - "-b ${toString cfg.brightness.day}:${toString cfg.brightness.night}" - ] ++ cfg.extraOptions; - - command = if cfg.tray then "redshift-gtk" else "redshift"; - in - "${cfg.package}/bin/${command} ${concatStringsSep " " args}"; + ExecStart = let + providerString = if cfg.provider == "manual" then + "${cfg.latitude}:${cfg.longitude}" + else + cfg.provider; + + args = [ + "-l ${providerString}" + "-t ${toString cfg.temperature.day}:${ + toString cfg.temperature.night + }" + "-b ${toString cfg.brightness.day}:${toString cfg.brightness.night}" + ] ++ cfg.extraOptions; + + command = if cfg.tray then "redshift-gtk" else "redshift"; + in "${cfg.package}/bin/${command} ${concatStringsSep " " args}"; RestartSec = 3; Restart = "always"; }; diff --git a/home-manager/modules/services/rsibreak.nix b/home-manager/modules/services/rsibreak.nix index 242e03432e8..77eaa71f958 100644 --- a/home-manager/modules/services/rsibreak.nix +++ b/home-manager/modules/services/rsibreak.nix @@ -6,9 +6,7 @@ let cfg = config.services.rsibreak; -in - -{ +in { options.services.rsibreak = { enable = mkEnableOption "rsibreak"; @@ -23,9 +21,7 @@ in PartOf = [ "graphical-session.target" ]; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { Environment = "PATH=${config.home.profileDirectory}/bin"; diff --git a/home-manager/modules/services/screen-locker.nix b/home-manager/modules/services/screen-locker.nix index e3da14069bc..30591a7d1a5 100644 --- a/home-manager/modules/services/screen-locker.nix +++ b/home-manager/modules/services/screen-locker.nix @@ -29,7 +29,7 @@ in { xautolockExtraOptions = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; description = '' Extra command-line arguments to pass to <command>xautolock</command>. ''; @@ -37,7 +37,7 @@ in { xssLockExtraOptions = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; description = '' Extra command-line arguments to pass to <command>xss-lock</command>. ''; @@ -53,9 +53,7 @@ in { PartOf = [ "graphical-session.target" ]; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { ExecStart = concatStringsSep " " ([ @@ -67,10 +65,21 @@ in { }; }; - # xss-lock will run specified screen locker when the session is locked via loginctl - # can't be started as a systemd service, - # see https://bitbucket.org/raymonad/xss-lock/issues/13/allow-operation-as-systemd-user-unit - xsession.initExtra = "${pkgs.xss-lock}/bin/xss-lock ${concatStringsSep " " cfg.xssLockExtraOptions} -- ${cfg.lockCmd} &"; + systemd.user.services.xss-lock = { + Unit = { + Description = "xss-lock, session locker service"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { + ExecStart = concatStringsSep " " + ([ "${pkgs.xss-lock}/bin/xss-lock" "-s \${XDG_SESSION_ID}" ] + ++ cfg.xssLockExtraOptions ++ [ "-- ${cfg.lockCmd}" ]); + }; + }; }; } diff --git a/home-manager/modules/services/spotifyd.nix b/home-manager/modules/services/spotifyd.nix new file mode 100644 index 00000000000..bc231814eba --- /dev/null +++ b/home-manager/modules/services/spotifyd.nix @@ -0,0 +1,52 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.spotifyd; + + configFile = pkgs.writeText "spotifyd.conf" '' + ${generators.toINI { } cfg.settings} + ''; + +in { + options.services.spotifyd = { + enable = mkEnableOption "SpotifyD connect"; + + settings = mkOption { + type = types.attrsOf (types.attrsOf types.str); + default = { }; + description = "Configuration for spotifyd"; + example = literalExample '' + { + global = { + user = "Alex"; + password = "foo"; + device_name = "nix"; + }; + } + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.spotifyd ]; + + systemd.user.services.spotifyd = { + Unit = { + Description = "spotify daemon"; + Documentation = "https://github.com/Spotifyd/spotifyd"; + }; + + Install.WantedBy = [ "default.target" ]; + + Service = { + ExecStart = + "${pkgs.spotifyd}/bin/spotifyd --no-daemon --config-path ${configFile}"; + Restart = "always"; + RestartSec = 12; + }; + }; + }; +} diff --git a/home-manager/modules/services/stalonetray.nix b/home-manager/modules/services/stalonetray.nix index 934e78c99a1..cca60498963 100644 --- a/home-manager/modules/services/stalonetray.nix +++ b/home-manager/modules/services/stalonetray.nix @@ -6,9 +6,7 @@ let cfg = config.services.stalonetray; -in - -{ +in { options = { services.stalonetray = { enable = mkEnableOption "Stalonetray system tray"; @@ -22,19 +20,18 @@ in }; config = mkOption { - type = with types; - attrsOf (nullOr (either str (either bool int))); - description = '' - Stalonetray configuration as a set of attributes. - ''; - default = {}; - example = { - geometry = "3x1-600+0"; - decorations = null; - icon_size = 30; - sticky = true; - background = "#cccccc"; - }; + type = with types; attrsOf (nullOr (either str (either bool int))); + description = '' + Stalonetray configuration as a set of attributes. + ''; + default = { }; + example = { + geometry = "3x1-600+0"; + decorations = null; + icon_size = 30; + sticky = true; + background = "#cccccc"; + }; }; extraConfig = mkOption { @@ -42,11 +39,11 @@ in description = "Additional configuration lines for stalonetrayrc."; default = ""; example = '' - geometry 3x1-600+0 - decorations none - icon_size 30 - sticky true - background "#cccccc" + geometry 3x1-600+0 + decorations none + icon_size 30 + sticky true + background "#cccccc" ''; }; }; @@ -63,9 +60,7 @@ in PartOf = [ "graphical-session.target" ]; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { ExecStart = "${cfg.package}/bin/stalonetray"; @@ -74,17 +69,18 @@ in }; } - (mkIf (cfg.config != {}) { - home.file.".stalonetrayrc".text = - let - valueToString = v: - if isBool v then (if v then "true" else "false") - else if (v==null) then "none" - else ''"${toString v}"''; - in - concatStrings ( - mapAttrsToList (k: v: "${k} ${valueToString v}\n") cfg.config - ); + (mkIf (cfg.config != { }) { + home.file.".stalonetrayrc".text = let + valueToString = v: + if isBool v then + (if v then "true" else "false") + else if (v == null) then + "none" + else + ''"${toString v}"''; + in concatStrings (mapAttrsToList (k: v: '' + ${k} ${valueToString v} + '') cfg.config); }) (mkIf (cfg.extraConfig != "") { diff --git a/home-manager/modules/services/status-notifier-watcher.nix b/home-manager/modules/services/status-notifier-watcher.nix index 8a2ded8720a..3c3e54877b4 100644 --- a/home-manager/modules/services/status-notifier-watcher.nix +++ b/home-manager/modules/services/status-notifier-watcher.nix @@ -6,9 +6,7 @@ let cfg = config.services.status-notifier-watcher; -in - -{ +in { meta.maintainers = [ maintainers.pltanton ]; options = { @@ -17,30 +15,30 @@ in package = mkOption { default = pkgs.haskellPackages.status-notifier-item; - defaultText = literalExample "pkgs.haskellPackages.status-notifier-item"; + defaultText = + literalExample "pkgs.haskellPackages.status-notifier-item"; type = types.package; example = literalExample "pkgs.haskellPackages.status-notifier-item"; - description = "The package to use for the status notifier watcher binary."; + description = + "The package to use for the status notifier watcher binary."; }; }; }; config = mkIf cfg.enable { systemd.user.services.status-notifier-watcher = { - Unit = { - Description = "SNI watcher"; - After = [ "graphical-session-pre.target" ]; - PartOf = [ "graphical-session.target" ]; - Before = [ "taffybar.service" ]; - }; - - Service = { - ExecStart = "${cfg.package}/bin/status-notifier-watcher"; - }; - - Install = { - WantedBy = [ "graphical-session.target" "taffybar.service" ]; - }; + Unit = { + Description = "SNI watcher"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + Before = [ "taffybar.service" ]; + }; + + Service = { ExecStart = "${cfg.package}/bin/status-notifier-watcher"; }; + + Install = { + WantedBy = [ "graphical-session.target" "taffybar.service" ]; + }; }; }; } diff --git a/home-manager/modules/services/syncthing.nix b/home-manager/modules/services/syncthing.nix index 7fc556c5234..2ef10540164 100644 --- a/home-manager/modules/services/syncthing.nix +++ b/home-manager/modules/services/syncthing.nix @@ -22,21 +22,21 @@ with lib; systemd.user.services = { syncthing = { Unit = { - Description = "Syncthing - Open Source Continuous File Synchronization"; + Description = + "Syncthing - Open Source Continuous File Synchronization"; Documentation = "man:syncthing(1)"; After = [ "network.target" ]; }; Service = { - ExecStart = "${pkgs.syncthing}/bin/syncthing -no-browser -no-restart -logflags=0"; + ExecStart = + "${pkgs.syncthing}/bin/syncthing -no-browser -no-restart -logflags=0"; Restart = "on-failure"; SuccessExitStatus = [ 3 4 ]; RestartForceExitStatus = [ 3 4 ]; }; - Install = { - WantedBy = [ "default.target" ]; - }; + Install = { WantedBy = [ "default.target" ]; }; }; }; }) @@ -46,10 +46,12 @@ with lib; qsyncthingtray = { Unit = { Description = "QSyncthingTray"; - After = [ "graphical-session-pre.target" - "polybar.service" - "taffybar.service" - "stalonetray.service" ]; + After = [ + "graphical-session-pre.target" + "polybar.service" + "taffybar.service" + "stalonetray.service" + ]; PartOf = [ "graphical-session.target" ]; }; @@ -58,9 +60,7 @@ with lib; ExecStart = "${pkgs.qsyncthingtray}/bin/QSyncthingTray"; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; }; }; }) diff --git a/home-manager/modules/services/taffybar.nix b/home-manager/modules/services/taffybar.nix index 69531a19dc9..5392755423d 100644 --- a/home-manager/modules/services/taffybar.nix +++ b/home-manager/modules/services/taffybar.nix @@ -6,9 +6,7 @@ let cfg = config.services.taffybar; -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; options = { @@ -38,9 +36,7 @@ in Restart = "on-failure"; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; }; xsession.importedVariables = [ "GDK_PIXBUF_MODULE_FILE" ]; diff --git a/home-manager/modules/services/tahoe-lafs.nix b/home-manager/modules/services/tahoe-lafs.nix index bb7be8d7db9..742b779b270 100644 --- a/home-manager/modules/services/tahoe-lafs.nix +++ b/home-manager/modules/services/tahoe-lafs.nix @@ -6,20 +6,14 @@ with lib; meta.maintainers = [ maintainers.rycee ]; options = { - services.tahoe-lafs = { - enable = mkEnableOption "Tahoe-LAFS"; - }; + services.tahoe-lafs = { enable = mkEnableOption "Tahoe-LAFS"; }; }; config = mkIf config.services.tahoe-lafs.enable { systemd.user.services.tahoe-lafs = { - Unit = { - Description = "Tahoe-LAFS"; - }; + Unit = { Description = "Tahoe-LAFS"; }; - Service = { - ExecStart = "${pkgs.tahoelafs}/bin/tahoe run -C %h/.tahoe"; - }; + Service = { ExecStart = "${pkgs.tahoelafs}/bin/tahoe run -C %h/.tahoe"; }; }; }; } diff --git a/home-manager/modules/services/taskwarrior-sync.nix b/home-manager/modules/services/taskwarrior-sync.nix index 4179ac8aa85..d16c0681bee 100644 --- a/home-manager/modules/services/taskwarrior-sync.nix +++ b/home-manager/modules/services/taskwarrior-sync.nix @@ -6,9 +6,7 @@ let cfg = config.services.taskwarrior-sync; -in - -{ +in { meta.maintainers = with maintainers; [ minijackson pacien ]; options.services.taskwarrior-sync = { @@ -32,9 +30,7 @@ in config = mkIf cfg.enable { systemd.user.services.taskwarrior-sync = { - Unit = { - Description = "Taskwarrior sync"; - }; + Unit = { Description = "Taskwarrior sync"; }; Service = { CPUSchedulingPolicy = "idle"; IOSchedulingClass = "idle"; @@ -43,16 +39,12 @@ in }; systemd.user.timers.taskwarrior-sync = { - Unit = { - Description = "Taskwarrior periodic sync"; - }; + Unit = { Description = "Taskwarrior periodic sync"; }; Timer = { Unit = "taskwarrior-sync.service"; OnCalendar = cfg.frequency; }; - Install = { - WantedBy = [ "timers.target" ]; - }; + Install = { WantedBy = [ "timers.target" ]; }; }; }; } diff --git a/home-manager/modules/services/udiskie.nix b/home-manager/modules/services/udiskie.nix index c058a23de6c..2444d68ff93 100644 --- a/home-manager/modules/services/udiskie.nix +++ b/home-manager/modules/services/udiskie.nix @@ -6,19 +6,17 @@ let cfg = config.services.udiskie; - commandArgs = - concatStringsSep " " ( - map (opt: "-" + opt) [ - (if cfg.automount then "a" else "A") - (if cfg.notify then "n" else "N") - ({ always = "t"; auto = "s"; never = "T"; }.${cfg.tray}) - ] - ++ optional config.xsession.preferStatusNotifierItems "--appindicator" - ); - -in - -{ + commandArgs = concatStringsSep " " (map (opt: "-" + opt) [ + (if cfg.automount then "a" else "A") + (if cfg.notify then "n" else "N") + ({ + always = "t"; + auto = "s"; + never = "T"; + }.${cfg.tray}) + ] ++ optional config.xsession.preferStatusNotifierItems "--appindicator"); + +in { meta.maintainers = [ maintainers.rycee ]; imports = [ @@ -77,19 +75,17 @@ in config = mkIf config.services.udiskie.enable { systemd.user.services.udiskie = { - Unit = { - Description = "udiskie mount daemon"; - After = [ "graphical-session-pre.target" ]; - PartOf = [ "graphical-session.target" ]; - }; + Unit = { + Description = "udiskie mount daemon"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; - Service = { - ExecStart = "${pkgs.udiskie}/bin/udiskie -2 ${commandArgs}"; - }; + Service = { + ExecStart = "${pkgs.udiskie}/bin/udiskie -2 ${commandArgs}"; + }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; }; }; } diff --git a/home-manager/modules/services/unclutter.nix b/home-manager/modules/services/unclutter.nix index 6b5ac866ec5..5e760639591 100644 --- a/home-manager/modules/services/unclutter.nix +++ b/home-manager/modules/services/unclutter.nix @@ -55,9 +55,7 @@ in { Restart = "always"; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; }; }; } diff --git a/home-manager/modules/services/unison.nix b/home-manager/modules/services/unison.nix new file mode 100644 index 00000000000..93c59e8fd62 --- /dev/null +++ b/home-manager/modules/services/unison.nix @@ -0,0 +1,121 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.unison; + + pairOf = t: + let list = types.addCheck (types.listOf t) (l: length l == 2); + in list // { description = list.description + " of length 2"; }; + + pairOptions = { + options = { + stateDirectory = mkOption { + type = types.path; + default = "${config.xdg.dataHome}/unison"; + defaultText = "$XDG_DATA_HOME/unison"; + description = '' + Unison state directory to use. + ''; + }; + + commandOptions = mkOption rec { + type = with types; attrsOf str; + apply = mergeAttrs default; + default = { + repeat = "watch"; + sshcmd = "${pkgs.openssh}/bin/ssh"; + ui = "text"; + auto = "true"; + batch = "true"; + log = "false"; # don't log to file, handled by systemd + }; + description = '' + Additional command line options as a dictionary to pass to the + <literal>unison</literal> program. + </para><para> + See + <citerefentry> + <refentrytitle>unison</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry> + for a list of available options. + ''; + }; + + roots = mkOption { + type = pairOf types.str; + example = literalExample '' + [ + "/home/user/documents" + "ssh://remote/documents" + ] + ''; + description = '' + Pair of roots to synchronise. + ''; + }; + }; + }; + + serialiseArg = key: val: "-${key}=${escapeShellArg val}"; + + serialiseArgs = args: concatStringsSep " " (mapAttrsToList serialiseArg args); + + makeDefs = gen: + mapAttrs' + (name: pairCfg: nameValuePair "unison-pair-${name}" (gen name pairCfg)) + cfg.pairs; + +in { + meta.maintainers = with maintainers; [ pacien ]; + + options.services.unison = { + enable = mkEnableOption "Unison synchronisation"; + + pairs = mkOption { + type = with types; attrsOf (submodule pairOptions); + default = { }; + example = literalExample '' + { + roots = [ + "/home/user/documents" + "ssh://remote/documents" + ]; + } + ''; + description = '' + Unison root pairs to keep synchronised. + ''; + }; + }; + + config = mkIf cfg.enable { + systemd.user.services = makeDefs (name: pairCfg: { + Unit = { + Description = "Unison pair sync (${name})"; + # Retry forever, useful in case of network disruption. + StartLimitIntervalSec = 0; + }; + + Service = { + Restart = "always"; + RestartSec = 60; + + CPUSchedulingPolicy = "idle"; + IOSchedulingClass = "idle"; + + Environment = [ "UNISON='${toString pairCfg.stateDirectory}'" ]; + ExecStart = '' + ${pkgs.unison}/bin/unison \ + ${serialiseArgs pairCfg.commandOptions} \ + ${strings.concatMapStringsSep " " escapeShellArg pairCfg.roots} + ''; + }; + + Install = { WantedBy = [ "default.target" ]; }; + }); + }; +} diff --git a/home-manager/modules/services/window-managers/awesome.nix b/home-manager/modules/services/window-managers/awesome.nix index fe914864e2a..d2e2903f83b 100644 --- a/home-manager/modules/services/window-managers/awesome.nix +++ b/home-manager/modules/services/window-managers/awesome.nix @@ -9,12 +9,9 @@ let getLuaPath = lib: dir: "${lib}/${dir}/lua/${pkgs.luaPackages.lua.luaversion}"; makeSearchPath = lib.concatMapStrings (path: " --search ${getLuaPath path "share"}" - + " --search ${getLuaPath path "lib"}" - ); + + " --search ${getLuaPath path "lib"}"); -in - -{ +in { options = { xsession.windowManager.awesome = { enable = mkEnableOption "Awesome window manager."; @@ -27,31 +24,29 @@ in }; luaModules = mkOption { - default = []; - type = types.listOf types.package; - description = '' - List of lua packages available for being - used in the Awesome configuration. - ''; - example = literalExample "[ luaPackages.oocairo ]"; + default = [ ]; + type = types.listOf types.package; + description = '' + List of lua packages available for being + used in the Awesome configuration. + ''; + example = literalExample "[ luaPackages.oocairo ]"; }; noArgb = mkOption { - default = false; - type = types.bool; - description = '' - Disable client transparency support, which can be greatly - detrimental to performance in some setups - ''; + default = false; + type = types.bool; + description = '' + Disable client transparency support, which can be greatly + detrimental to performance in some setups + ''; }; }; }; config = mkIf cfg.enable { home.packages = [ awesome ]; - xsession.windowManager.command = - "${awesome}/bin/awesome " - + optionalString cfg.noArgb "--no-argb " - + makeSearchPath cfg.luaModules; + xsession.windowManager.command = "${awesome}/bin/awesome " + + optionalString cfg.noArgb "--no-argb " + makeSearchPath cfg.luaModules; }; } diff --git a/home-manager/modules/services/window-managers/bspwm/default.nix b/home-manager/modules/services/window-managers/bspwm/default.nix new file mode 100644 index 00000000000..9ea5adbc880 --- /dev/null +++ b/home-manager/modules/services/window-managers/bspwm/default.nix @@ -0,0 +1,74 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.xsession.windowManager.bspwm; + bspwm = cfg.package; + + camelToSnake = s: + builtins.replaceStrings lib.upperChars (map (c: "_${c}") lib.lowerChars) s; + + formatConfig = n: v: + let + formatList = x: + if isList x then + throw "can not convert 2-dimensional lists to bspwm format" + else + formatValue x; + + formatValue = v: + if isBool v then + (if v then "true" else "false") + else if isList v then + concatMapStringsSep ", " formatList v + else if isString v then + "${lib.strings.escapeShellArg v}" + else + toString v; + in "bspc config ${n} ${formatValue v}"; + + formatMonitors = n: v: "bspc monitor ${n} -d ${concatStringsSep " " v}"; + + formatRules = target: directiveOptions: + let + formatDirective = n: v: + if isBool v then + (if v then "${camelToSnake n}=on" else "${camelToSnake n}=off") + else if (n == "desktop" || n == "node") then + "${camelToSnake n}='${v}'" + else + "${camelToSnake n}=${lib.strings.escapeShellArg v}"; + + directives = + filterAttrs (n: v: v != null && !(lib.strings.hasPrefix "_" n)) + directiveOptions; + directivesStr = builtins.concatStringsSep " " + (mapAttrsToList formatDirective directives); + in "bspc rule -a ${target} ${directivesStr}"; + + formatStartupPrograms = map (s: "${s} &"); + +in { + options = import ./options.nix { + inherit pkgs; + inherit lib; + }; + + config = mkIf cfg.enable { + home.packages = [ bspwm ]; + xsession.windowManager.command = let + configFile = pkgs.writeShellScript "bspwmrc" (concatStringsSep "\n" + ((mapAttrsToList formatMonitors cfg.monitors) + ++ (mapAttrsToList formatConfig cfg.settings) + ++ (mapAttrsToList formatRules cfg.rules) ++ ['' + # java gui fixes + export _JAVA_AWT_WM_NONREPARENTING=1 + bspc rule -a sun-awt-X11-XDialogPeer state=floating + ''] ++ [ cfg.extraConfig ] + ++ (formatStartupPrograms cfg.startupPrograms))); + configCmdOpt = optionalString (cfg.settings != null) "-c ${configFile}"; + in "${cfg.package}/bin/bspwm ${configCmdOpt}"; + }; +} diff --git a/home-manager/modules/services/window-managers/bspwm/options.nix b/home-manager/modules/services/window-managers/bspwm/options.nix new file mode 100644 index 00000000000..58a58a1a782 --- /dev/null +++ b/home-manager/modules/services/window-managers/bspwm/options.nix @@ -0,0 +1,214 @@ +{ pkgs, lib }: + +with lib; + +let + + rule = types.submodule { + options = { + monitor = mkOption { + type = types.nullOr types.str; + default = null; + description = "The monitor where the rule should be applied."; + example = "HDMI-0"; + }; + + desktop = mkOption { + type = types.nullOr types.str; + default = null; + description = "The desktop where the rule should be applied."; + example = "^8"; + }; + + node = mkOption { + type = types.nullOr types.str; + default = null; + description = "The node where the rule should be applied."; + example = "1"; + }; + + state = mkOption { + type = types.nullOr + (types.enum [ "tiled" "pseudo_tiled" "floating" "fullscreen" ]); + default = null; + description = "The state in which a new window should spawn."; + example = "floating"; + }; + + layer = mkOption { + type = types.nullOr (types.enum [ "below" "normal" "above" ]); + default = null; + description = "The layer where a new window should spawn."; + example = "above"; + }; + + splitDir = mkOption { + type = types.nullOr (types.enum [ "north" "west" "south" "east" ]); + default = null; + description = "The direction where the container is going to be split."; + example = "south"; + }; + + splitRatio = mkOption { + type = types.nullOr types.float; + default = null; + description = '' + The ratio between the new window and the previous existing window in + the desktop. + ''; + example = 0.65; + }; + + hidden = mkOption { + type = types.nullOr types.bool; + default = null; + description = "Whether the node should occupy any space."; + example = true; + }; + + sticky = mkOption { + type = types.nullOr types.bool; + default = null; + description = "Whether the node should stay on the focused desktop."; + example = true; + }; + + private = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Whether the node should stay in the same tiling position and size. + ''; + example = true; + }; + + locked = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Whether the node should ignore <command>node --close</command> + messages. + ''; + example = true; + }; + + marked = mkOption { + type = types.nullOr types.bool; + default = null; + description = "Whether the node will be marked for deferred actions."; + example = true; + }; + + center = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Whether the node will be put in the center, in floating mode. + ''; + example = true; + }; + + follow = mkOption { + type = types.nullOr types.bool; + default = null; + description = "Whether focus should follow the node when it is moved."; + example = true; + }; + + manage = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Whether the window should be managed by bspwm. If false, the window + will be ignored by bspwm entirely. This is useful for overlay apps, + e.g. screenshot tools. + ''; + example = true; + }; + + focus = mkOption { + type = types.nullOr types.bool; + default = null; + description = "Whether the node should gain focus on creation."; + example = true; + }; + + border = mkOption { + type = types.nullOr types.bool; + default = null; + description = "Whether the node should have border."; + example = true; + }; + }; + }; + +in { + xsession.windowManager.bspwm = { + enable = mkEnableOption "bspwm window manager."; + + package = mkOption { + type = types.package; + default = pkgs.bspwm; + defaultText = literalExample "pkgs.bspwm"; + description = "bspwm package to use."; + example = literalExample "pkgs.bspwm-unstable"; + }; + + settings = mkOption { + type = with types; + let primitive = either bool (either int (either float str)); + in attrsOf (either primitive (listOf primitive)); + default = { }; + description = "bspwm configuration"; + example = { + "border_width" = 2; + "split_ratio" = 0.52; + "gapless_monocle" = true; + }; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = "Additional configuration to add."; + example = '' + bspc subscribe all > ~/bspc-report.log & + ''; + }; + + monitors = mkOption { + type = types.attrsOf (types.listOf types.str); + default = { }; + description = "bspc monitor configurations"; + example = { "HDMI-0" = [ "web" "terminal" "III" "IV" ]; }; + }; + + rules = mkOption { + type = types.attrsOf rule; + default = { }; + description = "bspc rules"; + example = literalExample '' + { + "Gimp" = { + desktop = "^8"; + state = "floating"; + follow = true; + }; + "Kupfer.py" = { + focus = true; + }; + "Screenkey" = { + manage = false; + }; + } + ''; + }; + + startupPrograms = mkOption { + type = types.listOf types.str; + default = [ ]; + description = "Programs to be executed during startup."; + example = [ "numlockx on" "tilda" ]; + }; + }; +} diff --git a/home-manager/modules/services/window-managers/i3.nix b/home-manager/modules/services/window-managers/i3.nix index 6c52ff6c335..7a4ec90b1cd 100644 --- a/home-manager/modules/services/window-managers/i3.nix +++ b/home-manager/modules/services/window-managers/i3.nix @@ -416,6 +416,18 @@ let ''; }; + workspaceAutoBackAndForth = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + Assume you are on workspace "1: www" and switch to "2: IM" using + mod+2 because somebody sent you a message. You don’t need to remember + where you came from now, you can just press $mod+2 again to switch + back to "1: www". + ''; + }; + keybindings = mkOption { type = types.attrsOf (types.nullOr types.str); default = mapAttrs (n: mkOptionDefault) { @@ -444,25 +456,32 @@ let "${cfg.config.modifier}+Shift+space" = "floating toggle"; "${cfg.config.modifier}+space" = "focus mode_toggle"; - "${cfg.config.modifier}+1" = "workspace 1"; - "${cfg.config.modifier}+2" = "workspace 2"; - "${cfg.config.modifier}+3" = "workspace 3"; - "${cfg.config.modifier}+4" = "workspace 4"; - "${cfg.config.modifier}+5" = "workspace 5"; - "${cfg.config.modifier}+6" = "workspace 6"; - "${cfg.config.modifier}+7" = "workspace 7"; - "${cfg.config.modifier}+8" = "workspace 8"; - "${cfg.config.modifier}+9" = "workspace 9"; - - "${cfg.config.modifier}+Shift+1" = "move container to workspace 1"; - "${cfg.config.modifier}+Shift+2" = "move container to workspace 2"; - "${cfg.config.modifier}+Shift+3" = "move container to workspace 3"; - "${cfg.config.modifier}+Shift+4" = "move container to workspace 4"; - "${cfg.config.modifier}+Shift+5" = "move container to workspace 5"; - "${cfg.config.modifier}+Shift+6" = "move container to workspace 6"; - "${cfg.config.modifier}+Shift+7" = "move container to workspace 7"; - "${cfg.config.modifier}+Shift+8" = "move container to workspace 8"; - "${cfg.config.modifier}+Shift+9" = "move container to workspace 9"; + "${cfg.config.modifier}+a" = "focus parent"; + + "${cfg.config.modifier}+Shift+minus" = "move scratchpad"; + "${cfg.config.modifier}+minus" = "scratchpad show"; + + "${cfg.config.modifier}+1" = "workspace number 1"; + "${cfg.config.modifier}+2" = "workspace number 2"; + "${cfg.config.modifier}+3" = "workspace number 3"; + "${cfg.config.modifier}+4" = "workspace number 4"; + "${cfg.config.modifier}+5" = "workspace number 5"; + "${cfg.config.modifier}+6" = "workspace number 6"; + "${cfg.config.modifier}+7" = "workspace number 7"; + "${cfg.config.modifier}+8" = "workspace number 8"; + "${cfg.config.modifier}+9" = "workspace number 9"; + "${cfg.config.modifier}+0" = "workspace number 10"; + + "${cfg.config.modifier}+Shift+1" = "move container to workspace number 1"; + "${cfg.config.modifier}+Shift+2" = "move container to workspace number 2"; + "${cfg.config.modifier}+Shift+3" = "move container to workspace number 3"; + "${cfg.config.modifier}+Shift+4" = "move container to workspace number 4"; + "${cfg.config.modifier}+Shift+5" = "move container to workspace number 5"; + "${cfg.config.modifier}+Shift+6" = "move container to workspace number 6"; + "${cfg.config.modifier}+Shift+7" = "move container to workspace number 7"; + "${cfg.config.modifier}+Shift+8" = "move container to workspace number 8"; + "${cfg.config.modifier}+Shift+9" = "move container to workspace number 9"; + "${cfg.config.modifier}+Shift+0" = "move container to workspace number 10"; "${cfg.config.modifier}+Shift+c" = "reload"; "${cfg.config.modifier}+Shift+r" = "restart"; @@ -752,6 +771,7 @@ let focus_on_window_activation ${focus.newWindow} mouse_warping ${if focus.mouseWarping then "output" else "none"} workspace_layout ${workspaceLayout} + workspace_auto_back_and_forth ${if workspaceAutoBackAndForth then "yes" else "no"} client.focused ${colorSetStr colors.focused} client.focused_inactive ${colorSetStr colors.focusedInactive} diff --git a/home-manager/modules/services/window-managers/xmonad.nix b/home-manager/modules/services/window-managers/xmonad.nix index 6b3426b963b..7be03874a89 100644 --- a/home-manager/modules/services/window-managers/xmonad.nix +++ b/home-manager/modules/services/window-managers/xmonad.nix @@ -9,15 +9,13 @@ let xmonad = pkgs.xmonad-with-packages.override { ghcWithPackages = cfg.haskellPackages.ghcWithPackages; packages = self: - cfg.extraPackages self - ++ optionals cfg.enableContribAndExtras [ - self.xmonad-contrib self.xmonad-extras + cfg.extraPackages self ++ optionals cfg.enableContribAndExtras [ + self.xmonad-contrib + self.xmonad-extras ]; }; -in - -{ +in { options = { xsession.windowManager.xmonad = { enable = mkEnableOption "xmonad window manager"; @@ -35,7 +33,7 @@ in }; extraPackages = mkOption { - default = self: []; + default = self: [ ]; defaultText = "self: []"; example = literalExample '' haskellPackages: [ diff --git a/home-manager/modules/services/xcape.nix b/home-manager/modules/services/xcape.nix index 26115a93062..f4f77caa331 100644 --- a/home-manager/modules/services/xcape.nix +++ b/home-manager/modules/services/xcape.nix @@ -6,9 +6,7 @@ let cfg = config.services.xcape; -in - -{ +in { meta.maintainers = [ maintainers.nickhu ]; options = { @@ -27,8 +25,11 @@ in mapExpression = mkOption { type = types.attrsOf types.str; - default = {}; - example = { Shift_L = "Escape"; Control_L = "Control_L|O"; }; + default = { }; + example = { + Shift_L = "Escape"; + Control_L = "Control_L|O"; + }; description = '' The value has the grammar <literal>Key[|OtherKey]</literal>. </para> @@ -63,14 +64,13 @@ in Type = "forking"; ExecStart = "${pkgs.xcape}/bin/xcape" + optionalString (cfg.timeout != null) " -t ${toString cfg.timeout}" - + optionalString (cfg.mapExpression != {}) - " -e '${builtins.concatStringsSep ";" - (attrsets.mapAttrsToList (n: v: "${n}=${v}") cfg.mapExpression)}'"; + + optionalString (cfg.mapExpression != { }) " -e '${ + builtins.concatStringsSep ";" + (attrsets.mapAttrsToList (n: v: "${n}=${v}") cfg.mapExpression) + }'"; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; }; }; } diff --git a/home-manager/modules/services/xembed-sni-proxy.nix b/home-manager/modules/services/xembed-sni-proxy.nix index d9e5ae783f9..ff63d108b77 100644 --- a/home-manager/modules/services/xembed-sni-proxy.nix +++ b/home-manager/modules/services/xembed-sni-proxy.nix @@ -6,9 +6,7 @@ let cfg = config.services.xembed-sni-proxy; -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; options = { @@ -35,9 +33,7 @@ in PartOf = [ "graphical-session.target" ]; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { Environment = "PATH=${config.home.profileDirectory}/bin"; diff --git a/home-manager/modules/services/xscreensaver.nix b/home-manager/modules/services/xscreensaver.nix index 4001c294e86..73a365aa730 100644 --- a/home-manager/modules/services/xscreensaver.nix +++ b/home-manager/modules/services/xscreensaver.nix @@ -6,9 +6,7 @@ let cfg = config.services.xscreensaver; -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; options = { @@ -17,7 +15,7 @@ in settings = mkOption { type = with types; attrsOf (either bool (either int str)); - default = {}; + default = { }; example = { mode = "blank"; lock = false; @@ -38,19 +36,17 @@ in mapAttrs' (n: nameValuePair "xscreensaver.${n}") cfg.settings; systemd.user.services.xscreensaver = { - Unit = { - Description = "XScreenSaver"; - After = [ "graphical-session-pre.target" ]; - PartOf = [ "graphical-session.target" ]; - }; + Unit = { + Description = "XScreenSaver"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; - Service = { - ExecStart = "${pkgs.xscreensaver}/bin/xscreensaver -no-splash"; - }; + Service = { + ExecStart = "${pkgs.xscreensaver}/bin/xscreensaver -no-splash"; + }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; }; }; } diff --git a/home-manager/modules/services/xsuspender.nix b/home-manager/modules/services/xsuspender.nix index 22a5ca536a5..2eb40f5dd34 100644 --- a/home-manager/modules/services/xsuspender.nix +++ b/home-manager/modules/services/xsuspender.nix @@ -61,7 +61,7 @@ let ''; type = types.nullOr types.str; default = null; - example = ''echo resuming ...''; + example = "echo resuming ..."; }; sendSignals = mkOption { @@ -74,7 +74,8 @@ let }; suspendSubtreePattern = mkOption { - description = "Also suspend descendant processes that match this regex."; + description = + "Also suspend descendant processes that match this regex."; type = types.nullOr types.str; default = null; }; @@ -105,9 +106,7 @@ let }; }; -in - -{ +in { meta.maintainers = [ maintainers.offline ]; options = { @@ -117,13 +116,13 @@ in defaults = mkOption { description = "XSuspender defaults."; type = xsuspenderOptions; - default = {}; + default = { }; }; rules = mkOption { description = "Attribute set of XSuspender rules."; type = types.attrsOf xsuspenderOptions; - default = {}; + default = { }; example = { Chromium = { suspendDelay = 10; @@ -147,9 +146,9 @@ in }; config = mkIf cfg.enable { - services.xsuspender.iniContent = - let - mkSection = values: filterAttrs (_: v: v != null) { + services.xsuspender.iniContent = let + mkSection = values: + filterAttrs (_: v: v != null) { match_wm_class_contains = values.matchWmClassContains; match_wm_class_group_contains = values.matchWmClassGroupContains; match_wm_name_contains = values.matchWmNameContains; @@ -164,25 +163,22 @@ in auto_suspend_on_battery = values.autoSuspendOnBattery; downclock_on_battery = values.downclockOnBattery; }; - in - { - Default = mkSection cfg.defaults; - } - // mapAttrs (_: mkSection) cfg.rules; + in { + Default = mkSection cfg.defaults; + } // mapAttrs (_: mkSection) cfg.rules; # To make the xsuspender tool available. home.packages = [ pkgs.xsuspender ]; - xdg.configFile."xsuspender.conf".text = generators.toINI {} cfg.iniContent; + xdg.configFile."xsuspender.conf".text = generators.toINI { } cfg.iniContent; systemd.user.services.xsuspender = { Unit = { Description = "XSuspender"; After = [ "graphical-session-pre.target" ]; PartOf = [ "graphical-session.target" ]; - X-Restart-Triggers = [ - "${config.xdg.configFile."xsuspender.conf".source}" - ]; + X-Restart-Triggers = + [ "${config.xdg.configFile."xsuspender.conf".source}" ]; }; Service = { @@ -190,9 +186,7 @@ in Environment = mkIf cfg.debug [ "G_MESSAGE_DEBUG=all" ]; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; }; }; } diff --git a/home-manager/modules/systemd.nix b/home-manager/modules/systemd.nix index cdc4486f542..56164020577 100644 --- a/home-manager/modules/systemd.nix +++ b/home-manager/modules/systemd.nix @@ -6,8 +6,6 @@ let cfg = config.systemd.user; - dag = config.lib.dag; - enabled = cfg.services != {} || cfg.sockets != {} || cfg.targets != {} @@ -230,7 +228,7 @@ in # running this from the NixOS module then XDG_RUNTIME_DIR is not # set and systemd commands will fail. We'll therefore have to # set it ourselves in that case. - home.activation.reloadSystemD = dag.entryAfter ["linkGeneration"] ( + home.activation.reloadSystemD = hm.dag.entryAfter ["linkGeneration"] ( let autoReloadCmd = '' ${pkgs.ruby}/bin/ruby ${./systemd-activate.rb} \ @@ -242,15 +240,27 @@ in ''; ensureRuntimeDir = "XDG_RUNTIME_DIR=\${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"; + + systemctl = "${ensureRuntimeDir} ${cfg.systemctlPath}"; in '' - if ${ensureRuntimeDir} ${cfg.systemctlPath} --quiet --user is-system-running 2> /dev/null; then + systemdStatus=$(${systemctl} --user is-system-running 2>&1 || true) + + if [[ $systemdStatus == 'running' || $systemdStatus == 'degraded' ]]; then + if [[ $systemdStatus == 'degraded' ]]; then + warnEcho "The user systemd session is degraded:" + ${systemctl} --user --state=failed + warnEcho "Attempting to reload services anyway..." + fi + ${ensureRuntimeDir} \ PATH=${dirOf cfg.systemctlPath}:$PATH \ ${if cfg.startServices then autoReloadCmd else legacyReloadCmd} else echo "User systemd daemon not running. Skipping reload." fi + + unset systemdStatus '' ); }) diff --git a/home-manager/modules/xcursor.nix b/home-manager/modules/xcursor.nix index 171586028cd..63ceef387df 100644 --- a/home-manager/modules/xcursor.nix +++ b/home-manager/modules/xcursor.nix @@ -36,9 +36,7 @@ let }; }; -in - -{ +in { meta.maintainers = [ maintainers.league ]; options = { @@ -58,15 +56,17 @@ in config = mkIf (cfg != null) { - home.packages = [cfg.package]; + home.packages = [ cfg.package ]; xsession.initExtra = '' - ${pkgs.xorg.xsetroot}/bin/xsetroot -xcf ${cfg.package}/share/icons/${cfg.name}/cursors/${cfg.defaultCursor} ${toString cfg.size} + ${pkgs.xorg.xsetroot}/bin/xsetroot -xcf ${cfg.package}/share/icons/${cfg.name}/cursors/${cfg.defaultCursor} ${ + toString cfg.size + } ''; xresources.properties = { "Xcursor.theme" = cfg.name; - "Xcursor.size" = cfg.size; + "Xcursor.size" = cfg.size; }; gtk.gtk2.extraConfig = '' diff --git a/home-manager/modules/xresources.nix b/home-manager/modules/xresources.nix index 384008e2450..b74d671befb 100644 --- a/home-manager/modules/xresources.nix +++ b/home-manager/modules/xresources.nix @@ -9,31 +9,34 @@ let formatLine = n: v: let formatList = x: - if isList x - then throw "can not convert 2-dimensional lists to Xresources format" - else formatValue x; + if isList x then + throw "can not convert 2-dimensional lists to Xresources format" + else + formatValue x; formatValue = v: - if isBool v then (if v then "true" else "false") - else if isList v then concatMapStringsSep ", " formatList v - else toString v; - in - "${n}: ${formatValue v}"; + if isBool v then + (if v then "true" else "false") + else if isList v then + concatMapStringsSep ", " formatList v + else + toString v; + in "${n}: ${formatValue v}"; -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; options = { xresources.properties = mkOption { type = types.nullOr types.attrs; default = null; - example = { - "Emacs*toolBar" = 0; - "XTerm*faceName" = "dejavu sans mono"; - "XTerm*charClass" = [ "37:48" "45-47:48" "58:48" "64:48" "126:48" ]; - }; + example = literalExample '' + { + "Emacs*toolBar" = 0; + "XTerm*faceName" = "dejavu sans mono"; + "XTerm*charClass" = [ "37:48" "45-47:48" "58:48" "64:48" "126:48" ]; + } + ''; description = '' X server resources that should be set. Booleans are formatted as "true" or "false" respectively. @@ -70,11 +73,10 @@ in config = mkIf (cfg.properties != null || cfg.extraConfig != "") { home.file.".Xresources" = { - text = - concatStringsSep "\n" ([] - ++ optional (cfg.extraConfig != "") cfg.extraConfig - ++ optionals (cfg.properties != null) (mapAttrsToList formatLine cfg.properties) - ) + "\n"; + text = concatStringsSep "\n" ([ ] + ++ optional (cfg.extraConfig != "") cfg.extraConfig + ++ optionals (cfg.properties != null) + (mapAttrsToList formatLine cfg.properties)) + "\n"; onChange = '' if [[ -v DISPLAY ]] ; then $DRY_RUN_CMD ${pkgs.xorg.xrdb}/bin/xrdb -merge $HOME/.Xresources diff --git a/home-manager/modules/xsession.nix b/home-manager/modules/xsession.nix index e1cf9942e7c..d32c2849163 100644 --- a/home-manager/modules/xsession.nix +++ b/home-manager/modules/xsession.nix @@ -6,9 +6,7 @@ let cfg = config.xsession; -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; options = { @@ -89,30 +87,25 @@ in systemd.user = { services = mkIf (config.home.keyboard != null) { - setxkbmap = { + setxkbmap = { Unit = { Description = "Set up keyboard in X"; After = [ "graphical-session-pre.target" ]; PartOf = [ "graphical-session.target" ]; }; - Install = { - WantedBy = [ "graphical-session.target" ]; - }; + Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { Type = "oneshot"; RemainAfterExit = true; - ExecStart = - with config.home.keyboard; + ExecStart = with config.home.keyboard; let - args = - optional (layout != null) "-layout '${layout}'" + args = optional (layout != null) "-layout '${layout}'" ++ optional (variant != null) "-variant '${variant}'" ++ optional (model != null) "-model '${model}'" ++ map (v: "-option '${v}'") options; - in - "${pkgs.xorg.setxkbmap}/bin/setxkbmap ${toString args}"; + in "${pkgs.xorg.setxkbmap}/bin/setxkbmap ${toString args}"; }; }; }; @@ -128,25 +121,24 @@ in }; home.file.".xprofile".text = '' - . "${config.home.profileDirectory}/etc/profile.d/hm-session-vars.sh" + . "${config.home.profileDirectory}/etc/profile.d/hm-session-vars.sh" - if [ -e "$HOME/.profile" ]; then - . "$HOME/.profile" - fi + if [ -e "$HOME/.profile" ]; then + . "$HOME/.profile" + fi - # If there are any running services from a previous session. - # Need to run this in xprofile because the NixOS xsession - # script starts up graphical-session.target. - systemctl --user stop graphical-session.target graphical-session-pre.target + # If there are any running services from a previous session. + # Need to run this in xprofile because the NixOS xsession + # script starts up graphical-session.target. + systemctl --user stop graphical-session.target graphical-session-pre.target - ${optionalString (cfg.importedVariables != []) ( - "systemctl --user import-environment " - + toString (unique cfg.importedVariables) - )} + ${optionalString (cfg.importedVariables != [ ]) + ("systemctl --user import-environment " + + toString (unique cfg.importedVariables))} - ${cfg.profileExtra} + ${cfg.profileExtra} - export HM_XPROFILE_SOURCED=1 + export HM_XPROFILE_SOURCED=1 ''; home.file.${cfg.scriptPath} = { diff --git a/home-manager/nix-darwin/default.nix b/home-manager/nix-darwin/default.nix index 1482c7bb245..24f042a7f0b 100644 --- a/home-manager/nix-darwin/default.nix +++ b/home-manager/nix-darwin/default.nix @@ -6,17 +6,27 @@ let cfg = config.home-manager; - hmModule = types.submodule ({name, ...}: { - imports = import ../modules/modules.nix { inherit lib pkgs; }; + extendedLib = import ../modules/lib/stdlib-extended.nix pkgs.lib; - config = { - submoduleSupport.enable = true; - submoduleSupport.externalPackageInstall = cfg.useUserPackages; + hmModule = types.submoduleWith { + specialArgs = { lib = extendedLib; }; + modules = [( + {name, ...}: { + imports = import ../modules/modules.nix { + inherit pkgs; + lib = extendedLib; + }; - home.username = config.users.users.${name}.name; - home.homeDirectory = config.users.users.${name}.home; - }; - }); + config = { + submoduleSupport.enable = true; + submoduleSupport.externalPackageInstall = cfg.useUserPackages; + + home.username = config.users.users.${name}.name; + home.homeDirectory = config.users.users.${name}.home; + }; + } + )]; + }; in diff --git a/home-manager/nixos/default.nix b/home-manager/nixos/default.nix index f53b4d4d6b7..f4e417bda71 100644 --- a/home-manager/nixos/default.nix +++ b/home-manager/nixos/default.nix @@ -6,34 +6,38 @@ let cfg = config.home-manager; - hmModule = types.submodule ({name, ...}: { - imports = import ../modules/modules.nix { inherit lib pkgs; }; - - config = { - submoduleSupport.enable = true; - submoduleSupport.externalPackageInstall = cfg.useUserPackages; - - # The per-user directory inside /etc/profiles is not known by - # fontconfig by default. - fonts.fontconfig.enable = - cfg.useUserPackages && config.fonts.fontconfig.enable; - - home.username = config.users.users.${name}.name; - home.homeDirectory = config.users.users.${name}.home; - }; - }); - - serviceEnvironment = - optionalAttrs (cfg.backupFileExtension != null) { - HOME_MANAGER_BACKUP_EXT = cfg.backupFileExtension; - } - // optionalAttrs cfg.verbose { - VERBOSE = "1"; - }; + extendedLib = import ../modules/lib/stdlib-extended.nix pkgs.lib; + + hmModule = types.submoduleWith { + specialArgs = { lib = extendedLib; }; + modules = [ + ({ name, ... }: { + imports = import ../modules/modules.nix { + inherit pkgs; + lib = extendedLib; + }; + + config = { + submoduleSupport.enable = true; + submoduleSupport.externalPackageInstall = cfg.useUserPackages; + + # The per-user directory inside /etc/profiles is not known by + # fontconfig by default. + fonts.fontconfig.enable = cfg.useUserPackages + && config.fonts.fontconfig.enable; + + home.username = config.users.users.${name}.name; + home.homeDirectory = config.users.users.${name}.home; + }; + }) + ]; + }; -in + serviceEnvironment = optionalAttrs (cfg.backupFileExtension != null) { + HOME_MANAGER_BACKUP_EXT = cfg.backupFileExtension; + } // optionalAttrs cfg.verbose { VERBOSE = "1"; }; -{ +in { options = { home-manager = { useUserPackages = mkEnableOption '' @@ -55,7 +59,7 @@ in users = mkOption { type = types.attrsOf hmModule; - default = {}; + default = { }; description = '' Per-user Home Manager configuration. ''; @@ -63,57 +67,44 @@ in }; }; - config = mkIf (cfg.users != {}) { - warnings = - flatten (flip mapAttrsToList cfg.users (user: config: - flip map config.warnings (warning: - "${user} profile: ${warning}" - ) - )); - - assertions = - flatten (flip mapAttrsToList cfg.users (user: config: - flip map config.assertions (assertion: - { - inherit (assertion) assertion; - message = "${user} profile: ${assertion.message}"; - } - ) - )); - - users.users = mkIf cfg.useUserPackages ( - mapAttrs (username: usercfg: { - packages = usercfg.home.packages; - }) cfg.users - ); + config = mkIf (cfg.users != { }) { + warnings = flatten (flip mapAttrsToList cfg.users (user: config: + flip map config.warnings (warning: "${user} profile: ${warning}"))); + + assertions = flatten (flip mapAttrsToList cfg.users (user: config: + flip map config.assertions (assertion: { + inherit (assertion) assertion; + message = "${user} profile: ${assertion.message}"; + }))); + + users.users = mkIf cfg.useUserPackages + (mapAttrs (username: usercfg: { packages = usercfg.home.packages; }) + cfg.users); systemd.services = mapAttrs' (_: usercfg: - let - username = usercfg.home.username; - in - nameValuePair ("home-manager-${utils.escapeSystemdPath username}") { - description = "Home Manager environment for ${username}"; - wantedBy = [ "multi-user.target" ]; - wants = [ "nix-daemon.socket" ]; - after = [ "nix-daemon.socket" ]; - - environment = serviceEnvironment; - - serviceConfig = { - User = usercfg.home.username; - Type = "oneshot"; - RemainAfterExit = "yes"; - SyslogIdentifier = "hm-activate-${username}"; - - # The activation script is run by a login shell to make sure - # that the user is given a sane Nix environment. - ExecStart = pkgs.writeScript "activate-${username}" '' - #! ${pkgs.runtimeShell} -el - echo Activating home-manager configuration for ${username} - exec ${usercfg.home.activationPackage}/activate - ''; - }; - } - ) cfg.users; + let username = usercfg.home.username; + in nameValuePair ("home-manager-${utils.escapeSystemdPath username}") { + description = "Home Manager environment for ${username}"; + wantedBy = [ "multi-user.target" ]; + wants = [ "nix-daemon.socket" ]; + after = [ "nix-daemon.socket" ]; + + environment = serviceEnvironment; + + serviceConfig = { + User = usercfg.home.username; + Type = "oneshot"; + RemainAfterExit = "yes"; + SyslogIdentifier = "hm-activate-${username}"; + + # The activation script is run by a login shell to make sure + # that the user is given a sane Nix environment. + ExecStart = pkgs.writeScript "activate-${username}" '' + #! ${pkgs.runtimeShell} -el + echo Activating home-manager configuration for ${username} + exec ${usercfg.home.activationPackage}/activate + ''; + }; + }) cfg.users; }; } diff --git a/home-manager/overlay.nix b/home-manager/overlay.nix index fa779fe0370..35136cc8556 100644 --- a/home-manager/overlay.nix +++ b/home-manager/overlay.nix @@ -1,5 +1,3 @@ self: super: { - home-manager = super.callPackage ./home-manager { - path = toString ./.; - }; + home-manager = super.callPackage ./home-manager { path = toString ./.; }; } diff --git a/home-manager/tests/default.nix b/home-manager/tests/default.nix index ecb98e14188..49c27239730 100644 --- a/home-manager/tests/default.nix +++ b/home-manager/tests/default.nix @@ -2,52 +2,53 @@ let + lib = import ../modules/lib/stdlib-extended.nix pkgs.lib; + nmt = pkgs.fetchFromGitLab { owner = "rycee"; repo = "nmt"; - rev = "89fb12a2aaa8ec671e22a033162c7738be714305"; - sha256 = "07yc1jkgw8vhskzk937k9hfba401q8rn4sgj9baw3fkjl9zrbcyf"; + rev = "6f866d1acb89fa15cd3b62baa052deae1f685c0c"; + sha256 = "1qr1shhapjn4nnd4k6hml69ri8vgz4l8lakjll5hc516shs9a9nn"; + }; + + modules = import ../modules/modules.nix { + inherit lib pkgs; + check = false; }; in import nmt { - inherit pkgs; - modules = import ../modules/modules.nix { inherit pkgs; lib = pkgs.lib; }; + inherit lib pkgs modules; testedAttrPath = [ "home" "activationPackage" ]; - tests = { - browserpass = ./modules/programs/browserpass.nix; - files-executable = ./modules/files/executable.nix; - files-hidden-source = ./modules/files/hidden-source.nix; - files-source-with-spaces = ./modules/files/source-with-spaces.nix; - files-text = ./modules/files/text.nix; - git-with-email = ./modules/programs/git-with-email.nix; - git-with-most-options = ./modules/programs/git.nix; - git-with-str-extra-config = ./modules/programs/git-with-str-extra-config.nix; - mbsync = ./modules/programs/mbsync.nix; - texlive-minimal = ./modules/programs/texlive-minimal.nix; - xresources = ./modules/xresources.nix; - } - // pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux ( - { - getmail = ./modules/programs/getmail.nix; - i3-keybindings = ./modules/services/window-managers/i3-keybindings.nix; - } - // import ./modules/misc/pam - // import ./modules/misc/xdg - // import ./modules/misc/xsession - // import ./modules/programs/firefox - // import ./modules/programs/rofi - // import ./modules/services/sxhkd - // import ./modules/systemd - ) - // import ./modules/home-environment - // import ./modules/misc/fontconfig - // import ./modules/programs/alacritty - // import ./modules/programs/bash - // import ./modules/programs/gpg - // import ./modules/programs/newsboat - // import ./modules/programs/ssh - // import ./modules/programs/tmux - // import ./modules/programs/zsh; + tests = builtins.foldl' (a: b: a // (import b)) { } ([ + ./lib/types + ./modules/files + ./modules/home-environment + ./modules/misc/fontconfig + ./modules/programs/alacritty + ./modules/programs/bash + ./modules/programs/browserpass + ./modules/programs/git + ./modules/programs/gpg + ./modules/programs/mbsync + ./modules/programs/neomutt + ./modules/programs/newsboat + ./modules/programs/readline + ./modules/programs/ssh + ./modules/programs/texlive + ./modules/programs/tmux + ./modules/programs/zsh + ./modules/xresources + ] ++ lib.optionals pkgs.stdenv.hostPlatform.isLinux [ + ./modules/misc/pam + ./modules/misc/xdg + ./modules/misc/xsession + ./modules/programs/firefox + ./modules/programs/getmail + ./modules/programs/rofi + ./modules/services/sxhkd + ./modules/services/window-managers/i3 + ./modules/systemd + ]); } diff --git a/home-manager/tests/lib/types/dag-merge-result.txt b/home-manager/tests/lib/types/dag-merge-result.txt new file mode 100644 index 00000000000..9779ef13c0f --- /dev/null +++ b/home-manager/tests/lib/types/dag-merge-result.txt @@ -0,0 +1,3 @@ +before:before +between:between +after:after diff --git a/home-manager/tests/lib/types/dag-merge.nix b/home-manager/tests/lib/types/dag-merge.nix new file mode 100644 index 00000000000..138a0b64fb7 --- /dev/null +++ b/home-manager/tests/lib/types/dag-merge.nix @@ -0,0 +1,32 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + dag = config.lib.dag; + + result = let + sorted = dag.topoSort config.tested.dag; + data = map (e: "${e.name}:${e.data}") sorted.result; + in concatStringsSep "\n" data + "\n"; + +in { + options.tested.dag = mkOption { type = hm.types.dagOf types.str; }; + + config = { + tested = mkMerge [ + { dag.after = "after"; } + { dag.before = dag.entryBefore [ "after" ] "before"; } + { dag.between = dag.entryBetween [ "after" ] [ "before" ] "between"; } + ]; + + home.file."result.txt".text = result; + + nmt.script = '' + assertFileContent \ + home-files/result.txt \ + ${./dag-merge-result.txt} + ''; + }; +} diff --git a/home-manager/tests/lib/types/default.nix b/home-manager/tests/lib/types/default.nix new file mode 100644 index 00000000000..9fce65f88f0 --- /dev/null +++ b/home-manager/tests/lib/types/default.nix @@ -0,0 +1,4 @@ +{ + lib-types-dag-merge = ./dag-merge.nix; + lib-types-list-or-dag-merge = ./list-or-dag-merge.nix; +} diff --git a/home-manager/tests/lib/types/list-or-dag-merge-result.txt b/home-manager/tests/lib/types/list-or-dag-merge-result.txt new file mode 100644 index 00000000000..5fb67a5101c --- /dev/null +++ b/home-manager/tests/lib/types/list-or-dag-merge-result.txt @@ -0,0 +1,15 @@ +before:before +between:between +after:after +unnamed-1.1:k +unnamed-1.2:l +unnamed-2.01:a +unnamed-2.02:b +unnamed-2.03:c +unnamed-2.04:d +unnamed-2.05:e +unnamed-2.06:f +unnamed-2.07:g +unnamed-2.08:h +unnamed-2.09:i +unnamed-2.10:j diff --git a/home-manager/tests/lib/types/list-or-dag-merge.nix b/home-manager/tests/lib/types/list-or-dag-merge.nix new file mode 100644 index 00000000000..08216140e53 --- /dev/null +++ b/home-manager/tests/lib/types/list-or-dag-merge.nix @@ -0,0 +1,34 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + dag = config.lib.dag; + + result = let + sorted = dag.topoSort config.tested.dag; + data = map (e: "${e.name}:${e.data}") sorted.result; + in concatStringsSep "\n" data + "\n"; + +in { + options.tested.dag = mkOption { type = hm.types.listOrDagOf types.str; }; + + config = { + tested = mkMerge [ + { dag = [ "k" "l" ]; } + { dag = [ "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" ]; } + { dag.after = "after"; } + { dag.before = dag.entryBefore [ "after" ] "before"; } + { dag.between = dag.entryBetween [ "after" ] [ "before" ] "between"; } + ]; + + home.file."result.txt".text = result; + + nmt.script = '' + assertFileContent \ + home-files/result.txt \ + ${./list-or-dag-merge-result.txt} + ''; + }; +} diff --git a/home-manager/tests/modules/files/default.nix b/home-manager/tests/modules/files/default.nix new file mode 100644 index 00000000000..04c61d3b886 --- /dev/null +++ b/home-manager/tests/modules/files/default.nix @@ -0,0 +1,6 @@ +{ + files-executable = ./executable.nix; + files-hidden-source = ./hidden-source.nix; + files-source-with-spaces = ./source-with-spaces.nix; + files-text = ./text.nix; +} diff --git a/home-manager/tests/modules/files/hidden-source.nix b/home-manager/tests/modules/files/hidden-source.nix index a8635398f48..8169fedcd7f 100644 --- a/home-manager/tests/modules/files/hidden-source.nix +++ b/home-manager/tests/modules/files/hidden-source.nix @@ -9,7 +9,10 @@ with lib; nmt.script = '' assertFileExists home-files/.hidden; assertFileContent home-files/.hidden ${ - builtins.path { path = ./.hidden; name = "expected"; } + builtins.path { + path = ./.hidden; + name = "expected"; + } } ''; }; diff --git a/home-manager/tests/modules/misc/pam/default.nix b/home-manager/tests/modules/misc/pam/default.nix index 8a64f831caf..81c435e7641 100644 --- a/home-manager/tests/modules/misc/pam/default.nix +++ b/home-manager/tests/modules/misc/pam/default.nix @@ -1,3 +1 @@ -{ - pam-session-variables = ./session-variables.nix; -} +{ pam-session-variables = ./session-variables.nix; } diff --git a/home-manager/tests/modules/misc/xdg/default.nix b/home-manager/tests/modules/misc/xdg/default.nix index 5772becd712..e5d015759d5 100644 --- a/home-manager/tests/modules/misc/xdg/default.nix +++ b/home-manager/tests/modules/misc/xdg/default.nix @@ -1,3 +1 @@ -{ - xdg-mime-apps-basics = ./mime-apps-basics.nix; -} +{ xdg-mime-apps-basics = ./mime-apps-basics.nix; } diff --git a/home-manager/tests/modules/misc/xdg/mime-apps-basics.nix b/home-manager/tests/modules/misc/xdg/mime-apps-basics.nix index 2c32071064c..e181e8206f6 100644 --- a/home-manager/tests/modules/misc/xdg/mime-apps-basics.nix +++ b/home-manager/tests/modules/misc/xdg/mime-apps-basics.nix @@ -11,9 +11,7 @@ with lib; "mimetype1" = [ "foo1.desktop" "foo2.desktop" "foo3.desktop" ]; "mimetype2" = "foo4.desktop"; }; - removed = { - mimetype1 = "foo5.desktop"; - }; + removed = { mimetype1 = "foo5.desktop"; }; }; defaultApplications = { "mimetype1" = [ "default1.desktop" "default2.desktop" ]; diff --git a/home-manager/tests/modules/misc/xsession/basic.nix b/home-manager/tests/modules/misc/xsession/basic.nix index 60623d1bf6b..39df6362380 100644 --- a/home-manager/tests/modules/misc/xsession/basic.nix +++ b/home-manager/tests/modules/misc/xsession/basic.nix @@ -14,6 +14,14 @@ with lib; profileExtra = "profile extra commands"; }; + nixpkgs.overlays = [ + (self: super: { + xorg = super.xorg // { + setxkbmap = super.xorg.setxkbmap // { outPath = "@setxkbmap@"; }; + }; + }) + ]; + nmt.script = '' assertFileExists home-files/.xprofile assertFileContent \ @@ -28,10 +36,7 @@ with lib; assertFileExists home-files/.config/systemd/user/setxkbmap.service assertFileContent \ home-files/.config/systemd/user/setxkbmap.service \ - ${pkgs.substituteAll { - src = ./basic-setxkbmap-expected.service; - inherit (pkgs.xorg) setxkbmap; - }} + ${./basic-setxkbmap-expected.service} ''; }; } diff --git a/home-manager/tests/modules/misc/xsession/keyboard-without-layout.nix b/home-manager/tests/modules/misc/xsession/keyboard-without-layout.nix index b7eb3decebb..015efe6154a 100644 --- a/home-manager/tests/modules/misc/xsession/keyboard-without-layout.nix +++ b/home-manager/tests/modules/misc/xsession/keyboard-without-layout.nix @@ -8,9 +8,7 @@ with lib; home.homeDirectory = "/test-home"; - home.keyboard = { - options = [ "ctrl:nocaps" "altwin:no_win" ]; - }; + home.keyboard = { options = [ "ctrl:nocaps" "altwin:no_win" ]; }; xsession = { enable = true; @@ -20,14 +18,19 @@ with lib; profileExtra = "profile extra commands"; }; + nixpkgs.overlays = [ + (self: super: { + xorg = super.xorg // { + setxkbmap = super.xorg.setxkbmap // { outPath = "@setxkbmap@"; }; + }; + }) + ]; + nmt.script = '' assertFileExists home-files/.config/systemd/user/setxkbmap.service assertFileContent \ home-files/.config/systemd/user/setxkbmap.service \ - ${pkgs.substituteAll { - src = ./keyboard-without-layout-expected.service; - inherit (pkgs.xorg) setxkbmap; - }} + ${./keyboard-without-layout-expected.service} ''; }; } diff --git a/home-manager/tests/modules/programs/alacritty/empty-settings.nix b/home-manager/tests/modules/programs/alacritty/empty-settings.nix index f3f8486ad3d..65470473c1a 100644 --- a/home-manager/tests/modules/programs/alacritty/empty-settings.nix +++ b/home-manager/tests/modules/programs/alacritty/empty-settings.nix @@ -6,6 +6,10 @@ with lib; config = { programs.alacritty.enable = true; + nixpkgs.overlays = [ + (self: super: { alacritty = pkgs.writeScriptBin "dummy-alacritty" ""; }) + ]; + nmt.script = '' assertPathNotExists home-files/.config/alacritty ''; diff --git a/home-manager/tests/modules/programs/alacritty/example-settings.nix b/home-manager/tests/modules/programs/alacritty/example-settings.nix index 2c84710d100..46be1064ce6 100644 --- a/home-manager/tests/modules/programs/alacritty/example-settings.nix +++ b/home-manager/tests/modules/programs/alacritty/example-settings.nix @@ -13,16 +13,18 @@ with lib; columns = 200; }; - key_bindings = [ - { - key = "K"; - mods = "Control"; - chars = "\\x0c"; - } - ]; + key_bindings = [{ + key = "K"; + mods = "Control"; + chars = "\\x0c"; + }]; }; }; + nixpkgs.overlays = [ + (self: super: { alacritty = pkgs.writeScriptBin "dummy-alacritty" ""; }) + ]; + nmt.script = '' assertFileContent \ home-files/.config/alacritty/alacritty.yml \ diff --git a/home-manager/tests/modules/programs/bash/session-variables-expected.txt b/home-manager/tests/modules/programs/bash/session-variables-expected.txt index c586477ec4d..e13d63d4c78 100644 --- a/home-manager/tests/modules/programs/bash/session-variables-expected.txt +++ b/home-manager/tests/modules/programs/bash/session-variables-expected.txt @@ -1,6 +1,6 @@ # -*- mode: sh -*- -. "@homeDirectory@/.nix-profile/etc/profile.d/hm-session-vars.sh" +. "/home/testuser/.nix-profile/etc/profile.d/hm-session-vars.sh" export V1="v1" export V2="v2-v1" diff --git a/home-manager/tests/modules/programs/bash/session-variables.nix b/home-manager/tests/modules/programs/bash/session-variables.nix index a7a69a2a1f8..ea789a1d061 100644 --- a/home-manager/tests/modules/programs/bash/session-variables.nix +++ b/home-manager/tests/modules/programs/bash/session-variables.nix @@ -13,16 +13,13 @@ with lib; }; }; + home.homeDirectory = "/home/testuser"; + nmt.script = '' assertFileExists home-files/.profile assertFileContent \ home-files/.profile \ - ${ - pkgs.substituteAll { - src = ./session-variables-expected.txt; - inherit (config.home) homeDirectory; - } - } + ${./session-variables-expected.txt} ''; }; } diff --git a/home-manager/tests/modules/programs/browserpass.nix b/home-manager/tests/modules/programs/browserpass.nix deleted file mode 100644 index 229392e171b..00000000000 --- a/home-manager/tests/modules/programs/browserpass.nix +++ /dev/null @@ -1,35 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; - -{ - config = { - programs.browserpass = { - enable = true; - browsers = [ - "chrome" - "chromium" - "firefox" - "vivaldi" - ]; - }; - - nmt.script = - if pkgs.stdenv.hostPlatform.isDarwin then '' - for dir in "Google/Chrome" "Chromium" "Mozilla" "Vivaldi"; do - assertFileExists "home-files/Library/Application Support/$dir/NativeMessagingHosts/com.github.browserpass.native.json" - done - - for dir in "Google/Chrome" "Chromium" "Vivaldi"; do - assertFileExists "home-files/Library/Application Support/$dir/policies/managed/com.github.browserpass.native.json" - done - '' else '' - for dir in "google-chrome" "chromium" "vivaldi"; do - assertFileExists "home-files/.config/$dir/NativeMessagingHosts/com.github.browserpass.native.json" - assertFileExists "home-files/.config/$dir/policies/managed/com.github.browserpass.native.json" - done - - assertFileExists "home-files/.mozilla/native-messaging-hosts/com.github.browserpass.native.json" - ''; - }; -} diff --git a/home-manager/tests/modules/programs/browserpass/browserpass.nix b/home-manager/tests/modules/programs/browserpass/browserpass.nix new file mode 100644 index 00000000000..9189a445ac0 --- /dev/null +++ b/home-manager/tests/modules/programs/browserpass/browserpass.nix @@ -0,0 +1,29 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.browserpass = { + enable = true; + browsers = [ "chrome" "chromium" "firefox" "vivaldi" ]; + }; + + nmt.script = if pkgs.stdenv.hostPlatform.isDarwin then '' + for dir in "Google/Chrome" "Chromium" "Mozilla" "Vivaldi"; do + assertFileExists "home-files/Library/Application Support/$dir/NativeMessagingHosts/com.github.browserpass.native.json" + done + + for dir in "Google/Chrome" "Chromium" "Vivaldi"; do + assertFileExists "home-files/Library/Application Support/$dir/policies/managed/com.github.browserpass.native.json" + done + '' else '' + for dir in "google-chrome" "chromium" "vivaldi"; do + assertFileExists "home-files/.config/$dir/NativeMessagingHosts/com.github.browserpass.native.json" + assertFileExists "home-files/.config/$dir/policies/managed/com.github.browserpass.native.json" + done + + assertFileExists "home-files/.mozilla/native-messaging-hosts/com.github.browserpass.native.json" + ''; + }; +} diff --git a/home-manager/tests/modules/programs/browserpass/default.nix b/home-manager/tests/modules/programs/browserpass/default.nix new file mode 100644 index 00000000000..fa40ddcab31 --- /dev/null +++ b/home-manager/tests/modules/programs/browserpass/default.nix @@ -0,0 +1 @@ +{ browserpass = ./browserpass.nix; } diff --git a/home-manager/tests/modules/programs/firefox/profile-settings.nix b/home-manager/tests/modules/programs/firefox/profile-settings.nix index 45465b1d0bf..8c5fb4ec1fc 100644 --- a/home-manager/tests/modules/programs/firefox/profile-settings.nix +++ b/home-manager/tests/modules/programs/firefox/profile-settings.nix @@ -6,11 +6,23 @@ with lib; config = { programs.firefox = { enable = true; - profiles.test.settings = { - "general.smoothScroll" = false; - }; + profiles.test.settings = { "general.smoothScroll" = false; }; }; + nixpkgs.overlays = [ + (self: super: { + firefox-unwrapped = pkgs.runCommand "firefox-0" { + meta.description = "I pretend to be Firefox"; + preferLocalBuild = true; + allowSubstitutes = false; + } '' + mkdir -p "$out/bin" + touch "$out/bin/firefox" + chmod 755 "$out/bin/firefox" + ''; + }) + ]; + nmt.script = '' assertFileRegex \ home-path/bin/firefox \ diff --git a/home-manager/tests/modules/programs/firefox/state-version-19_09.nix b/home-manager/tests/modules/programs/firefox/state-version-19_09.nix index 0c93096190e..27dc867ad29 100644 --- a/home-manager/tests/modules/programs/firefox/state-version-19_09.nix +++ b/home-manager/tests/modules/programs/firefox/state-version-19_09.nix @@ -8,6 +8,20 @@ with lib; programs.firefox.enable = true; + nixpkgs.overlays = [ + (self: super: { + firefox-unwrapped = pkgs.runCommand "firefox-0" { + meta.description = "I pretend to be Firefox"; + preferLocalBuild = true; + allowSubstitutes = false; + } '' + mkdir -p "$out/bin" + touch "$out/bin/firefox" + chmod 755 "$out/bin/firefox" + ''; + }) + ]; + nmt.script = '' assertFileRegex \ home-path/bin/firefox \ diff --git a/home-manager/tests/modules/programs/getmail/default.nix b/home-manager/tests/modules/programs/getmail/default.nix new file mode 100644 index 00000000000..cb789a90d64 --- /dev/null +++ b/home-manager/tests/modules/programs/getmail/default.nix @@ -0,0 +1 @@ +{ getmail = ./getmail.nix; } diff --git a/home-manager/tests/modules/programs/getmail-expected.conf b/home-manager/tests/modules/programs/getmail/getmail-expected.conf index a652e7199d6..90dc963e574 100644 --- a/home-manager/tests/modules/programs/getmail-expected.conf +++ b/home-manager/tests/modules/programs/getmail/getmail-expected.conf @@ -2,7 +2,7 @@ [retriever] type = SimpleIMAPSSLRetriever server = imap.example.com - +port = 993 username = home.manager password_command = ('password-command') mailboxes = ( 'INBOX', 'Sent', 'Work' ) diff --git a/home-manager/tests/modules/programs/getmail.nix b/home-manager/tests/modules/programs/getmail/getmail.nix index 12806c25679..fe10b98f981 100644 --- a/home-manager/tests/modules/programs/getmail.nix +++ b/home-manager/tests/modules/programs/getmail/getmail.nix @@ -3,24 +3,29 @@ with lib; { - imports = [ ../accounts/email-test-accounts.nix ]; + imports = [ ../../accounts/email-test-accounts.nix ]; config = { home.username = "hm-user"; home.homeDirectory = "/home/hm-user"; accounts.email.accounts = { - "hm@example.com".getmail = { - enable = true; - mailboxes = ["INBOX" "Sent" "Work"]; - destinationCommand = "/bin/maildrop"; - delete = false; + "hm@example.com" = { + getmail = { + enable = true; + mailboxes = [ "INBOX" "Sent" "Work" ]; + destinationCommand = "/bin/maildrop"; + delete = false; + }; + imap.port = 993; }; }; nmt.script = '' assertFileExists home-files/.getmail/getmailhm@example.com - assertFileContent home-files/.getmail/getmailhm@example.com ${./getmail-expected.conf} + assertFileContent home-files/.getmail/getmailhm@example.com ${ + ./getmail-expected.conf + } ''; }; } diff --git a/home-manager/tests/modules/programs/git/default.nix b/home-manager/tests/modules/programs/git/default.nix new file mode 100644 index 00000000000..45aface8d26 --- /dev/null +++ b/home-manager/tests/modules/programs/git/default.nix @@ -0,0 +1,5 @@ +{ + git-with-email = ./git-with-email.nix; + git-with-most-options = ./git.nix; + git-with-str-extra-config = ./git-with-str-extra-config.nix; +} diff --git a/home-manager/tests/modules/programs/git-expected.conf b/home-manager/tests/modules/programs/git/git-expected.conf index d02ebf31649..d02ebf31649 100644 --- a/home-manager/tests/modules/programs/git-expected.conf +++ b/home-manager/tests/modules/programs/git/git-expected.conf diff --git a/home-manager/tests/modules/programs/git-with-email-expected.conf b/home-manager/tests/modules/programs/git/git-with-email-expected.conf index 01c1eec5823..01c1eec5823 100644 --- a/home-manager/tests/modules/programs/git-with-email-expected.conf +++ b/home-manager/tests/modules/programs/git/git-with-email-expected.conf diff --git a/home-manager/tests/modules/programs/git-with-email.nix b/home-manager/tests/modules/programs/git/git-with-email.nix index f8a762dcceb..ca577eef4d3 100644 --- a/home-manager/tests/modules/programs/git-with-email.nix +++ b/home-manager/tests/modules/programs/git/git-with-email.nix @@ -3,11 +3,12 @@ with lib; { - imports = [ ../accounts/email-test-accounts.nix ]; + imports = [ ../../accounts/email-test-accounts.nix ]; config = { programs.git = { enable = true; + package = pkgs.gitMinimal; userEmail = "hm@example.com"; userName = "H. M. Test"; }; @@ -24,7 +25,9 @@ with lib; } assertFileExists home-files/.config/git/config - assertFileContent home-files/.config/git/config ${./git-with-email-expected.conf} + assertFileContent home-files/.config/git/config ${ + ./git-with-email-expected.conf + } assertGitConfig "sendemail.hm@example.com.from" "hm@example.com" assertGitConfig "sendemail.hm-account.from" "hm@example.org" diff --git a/home-manager/tests/modules/programs/git-with-str-extra-config-expected.conf b/home-manager/tests/modules/programs/git/git-with-str-extra-config-expected.conf index 957438de13a..957438de13a 100644 --- a/home-manager/tests/modules/programs/git-with-str-extra-config-expected.conf +++ b/home-manager/tests/modules/programs/git/git-with-str-extra-config-expected.conf diff --git a/home-manager/tests/modules/programs/git-with-str-extra-config.nix b/home-manager/tests/modules/programs/git/git-with-str-extra-config.nix index 734c5ee764c..3dbc497a5ea 100644 --- a/home-manager/tests/modules/programs/git-with-str-extra-config.nix +++ b/home-manager/tests/modules/programs/git/git-with-str-extra-config.nix @@ -1,4 +1,4 @@ -{ config, lib, ... }: +{ config, lib, pkgs, ... }: with lib; @@ -6,6 +6,7 @@ with lib; config = { programs.git = { enable = true; + package = pkgs.gitMinimal; extraConfig = '' This can be anything. ''; diff --git a/home-manager/tests/modules/programs/git.nix b/home-manager/tests/modules/programs/git/git.nix index c5203e417dc..7c0bf52de55 100644 --- a/home-manager/tests/modules/programs/git.nix +++ b/home-manager/tests/modules/programs/git/git.nix @@ -11,19 +11,20 @@ let }; }; - substituteExpected = path: pkgs.substituteAll { - src = path; + substituteExpected = path: + pkgs.substituteAll { + src = path; - git_include_path = pkgs.writeText "contents" (generators.toINI {} gitInclude); - }; - -in + git_include_path = + pkgs.writeText "contents" (generators.toINI { } gitInclude); + }; -{ +in { config = { programs.git = mkMerge [ { enable = true; + package = pkgs.gitMinimal; aliases = { a1 = "foo"; a2 = "bar"; @@ -31,7 +32,7 @@ in extraConfig = { extra = { name = "value"; - multiple = [1]; + multiple = [ 1 ]; }; }; ignores = [ "*~" "*.swp" ]; @@ -61,14 +62,16 @@ in extraConfig."extra \"backcompat.with.dots\"".previously = "worked"; extraConfig.extra.boolean = true; extraConfig.extra.integer = 38; - extraConfig.extra.multiple = [2]; + extraConfig.extra.multiple = [ 2 ]; extraConfig.extra.subsection.value = "test"; } ]; nmt.script = '' assertFileExists home-files/.config/git/config - assertFileContent home-files/.config/git/config ${substituteExpected ./git-expected.conf} + assertFileContent home-files/.config/git/config ${ + substituteExpected ./git-expected.conf + } ''; }; } diff --git a/home-manager/tests/modules/programs/gpg/default.nix b/home-manager/tests/modules/programs/gpg/default.nix index 5cb24817cb0..7fed2cdcc69 100644 --- a/home-manager/tests/modules/programs/gpg/default.nix +++ b/home-manager/tests/modules/programs/gpg/default.nix @@ -1,3 +1 @@ -{ - gpg-override-defaults = ./override-defaults.nix; -} +{ gpg-override-defaults = ./override-defaults.nix; } diff --git a/home-manager/tests/modules/programs/mbsync/default.nix b/home-manager/tests/modules/programs/mbsync/default.nix new file mode 100644 index 00000000000..9c369fa5018 --- /dev/null +++ b/home-manager/tests/modules/programs/mbsync/default.nix @@ -0,0 +1 @@ +{ mbsync = ./mbsync.nix; } diff --git a/home-manager/tests/modules/programs/mbsync-expected.conf b/home-manager/tests/modules/programs/mbsync/mbsync-expected.conf index f1ca79fe738..f1ca79fe738 100644 --- a/home-manager/tests/modules/programs/mbsync-expected.conf +++ b/home-manager/tests/modules/programs/mbsync/mbsync-expected.conf diff --git a/home-manager/tests/modules/programs/mbsync.nix b/home-manager/tests/modules/programs/mbsync/mbsync.nix index fa9768a2fe1..03a54c178f5 100644 --- a/home-manager/tests/modules/programs/mbsync.nix +++ b/home-manager/tests/modules/programs/mbsync/mbsync.nix @@ -3,7 +3,7 @@ with lib; { - imports = [ ../accounts/email-test-accounts.nix ]; + imports = [ ../../accounts/email-test-accounts.nix ]; config = { home.username = "hm-user"; @@ -18,13 +18,9 @@ with lib; }; accounts.email.accounts = { - "hm@example.com".mbsync = { - enable = true; - }; + "hm@example.com".mbsync = { enable = true; }; - hm-account.mbsync = { - enable = true; - }; + hm-account.mbsync = { enable = true; }; }; nmt.script = '' diff --git a/home-manager/tests/modules/programs/neomutt/default.nix b/home-manager/tests/modules/programs/neomutt/default.nix new file mode 100644 index 00000000000..289f2705efa --- /dev/null +++ b/home-manager/tests/modules/programs/neomutt/default.nix @@ -0,0 +1 @@ +{ neomutt-simple = ./neomutt.nix; } diff --git a/home-manager/tests/modules/programs/neomutt/hm-example.com-expected b/home-manager/tests/modules/programs/neomutt/hm-example.com-expected new file mode 100644 index 00000000000..430509c36bd --- /dev/null +++ b/home-manager/tests/modules/programs/neomutt/hm-example.com-expected @@ -0,0 +1,37 @@ +# Generated by Home Manager. +set ssl_force_tls = yes +set certificate_file=/etc/ssl/certs/ca-certificates.crt + +# GPG section +set crypt_use_gpgme = yes +set crypt_autosign = no +set pgp_use_gpg_agent = yes +set mbox_type = Maildir +set sort = "threads" + +# MTA section +set smtp_pass='`password-command`' +set smtp_url='smtps://home.manager@smtp.example.com' + + + + + +# MRA section +set folder='/home/hm-user/Mail/hm@example.com' +set from='hm@example.com' +set postponed='+Drafts' +set realname='H. M. Test' +set record='+Sent' +set spoolfile='+Inbox' +set trash='+Trash' +color status cyan default + + + +# Extra configuration +color status cyan default + +# notmuch section +set nm_default_uri = "notmuch:///home/hm-user/Mail" +virtual-mailboxes "My INBOX" "notmuch://?query=tag:inbox" diff --git a/home-manager/tests/modules/programs/neomutt/neomutt-expected.conf b/home-manager/tests/modules/programs/neomutt/neomutt-expected.conf new file mode 100644 index 00000000000..7711aa5a652 --- /dev/null +++ b/home-manager/tests/modules/programs/neomutt/neomutt-expected.conf @@ -0,0 +1,27 @@ +# Generated by Home Manager. +set header_cache = "/home/hm-user/.cache/neomutt/headers/" +set message_cachedir = "/home/hm-user/.cache/neomutt/messages/" +set editor = "$EDITOR" +set implicit_autoview = yes + +alternative_order text/enriched text/plain text + +set delete = yes + +# Binds + + +# Macros + + + + +# Extra configuration + + + +# register account hm@example.com +mailboxes "/home/hm-user/Mail/hm@example.com/Inbox" +folder-hook /home/hm-user/Mail/hm@example.com/ " \ + source /home/hm-user/.config/neomutt/hm@example.com " +source /home/hm-user/.config/neomutt/hm@example.com
\ No newline at end of file diff --git a/home-manager/tests/modules/programs/neomutt/neomutt.nix b/home-manager/tests/modules/programs/neomutt/neomutt.nix new file mode 100644 index 00000000000..91cb9dca249 --- /dev/null +++ b/home-manager/tests/modules/programs/neomutt/neomutt.nix @@ -0,0 +1,47 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + config = { + home.username = "hm-user"; + home.homeDirectory = "/home/hm-user"; + xdg.configHome = mkForce "/home/hm-user/.config"; + xdg.cacheHome = mkForce "/home/hm-user/.cache"; + + accounts.email.accounts = { + "hm@example.com" = { + primary = true; + notmuch.enable = true; + neomutt = { + enable = true; + extraConfig = '' + color status cyan default + ''; + }; + imap.port = 993; + }; + }; + + programs.neomutt = { + enable = true; + vimKeys = false; + }; + + nixpkgs.overlays = + [ (self: super: { neomutt = pkgs.writeScriptBin "dummy-neomutt" ""; }) ]; + + nmt.script = '' + assertFileExists home-files/.config/neomutt/neomuttrc + assertFileExists home-files/.config/neomutt/hm@example.com + assertFileContent home-files/.config/neomutt/neomuttrc ${ + ./neomutt-expected.conf + } + assertFileContent home-files/.config/neomutt/hm@example.com ${ + ./hm-example.com-expected + } + ''; + }; +} diff --git a/home-manager/tests/modules/programs/newsboat/default.nix b/home-manager/tests/modules/programs/newsboat/default.nix index a9b15a44359..27f523a629c 100644 --- a/home-manager/tests/modules/programs/newsboat/default.nix +++ b/home-manager/tests/modules/programs/newsboat/default.nix @@ -1,3 +1 @@ -{ - newsboat-basics = ./newsboat-basics.nix; -} +{ newsboat-basics = ./newsboat-basics.nix; } diff --git a/home-manager/tests/modules/programs/newsboat/newsboat-basics.nix b/home-manager/tests/modules/programs/newsboat/newsboat-basics.nix index 49a54f6d0c3..e6eb4151776 100644 --- a/home-manager/tests/modules/programs/newsboat/newsboat-basics.nix +++ b/home-manager/tests/modules/programs/newsboat/newsboat-basics.nix @@ -14,20 +14,14 @@ with lib; title = "Cool feed"; } - { - url = "http://example.org/feed2.xml"; - } + { url = "http://example.org/feed2.xml"; } ]; - queries = { - "foo" = "rssurl =~ \"example.com\""; - }; + queries = { "foo" = ''rssurl =~ "example.com"''; }; }; nixpkgs.overlays = [ - (self: super: { - newsboat = pkgs.writeScriptBin "dummy-newsboat" ""; - }) + (self: super: { newsboat = pkgs.writeScriptBin "dummy-newsboat" ""; }) ]; nmt.script = '' diff --git a/home-manager/tests/modules/programs/readline/default.nix b/home-manager/tests/modules/programs/readline/default.nix new file mode 100644 index 00000000000..c95745d19cd --- /dev/null +++ b/home-manager/tests/modules/programs/readline/default.nix @@ -0,0 +1 @@ +{ readline-using-all-options = ./using-all-options.nix; } diff --git a/home-manager/tests/modules/programs/readline/using-all-options.nix b/home-manager/tests/modules/programs/readline/using-all-options.nix new file mode 100644 index 00000000000..ab851020c2e --- /dev/null +++ b/home-manager/tests/modules/programs/readline/using-all-options.nix @@ -0,0 +1,31 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.readline = { + enable = true; + + bindings = { "\\C-h" = "backward-kill-word"; }; + + variables = { + bell-style = "audible"; + completion-map-case = true; + completion-prefix-display-length = 2; + }; + + extraConfig = '' + $if mode=emacs + "\e[1~": beginning-of-line + $endif + ''; + }; + + nmt.script = '' + assertFileContent \ + home-files/.inputrc \ + ${./using-all-options.txt} + ''; + }; +} diff --git a/home-manager/tests/modules/programs/readline/using-all-options.txt b/home-manager/tests/modules/programs/readline/using-all-options.txt new file mode 100644 index 00000000000..6b4aef51e69 --- /dev/null +++ b/home-manager/tests/modules/programs/readline/using-all-options.txt @@ -0,0 +1,11 @@ +# Generated by Home Manager. + +$include /etc/inputrc +set bell-style audible +set completion-map-case on +set completion-prefix-display-length 2 +"\C-h": backward-kill-word +$if mode=emacs +"\e[1~": beginning-of-line +$endif + diff --git a/home-manager/tests/modules/programs/rofi/assert-on-both-theme-and-colors.nix b/home-manager/tests/modules/programs/rofi/assert-on-both-theme-and-colors.nix index 2558a25832f..0f9cfc39a6c 100644 --- a/home-manager/tests/modules/programs/rofi/assert-on-both-theme-and-colors.nix +++ b/home-manager/tests/modules/programs/rofi/assert-on-both-theme-and-colors.nix @@ -13,16 +13,12 @@ with lib; border = "border"; separator = "separator"; }; - rows = { - }; + rows = { }; }; }; - home.file.result.text = - builtins.toJSON - (map (a: a.message) - (filter (a: !a.assertion) - config.assertions)); + home.file.result.text = builtins.toJSON + (map (a: a.message) (filter (a: !a.assertion) config.assertions)); nmt.script = '' assertFileContent \ diff --git a/home-manager/tests/modules/programs/rofi/default.nix b/home-manager/tests/modules/programs/rofi/default.nix index b42b43e949a..c18c3b0ed6a 100644 --- a/home-manager/tests/modules/programs/rofi/default.nix +++ b/home-manager/tests/modules/programs/rofi/default.nix @@ -1,3 +1,3 @@ { - rofi-assert-on-both-theme-and-colors = import ./assert-on-both-theme-and-colors.nix; + rofi-assert-on-both-theme-and-colors = ./assert-on-both-theme-and-colors.nix; } diff --git a/home-manager/tests/modules/programs/ssh/default-config.nix b/home-manager/tests/modules/programs/ssh/default-config.nix index 266bc9d1f5d..6d7e5508a2f 100644 --- a/home-manager/tests/modules/programs/ssh/default-config.nix +++ b/home-manager/tests/modules/programs/ssh/default-config.nix @@ -4,15 +4,10 @@ with lib; { config = { - programs.ssh = { - enable = true; - }; + programs.ssh = { enable = true; }; - home.file.assertions.text = - builtins.toJSON - (map (a: a.message) - (filter (a: !a.assertion) - config.assertions)); + home.file.assertions.text = builtins.toJSON + (map (a: a.message) (filter (a: !a.assertion) config.assertions)); nmt.script = '' assertFileExists home-files/.ssh/config diff --git a/home-manager/tests/modules/programs/ssh/forwards-dynamic-bind-path-with-port-asserts.nix b/home-manager/tests/modules/programs/ssh/forwards-dynamic-bind-path-with-port-asserts.nix index 2e9082de378..cf2efe5a5a5 100644 --- a/home-manager/tests/modules/programs/ssh/forwards-dynamic-bind-path-with-port-asserts.nix +++ b/home-manager/tests/modules/programs/ssh/forwards-dynamic-bind-path-with-port-asserts.nix @@ -8,25 +8,22 @@ with lib; enable = true; matchBlocks = { dynamicBindPathWithPort = { - dynamicForwards = [ - { - # Error: - address = "/run/user/1000/gnupg/S.gpg-agent.extra"; - port = 3000; - } - ]; + dynamicForwards = [{ + # Error: + address = "/run/user/1000/gnupg/S.gpg-agent.extra"; + port = 3000; + }]; }; }; }; - home.file.result.text = - builtins.toJSON - (map (a: a.message) - (filter (a: !a.assertion) - config.assertions)); + home.file.result.text = builtins.toJSON + (map (a: a.message) (filter (a: !a.assertion) config.assertions)); nmt.script = '' - assertFileContent home-files/result ${./forwards-paths-with-ports-error.json} + assertFileContent home-files/result ${ + ./forwards-paths-with-ports-error.json + } ''; }; } diff --git a/home-manager/tests/modules/programs/ssh/forwards-dynamic-valid-bind-no-asserts.nix b/home-manager/tests/modules/programs/ssh/forwards-dynamic-valid-bind-no-asserts.nix index 15ab59e82ca..d0c3a732256 100644 --- a/home-manager/tests/modules/programs/ssh/forwards-dynamic-valid-bind-no-asserts.nix +++ b/home-manager/tests/modules/programs/ssh/forwards-dynamic-valid-bind-no-asserts.nix @@ -8,31 +8,24 @@ with lib; enable = true; matchBlocks = { dynamicBindPathNoPort = { - dynamicForwards = [ - { - # OK: - address = "/run/user/1000/gnupg/S.gpg-agent.extra"; - } - ]; + dynamicForwards = [{ + # OK: + address = "/run/user/1000/gnupg/S.gpg-agent.extra"; + }]; }; dynamicBindAddressWithPort = { - dynamicForwards = [ - { - # OK: - address = "127.0.0.1"; - port = 3000; - } - ]; + dynamicForwards = [{ + # OK: + address = "127.0.0.1"; + port = 3000; + }]; }; }; }; - home.file.result.text = - builtins.toJSON - (map (a: a.message) - (filter (a: !a.assertion) - config.assertions)); + home.file.result.text = builtins.toJSON + (map (a: a.message) (filter (a: !a.assertion) config.assertions)); nmt.script = '' assertFileExists home-files/.ssh/config diff --git a/home-manager/tests/modules/programs/ssh/forwards-local-bind-path-with-port-asserts.nix b/home-manager/tests/modules/programs/ssh/forwards-local-bind-path-with-port-asserts.nix index c05cba82791..f9d8e2daf85 100644 --- a/home-manager/tests/modules/programs/ssh/forwards-local-bind-path-with-port-asserts.nix +++ b/home-manager/tests/modules/programs/ssh/forwards-local-bind-path-with-port-asserts.nix @@ -8,29 +8,26 @@ with lib; enable = true; matchBlocks = { localBindPathWithPort = { - localForwards = [ - { - # OK: - host.address = "127.0.0.1"; - host.port = 3000; + localForwards = [{ + # OK: + host.address = "127.0.0.1"; + host.port = 3000; - # Error: - bind.address = "/run/user/1000/gnupg/S.gpg-agent.extra"; - bind.port = 3000; - } - ]; + # Error: + bind.address = "/run/user/1000/gnupg/S.gpg-agent.extra"; + bind.port = 3000; + }]; }; }; }; - home.file.result.text = - builtins.toJSON - (map (a: a.message) - (filter (a: !a.assertion) - config.assertions)); + home.file.result.text = builtins.toJSON + (map (a: a.message) (filter (a: !a.assertion) config.assertions)); nmt.script = '' - assertFileContent home-files/result ${./forwards-paths-with-ports-error.json} + assertFileContent home-files/result ${ + ./forwards-paths-with-ports-error.json + } ''; }; } diff --git a/home-manager/tests/modules/programs/ssh/forwards-local-host-path-with-port-asserts.nix b/home-manager/tests/modules/programs/ssh/forwards-local-host-path-with-port-asserts.nix index 8cecc5e5121..02a7e5b168d 100644 --- a/home-manager/tests/modules/programs/ssh/forwards-local-host-path-with-port-asserts.nix +++ b/home-manager/tests/modules/programs/ssh/forwards-local-host-path-with-port-asserts.nix @@ -8,29 +8,26 @@ with lib; enable = true; matchBlocks = { localHostPathWithPort = { - localForwards = [ - { - # OK: - bind.address = "127.0.0.1"; - bind.port = 3000; + localForwards = [{ + # OK: + bind.address = "127.0.0.1"; + bind.port = 3000; - # Error: - host.address = "/run/user/1000/gnupg/S.gpg-agent.extra"; - host.port = 3000; - } - ]; + # Error: + host.address = "/run/user/1000/gnupg/S.gpg-agent.extra"; + host.port = 3000; + }]; }; }; }; - home.file.result.text = - builtins.toJSON - (map (a: a.message) - (filter (a: !a.assertion) - config.assertions)); + home.file.result.text = builtins.toJSON + (map (a: a.message) (filter (a: !a.assertion) config.assertions)); nmt.script = '' - assertFileContent home-files/result ${./forwards-paths-with-ports-error.json} + assertFileContent home-files/result ${ + ./forwards-paths-with-ports-error.json + } ''; }; } diff --git a/home-manager/tests/modules/programs/ssh/forwards-remote-bind-path-with-port-asserts.nix b/home-manager/tests/modules/programs/ssh/forwards-remote-bind-path-with-port-asserts.nix index a0473147bd3..61ce9ae0385 100644 --- a/home-manager/tests/modules/programs/ssh/forwards-remote-bind-path-with-port-asserts.nix +++ b/home-manager/tests/modules/programs/ssh/forwards-remote-bind-path-with-port-asserts.nix @@ -8,29 +8,26 @@ with lib; enable = true; matchBlocks = { remoteBindPathWithPort = { - remoteForwards = [ - { - # OK: - host.address = "127.0.0.1"; - host.port = 3000; + remoteForwards = [{ + # OK: + host.address = "127.0.0.1"; + host.port = 3000; - # Error: - bind.address = "/run/user/1000/gnupg/S.gpg-agent.extra"; - bind.port = 3000; - } - ]; + # Error: + bind.address = "/run/user/1000/gnupg/S.gpg-agent.extra"; + bind.port = 3000; + }]; }; }; }; - home.file.result.text = - builtins.toJSON - (map (a: a.message) - (filter (a: !a.assertion) - config.assertions)); + home.file.result.text = builtins.toJSON + (map (a: a.message) (filter (a: !a.assertion) config.assertions)); nmt.script = '' - assertFileContent home-files/result ${./forwards-paths-with-ports-error.json} + assertFileContent home-files/result ${ + ./forwards-paths-with-ports-error.json + } ''; }; } diff --git a/home-manager/tests/modules/programs/ssh/forwards-remote-host-path-with-port-asserts.nix b/home-manager/tests/modules/programs/ssh/forwards-remote-host-path-with-port-asserts.nix index 770b8ab2870..71bdbcb70fd 100644 --- a/home-manager/tests/modules/programs/ssh/forwards-remote-host-path-with-port-asserts.nix +++ b/home-manager/tests/modules/programs/ssh/forwards-remote-host-path-with-port-asserts.nix @@ -8,29 +8,26 @@ with lib; enable = true; matchBlocks = { remoteHostPathWithPort = { - remoteForwards = [ - { - # OK: - bind.address = "127.0.0.1"; - bind.port = 3000; + remoteForwards = [{ + # OK: + bind.address = "127.0.0.1"; + bind.port = 3000; - # Error: - host.address = "/run/user/1000/gnupg/S.gpg-agent.extra"; - host.port = 3000; - } - ]; + # Error: + host.address = "/run/user/1000/gnupg/S.gpg-agent.extra"; + host.port = 3000; + }]; }; }; }; - home.file.result.text = - builtins.toJSON - (map (a: a.message) - (filter (a: !a.assertion) - config.assertions)); + home.file.result.text = builtins.toJSON + (map (a: a.message) (filter (a: !a.assertion) config.assertions)); nmt.script = '' - assertFileContent home-files/result ${./forwards-paths-with-ports-error.json} + assertFileContent home-files/result ${ + ./forwards-paths-with-ports-error.json + } ''; }; } diff --git a/home-manager/tests/modules/programs/ssh/match-blocks-attrs.nix b/home-manager/tests/modules/programs/ssh/match-blocks-attrs.nix index 94263ef9d27..a84a703e89d 100644 --- a/home-manager/tests/modules/programs/ssh/match-blocks-attrs.nix +++ b/home-manager/tests/modules/programs/ssh/match-blocks-attrs.nix @@ -15,13 +15,11 @@ with lib; xyz = { identityFile = "file"; serverAliveInterval = 60; - localForwards = [ - { - bind.port = 8080; - host.address = "10.0.0.1"; - host.port = 80; - } - ]; + localForwards = [{ + bind.port = 8080; + host.address = "10.0.0.1"; + host.port = 80; + }]; remoteForwards = [ { bind.port = 8081; @@ -33,25 +31,18 @@ with lib; host.address = "/run/user/1000/gnupg/S.gpg-agent"; } ]; - dynamicForwards = [ - { - port = 2839; - } - ]; + dynamicForwards = [{ port = 2839; }]; }; "* !github.com" = { - identityFile = ["file1" "file2"]; + identityFile = [ "file1" "file2" ]; port = 516; }; }; }; - home.file.assertions.text = - builtins.toJSON - (map (a: a.message) - (filter (a: !a.assertion) - config.assertions)); + home.file.assertions.text = builtins.toJSON + (map (a: a.message) (filter (a: !a.assertion) config.assertions)); nmt.script = '' assertFileExists home-files/.ssh/config diff --git a/home-manager/tests/modules/programs/texlive/default.nix b/home-manager/tests/modules/programs/texlive/default.nix new file mode 100644 index 00000000000..23bfe2daf0a --- /dev/null +++ b/home-manager/tests/modules/programs/texlive/default.nix @@ -0,0 +1 @@ +{ texlive-minimal = ./texlive-minimal.nix; } diff --git a/home-manager/tests/modules/programs/texlive-minimal.nix b/home-manager/tests/modules/programs/texlive/texlive-minimal.nix index df143dbc660..df143dbc660 100644 --- a/home-manager/tests/modules/programs/texlive-minimal.nix +++ b/home-manager/tests/modules/programs/texlive/texlive-minimal.nix diff --git a/home-manager/tests/modules/programs/tmux/disable-confirmation-prompt.nix b/home-manager/tests/modules/programs/tmux/disable-confirmation-prompt.nix index 82c53438b00..e3d13a4b1b2 100644 --- a/home-manager/tests/modules/programs/tmux/disable-confirmation-prompt.nix +++ b/home-manager/tests/modules/programs/tmux/disable-confirmation-prompt.nix @@ -2,27 +2,27 @@ with lib; -let - - substituteExpected = path: pkgs.substituteAll { - src = path; - - sensible_rtp = pkgs.tmuxPlugins.sensible.rtp; - }; - -in - { config = { programs.tmux = { enable = true; disableConfirmationPrompt = true; }; - + + nixpkgs.overlays = [ + (self: super: { + tmuxPlugins = super.tmuxPlugins // { + sensible = super.tmuxPlugins.sensible // { + rtp = "@sensible_rtp@"; + }; + }; + }) + ]; + nmt.script = '' assertFileExists home-files/.tmux.conf assertFileContent home-files/.tmux.conf \ - ${substituteExpected ./disable-confirmation-prompt.conf} + ${./disable-confirmation-prompt.conf} ''; }; } diff --git a/home-manager/tests/modules/programs/tmux/emacs-with-plugins.conf b/home-manager/tests/modules/programs/tmux/emacs-with-plugins.conf index b047c97a766..66b10183750 100644 --- a/home-manager/tests/modules/programs/tmux/emacs-with-plugins.conf +++ b/home-manager/tests/modules/programs/tmux/emacs-with-plugins.conf @@ -37,18 +37,18 @@ set -g history-limit 2000 # tmuxplugin-logging # --------------------- -run-shell @tmuxplugin_logging@/share/tmux-plugins/logging/logging.tmux +run-shell @tmuxplugin_logging_rtp@ # tmuxplugin-prefix-highlight # --------------------- -run-shell @tmuxplugin_prefix_highlight@/share/tmux-plugins/prefix-highlight/prefix_highlight.tmux +run-shell @tmuxplugin_prefix_highlight_rtp@ # tmuxplugin-fzf-tmux-url # --------------------- -run-shell @tmuxplugin_fzf_tmux_url@/share/tmux-plugins/fzf-tmux-url/fzf-url.tmux +run-shell @tmuxplugin_fzf_tmux_url_rtp@ # ============================================= # diff --git a/home-manager/tests/modules/programs/tmux/emacs-with-plugins.nix b/home-manager/tests/modules/programs/tmux/emacs-with-plugins.nix index 5e147b7290e..f9bccaa2ce4 100644 --- a/home-manager/tests/modules/programs/tmux/emacs-with-plugins.nix +++ b/home-manager/tests/modules/programs/tmux/emacs-with-plugins.nix @@ -2,19 +2,6 @@ with lib; -let - - substituteExpected = path: pkgs.substituteAll { - src = path; - - tmuxplugin_fzf_tmux_url = pkgs.tmuxPlugins.fzf-tmux-url; - tmuxplugin_logging = pkgs.tmuxPlugins.logging; - tmuxplugin_prefix_highlight = pkgs.tmuxPlugins.prefix-highlight; - tmuxplugin_sensible_rtp = pkgs.tmuxPlugins.sensible.rtp; - }; - -in - { config = { programs.tmux = { @@ -32,10 +19,31 @@ in ]; }; + nixpkgs.overlays = [ + (self: super: { + tmuxPlugins = super.tmuxPlugins // { + fzf-tmux-url = super.tmuxPlugins.fzf-tmux-url // { + rtp = "@tmuxplugin_fzf_tmux_url_rtp@"; + }; + + logging = super.tmuxPlugins.logging // { + rtp = "@tmuxplugin_logging_rtp@"; + }; + + prefix-highlight = super.tmuxPlugins.prefix-highlight // { + rtp = "@tmuxplugin_prefix_highlight_rtp@"; + }; + + sensible = super.tmuxPlugins.sensible // { + rtp = "@tmuxplugin_sensible_rtp@"; + }; + }; + }) + ]; + nmt.script = '' assertFileExists home-files/.tmux.conf - assertFileContent home-files/.tmux.conf \ - ${substituteExpected ./emacs-with-plugins.conf} + assertFileContent home-files/.tmux.conf ${./emacs-with-plugins.conf} ''; }; } diff --git a/home-manager/tests/modules/programs/tmux/vi-all-true.nix b/home-manager/tests/modules/programs/tmux/vi-all-true.nix index e88ed587c03..bce032fd654 100644 --- a/home-manager/tests/modules/programs/tmux/vi-all-true.nix +++ b/home-manager/tests/modules/programs/tmux/vi-all-true.nix @@ -2,15 +2,7 @@ with lib; -let - - substituteExpected = path: pkgs.substituteAll { - src = path; - - sensible_rtp = pkgs.tmuxPlugins.sensible.rtp; - }; - -in { +{ config = { programs.tmux = { aggressiveResize = true; @@ -21,10 +13,17 @@ in { reverseSplit = true; }; + nixpkgs.overlays = [ + (self: super: { + tmuxPlugins = super.tmuxPlugins // { + sensible = super.tmuxPlugins.sensible // { rtp = "@sensible_rtp@"; }; + }; + }) + ]; + nmt.script = '' assertFileExists home-files/.tmux.conf - assertFileContent home-files/.tmux.conf \ - ${substituteExpected ./vi-all-true.conf} + assertFileContent home-files/.tmux.conf ${./vi-all-true.conf} ''; }; } diff --git a/home-manager/tests/modules/programs/zsh/default.nix b/home-manager/tests/modules/programs/zsh/default.nix index da5dd5b55ed..37339598e35 100644 --- a/home-manager/tests/modules/programs/zsh/default.nix +++ b/home-manager/tests/modules/programs/zsh/default.nix @@ -1,3 +1,7 @@ { zsh-session-variables = ./session-variables.nix; + zsh-history-path-new-default = ./history-path-new-default.nix; + zsh-history-path-new-custom = ./history-path-new-custom.nix; + zsh-history-path-old-default = ./history-path-old-default.nix; + zsh-history-path-old-custom = ./history-path-old-custom.nix; } diff --git a/home-manager/tests/modules/programs/zsh/history-path-new-custom.nix b/home-manager/tests/modules/programs/zsh/history-path-new-custom.nix new file mode 100644 index 00000000000..0c052d6949e --- /dev/null +++ b/home-manager/tests/modules/programs/zsh/history-path-new-custom.nix @@ -0,0 +1,20 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "20.03"; + programs.zsh = { + enable = true; + history.path = "$HOME/some/directory/zsh_history"; + }; + + nixpkgs.overlays = + [ (self: super: { zsh = pkgs.writeScriptBin "dummy-zsh" ""; }) ]; + + nmt.script = '' + assertFileRegex home-files/.zshrc '^HISTFILE="$HOME/some/directory/zsh_history"$' + ''; + }; +} diff --git a/home-manager/tests/modules/programs/zsh/history-path-new-default.nix b/home-manager/tests/modules/programs/zsh/history-path-new-default.nix new file mode 100644 index 00000000000..6d1f58a29dc --- /dev/null +++ b/home-manager/tests/modules/programs/zsh/history-path-new-default.nix @@ -0,0 +1,17 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "20.03"; + programs.zsh.enable = true; + + nixpkgs.overlays = + [ (self: super: { zsh = pkgs.writeScriptBin "dummy-zsh" ""; }) ]; + + nmt.script = '' + assertFileRegex home-files/.zshrc '^HISTFILE="$HOME/.zsh_history"$' + ''; + }; +} diff --git a/home-manager/tests/modules/programs/zsh/history-path-old-custom.nix b/home-manager/tests/modules/programs/zsh/history-path-old-custom.nix new file mode 100644 index 00000000000..f5b178b5e97 --- /dev/null +++ b/home-manager/tests/modules/programs/zsh/history-path-old-custom.nix @@ -0,0 +1,20 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "19.09"; + programs.zsh = { + enable = true; + history.path = "some/directory/zsh_history"; + }; + + nixpkgs.overlays = + [ (self: super: { zsh = pkgs.writeScriptBin "dummy-zsh" ""; }) ]; + + nmt.script = '' + assertFileRegex home-files/.zshrc '^HISTFILE="$HOME/some/directory/zsh_history"$' + ''; + }; +} diff --git a/home-manager/tests/modules/programs/zsh/history-path-old-default.nix b/home-manager/tests/modules/programs/zsh/history-path-old-default.nix new file mode 100644 index 00000000000..d880d966454 --- /dev/null +++ b/home-manager/tests/modules/programs/zsh/history-path-old-default.nix @@ -0,0 +1,17 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "19.03"; + programs.zsh.enable = true; + + nixpkgs.overlays = + [ (self: super: { zsh = pkgs.writeScriptBin "dummy-zsh" ""; }) ]; + + nmt.script = '' + assertFileRegex home-files/.zshrc '^HISTFILE="$HOME/.zsh_history"$' + ''; + }; +} diff --git a/home-manager/tests/modules/programs/zsh/session-variables.nix b/home-manager/tests/modules/programs/zsh/session-variables.nix index a87d39820cf..ca903619d68 100644 --- a/home-manager/tests/modules/programs/zsh/session-variables.nix +++ b/home-manager/tests/modules/programs/zsh/session-variables.nix @@ -1,4 +1,4 @@ -{ config, lib, ... }: +{ config, lib, pkgs, ... }: with lib; @@ -13,6 +13,12 @@ with lib; }; }; + nixpkgs.overlays = [ + (self: super: { + zsh = pkgs.writeScriptBin "dummy-zsh" ""; + }) + ]; + nmt.script = '' assertFileExists home-files/.zshrc assertFileRegex home-files/.zshrc 'export V1="v1"' diff --git a/home-manager/tests/modules/services/sxhkd/configuration.nix b/home-manager/tests/modules/services/sxhkd/configuration.nix index ac04a7ecf30..992c4b18a94 100644 --- a/home-manager/tests/modules/services/sxhkd/configuration.nix +++ b/home-manager/tests/modules/services/sxhkd/configuration.nix @@ -1,5 +1,4 @@ -{ config, ... }: -{ +{ config, ... }: { config = { services.sxhkd = { enable = true; @@ -13,7 +12,7 @@ extraConfig = '' super + c call command c - + # comment super + d call command d diff --git a/home-manager/tests/modules/services/window-managers/i3-keybindings.nix b/home-manager/tests/modules/services/window-managers/i3-keybindings.nix deleted file mode 100644 index b5ee4fd8765..00000000000 --- a/home-manager/tests/modules/services/window-managers/i3-keybindings.nix +++ /dev/null @@ -1,34 +0,0 @@ -{ config, lib, ... }: - -with lib; - -{ - config = { - xsession.windowManager.i3 = { - enable = true; - - config.keybindings = - let - modifier = config.xsession.windowManager.i3.config.modifier; - in - lib.mkOptionDefault { - "${modifier}+Left" = "overridden-command"; - "${modifier}+Right" = null; - "${modifier}+Invented" = "invented-key-command"; - }; - }; - - nmt.script = '' - assertFileExists home-files/.config/i3/config - - assertFileRegex home-files/.config/i3/config \ - 'bindsym Mod1+Left overridden-command' - - assertFileNotRegex home-files/.config/i3/config \ - 'Mod1+Right' - - assertFileRegex home-files/.config/i3/config \ - 'bindsym Mod1+Invented invented-key-command' - ''; - }; -} diff --git a/home-manager/tests/modules/services/window-managers/i3/default.nix b/home-manager/tests/modules/services/window-managers/i3/default.nix new file mode 100644 index 00000000000..e239d6c07f1 --- /dev/null +++ b/home-manager/tests/modules/services/window-managers/i3/default.nix @@ -0,0 +1 @@ +{ i3-keybindings = ./i3-keybindings.nix; } diff --git a/home-manager/tests/modules/services/window-managers/i3/i3-keybindings-expected.conf b/home-manager/tests/modules/services/window-managers/i3/i3-keybindings-expected.conf new file mode 100644 index 00000000000..1e385e8c734 --- /dev/null +++ b/home-manager/tests/modules/services/window-managers/i3/i3-keybindings-expected.conf @@ -0,0 +1,106 @@ +font pango:monospace 8 +floating_modifier Mod1 +new_window normal 2 +new_float normal 2 +hide_edge_borders none +force_focus_wrapping no +focus_follows_mouse yes +focus_on_window_activation smart +mouse_warping output +workspace_layout default +workspace_auto_back_and_forth no + +client.focused #4c7899 #285577 #ffffff #2e9ef4 #285577 +client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a +client.unfocused #333333 #222222 #888888 #292d2e #222222 +client.urgent #2f343a #900000 #ffffff #900000 #900000 +client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c +client.background #ffffff + +bindsym Mod1+0 workspace number 10 +bindsym Mod1+1 workspace number 1 +bindsym Mod1+2 workspace number 2 +bindsym Mod1+3 workspace number 3 +bindsym Mod1+4 workspace number 4 +bindsym Mod1+5 workspace number 5 +bindsym Mod1+6 workspace number 6 +bindsym Mod1+7 workspace number 7 +bindsym Mod1+8 workspace number 8 +bindsym Mod1+9 workspace number 9 +bindsym Mod1+Down focus down +bindsym Mod1+Invented invented-key-command +bindsym Mod1+Left overridden-command +bindsym Mod1+Return exec i3-sensible-terminal + +bindsym Mod1+Shift+0 move container to workspace number 10 +bindsym Mod1+Shift+1 move container to workspace number 1 +bindsym Mod1+Shift+2 move container to workspace number 2 +bindsym Mod1+Shift+3 move container to workspace number 3 +bindsym Mod1+Shift+4 move container to workspace number 4 +bindsym Mod1+Shift+5 move container to workspace number 5 +bindsym Mod1+Shift+6 move container to workspace number 6 +bindsym Mod1+Shift+7 move container to workspace number 7 +bindsym Mod1+Shift+8 move container to workspace number 8 +bindsym Mod1+Shift+9 move container to workspace number 9 +bindsym Mod1+Shift+Down move down +bindsym Mod1+Shift+Left move left +bindsym Mod1+Shift+Right move right +bindsym Mod1+Shift+Up move up +bindsym Mod1+Shift+c reload +bindsym Mod1+Shift+e exec i3-nagbar -t warning -m 'Do you want to exit i3?' -b 'Yes' 'i3-msg exit' +bindsym Mod1+Shift+minus move scratchpad +bindsym Mod1+Shift+q kill +bindsym Mod1+Shift+r restart +bindsym Mod1+Shift+space floating toggle +bindsym Mod1+Up focus up +bindsym Mod1+a focus parent +bindsym Mod1+d exec @dmenu@/bin/dmenu_run +bindsym Mod1+e layout toggle split +bindsym Mod1+f fullscreen toggle +bindsym Mod1+h split h +bindsym Mod1+minus scratchpad show +bindsym Mod1+r mode resize +bindsym Mod1+s layout stacking +bindsym Mod1+space focus mode_toggle +bindsym Mod1+v split v +bindsym Mod1+w layout tabbed + +mode "resize" { +bindsym Down resize grow height 10 px or 10 ppt +bindsym Escape mode default +bindsym Left resize shrink width 10 px or 10 ppt +bindsym Return mode default +bindsym Right resize grow width 10 px or 10 ppt +bindsym Up resize shrink height 10 px or 10 ppt +} + + +bar { + + font pango:monospace 8 + mode dock + hidden_state hide + position bottom + status_command @i3status@/bin/i3status + i3bar_command @i3@/bin/i3bar + workspace_buttons yes + strip_workspace_numbers no + tray_output primary + colors { + background #000000 + statusline #ffffff + separator #666666 + focused_workspace #4c7899 #285577 #ffffff + active_workspace #333333 #5f676a #ffffff + inactive_workspace #333333 #222222 #888888 + urgent_workspace #2f343a #900000 #ffffff + binding_mode #2f343a #900000 #ffffff + } + +} + + + + + + diff --git a/home-manager/tests/modules/services/window-managers/i3/i3-keybindings.nix b/home-manager/tests/modules/services/window-managers/i3/i3-keybindings.nix new file mode 100644 index 00000000000..4f8515e61ff --- /dev/null +++ b/home-manager/tests/modules/services/window-managers/i3/i3-keybindings.nix @@ -0,0 +1,35 @@ +{ config, lib, ... }: + +with lib; + +{ + config = { + xsession.windowManager.i3 = { + enable = true; + + config.keybindings = + let modifier = config.xsession.windowManager.i3.config.modifier; + in lib.mkOptionDefault { + "${modifier}+Left" = "overridden-command"; + "${modifier}+Right" = null; + "${modifier}+Invented" = "invented-key-command"; + }; + }; + + nixpkgs.overlays = [ + (self: super: { + dmenu = super.dmenu // { outPath = "@dmenu@"; }; + + i3 = super.i3 // { outPath = "@i3@"; }; + + i3status = super.i3status // { outPath = "@i3status@"; }; + }) + ]; + + nmt.script = '' + assertFileExists home-files/.config/i3/config + assertFileContent home-files/.config/i3/config \ + ${./i3-keybindings-expected.conf} + ''; + }; +} diff --git a/home-manager/tests/modules/systemd/timers.nix b/home-manager/tests/modules/systemd/timers.nix index 0fa0070cd77..eaa43f17695 100644 --- a/home-manager/tests/modules/systemd/timers.nix +++ b/home-manager/tests/modules/systemd/timers.nix @@ -5,17 +5,11 @@ with lib; { config = { systemd.user.timers.test-timer = { - Unit = { - Description = "A basic test timer"; - }; + Unit = { Description = "A basic test timer"; }; - Timer = { - OnUnitActiveSec = "1h 30m"; - }; + Timer = { OnUnitActiveSec = "1h 30m"; }; - Install = { - WantedBy = [ "timers.target" ]; - }; + Install = { WantedBy = [ "timers.target" ]; }; }; nmt.script = '' diff --git a/home-manager/tests/modules/xresources/default.nix b/home-manager/tests/modules/xresources/default.nix new file mode 100644 index 00000000000..afd15fbd300 --- /dev/null +++ b/home-manager/tests/modules/xresources/default.nix @@ -0,0 +1 @@ +{ xresources = ./xresources.nix; } diff --git a/home-manager/tests/modules/xresources-expected.conf b/home-manager/tests/modules/xresources/xresources-expected.conf index 20b47e5080b..20b47e5080b 100644 --- a/home-manager/tests/modules/xresources-expected.conf +++ b/home-manager/tests/modules/xresources/xresources-expected.conf diff --git a/home-manager/tests/modules/xresources.nix b/home-manager/tests/modules/xresources/xresources.nix index f73e326f31e..f73e326f31e 100644 --- a/home-manager/tests/modules/xresources.nix +++ b/home-manager/tests/modules/xresources/xresources.nix |