Compare commits

...

544 Commits

Author SHA1 Message Date
Robert Helgesson
9a61b83445 news: add entry about support stopping as of May 1 2019-04-23 21:28:17 +02:00
ash lea
2ccbf43e46 browserpass: update app id
(cherry picked from commit cb93316fed)
2019-04-14 17:25:37 +02:00
Robert Helgesson
5c1d10497d modules: register the base modules path
This is needed, for example, to support relative paths when disabling
modules.

(cherry picked from commit f8b03f5750)
2019-04-14 17:23:40 +02:00
Robert Helgesson
69851e4c35 home-environment: make home.keyboard optional
When set to `null` then the `xsession` module will not attempt to
manage the keyboard settings.

(cherry picked from commit b6e1d82685)
2019-04-11 01:18:13 +02:00
Tadeo Kondrak
9d23f09790 qt: use xdg.configHome instead of hard-coding
(cherry picked from commit bc2b7d4f09)
2019-04-04 23:43:08 +02:00
Robert Helgesson
2fa6dd4cf5 taffybar: restart the service on failure
(cherry picked from commit f77d6b7a2d)
2019-04-04 23:43:08 +02:00
Robert Helgesson
d5f6e84862 systemd: add some basic tests
(cherry picked from commit 6ebf14143a)
2019-04-04 23:42:28 +02:00
Robert Helgesson
0312d450e2 random-background: minor documentation improvements
(cherry picked from commit cf5dac9563)
2019-04-04 23:39:56 +02:00
Robert Helgesson
15ef36a7f4 readme: expand contact section slightly
In particular, mention that the channel is hosted by freenode and the
channel logs are hosted by samueldr.

(cherry picked from commit 2e1c825b90)
2019-04-04 23:39:56 +02:00
Robert Helgesson
78ce79e57d readme: add contact section with the IRC channel
(cherry picked from commit a974ce6257)
2019-04-04 23:39:56 +02:00
Robert Helgesson
b8eb7a03c5 manual: use writeShellScriptBin
(cherry picked from commit 5d81cb6ac7)
2019-04-04 23:39:56 +02:00
Robert Helgesson
deb2868d57 polybar: use writeShellScriptBin
(cherry picked from commit 41356ac267)
2019-04-04 23:39:56 +02:00
Robert Helgesson
6fcaef5235 firefox: make the extensions option visible
Also change the example to use the firefox-addons available on NUR.

(cherry picked from commit 86af599a18)
2019-04-04 23:39:56 +02:00
Robert Helgesson
6bc07d4f53 ssh: add some basic tests
(cherry picked from commit 989e636d98)
2019-04-04 23:37:05 +02:00
Robert Helgesson
c40fa72cde ssh: support multiple identity files in a match block
Fixes #625

(cherry picked from commit eec78fbd1e)
2019-04-04 23:36:18 +02:00
Robert Helgesson
594294e2ca Remove some use of mkDerivation
Instead use `runCommand`, which by default uses `stdenvNoCC` resulting
in a reduced dependency footprint.

Fixes #612

(cherry picked from commit 70d4cf2cd9)
2019-04-04 23:36:02 +02:00
arcnmx
2b19f15be3 git: make userName and userEmail options optional
(cherry picked from commit 52692e299d)
2019-04-04 23:35:34 +02:00
Robert Helgesson
9901509ef8 faq: add entry about missing ca.desrt.dconf
(cherry picked from commit fd2bc150d8)
2019-04-04 23:35:34 +02:00
Robert Helgesson
5d5bc3dc5a firefox: add support for add-on packages
Since no official source of packages exist the option is hidden for
now. For adventurous people there is an overlay of a few selected
add-ons available at

    https://rycee.gitlab.io/nixpkgs-firefox-addons/overlay.tar.gz

This overlay is automatically built daily using the REST API available
on https://addons.mozilla.org/.

(cherry picked from commit 267afa5a3b)
2019-04-04 23:35:34 +02:00
Wael M. Nasreddine
ec05213a41 nix-darwin: login as the user when activating
(cherry picked from commit 7ec153889c)
2019-04-04 23:35:34 +02:00
Wael M. Nasreddine
9b82a37d28 nix-darwin: support package install through user packages
(cherry picked from commit efc795920b)
2019-04-04 23:35:33 +02:00
Wael M. Nasreddine
0ac92c6a42 nix-darwin: activate home-manager through postActivation
(cherry picked from commit d3fd287efb)
2019-04-04 23:35:33 +02:00
Robert Helgesson
5342c9479b docs: add NixOS module installation instructions
(cherry picked from commit 52fdf5b7ec)
2019-04-04 23:35:09 +02:00
Robert Helgesson
d99f0cbe62 docs: add language attribute to program listings
(cherry picked from commit a09196c4ae)
2019-04-04 23:35:09 +02:00
Robert Helgesson
87a897e0c9 docs: use <screen> for terminal interaction
(cherry picked from commit 1d8997633c)
2019-04-04 23:35:09 +02:00
Mario Rodas
fdda547e9e git: allow contents in git.includes
(cherry picked from commit 6da88339f5)
2019-04-04 23:34:35 +02:00
Maximilian Bosch
da31e466a1 nixos module: evaluate assertions from Home Manager modules
(cherry picked from commit 0898b6b482)
2019-04-04 23:32:34 +02:00
Olli Helenius
fa19c18343 pam: enclose session variable values in quotes
(cherry picked from commit 848b8b983e)
2019-04-04 23:32:34 +02:00
Maximilian Bosch
3c2823e3cd programs/zsh: properly escape shell aliases
Otherwise all aliases break that use single quotes inside.

Already fixed in the nixpkgs module in 1e211a70cbdaf230a18ea4cb67a959039d5c2ddb.

(cherry picked from commit 465d08d99f)
2019-04-04 23:32:34 +02:00
Robert Helgesson
dd94a849df tests: remove tests attribute from root default.nix
Having it there prevented, e.g., `nix-env -qaP` from working in some
cases.

Fixes #509

(cherry picked from commit b8b391ad18)
2019-02-23 22:59:15 +01:00
Douglas Wilson
ee1bfa0d92 systemd: sanitize unit derivation names
To allow a few special characters such as "@".

This is taken from

    c414e5bd08/nixos/modules/system/boot/systemd-lib.nix (L14)

(cherry picked from commit 74811679b7)
2019-02-23 22:59:08 +01:00
Robert Helgesson
8980e08240 msmtp: use <parameter> for CLI options in description
(cherry picked from commit 93f5fcae1e)
2019-02-23 22:59:01 +01:00
Robert Helgesson
afd2d0fb84 fontconfig: make fonts accessible when in NixOS module
(cherry picked from commit 799a90ecfa)
2019-02-23 22:58:47 +01:00
Robert Helgesson
2bdaf4ae98 nixos module: support NixOS user packages install
When using the NixOS module we cannot guarantee that the Nix store
will be writable during startup. Installing the user packages through
`nix-env -i` will fail in these cases.

This commit adds a NixOS option `home-manager.useUserPackages` that,
when enabled, installs user packages through the NixOS

    users.users.<name?>.packages

option.

Note, when submodule support and external package install is enabled
then the installed packages are not available in `~/.nix-profile`. We
therefore set `home.profileDirectory` directly to the HM profile
packages.

(cherry picked from commit ef168979bf)
2019-02-23 22:58:47 +01:00
Robert Helgesson
1ade5cad80 Revert "fish: use global for abbr"
This reverts commit 7d6a6cbbe3.

The version of fish in Nixpkgs 18.09 is not compatible with this
option. See #581.
2019-02-13 17:25:03 +01:00
Olli Helenius
cf5b16b45f msmtp: use XDG config directory
(cherry picked from commit a3462daeb1)
2019-02-11 01:23:50 +01:00
Robert Helgesson
45057f353c tests: bump to latest nmt version
(cherry picked from commit a334a941c4)
2019-02-11 01:22:02 +01:00
Robert Helgesson
ee7631fbe3 git: add basic support for LFS
Fixes #542

(cherry picked from commit 1cdb8abf30)
2019-02-11 01:22:02 +01:00
Ingolf Wanger
fdb81a7ea0 nixos: use correct username for systemd service
(cherry picked from commit fbdb5beb59)
2019-02-11 01:22:02 +01:00
Robert Helgesson
1c3614cbc8 Clean up support code for Home Manager as a submodule
This removes the `nixosSubmodule` option in favor of a new option
`submoduleSupport.enable`. This name better indicates that the
submodule mode applies to both NixOS and nix-darwin.

(cherry picked from commit 2f372ab4d6)
2019-02-11 01:22:02 +01:00
Lorenzo Manacorda
75538973db doc: add "See also" section to manpages
Pointing to each other.

(cherry picked from commit 524ce43e23)
2019-02-11 01:22:02 +01:00
Lorenzo Manacorda
37760ed934 doc: remove extraneous contrib element
`contrib` is "A summary of the contributions made to a document by a
credited source", which we don't need in this case.

(cherry picked from commit 7f8e139413)
2019-02-11 01:22:01 +01:00
Robert Helgesson
6924761aaf doc: move home-manager man page to section 1
This is not really a system administration tool so 8 is unsuitable.

(cherry picked from commit 99d79d0a80)
2019-02-11 01:22:01 +01:00
Jonas Holst Damtoft
5ccc2298de emacs: add service module
(cherry picked from commit 0ca1bf3cfd)
2019-02-11 01:22:01 +01:00
Matthieu Coudron
0f4c798c81 neovim: allow to override package
If you want to run a development version for instance, it is easier to
set neovim.package rather than work around the wrapping mechanism etc.

(cherry picked from commit c18984c452)
2019-02-11 01:22:01 +01:00
Robert Helgesson
f89522362f git: use attrsOf instead of attrs
This makes sure that values added to

    programs.git.aliases

or

    programs.git.extraConfig

are merged as expected.

Also add a few option examples.

(cherry picked from commit 445c0b1482)
2019-02-11 01:22:01 +01:00
Robert Helgesson
7772158ac4 mbsync: add basic test of result configuration
(cherry picked from commit 0590c2a4f6)
2019-02-11 01:22:01 +01:00
Nadrieril
fb96af9b9d mbsync: add some required assertions
(cherry picked from commit 81ec856a0f)
2019-02-11 01:22:01 +01:00
Yurii Rashkovskii
c73685ec74 nixpkgs: fix installation on non-x86
On non-x86 architectures (for example, aarch64) the installation of
home-manager fails indicating that it is attempting to select i686
packages for Linux and those aren't available.

Solution: make the condition for choosing these packages stricter
(cherry picked from commit 2410bc603b)
2019-02-11 01:22:00 +01:00
Robert Helgesson
de2d6a5d95 git: quote sendemail section header
This will allow, e.g., the character `@` in the email identity.

Also adds a test case.

Fixes #557

(cherry picked from commit 45cadbd4f3)
2019-02-11 01:22:00 +01:00
Amarandus
3bef871dac irssi: add module
irssi is a cli IRC client.

(cherry picked from commit 02a5a678f6)
2019-02-11 01:22:00 +01:00
Robert Helgesson
27042d1050 flameshot: add bars to systemd After
Fixes #544

(cherry picked from commit 98f534e172)
2019-02-11 01:22:00 +01:00
Matthieu Coudron
a6475e3e60 git: generate identities from mail accounts
(cherry picked from commit a68c8cf5f1)
2019-02-11 01:22:00 +01:00
wedens
17aaf04f72 polybar: add /run/wrappers/bin to PATH
Without this the network module in polybar is unable to check
connection as it invokes 'ping' command directly.

(cherry picked from commit 604fc92943)
2019-02-11 01:21:05 +01:00
Robert Helgesson
708de1ac8d xembed-sni-proxy: add module
(cherry picked from commit 008d93928f)
2019-02-11 01:21:04 +01:00
Jonas Holst Damtoft
7d6a6cbbe3 fish: use global for abbr
Makes fish use global scope for abbreviations.
This makes it so that they don't stick across config changes.
Before, an abbreviation would still exist even if removed from the config.

(cherry picked from commit 601619660d)
2019-02-11 01:21:04 +01:00
Robert Helgesson
016005a3a3 doc: bump copyright year to 2019 in man pages
(cherry picked from commit 4aa07c3547)
2019-02-11 01:21:04 +01:00
Robert Helgesson
966b790859 doc: reformat XML files
(cherry picked from commit f3f7c5cc57)
2019-02-11 01:21:04 +01:00
Robert Helgesson
bceb74a78c doc: add basic release notes
(cherry picked from commit c035046999)
2019-02-11 01:21:04 +01:00
Robert Helgesson
bde13d0482 Update LICENSE file for 2019
(cherry picked from commit e15cd64ac9)
2019-02-11 01:21:04 +01:00
Robert Helgesson
6c30decf8d i3: replace use of types.string by types.str
(cherry picked from commit 59a4ac71f9)
2019-02-11 01:21:04 +01:00
Robert Helgesson
4bed99c71c files: allow a wider range of source file names
In particular support source files whose name start with `.` or
contain characters not allowed in the nix store, such as spaces.

Also add some test cases for `home.file`.

(cherry picked from commit 7c04351a57)
2019-02-11 01:21:04 +01:00
Robert Helgesson
f174f90fdf tests: bump nmt version
(cherry picked from commit 46f787950a)
2019-02-11 01:21:03 +01:00
Adam Washington
a9e218dddd matplotlib: add module
(cherry picked from commit 6a244b3a8d)
2019-02-11 01:21:03 +01:00
John Wiegley
3656bf1ad7 ssh: add proxyJump option
(cherry picked from commit 3cf8b9ea86)
2019-02-11 01:20:30 +01:00
Nadrieril
47450371d9 i3: add bar.extraConfig option
(cherry picked from commit df8a14e12a)
2019-02-11 01:20:30 +01:00
Robert Helgesson
4bb40ac42d tests: simplify test names
(cherry picked from commit f6ec26075d)
2019-02-11 01:20:29 +01:00
Robert Helgesson
4c311835a7 i3: add test of keybinding merge logic
(cherry picked from commit c42206db02)
2019-02-11 01:20:29 +01:00
Robert Helgesson
e9942375ce tests: bump nmt to latest
(cherry picked from commit bb64012914)
2019-02-11 01:20:29 +01:00
Nadrieril
e6bc17e7fb i3: reallow using null to disable a keybinding
(cherry picked from commit d5cc53a4e1)
2019-02-11 01:20:29 +01:00
Robert Helgesson
9f013a8fb8 dunst: avoid error on missing dunst process
(cherry picked from commit 55100918cc)
2019-01-14 18:40:51 +01:00
Robert Helgesson
3c429c2462 dunst: kill daemon on configuration change
Since Dunst is DBus activated it is OK to simply kill it since DBus
will restart it when necessary.

(cherry picked from commit faee571850)
2019-01-14 18:40:51 +01:00
hyperfekt
f60f0c647f fish: autogenerate completions from man pages
(cherry picked from commit 6f422785c3)
2019-01-14 18:40:51 +01:00
David Guibert
6d8a296625 msmtp: add extraConfig account option
This patch allow to define custom msmtp options per email account. For
example: to change the "auth" method from "on" to "login", add
`msmtp.extraConfig.auth="login"`.

(cherry picked from commit a7affc93ba)
2019-01-14 18:40:51 +01:00
Marcial Gaißert
2d77421d7c programs.zsh: option localVariables
Add option "extraLocalVars" for additional local variable definitions
in .zshrc, at the top of the file.

Some zsh plugins/themes expect configuration in local variables before they
are loaded (example: https://github.com/bhilburn/powerlevel9k). Exporting
those clutters the environment and is unnecessary.

(cherry picked from commit 9052131aef)
2019-01-14 18:40:51 +01:00
Marcial Gaißert
257dcbcd8a programs.zsh: generate export statements in zsh syntax
Use the new module lib.zsh to generate export statements in zsh syntax, using
zsh arrays for lists.

Being a zsh script, this seems more intuitive for .zshrc

(cherry picked from commit 6b5e0efd1e)
2019-01-14 18:40:50 +01:00
Marcial Gaißert
f221e4935d lib.zsh: add module
Added utilities to generate export statements and definitions for zsh scripts.

Currently, there is only lib.shell which generates export statements in bash
syntax. However, this does not allow to generate export statements for zsh
arrays (syntax: NAME=(elem1 elem2 ...) ), which would be the natural
representation of lists in the nix language.

(cherry picked from commit 62eb7ebeba)
2019-01-14 18:40:50 +01:00
Wael M. Nasreddine
29161b6e21 autorandr: add support for xrandr transformation
(cherry picked from commit c48fd9d842)
2019-01-14 18:40:50 +01:00
Robert Helgesson
9e913a9a30 texlive: always require at least one extra package
Fixes #526

(cherry picked from commit e150dd4a66)
2019-01-14 18:40:50 +01:00
Olli Helenius
e57e34f799 gnome-terminal: enable VTE OSC7 support for bash and zsh
(cherry picked from commit b3d73e0aff)
2019-01-14 18:40:50 +01:00
Olli Helenius
af94896ba1 Address review comments
(cherry picked from commit 16946a6f00)
2019-01-14 18:40:50 +01:00
Olli Helenius
8026e4ff6f zsh: add default keymap configuration
(cherry picked from commit a4383075af)
2019-01-14 18:40:50 +01:00
Robert Helgesson
ad0b33387d emacs: make finalPackage option more accessible
Instead of "internal" mark it as "invisible".

(cherry picked from commit 20a60be550)
2019-01-14 18:40:49 +01:00
Mario Rodas
c67d2a916f opam: add module
(cherry picked from commit 7afefcf75d)
2019-01-14 18:40:49 +01:00
Robert Helgesson
82ed4dae2a dconf: add some information of use under NixOS
(cherry picked from commit 40b3443c8f)
2019-01-14 18:37:51 +01:00
Robert Helgesson
7e65605d8f gtk: remove option gtk.gtk3.waylandSupport
(cherry picked from commit cc964b4609)
2019-01-14 18:37:51 +01:00
Robert Helgesson
be7017b9c8 gtk: make gtk.gtk2 and gtk.gtk3 not submodules
(cherry picked from commit 370a84192e)
2019-01-14 18:37:51 +01:00
Robert Helgesson
5b66b89d6e gtk: use dconf module for settings
(cherry picked from commit 4104ff2b6a)
2019-01-14 18:37:50 +01:00
Robert Helgesson
1e7fbde1be gnome-terminal: use dconf module for settings
(cherry picked from commit a0162dacf6)
2019-01-14 18:37:50 +01:00
Robert Helgesson
54fc5f778b dconf: add module
This module allows unified configuration of dconf settings.

(cherry picked from commit b2cc186d22)
2019-01-14 18:37:46 +01:00
Robert Helgesson
f60f9c4bb6 readme: add notice that relog may be needed
Also add instructions for non-NixOS users to add the user channel
directory to `NIX_PATH`.

(cherry picked from commit 235a6617c4)
2019-01-14 18:36:50 +01:00
Robert Helgesson
944c12dbbb modules: support conditional module inclusion
Also make use of this functionality for the `programs.chromium`
module.

See #501

(cherry picked from commit 218a8c4d90)
2019-01-14 18:36:50 +01:00
hyperfekt
17fd9cbbd0 vscode: add module
(cherry picked from commit 6ab6488e5a)
2019-01-07 18:35:39 +01:00
Robert Helgesson
dc9be1eee6 emacs: add overrides option
This option enables overriding packages within the generated Emacs
package set.

Fixes #486

(cherry picked from commit e68d6e7924)
2018-12-24 11:20:25 +01:00
Olli Helenius
c2cff13f15 jq: add module
(cherry picked from commit dc72aa2305)
2018-12-24 11:20:08 +01:00
Lorenzo
e267dfea2d readme: fix .gitconfig example
The example was referencing `~/.gitconfig`, which isn't being checked
anymore since 356c0bf751.

(cherry picked from commit 93b10bcf3c)
2018-12-12 00:56:40 +01:00
Lorenzo Manacorda
461869b438 readme: clarify bash/zsh compatibility
Makes it clearer that the compatibility mentioned only relates to the
manual loading approach.

(cherry picked from commit 4971e3735e)
2018-12-12 00:56:40 +01:00
Robert Helgesson
1484b1d48b tests: add initial test framework
(cherry picked from commit 6d56abcec1)
2018-12-12 00:56:40 +01:00
Nikita Uvarov
d5e21feebb i3: fix default keybindings override
All default keybindings should have a default priority attached to them.
This will allow users to redefine some of the default keybindings
without using mkForce. Fixes #485.

(cherry picked from commit 5d63abb473)
2018-12-12 00:56:40 +01:00
Robert Helgesson
cb29a29055 doc: add installation instructions to manual
Also minor cleanups in README.

(cherry picked from commit 6e67bb7ae6)
2018-12-12 00:56:40 +01:00
Nikita Uvarov
c2646f9f2b polybar: switch from attrs to attrsOf
(cherry picked from commit d67835260d)
2018-12-06 00:32:53 +01:00
Nikita Uvarov
48ba1010ab dunst: switch from attrs to attrsOf
(cherry picked from commit b085344b91)
2018-12-06 00:32:53 +01:00
Nikita Uvarov
b837f8ae41 i3: switch from attrs to attrsOf
(cherry picked from commit c108eaba42)
2018-12-06 00:32:52 +01:00
dsx
0312cb611e ssh: add addressFamily option
(cherry picked from commit 6ce3ce69b9)
2018-12-06 00:32:52 +01:00
Robert Helgesson
3b7f74ab87 ssh: add certificateFile option
(cherry picked from commit 6826521ec5)
2018-12-06 00:32:52 +01:00
Robert Helgesson
c9945550de ssh: realign options
(cherry picked from commit 5fe62660aa)
2018-12-06 00:32:52 +01:00
dsx
a471c62bf2 dunst: use 'icon_path' instead of 'icon_folders'
The 'icon_folders' option is deprecated.

(cherry picked from commit 7a28f68ad0)
2018-12-06 00:32:52 +01:00
Robert Helgesson
1e2d80a583 rofi: switch from types.string to types.str
(cherry picked from commit ea9d44bede)
2018-12-06 00:32:52 +01:00
Robert Helgesson
159ee7a269 newsboat: switch from types.string to types.str
(cherry picked from commit fd3692b36f)
2018-12-06 00:32:52 +01:00
Robert Helgesson
ab562d4c2a autorandr: switch from types.string to types.str
(cherry picked from commit cd7b6fdbc1)
2018-12-06 00:32:52 +01:00
zimbatm
3646088248 home-manager: add edit command
With this change, running

    home-manager edit

opens `$HOME_MANAGER_CONFIG` in `$EDITOR`.

This is mainly for convenience. Users should not have to remember the
exact location of the Home Manager configuration.

(cherry picked from commit 571e17410a)
2018-12-06 00:32:51 +01:00
Robert Helgesson
371715a51c beets: add enable option
(cherry picked from commit 797fbbf826)
2018-12-06 00:32:47 +01:00
Robert Helgesson
c4a9546831 Change installation instructions to use nix-channel
This avoids the uncontrollable nature of fetching the tarball as part
of the evaluation. Instead the user can decide when to update and also
perform rollbacks, if necessary.

(cherry picked from commit a37b5c9c61)
2018-12-06 00:31:54 +01:00
Wael M. Nasreddine
88c681606b home-manager: import modules using relative path
(cherry picked from commit 30f3baabaf)
2018-12-06 00:31:54 +01:00
Robert Helgesson
63668b2172 readme: switch stable channel to 18.09
(cherry picked from commit ef29f321e0)
2018-12-06 00:31:54 +01:00
dsx
0686063f62 i3: support for workspace_layout option
(cherry picked from commit 15bca92b2c)
2018-12-06 00:31:53 +01:00
dsx
4a574ca544 i3: support for bar tray_output option
(cherry picked from commit 71f6bc41eb)
2018-12-06 00:31:53 +01:00
Robert Helgesson
f4af8151de pasystray: add paprefs and pavucontrol
This enables the "volume control" and "control local sound server"
menu options.

Fixes #461

(cherry picked from commit 6d2f16a7ae)
2018-12-06 00:31:53 +01:00
zimbatm
b535770bd4 ssh: tweak default controlPath
Instead of using the hostname `%h`, which can be changed by the
~/.ssh/config file, use the commandline-given hostname `%n`.

This allows to alias a host with different hostnames, which then point
to different configurations. A common use-case for this is if you have
multiple accounts on github with each access to different private repos:

    Host github.com
      IdentitiesOnly yes
      User git
      IdentityFile ~/.ssh/id_rsa

    Host customer.github.com
      IdentitiesOnly yes
      User git
      IdentityFile ~/.ssh/customer
      HostName github.com

Without this change, if a connection was established with the first
github.com alias, then the user would try to pull a repo from the second
account, ssh would re-use the SSH connection which doesn't have access
to that repository.

(cherry picked from commit 40b279e3a3)
2018-12-06 00:31:53 +01:00
Wael M. Nasreddine
7ab6441ab7 keybase: install the keybase package
(cherry picked from commit 9686d93ff6)
2018-12-06 00:31:13 +01:00
zimbatm
2297450ec8 termite: setup the shell hook
This fixes Ctrl+Shift+T not working.

(cherry picked from commit 67ebe16b40)
2018-12-06 00:31:13 +01:00
Manuel Bärenz
ffdbefe22c nextcloud-client: add module
Adds the nextcloud-client as a service, simply copying the syntax from owncloud.client.
2018-11-25 23:13:13 +01:00
zimbatm
456e2d7ed5 ssh: add more options 2018-11-25 22:46:06 +01:00
Robert Helgesson
fa3d1f98e0 astroid: require notmuch synchronize flags 2018-11-25 13:53:45 +01:00
Robert Helgesson
c21b69e73e notmuch: add maildir.synchronizeFlags option 2018-11-25 13:33:30 +01:00
Robert Helgesson
9318bd3b0d notmuch: replace incorrect use of toJSON 2018-11-25 13:33:30 +01:00
Robert Helgesson
59448d635c version: add module 2018-11-24 17:27:59 +01:00
Will Fancher
a9a4fb641f nix-darwin: add system module for nix-darwin 2018-11-20 00:22:53 +01:00
Wael M. Nasreddine
f247b3b99b offlineimap: add an extraConfig for the account section 2018-11-19 23:57:58 +01:00
Robert Helgesson
fa62c5afb6 modules: fix list sort order 2018-11-19 00:07:29 +01:00
Ben Sima
061c7b633f afew: add module 2018-11-18 23:47:45 +01:00
Matthieu Coudron
dacc07136c astroid: add module
Astroid is a notmuch/gtk based MUA: https://github.com/astroidmail/astroid
2018-11-18 19:55:28 +01:00
Robert Helgesson
abfc37076a compton: minor reformatting 2018-11-15 00:28:52 +01:00
Robert Helgesson
9a0f388f66 compton: fix corrupt colors under Mesa 18
Fixes #441
2018-11-15 00:28:50 +01:00
Ben Sima
b08e6221e0 faq: add instructions on targeting multiple logins
Content adapted from

    https://github.com/rycee/home-manager/issues/394#issuecomment-422958338
2018-11-14 23:25:17 +01:00
Robert Helgesson
0efda9cd6b Use preferLocalBuild with runCommand 2018-11-14 20:59:45 +01:00
Sam Stites
f4ebbcbf70 tmux: add module
This commit adds the tmux program to Home Manager.

In addition to configuring tmux, a user may specify tmux plugins from
Nixpkgs. These can be included in the list of `plugins` and can either
be a package (all tmux plugins live under `nixpkgs.tmuxPlugins.*`), or
an object which includes the plugin and an `extraConfig`, which will
be run immediately after sourcing the tmux plugin.

Finally, this commit introduces two nested programs which may be
enabled which depend on tmux: tmuxp and tmuxinator. These do not have
the ability to be configured, although this may be a future
contribution.
2018-11-14 00:08:39 +01:00
Robert Helgesson
36ecad6cbe Add basic gitignore file 2018-11-14 00:08:39 +01:00
Robert Helgesson
22568a3d26 Revert PR #408
This reverts the commits

- "alot: change msmtp default command"
  8e798e4c28

- "astroid: init"
  736e340bde

because they include changes that break some configurations and some
options that are misplaced.
2018-11-12 21:59:11 +01:00
Matthieu Coudron
8e798e4c28 alot: change msmtp default command 2018-11-12 23:16:03 +09:00
Matthieu Coudron
736e340bde astroid: init
Astroid is a notmuch/gtk based MUA: https://github.com/astroidmail/astroid
2018-11-12 23:16:03 +09:00
Robert Helgesson
05c93ff3ae home-manager: remove uninstall activation phase
The manual install has been long deprecated so it should be safe to no
longer attempt to do an uninstall on each activation.
2018-11-04 09:58:00 +01:00
Robert Helgesson
8d4c65f259 fzf: only enable when line editing is available
Fixes #401

Suggested-by: Alex Vorobiev
Suggested-by: Mario Rodas
2018-10-30 00:17:09 +01:00
Robert Helgesson
0435d9c338 news: remove news item about removed vim options 2018-10-29 19:42:09 +01:00
Jonas Carpay
15a5f3278a Remove tabSize and lineNumbers check from news item 2018-10-20 16:57:27 +02:00
Nikita Uvarov
34bbd0ded1 vim: remove deprecated options 2018-10-20 13:13:19 +02:00
Nikita Uvarov
c17f37857c urxvt: add module 2018-10-20 11:35:39 +02:00
Nikita Uvarov
a2e09b4c9d vim: add options 2018-10-20 11:00:13 +02:00
Robert Helgesson
5013155e58 readme: documentation is now hosted on GitLab 2018-10-18 23:42:15 +02:00
Alex Brandt
7575e119d6 systemd: add more detail to user unit documentation
The current documentation does not provide guidance to users on how
systemd units are defined in Home Manager. A user may expect the
configuration to be similar to NixOS, when it actually differs.

Fixes #418
2018-10-18 23:39:28 +02:00
Alex Brandt
3b9b897af3 home-manager: add generation expiration command
This adds a new command to the home-manager shell script that allows
generations to be removed that are older than an given absolute or
relative date.

This allows users to manage the expiration of their home-manager
generations separately from their system or user profiles via
nix-collect-garbage. It is most important if the user desires to have
a convenient way to have different expiration times for Home Manager
generations than other system or user profiles.
2018-10-18 23:12:29 +02:00
Will Dietz
0cfd21cc15 compton: drop no-dock-blur option, add dock and dnd shadow
no-dock-blur doesn't exist in compton and was added by mistake.
2018-10-14 12:13:57 +02:00
Daniël de Kok
05a98b6be0 mbsync: change service unit type to 'oneshot'
The ExecStartPost command is currently started when the mbsync is
invoked succesfully. However, we typically want to run something like
'mu index' or 'notmuch new' after mbsync completes.  This changes the
unit type to oneshot, so that the ExecStartPost command is run after
mbsync finishes succesfully.
2018-10-13 19:28:40 +02:00
Nikita Uvarov
52b9363745 rofi: set configPath defaultText to avoid rebuilds 2018-10-12 10:52:41 +02:00
Mario Rodas
f947fafec9 direnv: add config option 2018-10-10 23:05:30 +02:00
Mario Rodas
68d3cdd722 direnv: add stdlib option 2018-10-10 23:02:31 +02:00
Will Dietz
5770dc58b9 mbsync: add option to add extra account configuration 2018-10-03 13:35:04 -05:00
Edward Betts
36da7a918f Correct spelling mistakes 2018-10-02 22:41:08 +02:00
Matthieu Coudron
782d2fab83 rofi: fix default path 2018-10-01 09:27:33 +02:00
Matthieu Coudron
d9c5d3c868 alot: add module
Alot is a python mail user agent (MUA) built around the Notmuch mail
system.
2018-09-28 23:43:40 +02:00
Robert Helgesson
9b3122e92c lib: copy module from NixOS
Importing the module directly from NixOS causes the documentation to
break, in particular the "Declared by" section.

Fixes #405
2018-09-27 21:01:13 +02:00
adisbladis
f44d4a1d86 obs-studio: add module 2018-09-27 19:58:31 +02:00
gnidorah
33a2943e8c gtk: add support for wayland 2018-09-26 21:32:43 +02:00
Mario Rodas
a1a7e7cd24 bash: fix bashrcExtra interactive shell test
To determine if bash is running interactively test whether "$-"
contains "i".

See: https://www.gnu.org/software/bash/manual/html_node/Is-this-Shell-Interactive_003f.html
2018-09-26 18:18:57 +02:00
Robert Helgesson
6957911657 xresources: remove unnecessary parentheses 2018-09-24 23:24:04 +02:00
Robert Helgesson
7cc36b7703 xresources: run xrdb -merge on change
Fixes #400
2018-09-24 23:19:54 +02:00
Matthieu Coudron
9407b42f97 accounts.emails: adding gpg/signature modules 2018-09-23 23:22:39 +02:00
Matthieu Coudron
151f29a17a mbsync: add options extraConfig.{channel|local|remote}
To allow supporting more advanced configurations. The local refers to
the "maildir store" configuration, remote to the "IMAP store", and
"channel" to the channel.
2018-09-23 23:22:39 +02:00
Roman Volosatovs
f7dc354f42 go: Fix package example 2018-09-21 09:46:11 +02:00
Robert Helgesson
4d870f665b taffybar: fix indentation 2018-09-21 00:51:23 +02:00
Roman Volosatovs
0635423e73 go: add module 2018-09-21 00:11:25 +02:00
Mario Rodas
3f34bf4465 noti: add module 2018-09-20 21:26:55 +02:00
Robert Helgesson
9f0fdc68a9 xsession: add option xsession.scriptPath
This option allows overriding the default script path `~/.xsession`.
On NixOS, this is needed to allow multiple possible graphical login
sessions.

Fixes #391.
2018-09-19 23:33:13 +02:00
Robert Helgesson
701b4130bd Remove unnecessary dag variables
Also remove a few trailing whitespaces.
2018-09-19 00:13:31 +02:00
Adam Washington
d27bccdff1 zathura: add module
Add the zathura document viewer as a program option with support for
managing the zathurarc configuration file.
2018-09-18 23:57:36 +02:00
Minijackson
5ff03ce5ac taskwarrior: add module 2018-09-18 23:31:37 +02:00
Nikita Uvarov
6eea2a409e vim: improve instructions for listing available plugins 2018-09-15 12:01:36 +02:00
Robert Helgesson
ea74820176 home-environment: add option home.extraProfileCommands
This _internal_ option indicates extra commands that should be run in
the `postBuild` step of the profile environment build.

Fixes #386
2018-09-14 21:08:51 +02:00
Robert Helgesson
50de1a6885 emacs: add internal finalPackage option 2018-09-11 21:23:11 +02:00
gnidorah
055d100548 i3 module: add missing pieces to default config 2018-09-10 11:33:51 +09:00
Roman Volosatovs
63efd26767 neovim: support new extraPython*Packages options
Also fix `configure` argument.
2018-09-09 22:09:00 +02:00
Robert Helgesson
8d2cb0ef9b fish: minor formatting fixes 2018-09-09 21:18:39 +02:00
gnidorah
2bff6e5188 fish module: envoke hm-session-vars.sh 2018-09-09 21:17:13 +02:00
Matthieu Coudron
453d0494fb notmuch: synchronize_flag should be "true"
...and not "True"

According to doc https://notmuchmail.org/manpages/notmuch-config-1/

It also causes a crash in astroid :
https://github.com/astroidmail/astroid/issues/546
2018-09-07 19:38:39 +02:00
gnidorah
97c6073d39 i3 module: fonts option for bar section 2018-09-06 17:09:47 +02:00
Roman Volosatovs
9fe6fa7f44 neovim: add vi{,m}Alias options 2018-09-04 07:32:01 +02:00
Mario Rodas
7699ed3fc8 email: fix port setting for flavor gmail.com
See https://support.google.com/mail/answer/7126229.
2018-09-02 12:07:30 +02:00
Matthieu Coudron
5eca556fe7 offlineimap: add module
OfflineIMAP is a Mail Retrieval Agent (MRA) like mbsync but written in
Python.
2018-08-30 18:57:35 +02:00
Robert Helgesson
4602c00dcf polybar: minor reformatting 2018-08-29 21:46:11 +02:00
Jonathan Reeve
629d66e0b9 polybar: only quote strings if needed
Polybar expects quoted values only when whitespace is important to the
value.

Fixes #356
2018-08-29 21:42:42 +02:00
Robert Helgesson
859c132ee2 home-manager: enable build output during switch
Fixes #352
2018-08-28 00:17:57 +02:00
adisbladis
99a0e2469b direnv: add fish support 2018-08-27 22:52:53 +02:00
Mogria
2548c43175 fzf: add options for setting commands for all keys
This allows you to specify your own custom commands
to be run when calling fzf. You might use tools like
fd to search faster and take `.gitignore` files into
consideration.
2018-08-23 23:22:53 +02:00
Anton Plotnikov
90bcaaf582 pasystray: add module 2018-08-22 23:17:47 +02:00
Tad Fisher
da8307cd26 chromium: parseDrvName quick fix 2018-08-22 23:13:54 +02:00
Matthieu Coudron
cfa06c3f38 msmtp: add module
msmtp is a simple mail transfer agent (MTA).
2018-08-21 00:22:51 +02:00
Robert Helgesson
906965b48b Revert "email: note that passwordCommand should output '\n'"
This reverts commit d5bbbbd41d.

This was premature, the example will not emit a terminal newline and
it is not clear whether it is a good idea to force this limitation.
2018-08-21 00:19:33 +02:00
Robert Helgesson
d5bbbbd41d email: note that passwordCommand should output '\n'
This is because some programs, for example msmtp, expect the output to
end with a newline character.
2018-08-20 22:47:49 +02:00
Robert Helgesson
8e05229e62 Add initial GitLab CI configuration
This will automatically build and publish the Home Manager manual on
GitLab Pages.
2018-08-20 22:03:26 +02:00
Matthieu Coudron
7a8d50a803 xdg: create $XDG_CACHE_HOME
Some programs fail silently (bash with HISTFILE for instance) when the
folder doesn't exist.
2018-08-20 20:37:26 +02:00
Robert Helgesson
6630cfbe16 chromium: only enable for the linux platform 2018-08-20 07:11:00 +02:00
Tad Fisher
dd25fbcb4b chromium: add module 2018-08-19 22:46:30 +02:00
LightDiscord
f9ac73732b awesome: fix missing concatenation 2018-08-19 22:42:14 +02:00
Tad Fisher
26342588ab gpg-agent: add extraConfig option 2018-08-19 21:46:25 +02:00
Vincent Demeester
29191eb2c7 fish: add module
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2018-08-17 22:32:08 +02:00
Matthieu Coudron
168d546304 accounts.mail: add "gmail.com" as a flavor
To help with some autoconfiguration.
2018-08-16 23:46:27 +02:00
Robert Helgesson
34133ca7f3 accounts.email: add global certificatesFile option
This defaults to `/etc/ssl/certs/ca-certificates.crt` and will be
picked up as default by the account specific option.
2018-08-16 23:29:10 +02:00
Robert Helgesson
4b32f16747 Use submodules for program email accounts
This reworks the way program specific email account options are
specified. In particular, we no longer use the deprecated `options`
field of `mkOption`. Instead submodules are used.
2018-08-16 21:37:42 +02:00
Robert Helgesson
99c900946d Avoid substitution for some derivations
In particular, don't bother attempting to do substitution of the home
files and home generation derivations since these rarely, if ever,
could be substituted.

Fixes #330
2018-07-31 21:16:36 +02:00
Robert Helgesson
39213a1847 home-manager: fix work directory when building generation 2018-07-31 21:05:05 +02:00
Malte Brandy
c18b1328a5 Parametrize path to profile directory 2018-07-31 16:04:19 +02:00
Robert Helgesson
93ef6aefce direnv: add module 2018-07-31 15:48:08 +02:00
Anton Plotnikov
2e9e1909da status-notifier-watcher: add service 2018-07-31 15:33:57 +02:00
Robert Helgesson
4f67e8d0c3 home-manager: fix GC issue
It was previously possible to create the news information and lose it
in a Nix GC before being able to view it. This also causes a switch to
error out. This change makes the news information a root in the
garbage collector.

Note, this change also removes the need for `nix eval` so the
`doBuildAttr` function is simplified accordingly.

Fixes #327
2018-07-31 13:42:56 +02:00
Andrew Scott
30cba446f2 files: add onChange option
This option allows execution of arbitrary shell code when a file that
is linked into the home directory has been changed between
generations.
2018-07-27 22:07:12 +02:00
Robert Helgesson
dda65c0877 polybar: let systemd reload trigger restart 2018-07-26 18:01:35 +02:00
Roman Volosatovs
cf80199bfc xresources: join lists with a "," 2018-07-25 20:53:02 +02:00
Robert Helgesson
6694330bb2 udiskie: use xsession.preferStatusNotifierItems 2018-07-24 12:59:56 +02:00
Robert Helgesson
a5a49c350d network-manager-applet: use xsession.preferStatusNotifierItems 2018-07-24 12:59:50 +02:00
Robert Helgesson
6ae2d74fca xsession: add option preferStatusNotifierItems
The intent is for tray applets to honor this option if they support
the SNI protocol.
2018-07-24 12:53:20 +02:00
Anton Plotnikov
29ad012763 udiskie: add sni support 2018-07-24 11:52:38 +02:00
Robert Helgesson
9570cedff6 nixos module: we need a running nix-daemon
Make sure the nix-daemon is prepared before we attempt to do the user
activation otherwise the script may fail due to not being able to
communicate.
2018-07-21 13:15:34 +02:00
rembo10
d3871ed774 mpd: add module 2018-07-18 22:17:26 +02:00
rembo10
34db8df6d9 redshift: enable geoclue2 2018-07-13 22:07:07 +02:00
Mario Rodas
092706eff8 nixpkgs: only pass pkgs_i686 argument on Linux
Nixpkgs added an assertion on pkgsi686Linux [1] to avoid evaluating it
pkgsi686Linux on non-Linux systems.

[1] ad20a4a1c3
2018-07-13 19:26:08 +02:00
Robert Helgesson
f4a1a5e94c home-manager: resolve default configuration file path
Home Manager needs an absolute and resolved path to its configuration
file. The default configuration path is absolute but not necessarily
resolved. For example, some users may have `~/.config` be a symbolic
link to somewhere else. We therefore run the default configuration
path through the `realpath` tool to resolve it.

Fixes #304
2018-07-12 00:30:54 +02:00
Robert Helgesson
dadfaed829 home-manager: add support for the nix tool
This adds an experimantal, undocumented, and unsupported flag `-2` for
the `home-manager` command that enables the use of the new `nix`
command instead of `nix-build`.
2018-07-08 23:24:35 +02:00
LightDiscord
e365943a70 awesome: add module 2018-07-07 17:49:11 +02:00
Robert Helgesson
86fcfc74da nixpkgs: replace use of traceValIfNot
The `traceValIfNot` function is deprecated in Nixpkgs master. Instead
use `traceSeqN`.

Fixes #301
2018-07-04 19:56:13 +02:00
Robert Helgesson
eecebbf186 notmuch: add module
Co-authored-by: Matthieu Coudron <mattator@gmail.com>
2018-07-01 18:44:53 +02:00
Robert Helgesson
8dc1737e39 mbsync: add module
Co-authored-by: Matthieu Coudron <mattator@gmail.com>
2018-07-01 18:44:53 +02:00
Robert Helgesson
34bb9b5766 email: add module
This adds a general module infrastructure for configuring email
accounts. The intent is to specify high level information such as IMAP
and SMTP hostnames and login information so that more specific program
and service modules do not have to duplicate options for specifying
accounts.

It is allowed for modules to inject further options within this
namespace where relevant. For example, an MUA may wish add an option
to add per-account filter rules.

Co-authored-by: Matthieu Coudron <mattator@gmail.com>
2018-07-01 18:06:09 +02:00
Olli Helenius
299e01722f Add support for systemd path units 2018-07-01 18:04:06 +02:00
jD91mZM2
97ee4578c9 gpg-agent: Add maxCacheTtl(Ssh) options 2018-06-29 00:39:14 +02:00
Robin Stumm
0d3f9ba913 compton: fix syntax error 2018-06-27 15:18:30 +02:00
Denny Schaefer
6aa44d62ad autorandr: add rotate option 2018-06-26 21:17:54 +02:00
Nadrieril
5641ee3f94 i3: use null to disable a keybinding 2018-06-14 09:26:30 +02:00
Robert Helgesson
2e9fbbc978 termite: use docbook man page reference 2018-06-13 23:56:47 +02:00
Robert Helgesson
ad634c0a94 compton: use docbook man page references 2018-06-13 23:51:53 +02:00
gmarmstrong
7190f46938 bash: fix shellAliases description
The aliases aren't added to all users' shells.
2018-06-11 22:32:53 +02:00
Robert Helgesson
e27cd96494 newsboat: remove unnecessary period 2018-06-09 11:40:49 +02:00
Mats Rauhala
4caa45b8bb newsboat: add module 2018-06-09 11:36:45 +02:00
Robert Helgesson
f3473b9eba zsh: add missing periods in descriptions 2018-06-09 10:29:02 +02:00
Mats Rauhala
06a984e4ff zsh: add extended, expireDuplicatesFirst history options 2018-06-09 10:26:41 +02:00
adisbladis
53f10f4d46 kdeconnect: add module 2018-06-05 14:58:54 +02:00
Robert Helgesson
ed0cd78e05 i3: use fancy docbook markup in description 2018-06-03 20:53:07 +02:00
Robert Helgesson
faf04b009b qt: support GTK+ theming for Qt services 2018-06-03 17:26:47 +02:00
Lenz Weber
965bad626a flameshot: set PATH to let Qt find plugins 2018-05-31 20:26:25 +02:00
Julien Langlois
69445cb4a0 udiskie: change package
The old package is deprecated.
2018-05-31 20:10:47 +02:00
Nikita Uvarov
30c97391d7 i3: add modifier option
This allows to easily change modifier key for default keybindings and
gives a possibility to reference specified value in other modules.

Fixes #147.
2018-05-27 20:20:00 +02:00
Nikita Uvarov
cacb8d410e i3: deprecate i3.config.startup.*.workspace option
Fixes #265.
2018-05-27 00:00:10 +02:00
Nikita Uvarov
4b388ee902 i3: fix reloading for nixos module
By default, i3-msg gets socket from X11 property
which is not available when home manager is running
as nixos module.

This patch changes i3-msg command call by specifying
all i3 sockets found in $XDG_RUNTIME_DIR/i3 folder.

Fixes #252.
2018-05-26 19:14:05 +02:00
Robert Helgesson
10865f9952 bash: escape alias values
This should allow use of the apostrophe character within aliases
without having to escape them manually.

Fixes #273
2018-05-26 10:52:40 +02:00
Robert Helgesson
dfaccdd03b readme: make branch suggestion more clear
Fixes #270.
2018-05-22 18:14:37 +02:00
Robert Helgesson
f812260c23 manual: add HTML manual
Also add a `home-manager-help` script that attempts to open the HTML
manual in a browser.
2018-05-18 23:22:03 +02:00
Robert Helgesson
b6da6569c4 qt: add module 2018-05-18 20:57:36 +02:00
Robert Helgesson
bbcef2fd33 readme: add link to online options documentation 2018-05-11 22:38:47 +02:00
Robert Helgesson
ec3cbf81c4 manual: some cleanups 2018-05-11 22:26:21 +02:00
Adrian Kummerlaender
1a471b0a45 xcursor: add default cursor file option 2018-05-10 20:26:01 +02:00
Cornelius Mika
73b8aa8bcc systemd: merge unit definitions recursively
This removes the need for monolithic unit definitions and allows
users to modify existing units.

Example:
```
{
  systemd.user.services.owncloud-client.Unit.OnFailure = "my-notify-service";
}
```
2018-05-10 20:13:58 +02:00
Cornelius Mika
394045f68a systemd: improve comments 2018-05-09 16:22:02 +02:00
Robert Helgesson
f9af8e0390 manual: fix import path
Need to refer to the `default.nix` in the same home-manager source
otherwise you might get an old version.
2018-05-07 00:10:58 +02:00
Robert Helgesson
1260349384 doc: make documentation independent from NixOS
Unfortunately this duplicates some code from NixOS but it does allow
much more flexibility and, hopefully, stability in the Home Manager
documentation.

Fixes #254.
2018-05-06 22:16:48 +02:00
Nikita Uvarov
74f4ed5fd2 syncthing: fix tray startup
Workaround for #249.
2018-05-04 13:08:08 +02:00
Nikita Uvarov
91725ddced owncloud-client: fix startup
Workaround for #249.
2018-05-04 13:01:34 +02:00
Hamish Hutchings
e055e4a092 flameshot: add module 2018-05-03 17:21:03 +02:00
Peter Jones
f26cc3b957 mbsync: add module 2018-05-01 22:50:37 +02:00
Minijackson
9a3b1ec222 screen-locker: Add extraOptions for xss-lock and xautolock 2018-05-01 22:40:32 +02:00
Robert Helgesson
9141d11a7d readme: update stable NixOS version to 18.03 2018-04-19 18:29:04 +02:00
Tad Fisher
6dc4f31ba1 git: add 'includes' option 2018-04-19 17:45:09 +02:00
Silvan Mosberger
d294aa4356 zsh: only source plugin file if it exists
This allows adding plugins to fpath without sourcing anything
2018-04-19 16:43:03 +02:00
Nikita Uvarov
f314ee3d6a autorandr: add module 2018-04-19 10:41:52 +02:00
Tad Fisher
581ad6fc29 kbfs: fix systemd service PATH 2018-04-18 19:01:57 +02:00
Anton Plotnikov
8ff7d934b2 Add blur options to compton 2018-04-16 08:50:28 +02:00
Anton Plotnikov
5bdebf5ab0 Add opacity-rules to compton 2018-04-16 08:50:28 +02:00
Guthrie McAfee Armstrong
96250b7ad3 Fix typo: compton.shadowOffsets description 2018-04-16 08:45:48 +02:00
Lenz Weber
7c9278bd92 xresources: add option extraConfig 2018-03-26 21:10:32 +02:00
Robert Helgesson
4205c91609 ssh: move options to end of configuration file
This is needed to support overriding these options inside match
blocks. A new option `programs.ssh.extraOptionOverrides` has been
added to allow global overrides.
2018-03-25 08:51:20 +02:00
Robert Helgesson
75c4075345 nixpkgs: expand description of nixpkgs.config and nixpkgs.overlays 2018-03-20 20:23:42 +01:00
Gleb Peregud
f8398339a3 fzf: add enableZshIntegration option
When enabled this will extend user's `$HOME/.zshrc` with sourcing of fzf's
completion and key-bindings integration libraries.
2018-03-14 17:37:39 +01:00
Gleb Peregud
9bf9e7ac5c gpg-agent: add enableExtraSocket and verbose options.
This option enables a GPG Agent restricted socket (aka "extra-socket"), which
can be used to forward GPG Agent over SSH.

Additionally `verbose` option enables verbose output of an `gpg-agent.service`
unit for easier debugging.

See: https://wiki.gnupg.org/AgentForwarding
2018-03-13 22:36:30 +01:00
Robert Helgesson
567b21b1d6 activation-init: sanity check oldGenNum and oldGenPath
Something is terribly wrong if one is set but not the other so error
out with a message if that happens.
2018-03-13 20:49:45 +01:00
Robert Helgesson
fa7d63d9d1 fzf: add module 2018-03-07 22:44:29 +01:00
Robert Helgesson
46a94cce56 texlive: add option programs.texlive.package
This read-only option will hold a reference to the customized texlive
package.
2018-03-05 19:05:30 +01:00
Robert Helgesson
bc50202d0d gpg-agent: do updatestartuptty only when SSH is enabled
Inspired by #163.
2018-03-04 22:20:35 +01:00
Tad Fisher
8fc8e158e2 unclutter: add module 2018-03-03 22:54:46 -08:00
Robert Helgesson
06e7d087f2 home-manager: colorize only when connected to terminal
Before, the output of `home-manager generations` would be colorized
even when used in a pipeline.
2018-03-03 22:00:02 +01:00
Robert Helgesson
fbff38de33 xscreensaver: install the xscreensaver package
This is needed to make the xscreensaver tools available.
2018-03-01 23:21:45 +01:00
Robert Helgesson
19b4002f25 home-environment: use nix-env from PATH
It is safest to use the system install of Nix since that will be
compatible with the running nix-daemon and/or databases.

Also add a printout of the used Nix version in the activation script
when running in verbose mode.

Fixes #218.
2018-02-27 20:31:03 +01:00
Robert Helgesson
b47cc4bc66 qsyncthingtray: remove deprecated option 2018-02-26 22:30:28 +01:00
Robert Helgesson
e307ceeee7 systemd: replace use of who command
Curiously the `who` command sometimes does not list logged-in users,
resulting in systemd not being reloaded. Instead we use

    systemctl --user is-system-running

to more directly detect whether systemd is running.
2018-02-20 22:04:29 +01:00
Robert Helgesson
4745c7a00d pidgin: add module 2018-02-19 22:57:50 +01:00
Robert Helgesson
5c783e1a63 Add initial Travis-CI configuration 2018-02-19 22:52:56 +01:00
Nikita Uvarov
05ad0c9e06 i3: escape ${} in bars.command example 2018-02-19 20:17:33 +01:00
Matthieu Coudron
6d7b5c9513 i3: don't evaluate "command" example
else it attempts to build i3-gaps and fails on darwin see
https://github.com/rycee/home-manager/pull/214#issuecomment-366594833
2018-02-19 16:28:30 +09:00
Nikita Uvarov
de001e05da i3: add missing bar options
New options are: id, commmand, workspaceNumbers, colors.
Fixes #210.
2018-02-18 20:58:52 +01:00
Matthieu Coudron
08ce0579aa Merge pull request #212 from teto/neovim_configurable
neovim: add 'configure' flag
2018-02-18 22:42:24 +09:00
Matthieu Coudron
be60600a47 neovim: add 'configure' flag
so that we have the same options as in nixpkgs.
2018-02-19 07:41:24 +09:00
Andrew Scott
f2265b10e4 rofi: add theme option
The preferred method of theming rofi is now to use "rasi" theme files.
This commit therefore downplays the colors option and introduces the
theme option.
2018-02-10 20:11:33 +01:00
Nikita Uvarov
afa865587e zsh: move env variables setting before oh-my-zsh
Fixes #207.
2018-02-10 19:23:10 +01:00
Robert Helgesson
9ea353569a Remove deprecated option home.sessionVariableSetter 2018-02-08 22:54:29 +01:00
Robert Helgesson
1bc59f7290 allow Home Manager to be used as a NixOS module
This is a NixOS module that is intended to be imported into a NixOS
system configuration. It allows the system users to be set up directly
from the system configuration.

The actual profile switch is performed by a oneshot systemd unit per
configured user that acts much like the regular `home-manager switch`
command.

With this implementation, the NixOS module does not work properly with
the `nixos-rebuild build-vm` command. This can be solved by using the
`users.users.<name?>.packages` option to install packages but this
does not work flawlessly with certain Nixpkgs packages. In particular,
for programs using the Qt libraries.
2018-02-07 20:50:01 +01:00
Christopher League
563a20fc82 xcursor: add module
This is a new module for configuring the X cursor theme.
2018-02-05 22:40:16 +01:00
Robert Helgesson
6cca1fc512 faq: add basic FAQ 2018-02-05 22:27:42 +01:00
Mogria
6833f96c14 rofi: add options to for location, xoffset & yoffset 2018-02-03 22:07:53 +01:00
Nikita Uvarov
2304c145f3 zsh: add system packages' completion path to fpath 2018-02-03 21:57:44 +01:00
Nikita Uvarov
fa6f697dbb zsh: move session variables export to zshrc
Unlike .zshenv, .zshrc file is sourced only by interactive shells.
2018-02-03 21:16:00 +01:00
Alistair Potts
91a98f919d stalonetray: add module
Adds a service for the Stalonetray system tray.

Configured through a 'config' attribute set, which writes space
separated key value pairs on successive lines to `~/.stalonetrayrc`.
2018-02-03 10:44:37 +01:00
Alistair Potts
616dbd67f7 mercurial: add module
Very simple module for hg based on programs.git, and is intended to have
compatible options. For simple setups, a user should be able to write
something like:

    {...}:
    let vcsconfig = {
            enable = true;
            userName = "John Smith";
            userEmail = "js@example.com";
            ignores = [ "*.swp" "*~" ];
        };
    in
    {
        programs.git       = vcsconfig // {...extra git config...};
        programs.mercurial = vcsconfig // {...extra hg confg...};
    }

For this reason, the ignore options are `ignores` for `syntax: glob`
and `ignoresRegexp` for `syntax: regexp` so that simple glob ignores
can (very likely) be shared with a git config, despite regular
expressions being the default for mercurial.
2018-02-02 20:52:54 +01:00
Robert Helgesson
6fc0fd315c syncthing: allow enabling tray independently 2018-02-01 06:59:22 +01:00
Robert Helgesson
9de2549dfb contributing: explain how to use local clone
Fixes #180.
2018-01-28 18:37:01 +01:00
Robert Helgesson
81fb420457 home-manager: switch NIX_PATH order
This new order allows overriding the home-manager path from the
command line using `home-manager -I home-manager=/a/b/c`.
2018-01-28 18:37:01 +01:00
Nikita Uvarov
8b77f1db2c syncthing: start tray service after bars
The QSyncthingTray service requires running tray providers such as
polybar and taffybar.
2018-01-27 17:18:39 +01:00
Robert Helgesson
a154e2ea1a readme: add basic rollback instructions 2018-01-27 10:22:54 +01:00
Robert Helgesson
5fe8d574ca home-manager: add shellcheck directives 2018-01-27 09:49:35 +01:00
Robert Helgesson
a9dc7fa7cc home-manager: improve the generation timestamp format 2018-01-27 09:47:30 +01:00
Robert Helgesson
9d3d7426aa license: bump year 2018-01-26 19:39:28 +01:00
Nikita Uvarov
a597c66afe syncthing: merge qsyncthingtray into the module 2018-01-25 21:52:01 +01:00
Mario Rodas
21fefbc8f6 home-manager: check whether a command is passed
"set -u" treats unset variables as an error, and $1 is unbound when no
command is passed.
2018-01-22 19:18:10 +01:00
Nadrieril
38020d9068 redshift: add option to start redshift tray applet 2018-01-22 19:09:13 +01:00
Nikita Uvarov
1b0a5eb54a polybar: fix the case when config value is a path
Polybar treats 'include-file' property differently.
In particular, its value can't be enclosed in
double quotes. Fixes #185.
2018-01-21 21:01:26 +01:00
André-Patrick Bubel
071f7aea82 qsyncthingtray: add module 2018-01-20 11:51:39 +01:00
Robert Helgesson
32b3f7f2d2 ssh: allow disabling compression in host block
Fixes #181.
2018-01-14 22:08:31 +01:00
Robert Helgesson
576217d33a gpg-agent: use gpgconf to set SSH socket path
Inspired by #163.
2018-01-14 15:58:59 +01:00
John Wiegley
b8b595c6b2 ssh: add a few more options 2018-01-13 12:47:30 +01:00
Nikita Uvarov
a93445f3fe zsh: add history.save option 2018-01-13 11:38:39 +01:00
Nikita Uvarov
dbcb3dd1ae zsh: fix HISTSIZE and HISTFILE configuration
HISTSIZE and HISTFILE should be set in ~/.zshrc and before
sourcing oh-my-zsh since otherwise it will be overridden.
Fixes #177.
2018-01-13 11:38:39 +01:00
Nadrieril
d6ab6ee370 ssh: add extraConfig option for non-standard options 2018-01-10 22:24:03 +01:00
John Wiegley
c9294e30d9 bash: add option historyFile 2018-01-09 22:34:20 +01:00
Robert Helgesson
d7715f71ad eclipse: add option enableLombok 2018-01-09 22:03:13 +01:00
Robert Helgesson
b2ed0a902b Merge branch 'session-var-cleanup' 2018-01-08 21:45:46 +01:00
Robert Helgesson
18159c85b9 home-environment: deprecate option home.sessionVariableSetter 2018-01-08 21:40:32 +01:00
Robert Helgesson
d7755de116 pam: add option pam.sessionVariables 2018-01-07 17:52:13 +01:00
Robert Helgesson
7631921366 zsh: source session variables script
This replaces the explicit set within the Z shell `zshenv` file.
2018-01-07 17:52:13 +01:00
Robert Helgesson
803abb58f9 bash: source session variables script
This replaces the explicit set within the Bash profile file.
2018-01-07 17:52:13 +01:00
Robert Helgesson
a3250dfac7 xsession: source session variables script 2018-01-07 17:52:13 +01:00
Robert Helgesson
4f9158e533 readme: add note about session variables file
If a user does not want to manage their shell configuration through
Home Manager then they have to manually make sure that the session
variables are set.
2018-01-07 17:52:13 +01:00
Robert Helgesson
e624b9aa6a home-environment: install hm-session-vars.sh file
This is a file containing all session variables exported using a
Bourne-compatible syntax.
2018-01-07 17:52:13 +01:00
Robert Helgesson
2fc1b9b5e0 zsh: use shell library 2018-01-07 17:52:12 +01:00
Robert Helgesson
026375da49 bash: use shell library 2018-01-07 17:51:51 +01:00
Robert Helgesson
58a629b02e lib/shell: add library of convenience functions
This library holds a few convenience functions for generating shell
code.
2018-01-07 16:59:22 +01:00
Robert Helgesson
df6590abfc home-environment: describe session variable values a bit 2018-01-07 16:59:22 +01:00
Robert Helgesson
33af9948e5 home-environment: describe session variable trickyness 2018-01-07 16:59:22 +01:00
Robert Helgesson
8ab6298f30 bash: do not export HIST* variables
These are interpreted by the shell itself and it does not make sense
to export them to sub-processes.
2018-01-07 16:54:29 +01:00
Robert Helgesson
78c308c835 bash: add option bashrcExtra
This variable adds some extra flexibility in constructing the
`~/.bashrc` file. Currently the option is hidden from public
documentation since the option name is provisional.
2018-01-07 15:15:32 +01:00
Robert Helgesson
8a2bf21cee bash: reword option descriptions 2018-01-07 15:04:57 +01:00
Robert Helgesson
59f44c1189 home-environment: run activation script in $HOME
This avoids issues when starting the activation script somewhere
inaccessible.
2018-01-05 08:09:18 +01:00
Robert Helgesson
02219dcd79 home-environment: minor code simplification 2018-01-05 08:05:53 +01:00
Robert Helgesson
f0d207f380 Add dag library to config.lib
Also replace all imports of `dag.nix` by the entry in `config.lib`.
2017-12-26 17:27:21 +01:00
Robert Helgesson
7dd09cecda gtk: remove deprecated options 2017-12-23 12:46:02 +01:00
Robert Helgesson
e75b68e391 home-environment: make username and home directory writable
In certain cases it makes sense to override the target username and
home directory. In particular, if you're building a configuration for
a remote profile.
2017-12-13 16:31:35 +01:00
Silvan Mosberger
8d360c5a57 systemd: remove filename hack 2017-12-12 18:05:04 +01:00
Cornelius Mika
f6900f0689 files: improve 'target not in $HOME' check
Check for prefix instead of inclusion.
2017-12-12 17:46:48 +01:00
Cornelius Mika
8759a5a63e systemd: add option to automatically start services 2017-12-11 18:25:49 +01:00
Cornelius Mika
52bdbc42bb systemd: move activation script to separate file
This makes the following commit more readable.
2017-12-11 18:08:33 +01:00
Robert Helgesson
28e00b68fd home-environment: optionally empty PATH in activation
This adds the option `home.emptyActivationPath` that, when enabled,
will cause the activation script to ignore the calling user's `PATH`.
The option is disabled by default to match current behavior but the
intent is to change this in the future to reduce risk of accidental
dependencies of the environment.
2017-12-11 17:03:34 +01:00
Robert Helgesson
2ff09158f3 systemd: fix systemctl command
The command's path should be taken from the configuration, not be
assumed to be in `PATH`.
2017-12-11 16:58:50 +01:00
Robert Helgesson
6764c26954 files: remove mode option
This option was deprecated >1 month ago and is therefore removed as
per the corresponding news entry.
2017-12-11 15:14:45 +01:00
Robert Helgesson
040159c02f modules: fix sorting 2017-12-11 13:51:22 +01:00
Robert Helgesson
61c6c83de4 modules: do not import modules
The `evalModules` function is smart enough to import modules and will
then also use correct file names.
2017-12-11 13:48:46 +01:00
Silvan Mosberger
0be32c9d42 xmonad: make package lower priority
This avoids a conflict for when the user has an xmonad package
installed through `haskellPackages.ghcWithPackages`, which is
necessary for wanting to load the xmonad config with ghc.
2017-12-08 11:48:05 +01:00
Gleb Peregud
aa1bf31bcb parcellite: add module
This adds a Parcellite service. It has no configuration options, since
the app has its own mutable preferences dialog, which unconditionally
replaces `~/.config/parcellite/parcelliterc` when preferences are
saved.
2017-12-08 00:40:28 +01:00
Roman Volosatovs
c023b0532a gpg-agent: add missing options 2017-12-02 19:44:53 +01:00
Silvan Mosberger
f8aaba6704 lib: add module 2017-12-02 18:11:53 +01:00
Robert Helgesson
26cf42049d readme: minor rewording 2017-11-29 23:53:49 +01:00
Robert Helgesson
06d4f39e7b home-manager: use shellHook to install
This changes the installation command from

    nix-shell $HM_PATH -A install --run 'home-manager switch'

to

    nix-shell $HM_PATH -A install

The added shell hook will print some useful information and run
`home-manager switch`.
2017-11-29 23:48:58 +01:00
Robert Helgesson
a1e36a9a37 xmonad: install xmonad command to profile
Fixes #153.
2017-11-29 23:40:43 +01:00
Tad Fisher
11da41e106 kbfs: add binaries to user profile
Add the binaries produced by 'pkgs.kbfs' to the profile, so that
the git-remote-keybase helper can work automatically with
'keybase://' remotes.
2017-11-29 23:35:50 +01:00
Tad Fisher
7a5b9152e9 keybase, kbfs: add modules 2017-11-26 23:11:37 +01:00
Robert Helgesson
7876d533cf gtk: fix erroneous variable reference 2017-11-24 22:25:36 +01:00
Robert Helgesson
e99de88c5c modules core: move modules list to own file
This is to simplify use of Home Manager as a NixOS module.
2017-11-24 21:58:16 +01:00
Robert Helgesson
bcb82da88f gtk: improve theme and font configuration
Specifically, allow the user to specify the package that provides the
theme or font.

Fixes #1.
2017-11-24 21:24:31 +01:00
Robert Helgesson
592fd61788 module/home-manager: remove modulesPath option
This option has been deprecated for a month and is removed according
to the news entry.
2017-11-24 13:51:21 +01:00
Florian Klink
3c875267af i3: config.modes.resize: add Return to defaults 2017-11-21 09:14:13 +01:00
Robert Helgesson
455ce37398 home-manager: avoid unnecessary copy 2017-11-20 14:02:28 +01:00
Robert Helgesson
64befb27eb news: minor formatting fix 2017-11-20 13:58:04 +01:00
Nikita Uvarov
177565567e i3: extend module
New options:
  i3.config.keycodebindings
  i3.config.window.commands
  i3.config.window.hideEdgeBorders
  i3.config.focus.mouseWarping
2017-11-20 11:50:20 +01:00
Nikita Uvarov
8045e56df2 i3: fix config.gaps.smartBorders default value 2017-11-17 09:43:48 +01:00
Nicolò Balzarotti
206a4e17b5 i3: fix small formatting error (missing space) 2017-11-17 09:31:37 +01:00
Florian Klink
2785bf9cb2 i3: correct example for config.floating.criteria
The parameter accepts a listOf criteriaModule
(which is types.attrs, not types.string)
2017-11-17 09:27:23 +01:00
Robert Helgesson
bc2f2ad546 systemd: honor RefuseManualStart and RefuseManualStop
Fixes https://github.com/rycee/home-manager/issues/140
2017-11-16 15:37:53 +01:00
Robert Helgesson
4fce730326 files: log when creating home file links 2017-11-15 18:31:04 +01:00
Robert Helgesson
9206f363ff files: fix order of activation actions
Specifically, move the cleanup phase to before we switch over the
generation links in `gcroots` and `profiles`.

Fixes https://github.com/rycee/home-manager/issues/134
2017-11-15 18:26:42 +01:00
Robert Helgesson
130e33a4e7 contributing: add basic style guidelines
In particular, refer to the Nixpkgs guidelines and add a note about
attribute names referencing packages in Nixpkgs.
2017-11-15 17:02:43 +01:00
Robert Helgesson
a36989a860 gnome-terminal: remove commented code 2017-11-15 17:02:19 +01:00
Nikita Uvarov
1946343d5b i3: add notification option to startup submodule
Fixes https://github.com/rycee/home-manager/issues/129.
2017-11-15 15:43:05 +01:00
Robert Helgesson
4ccf43d753 readme: use IcedTea in example 2017-11-13 00:38:26 +01:00
Robert Helgesson
7ca68c6492 emacs: minor cleanup of extra packages option 2017-11-13 00:03:49 +01:00
Matthieu Coudron
61a869a1f5 neovim: add module
This is a basic module that allows to configure different Neovim
providers than the system ones. Note, it does not generate any
`init.vim`.
2017-11-12 23:57:14 +01:00
Florian Klink
c718951e97 git: add option 'programs.git.ignores'
This allows the global Git ignores to be configured.
2017-11-12 14:22:59 +01:00
Robert Helgesson
04ea044917 home-manager: look for '--help' on command line
This is a special case to work around the lack of long options in
`getopts`.
2017-11-12 14:11:59 +01:00
Robert Helgesson
66219f23bb home-manager: add 'remove-generations' command
This command allows the user to immediately remove specific
generations from the profiles directory.
2017-11-12 14:07:41 +01:00
Robert Helgesson
187a12e90a home-manager: minor cleanup output from generations 2017-11-12 13:37:59 +01:00
Florian Klink
356c0bf751 git: use XDG config directory 2017-11-12 13:16:02 +01:00
Robert Helgesson
7a9c873093 files: add special handling of systemd files
Unfortunately systemd derives nonsensical unit names when the unit
file is a link to a link to a file. This commit ensures that any file
whose target path matches the pattern `*/systemd/user/*` will be
reachable with only one link hop.

This also reverts f52ec0df7c, which
contained a temporary fix. This commit is an improvements in that it
is more explicit and also handles unit files given directly as a home
file source.
2017-11-12 00:56:34 +01:00
Robert Helgesson
d7537777c3 files: improve keyword for inheriting executable bit 2017-11-12 00:13:29 +01:00
Robert Helgesson
145aefc9d1 files: simplify cleanup script slightly
The cleanup script now takes relative paths as arguments, not absolute
paths into the old generation. This uses a GNU specific feature of
find.
2017-11-11 14:21:11 +01:00
Robert Helgesson
2b2e20da24 dunst: use xdg.dataFile for D-Bus service file 2017-11-11 00:31:44 +01:00
Robert Helgesson
a977c79f9f xdg: add option 'xdg.dataFile'
This allows creating files within the user's XDG data directory.
2017-11-11 00:30:53 +01:00
Robert Helgesson
f52ec0df7c systemd: force copying of unit files
This is done by exploiting the fact that home files will be copied if
the executable bit of the source file and the target file is
different. This should be considered a hack until some nicer solution
is found.
2017-11-09 17:14:37 +01:00
Robert Helgesson
54043df8fb files: support recursive linking of directory 2017-11-07 17:18:00 +01:00
Robert Helgesson
fad1e108d8 dunst: add option services.dunst.iconTheme
Fixes #119
2017-11-07 17:13:51 +01:00
BjornMelgaard
fc3e82584b readme: expand preconditions installation step
Also fix markdown list item numbering.
2017-11-06 18:02:15 +01:00
Robert Helgesson
a0afb6ec8e Merge branch 'pr-59' 2017-11-06 14:29:18 +01:00
Robert Helgesson
549deb51d6 xdg: use fileType for xdg.configFile 2017-11-06 14:24:04 +01:00
Robert Helgesson
4f842d9f1b files: extract type of home.file into own file 2017-11-06 14:24:04 +01:00
Cornelius Mika
9627fe6be6 files: link home files instead of copying
Only copy files that need their execute bit changed or use the
deprecated `mode` option.
2017-11-06 14:24:04 +01:00
Cornelius Mika
b8ddb11796 use buildCommand for single phase builds 2017-11-06 14:24:04 +01:00
Cornelius Mika
f04cc227a6 home-environment: clean up activation script creation 2017-11-06 14:24:04 +01:00
Cornelius Mika
811bc1b8e5 files: extract common variable
Also improve the pattern used to determine whether a symlink target
points to a Home Manager file path.
2017-11-06 14:24:04 +01:00
Cornelius Mika
ccb291ce66 files: add option 'executable'
This also deprecates the `home.file.<name?>.mode` option, which is
misleading because the Nix store only allows modes 'r--' and 'r-x'.
2017-11-06 14:24:04 +01:00
Cornelius Mika
676f5c4b31 files: allow arbitrary paths as home file names
By sanitizing the home file name in the derivation name, the home file
name is no longer exposed to the naming restrictions for nix store
paths.

For example, it is now possible to define home files with spaces in
their names without providing a target or source attribute.
2017-11-06 10:34:45 +01:00
Robert Helgesson
14083a0857 home-manager: refuse build if CWD is read-only
This produces a clearer error message than produced by Nix.

Fixes #116.
2017-11-05 19:33:08 +01:00
Anton Strömkvist
b4f5b5556f zsh: Add options for remaining config files
`profileExtra`, `loginExtra` and `logoutExtra` for `zprofile`,
`zlogin`, and `zlogout` respectively
2017-11-02 12:53:43 +01:00
Robert Helgesson
fa4f9197ee home-manager: avoid import to improve error messages
When using `import` to inject the configuration into the module system
we lose the location in error messages, i.e., it just says
``<unknown-file>'`.
2017-11-02 11:19:12 +01:00
Robert Helgesson
bfb5a678d2 modules/home-manager: add warning about modulesPath 2017-11-02 10:32:25 +01:00
Robert Helgesson
d2572315ca i3: use XDG configuration directory
Fixes #111.
2017-11-01 09:51:18 +01:00
Nikita Uvarov
467b774d13 i3: add module 2017-10-31 16:10:42 +01:00
Robert Helgesson
78a1424582 xsession: remove xsession.windowManager option
This removes the deprecated use of `xsession.windowManager` as a
string.

This commit also adjusts the xmonad module to become a full module.
I.e., the backwards compatibility hack was removed.
2017-10-31 14:05:54 +01:00
Robert Helgesson
82d6aa0c97 xdg: fix use of base path 2017-10-31 12:26:39 +01:00
Nikita Uvarov
1213578eb7 zsh: turn fpath into a set
Forcing fpath to contain unique values increases startup speed by
eliminating extra work of processing duplicated folders.
In addition, it increases startup time when zsh is enabled in both
system and home configuration due to having the same fpath value
between different compinit calls.
Fixes https://github.com/rycee/home-manager/issues/108.
2017-10-30 13:53:40 +01:00
Ruben Maher
268d027770 modules/home-manager: fix syntax error
Fixes the error

    error: syntax error, unexpected $undefined, expecting IND_STR or
    DOLLAR_CURLY or IND_STRING_CLOSE, at
    .../home-manager/modules/programs/home-manager.nix:70:47
2017-10-30 10:47:16 +01:00
Robert Helgesson
f55fbe037a Merge branch 'add/xdg' 2017-10-29 02:00:28 +02:00
Robert Helgesson
3a95ff7435 xdg: add news entry 2017-10-29 01:59:34 +02:00
Robert Helgesson
d70715a635 use xdg.configFile for files in XDG config home 2017-10-29 01:59:34 +02:00
Robert Helgesson
54a9058ee0 xdg: add module
When enabled this module will cause Home Manager to manage the user
environment XDG variables. When disabled, then Home Manager will use
the XDG variables taken from the user environment.
2017-10-29 01:59:34 +02:00
Robert Helgesson
efb5256d28 home-manager: use XDG configuration directory 2017-10-29 01:59:34 +02:00
Robert Helgesson
a4c0fead1f files: be less verbose when linking a directory 2017-10-29 01:21:40 +02:00
Silvan Mosberger
35775b3bc5 fix typo 2017-10-24 13:12:18 +02:00
Robert Helgesson
7417d8e86e nixpkgs: add module 2017-10-24 01:29:35 +02:00
Robert Helgesson
df84c466c1 readme: update installation instructions
Also clean up usage section slightly.
2017-10-24 01:17:54 +02:00
Robert Helgesson
bf3a8c6383 home-manager: point <home-manager> to project root
Before this path would point to the modules path. Using the project
root instead makes it possible to set `<home-manager>` to point to a
downloadable archive of Home Manager. This should make it
significantly easier to install and keep Home Manager up to date.

To match this change we also deprecate the Home Manager option

    programs.home-manager.modulesPath

and instead ask users to use

    programs.home-manager.path
2017-10-24 01:14:22 +02:00
Ruben Maher
5605e46acb home-manager: fix typo 2017-10-22 10:59:09 +02:00
Robert Helgesson
3346c7f455 xsession: prepare for session in ~/.xprofile
This works around the way NixOS starts up the systemd graphical
session target.
2017-10-21 14:37:30 +02:00
pasqui23
b78b2b6b35 firefox: add enableIcedTea option 2017-10-21 12:09:39 +02:00
Silvan Mosberger
0f43d5df6a home-environment: add extraBuilderCommands option 2017-10-21 00:22:05 +02:00
Robert Helgesson
30b9d7f00e Use only tools from Nixpkgs in activation script
Note, we still pull in the user's `PATH` in case the user has defined
their own activation blocks that depend on additional tools.
Eventually this will be deprecated and removed.

See #99.
2017-10-20 19:04:33 +02:00
Robert Helgesson
b9f49cee45 home-environment: use makeBinPath for activation PATH 2017-10-19 22:44:02 +02:00
Robert Helgesson
c144580c98 xsession: warn about windowManager option removal 2017-10-19 11:45:04 +02:00
Robert Helgesson
2ff8c12bf9 home-manager: change platforms to unix 2017-10-18 00:45:29 +02:00
Robert Helgesson
335cffe9a9 man: install man, not man-db
This may help with installing on Darwin.
2017-10-18 00:33:31 +02:00
Robert Helgesson
bc40ab378c home-manager: add license field 2017-10-16 18:40:34 +02:00
Silvan Mosberger
d81276607c files: support absolute home directory path 2017-10-15 17:15:16 +02:00
Silvan Mosberger
3bc3b34d97 home-environment: add username and homeDirectory options 2017-10-15 17:15:16 +02:00
Silvan Mosberger
f0a1d69f50 Separate home files module from home-environment.nix 2017-10-15 17:14:32 +02:00
Robert Helgesson
0672936134 info: add "info" to extra outputs to install 2017-10-15 16:03:35 +02:00
Robert Helgesson
3632478b8d man: add module 2017-10-15 16:01:41 +02:00
Robert Helgesson
c07fa70d58 home-environment: add option home.extraOutputsToInstall 2017-10-15 15:58:34 +02:00
Nikita Uvarov
ee7f2413ed zsh: use new option to set internal session vars 2017-10-13 16:34:02 +02:00
Robert Helgesson
12ebf21be5 bash: add sessionVariables option 2017-10-12 15:06:51 +02:00
Nikita Uvarov
691eea9b45 zsh: add sessionVariables option 2017-10-12 14:14:06 +02:00
Nikita Uvarov
7e6f3364bc blueman-applet: add note about required system service 2017-10-11 13:05:47 +02:00
Robert Helgesson
3f430627df fontconfig: add module 2017-10-10 20:29:22 +02:00
Nikita Uvarov
3160c03843 dunst: implement settings parameter 2017-10-09 14:51:07 +02:00
Nikita Uvarov
420a3f4a01 vim: add more vim settings
New settings: copyindent, hidden, ignorecase, modeline, smartcase.
2017-10-09 14:39:56 +02:00
Nikita Uvarov
9eb48312c7 polybar: enclose strings in double quotes
This fixes the case when there are trailing spaces in
string values which can be used for elements padding.
2017-10-09 14:21:43 +02:00
Nikita Uvarov
469caa1a14 polybar: add module 2017-10-07 12:40:08 +02:00
Robert Helgesson
3aca8a938c gpg-agent: use full path to gpg-connect-agent 2017-10-05 19:54:09 +02:00
Robert Helgesson
01d46a1751 readme: current NixOS stable is version 17.09 2017-10-04 20:45:20 +02:00
Robert Helgesson
9c859d2655 xmonad: add module
Adapted from #78 and originally authored by Infinisil.
2017-10-04 20:36:31 +02:00
Robert Helgesson
fb5dbe13c2 readme: minor fixes 2017-10-04 00:24:59 +02:00
Robert Helgesson
e4c359d8b9 udiskie: add a few configuration options
The new options allow some control over automounting, notifications,
and the tray icon.

This commit also changes the defaults to automatically mount new
devices, udiskie was previously told not to automount. The change in
behavior is to closer match the default options.
2017-10-02 13:25:31 +02:00
Nikita Uvarov
52256d7a73 rofi: add fullscreen option 2017-09-30 14:14:07 +02:00
Robert Helgesson
aa974c0dc3 vim: add option programs.vim.settings
This option gathers basic Vim options into a single place. The idea is
to allow many options without making the Home Manager documentation
too verbose.

This also deprecates the options `programs.vim.lineNumbers` and
`programs.vim.tabSize`.

Fixes #69.
2017-09-30 13:30:42 +02:00
Robert Helgesson
23d3539fcb xsession: deprecate xsession.windowManager
The intention is for the `xsession.windowManager` option to be
available for full modules in the future. The option
`xsession.windowManager.command` should now be used to specify the
window manager startup command.
2017-09-30 12:48:47 +02:00
Robert Helgesson
bcff7274f4 vim, zsh: use DocBook links in description 2017-09-30 12:10:52 +02:00
Nikita Uvarov
e9deaf2ca5 rofi: add module 2017-09-28 15:39:25 +02:00
Robert Helgesson
e1bceb2adb readme: add 'console' syntax highlighting 2017-09-27 13:30:05 +02:00
Linus Heckemann
34428fc709 Add overlay and instructions for using it 2017-09-27 13:27:40 +02:00
Nikita Uvarov
393274d142 command-not-found: add module 2017-09-27 09:49:32 +02:00
Robert Helgesson
a8e08d14bb Mark rycee as maintainer for a bunch of modules 2017-09-26 23:40:31 +02:00
Silvan Mosberger
bf9b9026d9 compton: extend module 2017-09-26 14:06:13 +02:00
Nikita Uvarov
0f096f9ad4 git: change extraConfig from lines to attrs 2017-09-22 23:32:38 +02:00
Silvan Mosberger
db55e596d2 zsh: refine module
- fix part of zsh config being built even though cfg.enable is false
- fix .zshenv sourcing when ZDOTDIR already set

and some other minor adjustments
2017-09-22 23:27:49 +02:00
Nikita Uvarov
82c5aa82d2 readme: add man page info 2017-09-21 13:32:16 +02:00
Robert Helgesson
742d1889c5 lib: make dag.nix take lib as argument 2017-09-21 13:19:29 +02:00
Robert Helgesson
61042c7606 lib: use generators from Nixpkgs 2017-09-21 13:18:33 +02:00
Nikita Uvarov
3e4f7228a0 screen-locker: add module 2017-09-20 17:16:21 +02:00
Robert Helgesson
76e0e09aca emacs: allow custom Emacs package 2017-09-19 23:38:18 +02:00
Silvan Mosberger
e4deffcbe8 vim: add package option
This adds a readonly package option which will be set to the resulting
configured vim package, so it can be refered to by other configuration.
An example would be home.sessionVariables.EDITOR =
config.programs.vim.package + "/bin/vim".
2017-09-18 09:22:01 +02:00
Silvan Mosberger
de5f902487 zsh: add custom dotDir parameter 2017-09-16 21:30:47 +02:00
Robert Helgesson
cab9237d95 Add initial CONTRIBUTING file 2017-09-15 16:22:58 +02:00
Robert Helgesson
6ecf9e091c home-environment: fail if a home.file is outside $HOME 2017-09-13 15:23:43 +02:00
Nikita Uvarov
aa69598b57 compton: add module 2017-09-13 14:40:30 +02:00
Robert Helgesson
f47084968d news: minor cleanup
This puts entries in chronological order and adds a comment describing
how to get a suitable time stamp.
2017-09-12 18:08:44 +02:00
Nikita Uvarov
6a8e8e92a7 blueman-applet: add module 2017-09-12 16:44:16 +02:00
Nikita Uvarov
c7edde6ca4 zsh: add user nix-profile dir to fpath
Fixes zsh plugins installed to nix user profile via nixpkgs.
2017-09-12 15:39:36 +02:00
Nikita Uvarov
379e2c694b zsh: move aliases definitions after initExtra
Same motivation as in https://github.com/NixOS/nixpkgs/pull/28378.
zsh.initExtra parameter can be used by external modules which can
redefine user aliases. This change will give user-defined aliases
the highest priority.
2017-09-12 15:21:38 +02:00
Robin Stumm
29d5f5d760 zsh: fix double compinit slowdown with oh-my-zsh
Integrate oh-my-zsh into zsh module
to be able to control invocation order.
2017-09-12 14:52:04 +02:00
Robin Stumm
258bc85b9c zsh: add plugins submodule
To pass compinit security checks,
plugins are liked into ~/zsh/plugins folder.
This also solves issues with a slow start up,
see https://github.com/rycee/home-manager/pull/56#issuecomment-328057513.
2017-09-12 14:42:38 +02:00
Silvan Mosberger
fc1d4f5362 ssh: allow attrset matchBlock 2017-09-12 08:54:18 +02:00
Robert Helgesson
cda222d2ec home-manager: present news even if assertion failed 2017-09-09 17:14:07 +02:00
Robert Helgesson
07b4228988 README: add instructions for release-17.03 branch
(cherry picked from commit 46f0338092)
2017-09-08 12:38:05 +02:00
Robert Helgesson
ad1eee7aa5 home-manager: minor news build cleanups
- Rename the build function.

- Specify the built attribute in the build function.

- Make the news build silent.
2017-09-06 23:44:58 +02:00
Robert Helgesson
9c1b3735b4 home-manager: add news sub-command
This command allows the user to examine the news items generated by
the news module. See #52.

Many thanks to @nonsequitur and @uvNikita for suggestions and
improvements.
2017-09-05 11:37:07 +02:00
Robert Helgesson
ab0338f6ae news: add module
This new module adds a "news" feature to Home Manager. See #52.

Many thanks to @nonsequitur and @uvNikita for suggestions and
improvements.
2017-09-05 11:36:33 +02:00
Robert Helgesson
39fc16954b home-manager: make sure switch generation is GC root
Using `--no-out-link` is convenient but it does not set up a GC root,
so an unfortunately timed GC could remove the generation before
activation completes. Many thanks to @nonsequitur for noting this
problem.
2017-09-04 22:19:56 +02:00
Nikita Uvarov
f5289c546e feh: add module 2017-09-04 21:36:06 +02:00
Jean Potier
721f924e15 zsh: remove search for installed completions
1. It slows down the initial start: it takes around 2s at first launch,
and around 0.25s for the following launches;
2. It seems to be redundant since just installing zsh package gives
working completions with correct $fpath set.
2017-09-04 11:45:41 +02:00
Robert Helgesson
6611c16099 home-manager: print errors to stderr 2017-09-01 10:24:01 +02:00
Nikita Uvarov
2c5151726c vim: add module 2017-08-28 21:59:38 +02:00
Nikita Uvarov
5eff7f38df home-manager: remove escaping
The Nix code that was extracted to its own file erroneously included
escaping of "${".
2017-08-28 17:56:56 +02:00
Robert Helgesson
e9ca4305a6 home-manager: move Nix code to own file 2017-08-28 11:37:34 +02:00
Robert Helgesson
125deafc84 home-manager: add explanatory comment 2017-08-27 17:44:23 +02:00
Robert Helgesson
1445673e18 home-manager: temporarily re-add attribute 2017-08-27 17:13:06 +02:00
Robert Helgesson
4a17d8ef97 home-manager: remove unused attribute 2017-08-27 13:13:43 +02:00
Robert Helgesson
b4fff6b9b7 home-manager: minor attribute rename
The "activation-script" attribute doesn't actually point directly at
the activation script. Renamed the attribute to be more descriptive.
2017-08-27 13:04:39 +02:00
Robert Helgesson
2245b0ac94 home-manager: simplify use of nix-build output
There is no need to specify an out link when switching to a new
generation since nix-build prints the store path on standard output.
Similarly, when just building a generation we specify no out link
since nix-build will use "result" by default.
2017-08-27 12:55:30 +02:00
Robert Helgesson
e561beab44 home-environment: include home path in generation directory
Technically not necessary but it was a bit silly to leave out this
important directory from the generation directory. This also makes it
more convenient to browse the installed packages after a
`home-manager build`.
2017-08-27 00:18:13 +02:00
Nikita Uvarov
3bcd9d747b owncloud-client: add module 2017-08-26 22:56:26 +02:00
Nikita Uvarov
85a71a3923 oh-my-zsh: set ZSH_CACHE_DIR 2017-08-26 18:24:52 +02:00
Robert Helgesson
a30751464a info: use XDG_CACHE_HOME if defined 2017-08-26 12:10:14 +02:00
Nikita Uvarov
1678548353 zsh: set HELPDIR 2017-08-24 13:13:35 +02:00
Nikita Uvarov
7218c45443 zsh: add completions to fpath 2017-08-24 13:13:34 +02:00
Nikita Uvarov
bd914d49f1 zsh: add history submodule 2017-08-24 13:13:34 +02:00
Robert Helgesson
fed112e497 git: simplify submodule slightly 2017-08-24 01:03:01 +02:00
Nikita Uvarov
c3be4c4629 termite: add module 2017-08-23 23:31:47 +02:00
Cornelius Mika
286d678785 systemd: don't fail on activation when services changed
The diff command exits with status 1 when detecting differences.
Because of 'set -e', this caused the activation to fail.
2017-08-23 20:07:06 +02:00
Nikita Uvarov
42ae135d38 gpg-agent: add zsh support 2017-08-22 10:10:13 +02:00
Richard Yang
42f5d4404d home-environment: use relative latest profile link
Using a relative path prevents the latest version from being garbage
collected.
2017-08-22 09:23:03 +02:00
Cornelius Mika
5c098dc7ad lib-bash: always print message announcing a dry run 2017-08-21 18:50:21 +02:00
Cornelius Mika
3dba6fc95c home-environment: replace superfluous spaces in debug messages 2017-08-21 18:50:21 +02:00
Cornelius Mika
1eee82272a home-environment: only notify about path deletion on verbose output 2017-08-21 18:50:21 +02:00
Cornelius Mika
da5b7bea78 home-environment: fix error when deleting empty directories
With --ignore-fail-on-non-empty, non-emptiness is the only failure
that gets ignored by rmdir. In the case that rmdir reaches $HOME and
considers deleting it, it will detect insufficient permissions and
subsequently exit with an error, even if $HOME is not empty.

Prevent this by calling rmdir with a relative path that excludes
$HOME.
2017-08-21 18:43:17 +02:00
Nikita Uvarov
910cdc0537 zsh: use .zshenv for env vars 2017-08-21 18:00:58 +02:00
Cornelius Mika
02a501705a home-manager: show full script path on activation error
Run the activation script in its original nix-store location so that
Bash error messages show the real script location instead of 'wrkdir',
which gets deleted right after the script exits.
2017-08-20 09:50:42 +02:00
Cornelius Mika
a9d9fb5d75 home-manager: exit with an error on build failure
Because 'set -e' has no effect on commands that run in an if condition,
the script was always exiting with no error when 'doBuild' failed.

As a bonus, $wrkdir is now always removed after building.
2017-08-20 09:50:37 +02:00
Cornelius Mika
ffbc7e723d home-manager: add config file attribute 2017-08-18 21:37:07 +02:00
Nikita Uvarov
3ef56576d3 oh-my-zsh: add module 2017-08-16 15:44:27 +02:00
Nikita Uvarov
cde8e02bf2 zsh: add module 2017-08-16 13:58:30 +02:00
Silvan Mosberger
1d24e96074 htop: use types.coercedTo 2017-08-02 22:22:54 +02:00
Robert Helgesson
be432c8654 ssh: add control persist option 2017-07-29 17:47:18 +02:00
Silvan Mosberger
3778a69fbe htop: add module 2017-07-24 11:42:45 +02:00
Robert Helgesson
d807a5c314 home-environment: fix cleanup of user replaced directories
We must only follow the symbolic link once (i.e., not use the `-e`
option) since otherwise the pattern will not match when
`home.file.xyz.source` is a directory.
2017-07-22 00:38:12 +02:00
Robert Helgesson
5862a05fb1 home-environment: avoid harmless but scary error message 2017-07-22 00:18:31 +02:00
Robert Helgesson
dba14bfe90 manual: fix man pages build on unstable NixOS 2017-07-21 21:10:32 +02:00
Robert Helgesson
2e257f40e6 home-manager: remove manually installed home-manager
If the `home-manager` module is enabled then check if the
`home-manager` package is installed using `nix-env -i` and if so then
it is automatically uninstalled before the new package environment,
which includes home-manager, is installed.
2017-07-19 00:12:34 +02:00
Robert Helgesson
cdb2bec909 syncthing: expand service description
This models the user service on the upstream systemd file.
2017-07-18 13:49:02 +02:00
Utku Demir
dd5061d73b Add syncthing service 2017-07-18 12:50:30 +02:00
Robert Helgesson
7a18a0fb34 home-manager: add module
This module is a module to install and configure the home-manager
tool. By managing the home-manager tool through the Home Manager
module system it will be installed/updated on configuration
activation.
2017-07-11 20:53:42 +02:00
Robert Helgesson
28d3f74614 home-manager: allow a user-defined third module path
The user-defined path will be used if present, otherwise the two
"fallback" defaults (in `.nixpkgs` and `.config/nixpkgs`) will be
used.
2017-07-11 20:53:42 +02:00
Robert Helgesson
98c7b23178 home-manager: remove unnecessary variable setting
The `NIX_PATH` variable is set by the `setHomeManagerModulesPath`
function so it is unnecessary to set it again.
2017-07-11 19:48:49 +02:00
Robin Stumm
89dc8c2004 home-environment: fix home.activation.checkLinkTargets
Problem
-------

We resolve symlinks from inside `/nix/store/HASH-home-manager-files`
into the nix store as `/nix/store/HASH-DRVNAME` which does not match
the pattern.

This happened to me because I pull in some repos in via `home.file`.
The `home-manager-files` derivation links to the repo's derivation in
the nix store. For example:

    let nanorcs = fetchFromGitHub {
      owner = "scopatz";
      repo = "nanorc";
      …
    }; in [
      {
        target = ".nano";
        source = nanorcs;
      }
      {
        target = ".nanorc";
        source = "${nanorcs}/nanorc";
      }
    ]

Solution
--------

Call `readlink` without `-e` to obtain only the first redirection from
`~` to `/nix/store/HASH-home-manager-files`.
2017-07-08 00:38:57 +02:00
Robin Stumm
e274fc732b browserpass: add module (#16)
* browserpass: add module

* apply some review requests

* browserpass: update to 1.0.5

* browserpass: install from Nixpkgs using `home.file`
2017-06-30 22:45:09 +02:00
180 changed files with 15963 additions and 942 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/result*

14
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,14 @@
image: nixos/nix:latest
pages:
script:
- mkdir -p ~/.config/nixpkgs
- echo '{ manual.html.enable = true; }' > ~/.config/nixpkgs/home.nix
- nix-shell . -A install
- mkdir public
- cp -r ~/.nix-profile/share/doc/home-manager/* public/
artifacts:
paths:
- public
only:
- master

12
.travis.yml Normal file
View File

@@ -0,0 +1,12 @@
language: nix
os:
- linux
- osx
before_script:
- mkdir -m 0755 -p /nix/var/nix/{profiles,gcroots}/per-user/$USER
script:
- nix-shell . -A install
- nix-shell tests -A run.all

158
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,158 @@
Contributing
============
Thanks for wanting to contribute to Home Manager! These are some
guidelines to make the process as smooth as possible for both you and
the Home Manager developers.
If you are only looking to report a problem then it is sufficient to
read through the following section on reporting issues. If you instead
want to directly contribute improvements and additions then please
have a look at everything here.
Reporting an issue
------------------
If you notice a problem with Home Manager and want to report it then
have a look among the already [open issues][], if you find one
matching yours then feel free to comment on it to add any additional
information you may have.
If no matching issue exists then go to the [new issue][] page and
write a description of your problem. Include as much information as
you can, ideally also include relevant excerpts from your Home Manager
configuration.
Contributing code
-----------------
If you want to contribute code to improve Home Manager then please
follow these guidelines.
### Fork and create a pull request ###
If you have not previously forked Home Manager then you need to do
that first. Have a look at GitHub's "[Fork A Repo][]" for instructions
on how to do this.
Once you have a fork of Home Manager you should create a branch
starting at the most recent `master`. Give your branch a reasonably
descriptive name. Perform your changes on this branch and when you are
happy with the result push the branch to GitHub and
[create a pull request][].
Assuming your clone is at `$HOME/devel/home-manager` then you can make
the `home-manager` command use it by either
1. overriding the default path by using the `-I` command line option:
home-manager -I home-manager=$HOME/devel/home-manager
or
2. changing the default path by ensuring your configuration includes
programs.home-manager.enable = true;
programs.home-manager.path = "$HOME/devel/home-manager";
and running `home-manager switch` to activate the change.
Afterwards, `home-manager build` and `home-manager switch` will
use your cloned repository.
The first option is good if you only temporarily want to use your
clone.
### Commits ###
The commits in your pull request should be reasonably self-contained,
that is, each commit should make sense in isolation. In particular,
you will be asked to amend any commit that introduces syntax errors or
similar problems even if they are fixed in a later commit.
The commit messages should follow the format
{component}: {description}
{long description}
where `{component}` refers to the code component (or module) your
change affects, `{description}` is a brief description of your change,
and `{long description}` is an optional clarifying description. Note,
`{description}` should start with a lower case letter. As a rare
exception, if there is no clear component, or your change affects many
components, then the `{component}` part is optional.
When adding a new module, say `foo.nix`, we use the fixed commit
format `foo: add module`. You can, of course, still include a long
description if you wish.
In addition to the above commit message guidelines, try to follow the
[seven rules][] as much as possible.
### 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.
### News ###
Home Manager includes a system for presenting news to the user. When
making a change you, therefore, have the option to also include an
associated news entry. In general, a news entry should only be added
for truly noteworthy news. For example, a bug fix or new option does
generally not need a news entry.
If you do have a change worthy of a news entry then please add one in
[`news.nix`][] but you should follow some basic guidelines:
- The entry timestamp should be in ISO-8601 format having "+00:00" as
time zone. For example, "2017-09-13T17:10:14+00:00". A suitable
timestamp can be produced by the command
date --iso-8601=second --universal
- The entry condition should be as specific as possible. For example,
if you are changing or deprecating a specific option then you could
restrict the news to those users who actually use this option.
- Wrap the news message so that it will fit in the typical terminal,
that is, at most 80 characters wide. Ideally a bit less.
- Unlike commit messages, news will be read without any connection to
the Home Manager source code. It is therefore important to make the
message understandable in isolation and to those who do not have
knowledge of the Home Manager internals. To this end it should be
written in more descriptive, prose like way.
- If you refer to an option then write its full attribute path. That
is, instead of writing
> The option 'foo' has been deprecated, please use 'bar' instead.
it should read
> The option 'services.myservice.foo' has been deprecated, please
> 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
> A new service is available: 'services.foo'.
or
> A new program configuration is available: 'program.foo'.
depending on the type of module.
[open issues]: https://github.com/rycee/home-manager/issues
[new issue]: https://github.com/rycee/home-manager/issues/new
[Fork A Repo]: https://help.github.com/articles/fork-a-repo/
[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

121
FAQ.md Normal file
View File

@@ -0,0 +1,121 @@
Frequently Asked Questions (FAQ)
================================
Why is there a collision error when switching generation?
---------------------------------------------------------
Home Manager currently installs packages into the user environment,
precisely as if the packages were installed through
`nix-env --install`. This means that you will get a collision error if
your Home Manager configuration attempts to install a package that you
already have installed manually, that is, packages that shows up when
you run `nix-env --query`.
For example, imagine you have the `hello` package installed in your
environment
```console
$ nix-env --query
hello-2.10
```
and your Home Manager configuration contains
home.packages = [ pkgs.hello ];
Then attempting to switch to this configuration will result in an
error similar to
```console
$ home-manager switch
these derivations will be built:
/nix/store/xg69wsnd1rp8xgs9qfsjal017nf0ldhm-home-manager-path.drv
[…]
Activating installPackages
replacing old home-manager-path
installing home-manager-path
building path(s) /nix/store/b5c0asjz9f06l52l9812w6k39ifr49jj-user-environment
Wide character in die at /nix/store/64jc9gd2rkbgdb4yjx3nrgc91bpjj5ky-buildenv.pl line 79.
collision between /nix/store/fmwa4axzghz11cnln5absh31nbhs9lq1-home-manager-path/bin/hello and /nix/store/c2wyl8b9p4afivpcz8jplc9kis8rj36d-hello-2.10/bin/hello; use nix-env --set-flag priority NUMBER PKGNAME to change the priority of one of the conflicting packages
builder for /nix/store/b37x3s7pzxbasfqhaca5dqbf3pjjw0ip-user-environment.drv failed with exit code 2
error: build of /nix/store/b37x3s7pzxbasfqhaca5dqbf3pjjw0ip-user-environment.drv failed
```
The solution is typically to uninstall the package from the
environment using `nix-env --uninstall` and reattempt the Home Manager
generation switch.
Why are the session variables not set?
--------------------------------------
Home Manager is only able to set session variables automatically if it
manages your Bash or Z shell configuration. If you don't want to let
Home Manager manage your shell then you will have to manually source
the
~/.nix-profile/etc/profile.d/hm-session-vars.sh
file in an appropriate way. In Bash and Z shell this can be done by
adding
```sh
. "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh"
```
to your `.profile` and `.zshrc` files, respectively. The
`hm-session-vars.sh` file should work in most Bourne-like shells.
How do set up a configuration for multiple users/machines?
----------------------------------------------------------
A typical way to prepare a repository of configurations for multiple
logins and machines is to prepare one "top-level" file for each unique
combination.
For example, if you have two machines, called "kronos" and "rhea" on
which you want to configure your user "jane" then you could create the
files
- `kronos-jane.nix`,
- `rhea-jane.nix`, and
- `common.nix`
in your repository. On the kronos and rhea machines you can then make
`~jane/.config/nixpkgs/home.nix` be a symbolic link to the
corresponding file in your configuration repository.
The `kronos-jane.nix` and `rhea-jane.nix` files follow the format
```nix
{ ... }:
{
imports = [ ./common.nix ];
# Various options that are specific for this machine/user.
}
```
while the `common.nix` file contains configuration shared across the
two logins. Of course, instead of just a single `common.nix` file you
can have multiple ones, even one per program or service.
You can get some inspiration from the [Post your home-manager home.nix
file!][1] Reddit thread.
[1]: https://www.reddit.com/r/NixOS/comments/9bb9h9/post_your_homemanager_homenix_file/
Why do I get an error message about `ca.desrt.dconf`?
-----------------------------------------------------
You are most likely trying to configure the GTK or Gnome Terminal but
the DBus session is not aware of the dconf service. The full error you
might get is
error: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name ca.desrt.dconf was not provided by any .service files
The solution on NixOS is to add
services.dbus.packages = with pkgs; [ gnome3.dconf ];
to your system configuration.

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2017 Robert Helgesson
Copyright (c) 2017-2019 Robert Helgesson and Home Manager contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

177
README.md
View File

@@ -19,18 +19,25 @@ 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][] version 17.03 (the current stable
version), it may or may not work on other Linux distributions and
NixOS versions.
Home Manager targets [NixOS][] unstable and NixOS version 18.09 (the
current stable version), it may or may not work on other Linux
distributions and NixOS versions.
Also, the `home-manager` tool does not explicitly support rollbacks at
the moment so if your home directory gets messed up you'll have to fix
it yourself (you can attempt to run the activation script for the
desired generation).
it yourself. See the [rollbacks](#rollbacks) section for instructions
on how to manually perform a rollback.
Now when your expectations have been built up and you are eager to try
all this out you can go ahead and read the rest of this text.
Contact
-------
You can chat with us on IRC in the channel [#home-manager][] on
[freenode][]. The [channel logs][] are hosted courtesy of
[samueldr][].
Installation
------------
@@ -39,53 +46,95 @@ Currently the easiest way to install Home Manager is as follows:
1. Make sure you have a working Nix installation. If you are not
using NixOS then you may here have to run
```
```console
$ mkdir -m 0755 -p /nix/var/nix/{profiles,gcroots}/per-user/$USER
```
since Home Manager uses these directories to manage your profile
generations. On NixOS these should already be available.
2. Clone the Home Manager repository into the `~/.config/nixpkgs`
directory:
Also make sure that your user is able to build and install Nix
packages. For example, you should be able to successfully run a
command like `nix-instantiate '<nixpkgs>' -A hello` without having
to switch to the root user. For a multi-user install of Nix this
means that your user must be covered by the
[`allowed-users`][nixAllowedUsers] Nix option. On NixOS you can
control this option using the
[`nix.allowedUsers`][nixosAllowedUsers] system option.
```
$ git clone https://github.com/rycee/home-manager ~/.config/nixpkgs/home-manager
2. Add the appropriate Home Manager channel. Typically this is
```console
$ nix-channel --add https://github.com/rycee/home-manager/archive/master.tar.gz home-manager
$ nix-channel --update
```
3. Add Home Manager to your user's Nixpkgs, for example by adding it
to the `packageOverrides` section in your
`~/.config/nixpkgs/config.nix` file:
if you are following Nixpkgs master or an unstable channel and
```nix
{
packageOverrides = pkgs: rec {
home-manager = import ./home-manager { inherit pkgs; };
};
}
```console
$ nix-channel --add https://github.com/rycee/home-manager/archive/release-18.09.tar.gz home-manager
$ nix-channel --update
```
4. Install the `home-manager` package:
if you follow a Nixpkgs version 18.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
```shell
export NIX_PATH=$HOME/.nix-defexpr/channels${NIX_PATH:+:}$NIX_PATH
```
to your shell (see [nix#2033](https://github.com/NixOS/nix/issues/2033)).
3. Install Home Manager and create the first Home Manager generation:
```console
$ nix-shell '<home-manager>' -A install
```
Once finished, Home Manager should be active and available in your
user environment.
3. If you do not plan on having Home Manager manage your shell
configuration then you must source the
```
$ nix-env -f '<nixpkgs>' -iA home-manager
installing home-manager
$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh
```
file in your shell configuration. Unfortunately, in this specific
case we currently only support POSIX.2-like shells such as
[Bash][] or [Z shell][].
For example, if you use Bash then add
```bash
. "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh"
```
to your `~/.profile` file.
If instead of using channels you want to run Home Manager from a Git
checkout of the repository then you can use the
`programs.home-manager.path` option to specify the absolute path to
the repository.
Usage
-----
The `home-manager` package installs a tool that is conveniently called
`home-manager`. This tool can apply configurations to your home
Home Manager is typically managed through the `home-manager` tool.
This tool can, for example, apply configurations to your home
directory, list user packages installed by the tool, and list the
configuration generations.
As an example, let us set up a very simple configuration that installs
the htop and fortune packages, installs Emacs with a few extra
packages enabled, installs Firefox with Adobe Flash enabled, and
enables the user gpg-agent service.
As an example, let us expand the initial configuration file from the
installation above to install the htop and fortune packages, install
Emacs with a few extra packages enabled, install Firefox with the
IcedTea plugin enabled, and enable the user gpg-agent service.
First create a file `~/.config/nixpkgs/home.nix` containing
To satisfy the above setup we should elaborate the
`~/.config/nixpkgs/home.nix` file as follows:
```nix
{ pkgs, ... }:
@@ -106,7 +155,7 @@ First create a file `~/.config/nixpkgs/home.nix` containing
programs.firefox = {
enable = true;
enableAdobeFlash = true;
enableIcedTea = true;
};
services.gpg-agent = {
@@ -114,28 +163,75 @@ First create a file `~/.config/nixpkgs/home.nix` containing
defaultCacheTtl = 1800;
enableSshSupport = true;
};
programs.home-manager = {
enable = true;
path = "…";
};
}
```
To activate this configuration you can then run
```
```console
$ home-manager switch
```
or if you are not feeling so lucky,
```
```console
$ home-manager build
```
which will create a `result` link to a directory containing an
activation script and the generated home directory files.
Documentation of available configuration options, including
descriptions and usage examples, is available in the [Home Manager
manual][configuration options] or offline by running
```console
$ man home-configuration.nix
```
Rollbacks
---------
While the `home-manager` tool does not explicitly support rollbacks at
the moment it is relatively easy to perform one manually. The steps to
do so are
1. Run `home-manager generations` to determine which generation you
wish to rollback to:
```console
$ home-manager generations
2018-01-04 11:56 : id 765 -> /nix/store/kahm1rxk77mnvd2l8pfvd4jkkffk5ijk-home-manager-generation
2018-01-03 10:29 : id 764 -> /nix/store/2wsmsliqr5yynqkdyjzb1y57pr5q2lsj-home-manager-generation
2018-01-01 12:21 : id 763 -> /nix/store/mv960kl9chn2lal5q8lnqdp1ygxngcd1-home-manager-generation
2017-12-29 21:03 : id 762 -> /nix/store/6c0k1r03fxckql4vgqcn9ccb616ynb94-home-manager-generation
2017-12-25 18:51 : id 761 -> /nix/store/czc5y6vi1rvnkfv83cs3rn84jarcgsgh-home-manager-generation
```
2. Copy the Nix store path of the generation you chose, e.g.,
/nix/store/mv960kl9chn2lal5q8lnqdp1ygxngcd1-home-manager-generation
for generation 763.
3. Run the `activate` script inside the copied store path:
```console
$ /nix/store/mv960kl9chn2lal5q8lnqdp1ygxngcd1-home-manager-generation/activate
Starting home manager activation
```
Keeping your ~ safe from harm
-----------------------------
To configure programs and services the Home Manager must write various
To configure programs and services Home Manager must write various
things to your home directory. To prevent overwriting any existing
files when switching to a new generation, Home Manager will attempt to
detect collisions between existing files and generated files. If any
@@ -143,7 +239,7 @@ such collision is detected the activation will terminate before
changing anything on your computer.
For example, suppose you have a wonderful, painstakingly created
`~/.gitconfig` and add
`~/.config/git/config` and add
```nix
{
@@ -162,7 +258,7 @@ For example, suppose you have a wonderful, painstakingly created
to your configuration. Attempting to switch to the generation will
then result in
```
```console
$ home-manager switch
Activating checkLinkTargets
@@ -196,7 +292,7 @@ in your system configuration and
# …
xsession.enable = true;
xsession.windowManager = "…";
xsession.windowManager.command = "…";
# …
}
@@ -204,6 +300,15 @@ in your system configuration and
in your Home Manager configuration.
[Bash]: https://www.gnu.org/software/bash/
[Nix]: https://nixos.org/nix/
[NixOS]: https://nixos.org/
[Nixpkgs]: https://nixos.org/nixpkgs/
[nixAllowedUsers]: https://nixos.org/nix/manual/#conf-allowed-users
[nixosAllowedUsers]: https://nixos.org/nixos/manual/options.html#opt-nix.allowedUsers
[Z shell]: http://zsh.sourceforge.net/
[configuration options]: https://rycee.gitlab.io/home-manager/options.html
[#home-manager]: https://webchat.freenode.net/?url=irc%3A%2F%2Firc.freenode.net%2Fhome-manager
[freenode]: https://freenode.net/
[channel logs]: https://logs.nix.samueldr.com/home-manager/
[samueldr]: https://github.com/samueldr/

View File

@@ -1,2 +1,14 @@
# Simply defer to the home-manager script derivation.
import ./home-manager
{ pkgs ? import <nixpkgs> {} }:
rec {
home-manager = import ./home-manager {
inherit pkgs;
path = toString ./.;
};
install = import ./home-manager/install.nix {
inherit home-manager pkgs;
};
nixos = import ./nixos;
}

328
doc/default.nix Normal file
View File

@@ -0,0 +1,328 @@
{ pkgs, options, config, version, revision, extraSources ? [] }:
with pkgs;
let
lib = pkgs.lib;
# Remove invisible and internal options.
optionsListVisible = lib.filter (opt: opt.visible && !opt.internal) (lib.optionAttrSetToDocList options);
# Replace functions by the string <function>
substFunction = x:
if builtins.isAttrs x then lib.mapAttrs (name: substFunction) x
else if builtins.isList x then map substFunction x
else if lib.isFunction x then "<function>"
else x;
# Generate DocBook documentation for a list of packages. This is
# what `relatedPackages` option of `mkOption` from
# ../../../lib/options.nix influences.
#
# Each element of `relatedPackages` can be either
# - a string: that will be interpreted as an attribute name from `pkgs`,
# - a list: that will be interpreted as an attribute path from `pkgs`,
# - an attrset: that can specify `name`, `path`, `package`, `comment`
# (either of `name`, `path` is required, the rest are optional).
genRelatedPackages = packages:
let
unpack = p: if lib.isString p then { name = p; }
else if lib.isList p then { path = p; }
else p;
describe = args:
let
name = args.name or (lib.concatStringsSep "." args.path);
path = args.path or [ args.name ];
package = args.package or (lib.attrByPath path (throw "Invalid package attribute path `${toString path}'") pkgs);
in "<listitem>"
+ "<para><literal>pkgs.${name} (${package.meta.name})</literal>"
+ lib.optionalString (!package.meta.available) " <emphasis>[UNAVAILABLE]</emphasis>"
+ ": ${package.meta.description or "???"}.</para>"
+ lib.optionalString (args ? comment) "\n<para>${args.comment}</para>"
# Lots of `longDescription's break DocBook, so we just wrap them into <programlisting>
+ lib.optionalString (package.meta ? longDescription) "\n<programlisting>${package.meta.longDescription}</programlisting>"
+ "</listitem>";
in "<itemizedlist>${lib.concatStringsSep "\n" (map (p: describe (unpack p)) packages)}</itemizedlist>";
optionsListDesc = lib.flip map optionsListVisible (opt: opt // {
# Clean up declaration sites to not refer to the NixOS source tree.
declarations = map stripAnyPrefixes opt.declarations;
}
// lib.optionalAttrs (opt ? example) { example = substFunction opt.example; }
// lib.optionalAttrs (opt ? default) { default = substFunction opt.default; }
// lib.optionalAttrs (opt ? type) { type = substFunction opt.type; }
// lib.optionalAttrs (opt ? relatedPackages) { relatedPackages = genRelatedPackages opt.relatedPackages; });
# We need to strip references to /nix/store/* from options,
# including any `extraSources` if some modules came from elsewhere,
# or else the build will fail.
#
# E.g. if some `options` came from modules in ${pkgs.customModules}/nix,
# you'd need to include `extraSources = [ pkgs.customModules ]`
prefixesToStrip = map (p: "${toString p}/") ([ ./.. ] ++ extraSources);
stripAnyPrefixes = lib.flip (lib.fold lib.removePrefix) prefixesToStrip;
# Custom "less" that pushes up all the things ending in ".enable*"
# and ".package*"
optionLess = a: b:
let
ise = lib.hasPrefix "enable";
isp = lib.hasPrefix "package";
cmp = lib.splitByAndCompare ise lib.compare
(lib.splitByAndCompare isp lib.compare lib.compare);
in lib.compareLists cmp a.loc b.loc < 0;
# Customly sort option list for the man page.
optionsList = lib.sort optionLess optionsListDesc;
# Convert the list of options into an XML file.
optionsXML = builtins.toFile "options.xml" (builtins.toXML optionsList);
optionsDocBook = runCommand "options-db.xml"
{
nativeBuildInputs = [ buildPackages.libxslt.bin ];
}
''
optionsXML=${optionsXML}
xsltproc \
--stringparam program 'home-manager' \
--stringparam revision '${revision}' \
-o $out ${./options-to-docbook.xsl} $optionsXML
'';
sources = lib.sourceFilesBySuffices ./. [".xml"];
modulesDoc = builtins.toFile "modules.xml" ''
<section xmlns:xi="http://www.w3.org/2001/XInclude" id="modules">
${(lib.concatMapStrings (path: ''
<xi:include href="${path}" />
'') (lib.catAttrs "value" config.meta.doc))}
</section>
'';
generatedSources = runCommand "generated-docbook" {} ''
mkdir $out
ln -s ${modulesDoc} $out/modules.xml
ln -s ${optionsDocBook} $out/options-db.xml
printf "%s" "${version}" > $out/version
'';
copySources =
''
cp -prd $sources/* . # */
ln -s ${generatedSources} ./generated
chmod -R u+w .
'';
toc = builtins.toFile "toc.xml"
''
<toc role="chunk-toc">
<d:tocentry xmlns:d="http://docbook.org/ns/docbook" linkend="book-home-manager-manual"><?dbhtml filename="index.html"?>
<d:tocentry linkend="ch-options"><?dbhtml filename="options.html"?></d:tocentry>
<d:tocentry linkend="ch-release-notes"><?dbhtml filename="release-notes.html"?></d:tocentry>
</d:tocentry>
</toc>
'';
manualXsltprocOptions = toString [
"--param section.autolabel 1"
"--param section.label.includes.component.label 1"
"--stringparam html.stylesheet 'style.css overrides.css highlightjs/mono-blue.css'"
"--stringparam html.script './highlightjs/highlight.pack.js ./highlightjs/loader.js'"
"--param xref.with.number.and.title 1"
"--param toc.section.depth 3"
"--stringparam admon.style ''"
"--stringparam callout.graphics.extension .svg"
"--stringparam current.docid manual"
"--param chunk.section.depth 0"
"--param chunk.first.sections 1"
"--param use.id.as.filename 1"
"--stringparam generate.toc 'book toc appendix toc'"
"--stringparam chunk.toc ${toc}"
];
manual-combined = runCommand "home-manager-manual-combined"
{ inherit sources;
nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ];
meta.description = "The Home Manager manual as plain docbook XML";
}
''
${copySources}
xmllint --xinclude --output ./manual-combined.xml ./manual.xml
xmllint --xinclude --noxincludenode \
--output ./man-pages-combined.xml ./man-pages.xml
# outputs the context of an xmllint error output
# LEN lines around the failing line are printed
function context {
# length of context
local LEN=6
# lines to print before error line
local BEFORE=4
# xmllint output lines are:
# file.xml:1234: there was an error on line 1234
while IFS=':' read -r file line rest; do
echo
if [[ -n "$rest" ]]; then
echo "$file:$line:$rest"
local FROM=$(($line>$BEFORE ? $line - $BEFORE : 1))
# number lines & filter context
nl --body-numbering=a "$file" | sed -n "$FROM,+$LEN p"
else
if [[ -n "$line" ]]; then
echo "$file:$line"
else
echo "$file"
fi
fi
done
}
function lintrng {
xmllint --debug --noout --nonet \
--relaxng ${docbook5}/xml/rng/docbook/docbook.rng \
"$1" \
2>&1 | context 1>&2
# ^ redirect assumes xmllint doesnt print to stdout
}
lintrng manual-combined.xml
lintrng man-pages-combined.xml
mkdir $out
cp manual-combined.xml $out/
cp man-pages-combined.xml $out/
'';
olinkDB = runCommand "manual-olinkdb"
{ inherit sources;
nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ];
}
''
xsltproc \
${manualXsltprocOptions} \
--stringparam collect.xref.targets only \
--stringparam targets.filename "$out/manual.db" \
--nonet \
${docbook5_xsl}/xml/xsl/docbook/xhtml/chunktoc.xsl \
${manual-combined}/manual-combined.xml
cat > "$out/olinkdb.xml" <<EOF
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE targetset SYSTEM
"file://${docbook5_xsl}/xml/xsl/docbook/common/targetdatabase.dtd" [
<!ENTITY manualtargets SYSTEM "file://$out/manual.db">
]>
<targetset>
<targetsetinfo>
Allows for cross-referencing olinks between the manpages
and manual.
</targetsetinfo>
<document targetdoc="manual">&manualtargets;</document>
</targetset>
EOF
'';
in rec {
inherit generatedSources;
# The Home Manager options in JSON format.
optionsJSON = runCommand "options-json"
{ meta.description = "List of Home Manager options in JSON format";
}
''
# Export list of options in different format.
dst=$out/share/doc/home-manager
mkdir -p $dst
cp ${builtins.toFile "options.json" (builtins.unsafeDiscardStringContext (builtins.toJSON
(builtins.listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) optionsList))))
} $dst/options.json
mkdir -p $out/nix-support
echo "file json $dst/options.json" >> $out/nix-support/hydra-build-products
''; # */
# Generate the Home Manager manual.
manual = runCommand "home-manager-manual"
{ inherit sources;
nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ];
meta.description = "The Home Manager manual in HTML format";
allowedReferences = ["out"];
}
''
# Generate the HTML manual.
dst=$out/share/doc/home-manager
mkdir -p $dst
xsltproc \
${manualXsltprocOptions} \
--stringparam target.database.document "${olinkDB}/olinkdb.xml" \
--nonet --output $dst/ \
${docbook5_xsl}/xml/xsl/docbook/xhtml/chunktoc.xsl \
${manual-combined}/manual-combined.xml
mkdir -p $dst/images/callouts
cp ${docbook5_xsl}/xml/xsl/docbook/images/callouts/*.svg $dst/images/callouts/
cp ${./style.css} $dst/style.css
cp ${./overrides.css} $dst/overrides.css
cp -r ${pkgs.documentation-highlighter} $dst/highlightjs
mkdir -p $out/nix-support
echo "nix-build out $out" >> $out/nix-support/hydra-build-products
echo "doc manual $dst" >> $out/nix-support/hydra-build-products
''; # */
manualEpub = runCommand "home-manager-manual-epub"
{ inherit sources;
buildInputs = [ libxml2.bin libxslt.bin zip ];
}
''
# Generate the epub manual.
dst=$out/share/doc/home-manager
xsltproc \
${manualXsltprocOptions} \
--stringparam target.database.document "${olinkDB}/olinkdb.xml" \
--nonet --xinclude --output $dst/epub/ \
${docbook5_xsl}/xml/xsl/docbook/epub/docbook.xsl \
${manual-combined}/manual-combined.xml
mkdir -p $dst/epub/OEBPS/images/callouts
cp -r ${docbook5_xsl}/xml/xsl/docbook/images/callouts/*.svg $dst/epub/OEBPS/images/callouts # */
echo "application/epub+zip" > mimetype
manual="$dst/home-manager-manual.epub"
zip -0Xq "$manual" mimetype
cd $dst/epub && zip -Xr9D "$manual" *
rm -rf $dst/epub
mkdir -p $out/nix-support
echo "doc-epub manual $manual" >> $out/nix-support/hydra-build-products
'';
# Generate the Home Manager manpages.
manpages = runCommand "home-manager-manpages"
{ inherit sources;
nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ];
allowedReferences = ["out"];
}
''
# Generate manpages.
mkdir -p $out/share/man
xsltproc --nonet \
--param man.output.in.separate.dir 1 \
--param man.output.base.dir "'$out/share/man/'" \
--param man.endnotes.are.numbered 0 \
--param man.break.after.slash 1 \
--stringparam target.database.document "${olinkDB}/olinkdb.xml" \
${docbook5_xsl}/xml/xsl/docbook/manpages/docbook.xsl \
${manual-combined}/man-pages-combined.xml
'';
}

236
doc/installation.xml Normal file
View File

@@ -0,0 +1,236 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="ch-installation">
<title>Installing Home Manager</title>
<para>
Home Manager can be used in three primary ways:
<orderedlist>
<listitem>
<para>
Using the standalone <command>home-manager</command> tool. For platforms
other than NixOS and Darwin, this is the only available choice. It is also
recommended for people on NixOS or Darwin that want to manage their home
directory independent of the system as a whole. See
<xref linkend="sec-install-standalone"/> for instructions on how to
perform this installation.
</para>
</listitem>
<listitem>
<para>
As a module within a NixOS system configuration. This allows the user
profiles to be built together with the system when running
<command>nixos-rebuild</command>. See
<xref linkend="sec-install-nixos-module"/> for a description of this
setup.
</para>
</listitem>
<listitem>
<para>
As a module within a
<link xlink:href="https://github.com/LnL7/nix-darwin/">nix-darwin</link>
system configuration. This allows the user profiles to be built together
with the system when running <command>darwin-rebuild</command>. See
<xref linkend="sec-install-nix-darwin-module"/> for a description of this
setup.
</para>
</listitem>
</orderedlist>
</para>
<section xml:id="sec-install-standalone">
<title>Standalone installation</title>
<orderedlist>
<listitem>
<para>
Make sure you have a working Nix installation. If you are not using NixOS
then it may be necessary to run
</para>
<screen>
<prompt>$</prompt> <userinput>mkdir -m 0755 -p /nix/var/nix/{profiles,gcroots}/per-user/$USER</userinput>
</screen>
<para>
since Home Manager uses these directories to manage your profile
generations. On NixOS these should already be available.
</para>
<para>
Also make sure that your user is able to build and install Nix packages.
For example, you should be able to successfully run a command like
<literal>nix-instantiate '&lt;nixpkgs&gt;' -A hello</literal> without
having to switch to the root user. For a multi-user install of Nix this
means that your user must be covered by the
<link xlink:href="https://nixos.org/nix/manual/#conf-allowed-users"><literal>allowed-users</literal></link>
Nix option. On NixOS you can control this option using the
<link xlink:href="https://nixos.org/nixos/manual/options.html#opt-nix.allowedUsers"><literal>nix.allowedUsers</literal></link>
system option.
</para>
</listitem>
<listitem>
<para>
Add the Home Manager channel that you wish to follow. This is done by
running
</para>
<screen>
<prompt>$</prompt> <userinput>nix-channel --add https://github.com/rycee/home-manager/archive/master.tar.gz home-manager</userinput>
<prompt>$</prompt> <userinput>nix-channel --update</userinput>
</screen>
<para>
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-18.09.tar.gz home-manager</userinput>
<prompt>$</prompt> <userinput>nix-channel --update</userinput>
</screen>
<para>
if you follow a Nixpkgs version 18.09 channel.
</para>
<para>
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
<programlisting language="bash">
export NIX_PATH=$HOME/.nix-defexpr/channels${NIX_PATH:+:}$NIX_PATH
</programlisting>
to your shell (see
<link xlink:href="https://github.com/NixOS/nix/issues/2033">nix#2033</link>).
</para>
</listitem>
<listitem>
<para>
Run the Home Manager installation command and create the first Home
Manager generation:
</para>
<screen>
<prompt>$</prompt> <userinput>nix-shell '&lt;home-manager&gt;' -A install</userinput>
</screen>
<para>
Once finished, Home Manager should be active and available in your user
environment.
</para>
</listitem>
<listitem>
<para>
If you do not plan on having Home Manager manage your shell configuration
then you must source the
</para>
<programlisting language="bash">
$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh
</programlisting>
<para>
file in your shell configuration. Unfortunately, we currently only support
POSIX.2-like shells such as
<link xlink:href="https://www.gnu.org/software/bash/">Bash</link> or
<link xlink:href="http://zsh.sourceforge.net/">Z shell</link>.
</para>
<para>
For example, if you use Bash then add
</para>
<programlisting language="bash">
. &quot;$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh&quot;
</programlisting>
<para>
to your <literal>~/.profile</literal> file.
</para>
</listitem>
</orderedlist>
<para>
If instead of using channels you want to run Home Manager from a Git
checkout of the repository then you can use the
<literal>programs.home-manager.path</literal> option to specify the absolute
path to the repository.
</para>
</section>
<section xml:id="sec-install-nixos-module">
<title>NixOS module</title>
<para>
Home Manager provides a NixOS module that allows you to prepare user
environments directly from the system configuration file, which often is
more convenient than using the <command>home-manager</command> tool. It also
opens up additional possibilities, for example, to automatically configure
user environments in NixOS declarative containers or on systems deployed
through NixOps.
</para>
<para>
To make the NixOS module available for use you must <option>import</option>
it into your system configuration. This is most conveniently done by adding
a Home Manager channel, for example
</para>
<screen>
<prompt>#</prompt> <userinput>nix-channel --add https://github.com/rycee/home-manager/archive/master.tar.gz home-manager</userinput>
<prompt>#</prompt> <userinput>nix-channel --update</userinput>
</screen>
<para>
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-18.09.tar.gz home-manager</userinput>
<prompt>#</prompt> <userinput>nix-channel --update</userinput>
</screen>
<para>
if you follow a Nixpkgs version 18.09 channel.
</para>
<para>
It is then possible to add
</para>
<programlisting language="nix">
imports = [ &lt;home-manager/nixos&gt; ];
</programlisting>
<para>
to your system <filename>configuration.nix</filename> file, which will
introduce a new NixOS option called <option>home-manager.users</option>
whose type is an attribute set that maps user names to Home Manager
configurations.
</para>
<para>
For example, a NixOS configuration may include the lines
</para>
<programlisting language="nix">
users.users.eve.isNormalUser = true;
home-manager.users.eve = { pkgs, ... }: {
home.packages = [ pkgs.atool pkgs.httpie ];
programs.bash.enable = true;
};
</programlisting>
<para>
and after a <command>nixos-rebuild switch</command> the user eve's
environment should include a basic Bash configuration and the packages atool
and httpie.
</para>
<note>
<para>
By default packages will be installed to
<filename>$HOME/.nix-profile</filename> but they can be installed to
<filename>/etc/profiles</filename> if
</para>
<programlisting language="nix">
home-manager.useUserPackages = true;
</programlisting>
<para>
is added to the system configuration. This is necessary if, for example,
you wish to use <command>nixos-rebuild build-vm</command>. This option may
become the default value in the future.
</para>
</note>
</section>
<section xml:id="sec-install-nix-darwin-module">
<title>nix-darwin module</title>
<para>
To be done.
</para>
</section>
</chapter>

40
doc/man-configuration.xml Normal file
View File

@@ -0,0 +1,40 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle><filename>home-configuration.nix</filename></refentrytitle>
<manvolnum>5</manvolnum>
<refmiscinfo class="source">Home Manager</refmiscinfo>
<!-- <refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo> -->
</refmeta>
<refnamediv>
<refname><filename>home-configuration.nix</filename></refname>
<refpurpose>Home Manager configuration specification</refpurpose>
</refnamediv>
<refsection>
<title>Description</title>
<para>
The file <filename>~/.config/nixpkgs/home.nix</filename> contains the
declarative specification of your Home Manager configuration. The command
<command>home-manager</command> takes this file and realises the user
environment configuration specified therein.
</para>
</refsection>
<refsection>
<title>Options</title>
<para>
You can use the following options in
<filename>home-configuration.nix</filename>:
</para>
<xi:include href="./generated/options-db.xml" xpointer="configuration-variable-list" />
</refsection>
<refsection>
<title>See also</title>
<para>
<citerefentry>
<refentrytitle>home-manager</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>
</para>
</refsection>
</refentry>

88
doc/man-home-manager.xml Normal file
View File

@@ -0,0 +1,88 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle><command>home-manager</command></refentrytitle>
<manvolnum>1</manvolnum>
<refmiscinfo class="source">Home Manager</refmiscinfo>
<!-- <refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo> -->
</refmeta>
<refnamediv>
<refname><command>home-manager</command></refname>
<refpurpose>reconfigure a user environment</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>home-manager</command> <group choice="req">
<arg choice="plain">
<option>help</option>
</arg>
<arg choice="plain">
<option>build</option>
</arg>
<arg choice="plain">
<option>switch</option>
</arg>
<arg choice="plain">
<option>generations</option>
</arg>
<arg choice="plain">
<option>remove-generations</option>
</arg>
<arg choice="plain">
<option>packages</option>
</arg>
<arg choice="plain">
<option>news</option>
</arg>
</group>
</cmdsynopsis>
</refsynopsisdiv>
<refsection>
<title>Description</title>
<para>
This command updates the user environment so that it corresponds to the
configuration specified in <filename>~/.config/nixpkgs/home.nix</filename>.
</para>
</refsection>
<refsection>
<title>Files</title>
<variablelist>
<varlistentry>
<term>
<filename>~/.local/share/home-manager/news-read-ids</filename>
</term>
<listitem>
<para>
Identifiers of news items that have been shown. Can be deleted to reset
the read news indicator.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsection>
<refsection>
<title>Bugs</title>
<para>
Please report any bugs on the
<link
xlink:href="https://github.com/rycee/home-manager/issues">project
issue tracker</link>.
</para>
</refsection>
<refsection>
<title>See also</title>
<para>
<citerefentry>
<refentrytitle>home-configuration.nix</refentrytitle>
<manvolnum>5</manvolnum>
</citerefentry>
</para>
</refsection>
</refentry>

12
doc/man-pages.xml Normal file
View File

@@ -0,0 +1,12 @@
<reference xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<title>Home Manager Reference Pages</title>
<info>
<author><personname>Home Manager contributors</personname></author>
<copyright><year>20172019</year><holder>Home Manager contributors</holder>
</copyright>
</info>
<xi:include href="man-configuration.xml" />
<xi:include href="man-home-manager.xml" />
</reference>

34
doc/manual.xml Normal file
View File

@@ -0,0 +1,34 @@
<book xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="book-home-manager-manual">
<info>
<title>Home Manager Manual</title>
</info>
<preface>
<title>Preface</title>
<para>
This manual will eventually describes how to install, use, and extend Home
Manager.
</para>
<para>
If you encounter problems or bugs then please report them on the
<link xlink:href="https://github.com/rycee/home-manager/issues">Home Manager
issue tracker</link>.
</para>
<note>
<para>
Commands prefixed with <literal>#</literal> have to be run as root, either
requiring to login as root user or temporarily switching to it using
<literal>sudo</literal> for example.
</para>
</note>
</preface>
<xi:include href="installation.xml" />
<appendix xml:id="ch-options">
<title>Configuration Options</title>
<xi:include href="./generated/options-db.xml" xpointer="configuration-variable-list" />
</appendix>
<xi:include href="./release-notes/release-notes.xml" />
</book>

239
doc/options-to-docbook.xsl Normal file
View File

@@ -0,0 +1,239 @@
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://docbook.org/ns/docbook"
extension-element-prefixes="str"
>
<xsl:output method='xml' encoding="UTF-8" />
<xsl:param name="revision" />
<xsl:param name="program" />
<xsl:template match="/expr/list">
<appendix>
<title>Configuration Options</title>
<variablelist xml:id="configuration-variable-list">
<xsl:for-each select="attrs">
<xsl:variable name="id" select="concat('opt-', str:replace(str:replace(str:replace(str:replace(attr[@name = 'name']/string/@value, '*', '_'), '&lt;', '_'), '>', '_'), '?', '_'))" />
<varlistentry>
<term xlink:href="#{$id}">
<xsl:attribute name="xml:id"><xsl:value-of select="$id"/></xsl:attribute>
<option>
<xsl:value-of select="attr[@name = 'name']/string/@value" />
</option>
</term>
<listitem>
<para>
<xsl:value-of disable-output-escaping="yes"
select="attr[@name = 'description']/string/@value" />
</para>
<xsl:if test="attr[@name = 'type']">
<para>
<emphasis>Type:</emphasis>
<xsl:text> </xsl:text>
<xsl:value-of select="attr[@name = 'type']/string/@value"/>
<xsl:if test="attr[@name = 'readOnly']/bool/@value = 'true'">
<xsl:text> </xsl:text>
<emphasis>(read only)</emphasis>
</xsl:if>
</para>
</xsl:if>
<xsl:if test="attr[@name = 'default']">
<para>
<emphasis>Default:</emphasis>
<xsl:text> </xsl:text>
<xsl:apply-templates select="attr[@name = 'default']" mode="top" />
</para>
</xsl:if>
<xsl:if test="attr[@name = 'example']">
<para>
<emphasis>Example:</emphasis>
<xsl:text> </xsl:text>
<xsl:choose>
<xsl:when test="attr[@name = 'example']/attrs[attr[@name = '_type' and string[@value = 'literalExample']]]">
<programlisting><xsl:value-of select="attr[@name = 'example']/attrs/attr[@name = 'text']/string/@value" /></programlisting>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="attr[@name = 'example']" mode="top" />
</xsl:otherwise>
</xsl:choose>
</para>
</xsl:if>
<xsl:if test="attr[@name = 'relatedPackages']">
<para>
<emphasis>Related packages:</emphasis>
<xsl:text> </xsl:text>
<xsl:value-of disable-output-escaping="yes"
select="attr[@name = 'relatedPackages']/string/@value" />
</para>
</xsl:if>
<xsl:if test="count(attr[@name = 'declarations']/list/*) != 0">
<para>
<emphasis>Declared by:</emphasis>
</para>
<xsl:apply-templates select="attr[@name = 'declarations']" />
</xsl:if>
<xsl:if test="count(attr[@name = 'definitions']/list/*) != 0">
<para>
<emphasis>Defined by:</emphasis>
</para>
<xsl:apply-templates select="attr[@name = 'definitions']" />
</xsl:if>
</listitem>
</varlistentry>
</xsl:for-each>
</variablelist>
</appendix>
</xsl:template>
<xsl:template match="*" mode="top">
<xsl:choose>
<xsl:when test="string[contains(@value, '&#010;')]">
<programlisting>
<xsl:text>''
</xsl:text><xsl:value-of select='str:replace(string/@value, "${", "&apos;&apos;${")' /><xsl:text>''</xsl:text></programlisting>
</xsl:when>
<xsl:otherwise>
<literal><xsl:apply-templates /></literal>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="null">
<xsl:text>null</xsl:text>
</xsl:template>
<xsl:template match="string">
<xsl:choose>
<xsl:when test="(contains(@value, '&quot;') or contains(@value, '\')) and not(contains(@value, '&#010;'))">
<xsl:text>''</xsl:text><xsl:value-of select='str:replace(@value, "${", "&apos;&apos;${")' /><xsl:text>''</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>"</xsl:text><xsl:value-of select="str:replace(str:replace(str:replace(str:replace(@value, '\', '\\'), '&quot;', '\&quot;'), '&#010;', '\n'), '$', '\$')" /><xsl:text>"</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="int">
<xsl:value-of select="@value" />
</xsl:template>
<xsl:template match="bool[@value = 'true']">
<xsl:text>true</xsl:text>
</xsl:template>
<xsl:template match="bool[@value = 'false']">
<xsl:text>false</xsl:text>
</xsl:template>
<xsl:template match="list">
[
<xsl:for-each select="*">
<xsl:apply-templates select="." />
<xsl:text> </xsl:text>
</xsl:for-each>
]
</xsl:template>
<xsl:template match="attrs[attr[@name = '_type' and string[@value = 'literalExample']]]">
<xsl:value-of select="attr[@name = 'text']/string/@value" />
</xsl:template>
<xsl:template match="attrs">
{
<xsl:for-each select="attr">
<xsl:value-of select="@name" />
<xsl:text> = </xsl:text>
<xsl:apply-templates select="*" /><xsl:text>; </xsl:text>
</xsl:for-each>
}
</xsl:template>
<xsl:template match="derivation">
<replaceable>(build of <xsl:value-of select="attr[@name = 'name']/string/@value" />)</replaceable>
</xsl:template>
<xsl:template match="attr[@name = 'declarations' or @name = 'definitions']">
<simplelist>
<xsl:for-each select="list/string">
<member><filename>
<!-- Hyperlink the filename either to the NixOS Subversion
repository (if its a module and we have a revision number),
or to the local filesystem. -->
<xsl:choose>
<xsl:when test="not(starts-with(@value, '/'))">
<xsl:choose>
<xsl:when test="$program = 'home-manager'">
<xsl:attribute name="xlink:href">https://github.com/rycee/home-manager/blob/<xsl:value-of select="$revision"/>/<xsl:value-of select="@value"/>#blob-path</xsl:attribute>
</xsl:when>
<xsl:when test="$revision = 'local'">
<xsl:attribute name="xlink:href">https://github.com/NixOS/nixpkgs/blob/master/<xsl:value-of select="@value"/></xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="xlink:href">https://github.com/NixOS/nixpkgs/blob/<xsl:value-of select="$revision"/>/<xsl:value-of select="@value"/></xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="$revision != 'local' and $program = 'nixops' and contains(@value, '/nix/')">
<xsl:attribute name="xlink:href">https://github.com/NixOS/nixops/blob/<xsl:value-of select="$revision"/>/nix/<xsl:value-of select="substring-after(@value, '/nix/')"/></xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="xlink:href">file://<xsl:value-of select="@value"/></xsl:attribute>
</xsl:otherwise>
</xsl:choose>
<!-- Print the filename and make it user-friendly by replacing the
/nix/store/<hash> prefix by the default location of nixos
sources. -->
<xsl:choose>
<xsl:when test="$program = 'home-manager'">
&lt;home-manager/<xsl:value-of select="@value"/>&gt;
</xsl:when>
<xsl:when test="not(starts-with(@value, '/'))">
&lt;nixpkgs/<xsl:value-of select="@value"/>&gt;
</xsl:when>
<xsl:when test="contains(@value, 'nixops') and contains(@value, '/nix/')">
&lt;nixops/<xsl:value-of select="substring-after(@value, '/nix/')"/>&gt;
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@value" />
</xsl:otherwise>
</xsl:choose>
</filename></member>
</xsl:for-each>
</simplelist>
</xsl:template>
<xsl:template match="function">
<xsl:text>λ</xsl:text>
</xsl:template>
</xsl:stylesheet>

9
doc/overrides.css Normal file
View File

@@ -0,0 +1,9 @@
.docbook .xref img[src^=images\/callouts\/],
.screen img,
.programlisting img {
width: 1em;
}
.calloutlist img {
width: 1.5em;
}

View File

@@ -0,0 +1,13 @@
<appendix xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="ch-release-notes">
<title>Release Notes</title>
<para>
This section lists the release notes for stable versions of Home Manager and
the current unstable version.
</para>
<xi:include href="rl-1903.xml" />
<xi:include href="rl-1809.xml" />
</appendix>

View File

@@ -0,0 +1,11 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-release-18.09">
<title>Release 18.09</title>
<para>
The 18.09 release branch became the stable branch in September, 2018.
</para>
</section>

View File

@@ -0,0 +1,67 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-release-19.03">
<title>Release 19.03 (unstable)</title>
<para>
This is the current unstable branch and the information in this section is
therefore not final.
</para>
<para>
Scheduled released is March, 2019.
</para>
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-release-19.03-highlights">
<title>Highlights</title>
<para>
This release has the following notable changes:
</para>
<itemizedlist>
<listitem>
<para>
The <option>home.file.&lt;name?&gt;.source</option> now allows source
files to be hidden, that is, having a name starting with the
<literal>.</literal> character. It also allows the source file name to
contain characters not typically allowed for Nix store paths. For example,
your configuration can now contain things such as
<programlisting>
home.file."my file".source = ./. + "/file with spaces!";
</programlisting>
</para>
</listitem>
</itemizedlist>
</section>
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-release-19.03-state-version-changes">
<title>State Version Changes</title>
<para>
The state version in this release includes the changes below. These changes
are only active if the <option>home.stateVersion</option> option is set to
"19.03" or later.
</para>
<itemizedlist>
<listitem>
<para>
There is now an option <option>programs.beets.enable</option> that
defaults to <literal>false</literal>. Before the module would be active if
the <option>programs.beets.settings</option> option was non-empty.
</para>
</listitem>
</itemizedlist>
</section>
</section>

271
doc/style.css Normal file
View File

@@ -0,0 +1,271 @@
/* Copied from http://bakefile.sourceforge.net/, which appears
licensed under the GNU GPL. */
/***************************************************************************
Basic headers and text:
***************************************************************************/
body
{
font-family: "Nimbus Sans L", sans-serif;
background: white;
margin: 2em 1em 2em 1em;
}
h1, h2, h3, h4
{
color: #005aa0;
}
h1 /* title */
{
font-size: 200%;
}
h2 /* chapters, appendices, subtitle */
{
font-size: 180%;
}
/* Extra space between chapters, appendices. */
div.chapter > div.titlepage h2, div.appendix > div.titlepage h2
{
margin-top: 1.5em;
}
div.section > div.titlepage h2 /* sections */
{
font-size: 150%;
margin-top: 1.5em;
}
h3 /* subsections */
{
font-size: 125%;
}
div.simplesect h2
{
font-size: 110%;
}
div.appendix h3
{
font-size: 150%;
margin-top: 1.5em;
}
div.refnamediv h2, div.refsynopsisdiv h2, div.refsection h2 /* refentry parts */
{
margin-top: 1.4em;
font-size: 125%;
}
div.refsection h3
{
font-size: 110%;
}
/***************************************************************************
Examples:
***************************************************************************/
div.example
{
border: 1px solid #b0b0b0;
padding: 6px 6px;
margin-left: 1.5em;
margin-right: 1.5em;
background: #f4f4f8;
border-radius: 0.4em;
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
}
div.example p.title
{
margin-top: 0em;
}
div.example pre
{
box-shadow: none;
}
/***************************************************************************
Screen dumps:
***************************************************************************/
pre.screen, pre.programlisting
{
border: 1px solid #b0b0b0;
padding: 3px 3px;
margin-left: 1.5em;
margin-right: 1.5em;
background: #f4f4f8;
font-family: monospace;
border-radius: 0.4em;
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
}
div.example pre.programlisting
{
border: 0px;
padding: 0 0;
margin: 0 0 0 0;
}
/***************************************************************************
Notes, warnings etc:
***************************************************************************/
.note, .warning
{
border: 1px solid #b0b0b0;
padding: 3px 3px;
margin-left: 1.5em;
margin-right: 1.5em;
margin-bottom: 1em;
padding: 0.3em 0.3em 0.3em 0.3em;
background: #fffff5;
border-radius: 0.4em;
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
}
div.note, div.warning
{
font-style: italic;
}
div.note h3, div.warning h3
{
color: red;
font-size: 100%;
padding-right: 0.5em;
display: inline;
}
div.note p, div.warning p
{
margin-bottom: 0em;
}
div.note h3 + p, div.warning h3 + p
{
display: inline;
}
div.note h3
{
color: blue;
font-size: 100%;
}
div.navfooter *
{
font-size: 90%;
}
/***************************************************************************
Links colors and highlighting:
***************************************************************************/
a { text-decoration: none; }
a:hover { text-decoration: underline; }
a:link { color: #0048b3; }
a:visited { color: #002a6a; }
/***************************************************************************
Table of contents:
***************************************************************************/
div.toc
{
font-size: 90%;
}
div.toc dl
{
margin-top: 0em;
margin-bottom: 0em;
}
/***************************************************************************
Special elements:
***************************************************************************/
tt, code
{
color: #400000;
}
.term
{
font-weight: bold;
}
div.variablelist dd p, div.glosslist dd p
{
margin-top: 0em;
}
div.variablelist dd, div.glosslist dd
{
margin-left: 1.5em;
}
div.glosslist dt
{
font-style: italic;
}
.varname
{
color: #400000;
}
span.command strong
{
font-weight: normal;
color: #400000;
}
div.calloutlist table
{
box-shadow: none;
}
table
{
border-collapse: collapse;
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
}
table.simplelist
{
text-align: left;
color: #005aa0;
border: 0;
padding: 5px;
background: #fffff5;
font-weight: normal;
font-style: italic;
box-shadow: none;
margin-bottom: 1em;
}
div.navheader table, div.navfooter table {
box-shadow: none;
}
div.affiliation
{
font-style: italic;
}

View File

@@ -1,41 +1,37 @@
{ pkgs, modulesPath ? "$HOME/.config/nixpkgs/home-manager/modules" }:
{ pkgs
# Extra path to Home Manager. If set then this path will be tried
# before `$HOME/.config/nixpkgs/home-manager` and
# `$HOME/.nixpkgs/home-manager`.
, path ? null
}:
let
homeManagerExpr = pkgs.writeText "home-manager.nix" ''
{ pkgs ? import <nixpkgs> {}, confPath }:
let
env = import <home-manager> {
configuration = import confPath;
pkgs = pkgs;
};
in
{
inherit (env) activation-script;
}
'';
pathStr = if path == null then "" else path;
in
pkgs.stdenv.mkDerivation {
name = "home-manager";
phases = [ "installPhase" ];
installPhase = ''
install -v -D -m755 ${./home-manager} $out/bin/home-manager
pkgs.runCommand
"home-manager"
{
preferLocalBuild = true;
allowSubstitutes = false;
meta = with pkgs.stdenv.lib; {
description = "A user environment configurator";
maintainers = [ maintainers.rycee ];
platforms = platforms.unix;
license = licenses.mit;
};
}
''
install -v -D -m755 ${./home-manager} $out/bin/home-manager
substituteInPlace $out/bin/home-manager \
--subst-var-by bash "${pkgs.bash}" \
--subst-var-by coreutils "${pkgs.coreutils}" \
--subst-var-by MODULES_PATH '${modulesPath}' \
--subst-var-by HOME_MANAGER_EXPR_PATH "${homeManagerExpr}"
'';
meta = with pkgs.stdenv.lib; {
description = "A user environment configurator";
maintainers = [ maintainers.rycee ];
platforms = platforms.linux;
};
}
--subst-var-by findutils "${pkgs.findutils}" \
--subst-var-by gnused "${pkgs.gnused}" \
--subst-var-by less "${pkgs.less}" \
--subst-var-by HOME_MANAGER_PATH '${pathStr}'
''

View File

@@ -1,12 +1,23 @@
#!@bash@/bin/bash
# This code explicitly requires GNU Core Utilities and we therefore
# need to ensure they are prioritized over any other similarly named
# tools on the system.
PATH=@coreutils@/bin:$PATH
# Prepare to use tools from Nixpkgs.
PATH=@coreutils@/bin:@findutils@/bin:@gnused@/bin:@less@/bin${PATH:+:}$PATH
set -euo pipefail
function errorEcho() {
# shellcheck disable=2048,2086
echo $* >&2
}
function setWorkDir() {
if [[ ! -v WORK_DIR ]]; then
WORK_DIR="$(mktemp --tmpdir -d home-manager-build.XXXXXXXXXX)"
# shellcheck disable=2064
trap "rm -r '$WORK_DIR'" EXIT
fi
}
# Attempts to set the HOME_MANAGER_CONFIG global variable.
#
# If no configuration file can be found then this function will print
@@ -14,7 +25,7 @@ set -euo pipefail
function setConfigFile() {
if [[ -v HOME_MANAGER_CONFIG ]] ; then
if [[ ! -e "$HOME_MANAGER_CONFIG" ]] ; then
echo "No configure file found at $HOME_MANAGER_CONFIG"
errorEcho "No configuration file found at $HOME_MANAGER_CONFIG"
exit 1
fi
@@ -22,55 +33,38 @@ function setConfigFile() {
return
fi
local defaultConfFile="${XDG_CONFIG_HOME:-$HOME/.config}/nixpkgs/home.nix"
local confFile
for confFile in "$HOME/.config/nixpkgs/home.nix" \
for confFile in "$defaultConfFile" \
"$HOME/.nixpkgs/home.nix" ; do
if [[ -e "$confFile" ]] ; then
HOME_MANAGER_CONFIG="$confFile"
HOME_MANAGER_CONFIG="$(realpath "$confFile")"
return
fi
done
echo "No configuration file found. " \
"Please create one at ~/.config/nixpkgs/home.nix"
errorEcho "No configuration file found." \
"Please create one at $defaultConfFile"
exit 1
}
function setHomeManagerModulesPath() {
local modulesPath
for modulesPath in "@MODULES_PATH@" \
"$HOME/.nixpkgs/home-manager/modules" ; do
if [[ -e "$modulesPath" ]] ; then
export NIX_PATH="$NIX_PATH${NIX_PATH:+:}home-manager=$modulesPath"
function setHomeManagerNixPath() {
local path
for path in "@HOME_MANAGER_PATH@" \
"${XDG_CONFIG_HOME:-$HOME/.config}/nixpkgs/home-manager" \
"$HOME/.nixpkgs/home-manager" ; do
if [[ -e "$path" || "$path" =~ ^https?:// ]] ; then
export NIX_PATH="home-manager=$path${NIX_PATH:+:}$NIX_PATH"
return
fi
done
}
function doBuild() {
if [[ -z "$1" ]]; then
echo "Need to provide generation output path."
exit 1
fi
if [[ -e "$1" ]]; then
echo "The output path $1 already exists."
exit 1
fi
function doBuildAttr() {
setConfigFile
setHomeManagerModulesPath
setHomeManagerNixPath
output="$(realpath "$1")"
if [[ $? -ne 0 ]]; then
exit 1
fi
export NIX_PATH="$NIX_PATH${NIX_PATH:+:}home-manager=@MODULES_PATH@"
local extraArgs
extraArgs=""
local extraArgs="$*"
for p in "${EXTRA_NIX_PATH[@]}"; do
extraArgs="$extraArgs -I $p"
@@ -80,38 +74,276 @@ function doBuild() {
extraArgs="$extraArgs --show-trace"
fi
nix-build $extraArgs \
"@HOME_MANAGER_EXPR_PATH@" \
--argstr confPath "$HOME_MANAGER_CONFIG" \
-A activation-script \
-o "$output"
# shellcheck disable=2086
if [[ -v USE_NIX2_COMMAND ]]; then
nix build \
-f "<home-manager/home-manager/home-manager.nix>" \
$extraArgs \
--argstr confPath "$HOME_MANAGER_CONFIG" \
--argstr confAttr "$HOME_MANAGER_CONFIG_ATTRIBUTE"
else
nix-build \
"<home-manager/home-manager/home-manager.nix>" \
$extraArgs \
--argstr confPath "$HOME_MANAGER_CONFIG" \
--argstr confAttr "$HOME_MANAGER_CONFIG_ATTRIBUTE"
fi
}
# Presents news to the user. Takes as argument the path to a "news
# info" file as generated by `buildNews`.
function presentNews() {
local infoFile="$1"
# shellcheck source=/dev/null
. "$infoFile"
# shellcheck disable=2154
if [[ $newsNumUnread -eq 0 ]]; then
return
elif [[ "$newsDisplay" == "silent" ]]; then
return
elif [[ "$newsDisplay" == "notify" ]]; then
local msg
if [[ $newsNumUnread -eq 1 ]]; then
msg="There is an unread and relevant news item.\n"
msg+="Read it by running the command '$(basename "$0") news'."
else
msg="There are $newsNumUnread unread and relevant news items.\n"
msg+="Read them by running the command '$(basename "$0") news'."
fi
# Not actually an error but here stdout is reserved for
# nix-build output.
errorEcho
errorEcho -e "$msg"
errorEcho
if [[ -v DISPLAY ]] && type -P notify-send > /dev/null; then
notify-send "Home Manager" "$msg"
fi
elif [[ "$newsDisplay" == "show" ]]; then
doShowNews --unread
else
errorEcho "Unknown 'news.display' setting '$newsDisplay'."
fi
}
function doEdit() {
if [[ ! -v EDITOR || -z $EDITOR ]]; then
errorEcho "Please set the \$EDITOR environment variable"
return 1
fi
setConfigFile
exec "$EDITOR" "$HOME_MANAGER_CONFIG"
}
function doBuild() {
if [[ ! -w . ]]; then
errorEcho "Cannot run build in read-only directory";
return 1
fi
setWorkDir
local newsInfo
newsInfo=$(buildNews)
local exitCode
if [[ -v USE_NIX2_COMMAND ]]; then
doBuildAttr activationPackage \
&& exitCode=0 || exitCode=1
else
doBuildAttr --attr activationPackage \
&& exitCode=0 || exitCode=1
fi
presentNews "$newsInfo"
return $exitCode
}
function doSwitch() {
local wrkdir
wrkdir="$(mktemp -d)"
setWorkDir
if doBuild "$wrkdir/generation" ; then
"$wrkdir/generation/activate"
local newsInfo
newsInfo=$(buildNews)
local generation
local exitCode=0
# Build the generation and run the activate script. Note, we
# specify an output link so that it is treated as a GC root. This
# prevents an unfortunately timed GC from removing the generation
# before activation completes.
generation="$WORK_DIR/generation"
if [[ -v USE_NIX2_COMMAND ]]; then
doBuildAttr \
--out-link "$generation" \
activationPackage \
&& "$generation/activate" || exitCode=1
else
doBuildAttr \
--out-link "$generation" \
--attr activationPackage \
&& "$generation/activate" || exitCode=1
fi
rm -r "$wrkdir"
presentNews "$newsInfo"
return $exitCode
}
function doListGens() {
# Whether to colorize the generations output.
local color="never"
if [[ -t 1 ]]; then
color="always"
fi
pushd "/nix/var/nix/profiles/per-user/$USER" > /dev/null
ls --color=yes -gG --sort time home-manager-*-link \
| cut -d' ' -f 4-
# shellcheck disable=2012
ls --color=$color -gG --time-style=long-iso --sort time home-manager-*-link \
| cut -d' ' -f 4- \
| sed -E 's/home-manager-([[:digit:]]*)-link/: id \1/'
popd > /dev/null
}
# Removes linked generations. Takes as arguments identifiers of
# generations to remove.
function doRmGenerations() {
if [[ -v VERBOSE ]]; then
export VERBOSE_ARG="--verbose"
else
export VERBOSE_ARG=""
fi
if [[ -v DRY_RUN ]] ; then
export DRY_RUN_CMD=echo
else
export DRY_RUN_CMD=""
fi
pushd "/nix/var/nix/profiles/per-user/$USER" > /dev/null
for generationId in "$@"; do
local linkName="home-manager-$generationId-link"
if [[ ! -e $linkName ]]; then
errorEcho "No generation with ID $generationId"
elif [[ $linkName == $(readlink home-manager) ]]; then
errorEcho "Cannot remove the current generation $generationId"
else
echo Removing generation $generationId
$DRY_RUN_CMD rm $VERBOSE_ARG $linkName
fi
done
popd > /dev/null
}
function doExpireGenerations() {
local profileDir="/nix/var/nix/profiles/per-user/$USER"
local generations
generations="$( \
find "$profileDir" -name 'home-manager-*-link' -not -newermt "$1" \
| sed 's/^.*-\([0-9]*\)-link$/\1/' \
)"
if [[ -n $generations ]]; then
# shellcheck disable=2086
doRmGenerations $generations
elif [[ -v VERBOSE ]]; then
echo "No generations to expire"
fi
}
function doListPackages() {
local outPath
outPath="$(nix-env -q --out-path | grep -o '/.*home-manager-path$')"
if [[ -n "$outPath" ]] ; then
nix-store -q --references "$outPath" | sed 's/[^-]*-//'
else
echo "No home-manager packages seem to be installed."
errorEcho "No home-manager packages seem to be installed."
fi
}
function newsReadIdsFile() {
local dataDir="${XDG_DATA_HOME:-$HOME/.local/share}/home-manager"
local path="$dataDir/news-read-ids"
# If the path doesn't exist then we should create it, otherwise
# Nix will error out when we attempt to use builtins.readFile.
if [[ ! -f "$path" ]]; then
mkdir -p "$dataDir"
touch "$path"
fi
echo "$path"
}
# Builds news meta information to be sourced into this script.
#
# Note, we suppress build output to remove unnecessary verbosity. We
# put the output in the work directory to avoid the risk of an
# unfortunately timed GC removing it.
function buildNews() {
local output
output="$WORK_DIR/news-info.sh"
if [[ -v USE_NIX2_COMMAND ]]; then
doBuildAttr \
--out-link "$output" \
--quiet \
--arg check false \
--argstr newsReadIdsFile "$(newsReadIdsFile)" \
newsInfo
else
doBuildAttr \
--out-link "$output" \
--no-build-output \
--quiet \
--arg check false \
--argstr newsReadIdsFile "$(newsReadIdsFile)" \
--attr newsInfo \
> /dev/null
fi
echo "$output"
}
function doShowNews() {
setWorkDir
local infoFile
infoFile=$(buildNews) || return 1
# shellcheck source=/dev/null
. "$infoFile"
# shellcheck disable=2154
case $1 in
--all)
${PAGER:-less} "$newsFileAll"
;;
--unread)
${PAGER:-less} "$newsFileUnread"
;;
*)
errorEcho "Unknown argument $1"
return 1
esac
# shellcheck disable=2154
if [[ -s "$newsUnreadIdsFile" ]]; then
local newsReadIdsFile
newsReadIdsFile="$(newsReadIdsFile)"
cat "$newsUnreadIdsFile" >> "$newsReadIdsFile"
fi
}
@@ -122,29 +354,65 @@ function doHelp() {
echo
echo " -f FILE The home configuration file."
echo " Default is '~/.config/nixpkgs/home.nix'."
echo " -A ATTRIBUTE Optional attribute that selects a configuration"
echo " expression in the configuration file."
echo " -I PATH Add a path to the Nix expression search path."
echo " -v Verbose output"
echo " -n Do a dry run, only prints what actions would be taken"
echo " -h Print this help"
echo
echo "Commands"
echo
echo " help Print this help"
echo
echo " edit Open the home configuration in \$EDITOR"
echo
echo " build Build configuration into result directory"
echo
echo " switch Build and activate configuration"
echo
echo " generations List all home environment generations"
echo
echo " remove-generations ID..."
echo " Remove indicated generations. Use 'generations' command to"
echo " find suitable generation numbers."
echo
echo " expire-generations TIMESTAMP"
echo " Remove generations older than TIMESTAMP where TIMESTAMP is"
echo " interpreted as in the -d argument of the date tool. For"
echo " example \"-30 days\" or \"2018-01-01\"."
echo
echo " packages List all packages installed in home-manager-path"
echo
echo " news Show news entries in a pager"
}
EXTRA_NIX_PATH=()
HOME_MANAGER_CONFIG_ATTRIBUTE=""
while getopts f:I:vnh opt; do
# As a special case, if the user has given --help anywhere on the
# command line then print help and exit.
for arg in "$@"; do
if [[ $arg == "--help" ]]; then
doHelp
exit 0
fi
done
while getopts 2f:I:A:vnh opt; do
case $opt in
2)
USE_NIX2_COMMAND=1
;;
f)
HOME_MANAGER_CONFIG="$OPTARG"
;;
I)
EXTRA_NIX_PATH+=("$OPTARG")
;;
A)
HOME_MANAGER_CONFIG_ATTRIBUTE="$OPTARG"
;;
v)
export VERBOSE=1
;;
@@ -156,7 +424,7 @@ while getopts f:I:vnh opt; do
exit 0
;;
*)
echo "Unknown option -$OPTARG" >&2
errorEcho "Unknown option -$OPTARG"
doHelp >&2
exit 1
;;
@@ -166,11 +434,20 @@ done
# Get rid of the options.
shift "$((OPTIND-1))"
cmd="$*"
if [[ $# -eq 0 ]]; then
doHelp >&2
exit 1
fi
cmd="$1"
shift 1
case "$cmd" in
edit)
doEdit
;;
build)
doBuild "result"
doBuild
;;
switch)
doSwitch
@@ -178,14 +455,23 @@ case "$cmd" in
generations)
doListGens
;;
remove-generations)
doRmGenerations "$@"
;;
expire-generations)
doExpireGenerations "$@"
;;
packages)
doListPackages
;;
news)
doShowNews --all
;;
help|--help)
doHelp
;;
*)
echo "Unknown command: $cmd"
errorEcho "Unknown command: $cmd"
doHelp >&2
exit 1
;;

View File

@@ -0,0 +1,88 @@
{ pkgs ? import <nixpkgs> {}
, confPath
, confAttr
, check ? true
, newsReadIdsFile ? null
}:
with pkgs.lib;
let
env = import ../modules {
configuration =
if confAttr == ""
then confPath
else (import confPath).${confAttr};
pkgs = pkgs;
check = check;
};
newsReadIds =
if newsReadIdsFile == null
then {}
else
let
ids = splitString "\n" (fileContents newsReadIdsFile);
in
builtins.listToAttrs (map (id: { name = id; value = null; }) ids);
newsIsRead = entry: builtins.hasAttr entry.id newsReadIds;
newsFiltered =
let
pred = entry: entry.condition && ! newsIsRead entry;
in
filter pred env.newsEntries;
newsNumUnread = length newsFiltered;
newsFileUnread = pkgs.writeText "news-unread.txt" (
concatMapStringsSep "\n\n" (entry:
let
time = replaceStrings ["T"] [" "] (removeSuffix "+00:00" entry.time);
in
''
* ${time}
${replaceStrings ["\n"] ["\n "] entry.message}
''
) newsFiltered
);
newsFileAll = pkgs.writeText "news-all.txt" (
concatMapStringsSep "\n\n" (entry:
let
flag = if newsIsRead entry then "read" else "unread";
time = replaceStrings ["T"] [" "] (removeSuffix "+00:00" entry.time);
in
''
* ${time} [${flag}]
${replaceStrings ["\n"] ["\n "] entry.message}
''
) env.newsEntries
);
# File where each line corresponds to an unread news entry
# identifier. If non-empty then the file ends in "\n".
newsUnreadIdsFile = pkgs.writeText "news-unread-ids" (
let
text = concatMapStringsSep "\n" (entry: entry.id) newsFiltered;
in
text + optionalString (text != "") "\n"
);
newsInfo = pkgs.writeText "news-info.sh" ''
local newsNumUnread=${toString newsNumUnread}
local newsDisplay="${env.newsDisplay}"
local newsFileAll="${newsFileAll}"
local newsFileUnread="${newsFileUnread}"
local newsUnreadIdsFile="${newsUnreadIdsFile}"
'';
in
{
inherit (env) activationPackage;
inherit newsInfo;
}

56
home-manager/install.nix Normal file
View File

@@ -0,0 +1,56 @@
{ home-manager, pkgs }:
pkgs.runCommand
"home-manager-install"
{
propagatedBuildInputs = [ home-manager ];
preferLocalBuild = true;
allowSubstitutes = false;
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
echo
echo "Creating initial Home Manager generation..."
echo
if home-manager switch; then
cat <<EOF
All done! The home-manager tool should now be installed and you
can edit
$confFile
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
https://github.com/rycee/home-manager/issues
if the error seems to be the fault of Home Manager.
EOF
exit 1
fi
'';
}
""

414
modules/accounts/email.nix Normal file
View File

@@ -0,0 +1,414 @@
{ config, lib, ... }:
with lib;
let
cfg = config.accounts.email;
gpgModule = types.submodule {
options = {
key = mkOption {
type = types.str;
description = ''
The key to use as listed in <command>gpg --list-keys</command>.
'';
};
signByDefault = mkOption {
type = types.bool;
default = false;
description = "Sign messages by default.";
};
encryptByDefault = mkOption {
type = types.bool;
default = false;
description = "Encrypt outgoing messages by default.";
};
};
};
signatureModule = types.submodule {
options = {
text = mkOption {
type = types.str;
default = "";
example = ''
--
Luke Skywalker
May the force be with you.
'';
description = ''
Signature content.
'';
};
showSignature = mkOption {
type = types.enum [ "append" "attach" "none" ];
default = "none";
description = "Method to communicate the signature.";
};
};
};
tlsModule = types.submodule {
options = {
enable = mkOption {
type = types.bool;
default = true;
description = ''
Whether to enable TLS/SSL.
'';
};
useStartTls = mkOption {
type = types.bool;
default = false;
description = ''
Whether to use STARTTLS.
'';
};
certificatesFile = mkOption {
type = types.path;
default = config.accounts.email.certificatesFile;
defaultText = "config.accounts.email.certificatesFile";
description = ''
Path to file containing certificate authorities that should
be used to validate the connection authenticity. If
<literal>null</literal> then the system default is used.
Note, if set then the system default may still be accepted.
'';
};
};
};
imapModule = types.submodule {
options = {
host = mkOption {
type = types.str;
example = "imap.example.org";
description = ''
Hostname of IMAP server.
'';
};
port = mkOption {
type = types.nullOr types.ints.positive;
default = null;
example = 993;
description = ''
The port on which the IMAP server listens. If
<literal>null</literal> then the default port is used.
'';
};
tls = mkOption {
type = tlsModule;
default = {};
description = ''
Configuration for secure connections.
'';
};
};
};
smtpModule = types.submodule {
options = {
host = mkOption {
type = types.str;
example = "smtp.example.org";
description = ''
Hostname of SMTP server.
'';
};
port = mkOption {
type = types.nullOr types.ints.positive;
default = null;
example = 465;
description = ''
The port on which the SMTP server listens. If
<literal>null</literal> then the default port is used.
'';
};
tls = mkOption {
type = tlsModule;
default = {};
description = ''
Configuration for secure connections.
'';
};
};
};
maildirModule = types.submodule ({ config, ... }: {
options = {
path = mkOption {
type = types.str;
description = ''
Path to maildir directory where mail for this account is
stored. This is relative to the base maildir path.
'';
};
absPath = mkOption {
type = types.path;
readOnly = true;
internal = true;
default = "${cfg.maildirBasePath}/${config.path}";
description = ''
A convenience option whose value is the absolute path of
this maildir.
'';
};
};
});
mailAccountOpts = { name, config, ... }: {
options = {
name = mkOption {
type = types.str;
readOnly = true;
description = ''
Unique identifier of the account. This is set to the
attribute name of the account configuration.
'';
};
primary = mkOption {
type = types.bool;
default = false;
description = ''
Whether this is the primary account. Only one account may be
set as primary.
'';
};
flavor = mkOption {
type = types.enum [ "plain" "gmail.com" "runbox.com" ];
default = "plain";
description = ''
Some email providers have peculiar behavior that require
special treatment. This option is therefore intended to
indicate the nature of the provider.
</para><para>
When this indicates a specific provider then, for example,
the IMAP and SMTP server configuration may be set
automatically.
'';
};
address = mkOption {
type = types.strMatching ".*@.*";
example = "jane.doe@example.org";
description = "The email address of this account.";
};
realName = mkOption {
type = types.str;
example = "Jane Doe";
description = "Name displayed when sending mails.";
};
userName = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
The server username of this account. This will be used as
the SMTP and IMAP user name.
'';
};
passwordCommand = mkOption {
type = types.nullOr (types.either types.str (types.listOf types.str));
default = null;
apply = p: if isString p then splitString " " p else p;
example = "secret-tool lookup email me@example.org";
description = ''
A command, which when run writes the account password on
standard output.
'';
};
folders = mkOption {
type = types.submodule {
options = {
inbox = mkOption {
type = types.str;
default = "Inbox";
description = ''
Relative path of the inbox mail.
'';
};
sent = mkOption {
type = types.nullOr types.str;
default = "Sent";
description = ''
Relative path of the sent mail folder.
'';
};
drafts = mkOption {
type = types.str;
default = "Drafts";
description = ''
Relative path of the drafts mail folder.
'';
};
trash = mkOption {
type = types.str;
default = "Trash";
description = ''
Relative path of the deleted mail folder.
'';
};
};
};
default = {};
description = ''
Standard email folders.
'';
};
imap = mkOption {
type = types.nullOr imapModule;
default = null;
description = ''
The IMAP configuration to use for this account.
'';
};
signature = mkOption {
type = signatureModule;
default = {};
description = ''
Signature configuration.
'';
};
gpg = mkOption {
type = types.nullOr gpgModule;
default = null;
description = ''
GPG configuration.
'';
};
smtp = mkOption {
type = types.nullOr smtpModule;
default = null;
description = ''
The SMTP configuration to use for this account.
'';
};
maildir = mkOption {
type = types.nullOr maildirModule;
defaultText = { path = "\${name}"; };
description = ''
Maildir configuration for this account.
'';
};
};
config = mkMerge [
{
name = name;
maildir = mkOptionDefault { path = "${name}"; };
}
(mkIf (config.flavor == "gmail.com") {
userName = mkDefault config.address;
imap = {
host = "imap.gmail.com";
};
smtp = {
host = "smtp.gmail.com";
port = if config.smtp.tls.useStartTls then 587 else 465;
};
})
(mkIf (config.flavor == "runbox.com") {
imap = {
host = "mail.runbox.com";
};
smtp = {
host = "mail.runbox.com";
};
})
];
};
in
{
options.accounts.email = {
certificatesFile = mkOption {
type = types.path;
default = "/etc/ssl/certs/ca-certificates.crt";
description = ''
Path to default file containing certificate authorities that
should be used to validate the connection authenticity. This
path may be overridden on a per-account basis.
'';
};
maildirBasePath = mkOption {
type = types.str;
default = "${config.home.homeDirectory}/Maildir";
defaultText = "$HOME/Maildir";
apply = p:
if hasPrefix "/" p
then p
else "${config.home.homeDirectory}/${p}";
description = ''
The base directory for account maildir directories. May be a
relative path, in which case it is relative the home
directory.
'';
};
accounts = mkOption {
type = types.attrsOf (types.submodule [
mailAccountOpts
(import ../programs/alot-accounts.nix)
(import ../programs/astroid-accounts.nix)
(import ../programs/mbsync-accounts.nix)
(import ../programs/msmtp-accounts.nix)
(import ../programs/notmuch-accounts.nix)
(import ../programs/offlineimap-accounts.nix)
]);
default = {};
description = "List of email accounts.";
};
};
config = mkIf (cfg.accounts != {}) {
assertions = [
(
let
primaries =
catAttrs "name"
(filter (a: a.primary)
(attrValues cfg.accounts));
in
{
assertion = length primaries == 1;
message =
"Must have exactly one primary mail account but found "
+ toString (length primaries)
+ optionalString (length primaries > 1)
(", namely " + concatStringsSep ", " primaries);
}
)
];
};
}

View File

@@ -1,46 +1,15 @@
{ configuration
, pkgs
, lib ? pkgs.stdenv.lib
# Whether to check that each option has a matching declaration.
, check ? true
}:
with lib;
let
modules = [
./home-environment.nix
./manual.nix
./misc/gtk.nix
./misc/pam.nix
./programs/bash.nix
./programs/beets.nix
./programs/eclipse.nix
./programs/emacs.nix
./programs/firefox.nix
./programs/git.nix
./programs/gnome-terminal.nix
./programs/info.nix
./programs/lesspipe.nix
./programs/ssh.nix
./programs/texlive.nix
./services/dunst.nix
./services/gnome-keyring.nix
./services/gpg-agent.nix
./services/keepassx.nix
./services/network-manager-applet.nix
./services/random-background.nix
./services/redshift.nix
./services/taffybar.nix
./services/tahoe-lafs.nix
./services/udiskie.nix
./services/xscreensaver.nix
./systemd.nix
./xresources.nix
./xsession.nix
<nixpkgs/nixos/modules/misc/assertions.nix>
<nixpkgs/nixos/modules/misc/meta.nix>
];
collectFailed = cfg:
map (x: x.message) (filter (x: !x.assertion) cfg.assertions);
@@ -50,23 +19,22 @@ let
in
fold f res res.config.warnings;
pkgsModule = {
config._module.args.pkgs = lib.mkForce pkgs;
config._module.args.baseModules = modules;
rawModule = lib.evalModules {
modules =
[ configuration ]
++ (import ./modules.nix { inherit check lib pkgs; });
specialArgs = {
modulesPath = builtins.toString ./.;
};
};
module = showWarnings (
let
mod = lib.evalModules {
modules = [ configuration ] ++ modules ++ [ pkgsModule ];
};
failed = collectFailed mod.config;
failed = collectFailed rawModule.config;
failedStr = concatStringsSep "\n" (map (x: "- ${x}") failed);
in
if failed == []
then mod
then rawModule
else throw "\nFailed assertions:\n${failedStr}"
);
@@ -75,6 +43,14 @@ in
{
inherit (module) options config;
activationPackage = module.config.home.activationPackage;
# For backwards compatibility. Please use activationPackage instead.
activation-script = module.config.home.activationPackage;
home-path = module.config.home.path;
newsDisplay = rawModule.config.news.display;
newsEntries =
sort (a: b: a.time > b.time) (
filter (a: a.condition) rawModule.config.news.entries
);
}

283
modules/files.nix Normal file
View File

@@ -0,0 +1,283 @@
{ pkgs, config, lib, ... }:
with lib;
let
cfg = config.home.file;
dag = config.lib.dag;
homeDirectory = config.home.homeDirectory;
fileType = (import lib/file-type.nix {
inherit homeDirectory lib pkgs;
}).fileType;
sourceStorePath = file:
let
sourcePath = toString file.source;
sourceName = config.lib.strings.storeFileName (baseNameOf sourcePath);
in
if builtins.hasContext sourcePath
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
{
options = {
home.file = mkOption {
description = "Attribute set of files to link into the user home.";
default = {};
type = fileType "<envar>HOME</envar>" homeDirectory;
};
home-files = mkOption {
type = types.package;
internal = true;
description = "Package to contain all home files";
};
};
config = {
# This verifies that the links we are about to create will not
# overwrite an existing file.
home.activation.checkLinkTargets = dag.entryBefore ["writeBoundary"] (
let
check = pkgs.writeText "check" ''
. ${./lib-bash/color-echo.sh}
newGenFiles="$1"
shift
for sourcePath in "$@" ; do
relativePath="''${sourcePath#$newGenFiles/}"
targetPath="$HOME/$relativePath"
if [[ -e "$targetPath" \
&& ! "$(readlink "$targetPath")" == ${homeFilePattern} ]] ; then
errorEcho "Existing file '$targetPath' is in the way"
collision=1
fi
done
if [[ -v collision ]] ; then
errorEcho "Please move the above files and try again"
exit 1
fi
'';
in
''
function checkNewGenCollision() {
local newGenFiles
newGenFiles="$(readlink -e "$newGenPath/home-files")"
find "$newGenFiles" -type f -print0 -or -type l -print0 \
| xargs -0 bash ${check} "$newGenFiles"
}
checkNewGenCollision || exit 1
''
);
# This activation script will
#
# 1. Remove files from the old generation that are not in the new
# generation.
#
# 2. Switch over the Home Manager gcroot and current profile
# links.
#
# 3. Symlink files from the new generation into $HOME.
#
# This order is needed to ensure that we always know which links
# belong to which generation. Specifically, if we're moving from
# generation A to generation B having sets of home file links FA
# and FB, respectively then cleaning before linking produces state
# transitions similar to
#
# FA → FA ∩ FB → (FA ∩ FB) FB = FB
#
# 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"] (
let
link = pkgs.writeText "link" ''
newGenFiles="$1"
shift
for sourcePath in "$@" ; do
relativePath="''${sourcePath#$newGenFiles/}"
targetPath="$HOME/$relativePath"
$DRY_RUN_CMD mkdir -p $VERBOSE_ARG "$(dirname "$targetPath")"
$DRY_RUN_CMD ln -nsf $VERBOSE_ARG "$sourcePath" "$targetPath"
done
'';
cleanup = pkgs.writeText "cleanup" ''
. ${./lib-bash/color-echo.sh}
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
warnEcho "Path '$targetPath' not link into Home Manager generation. Skipping delete."
else
$VERBOSE_ECHO "Checking $targetPath: gone (deleting)"
$DRY_RUN_CMD rm $VERBOSE_ARG "$targetPath"
# Recursively delete empty parent directories.
targetDir="$(dirname "$relativePath")"
if [[ "$targetDir" != "." ]] ; then
pushd "$HOME" > /dev/null
# Call rmdir with a relative path excluding $HOME.
# Otherwise, it might try to delete $HOME and exit
# with a permission error.
$DRY_RUN_CMD rmdir $VERBOSE_ARG \
-p --ignore-fail-on-non-empty \
"$targetDir"
popd > /dev/null
fi
fi
done
'';
in
''
function linkNewGen() {
echo "Creating home file links in $HOME"
local newGenFiles
newGenFiles="$(readlink -e "$newGenPath/home-files")"
find "$newGenFiles" -type f -print0 -or -type l -print0 \
| xargs -0 bash ${link} "$newGenFiles"
}
function cleanOldGen() {
if [[ ! -v oldGenPath ]] ; then
return
fi
echo "Cleaning up orphan links from $HOME"
local newGenFiles oldGenFiles
newGenFiles="$(readlink -e "$newGenPath/home-files")"
oldGenFiles="$(readlink -e "$oldGenPath/home-files")"
# Apply the cleanup script on each leaf in the old
# generation. The find command below will print the
# relative path of the entry.
find "$oldGenFiles" '(' -type f -or -type l ')' -printf '%P\0' \
| xargs -0 bash ${cleanup} "$newGenFiles"
}
cleanOldGen
if [[ ! -v oldGenPath || "$oldGenPath" != "$newGenPath" ]] ; then
echo "Creating profile generation $newGenNum"
$DRY_RUN_CMD ln -Tsf $VERBOSE_ARG "$newGenPath" "$newGenProfilePath"
$DRY_RUN_CMD ln -Tsf $VERBOSE_ARG $(basename "$newGenProfilePath") "$genProfilePath"
$DRY_RUN_CMD ln -Tsf $VERBOSE_ARG "$newGenPath" "$newGenGcPath"
else
echo "No change so reusing latest profile generation $oldGenNum"
fi
linkNewGen
''
);
home.activation.checkFilesChanged = dag.entryBefore ["linkGeneration"] (
''
declare -A changedFiles
'' + concatMapStrings (v: ''
cmp --quiet "${sourceStorePath v}" "${homeDirectory}/${v.target}" \
&& changedFiles["${v.target}"]=0 \
|| changedFiles["${v.target}"]=1
'') (filter (v: v.onChange != "") (attrValues cfg))
);
home.activation.onFilesChange = dag.entryAfter ["linkGeneration"] (
concatMapStrings (v: ''
if [[ ${"$\{changedFiles"}["${v.target}"]} -eq 1 ]]; then
${v.onChange}
fi
'') (filter (v: v.onChange != "") (attrValues cfg))
);
# Symlink directories and files that have the right execute bit.
# Copy files that need their execute bit changed.
home-files = pkgs.runCommand
"home-manager-files"
{
nativeBuildInputs = [ pkgs.xlibs.lndir ];
preferLocalBuild = true;
allowSubstitutes = false;
}
(''
mkdir -p $out
function insertFile() {
local source="$1"
local relTarget="$2"
local executable="$3"
local recursive="$4"
# Figure out the real absolute path to the target.
local target
target="$(realpath -m "$out/$relTarget")"
# Target path must be within $HOME.
if [[ ! $target == $out* ]] ; then
echo "Error installing file '$relTarget' outside \$HOME" >&2
exit 1
fi
mkdir -p "$(dirname "$target")"
if [[ -d $source ]]; then
if [[ $recursive ]]; then
mkdir -p "$target"
lndir -silent "$source" "$target"
else
ln -s "$source" "$target"
fi
else
[[ -x $source ]] && isExecutable=1 || isExecutable=""
# Link the file into the home file directory if possible,
# i.e., if the executable bit of the source is the same we
# expect for the target. Otherwise, we copy the file and
# set the executable bit to the expected value.
if [[ $executable == inherit || $isExecutable == $executable ]]; then
ln -s "$source" "$target"
else
cp "$source" "$target"
if [[ $executable == inherit ]]; then
# Don't change file mode if it should match the source.
:
elif [[ $executable ]]; then
chmod +x "$target"
else
chmod -x "$target"
fi
fi
fi
}
'' + concatStrings (
mapAttrsToList (n: v: ''
insertFile "${sourceStorePath v}" \
"${v.target}" \
"${if v.executable == null
then "inherit"
else builtins.toString v.executable}" \
"${builtins.toString v.recursive}"
'') cfg
));
};
}

View File

@@ -1,12 +1,13 @@
{ config, lib, pkgs, ... }:
with lib;
with import ./lib/dag.nix;
let
cfg = config.home;
dag = config.lib.dag;
languageSubModule = types.submodule {
options = {
base = mkOption {
@@ -93,53 +94,42 @@ let
in
{
meta.maintainers = [ maintainers.rycee ];
imports = [
(mkRemovedOptionModule [ "home" "sessionVariableSetter" ] ''
Session variables are now always set through the shell. This is
done automatically if the shell configuration is managed by Home
Manager. If not, then you must source the
~/.nix-profile/etc/profile.d/hm-session-vars.sh
file yourself.
'')
];
options = {
home.file = mkOption {
description = "Attribute set of files to link into the user home.";
default = {};
type = types.loaOf (types.submodule (
{ name, config, ... }: {
options = {
target = mkOption {
type = types.str;
description = ''
Path to target file relative to <envar>HOME</envar>.
'';
};
home.username = mkOption {
type = types.str;
defaultText = "$USER";
description = "The user's username.";
};
text = mkOption {
default = null;
type = types.nullOr types.lines;
description = "Text of the file.";
};
home.homeDirectory = mkOption {
type = types.path;
defaultText = "$HOME";
description = "The user's home directory.";
};
source = mkOption {
type = types.path;
description = ''
Path of the source file. The file name must not start
with a period since Nix will not allow such names in
the Nix store.
</para><para>
This may refer to a directory.
'';
};
mode = mkOption {
type = types.str;
default = "444";
description = "The permissions to apply to the file.";
};
};
config = {
target = mkDefault name;
source = mkIf (config.text != null) (
let name' = "user-etc-" + baseNameOf name;
in mkDefault (pkgs.writeText name' config.text)
);
};
})
);
home.profileDirectory = mkOption {
type = types.path;
defaultText = "~/.nix-profile";
internal = true;
readOnly = true;
description = ''
The profile directory where Home Manager generations are
installed.
'';
};
home.language = mkOption {
@@ -149,9 +139,12 @@ in
};
home.keyboard = mkOption {
type = keyboardSubModule;
type = types.nullOr keyboardSubModule;
default = {};
description = "Keyboard configuration.";
description = ''
Keyboard configuration. Set to <literal>null</literal> to
disable Home Manager keyboard management.
'';
};
home.sessionVariables = mkOption {
@@ -160,22 +153,34 @@ in
example = { EDITOR = "emacs"; GS_OPTIONS = "-sPAPERSIZE=a4"; };
description = ''
Environment variables to always set at login.
'';
};
home.sessionVariableSetter = mkOption {
default = "bash";
type = types.enum [ "pam" "bash" ];
example = "pam";
description = ''
Identifies the module that should set the session variables.
</para><para>
If "bash" is set then <varname>config.bash.enable</varname>
must also be enabled.
The values may refer to other environment variables using
POSIX.2 style variable references. For example, a variable
<varname>parameter</varname> may be referenced as
<code>$parameter</code> or <code>''${parameter}</code>. A
default value <literal>foo</literal> may be given as per
<code>''${parameter:-foo}</code> and, similarly, an alternate
value <literal>bar</literal> can be given as per
<code>''${parameter:+bar}</code>.
</para><para>
If "pam" is set then PAM must be used to set the system
environment. Also mind that typical environment variables
might not be set by the time PAM starts up.
Note, these variables may be set in any order so no session
variable may have a runtime dependency on another session
variable. In particular code like
<programlisting language="nix">
home.sessionVariables = {
FOO = "Hello";
BAR = "$FOO World!";
};
</programlisting>
may not work as expected. If you need to reference another
session variable, then do so inside Nix instead. The above
example then becomes
<programlisting language="nix">
home.sessionVariables = {
FOO = "Hello";
BAR = "''${config.home.sessionVariables.FOO} World!";
};
</programlisting>
'';
};
@@ -185,11 +190,33 @@ in
description = "The set of packages to appear in the user environment.";
};
home.extraOutputsToInstall = mkOption {
type = types.listOf types.str;
default = [];
example = [ "doc" "info" "devdoc" ];
description = ''
List of additional package outputs of the packages
<varname>home.packages</varname> that should be installed into
the user environment.
'';
};
home.path = mkOption {
internal = true;
description = "The derivation installing the user packages.";
};
home.emptyActivationPath = mkOption {
internal = true;
default = false;
type = types.bool;
description = ''
Whether the activation script should start with an empty
<envvar>PATH</envvar> variable. When <literal>false</literal>
then the user's <envvar>PATH</envvar> will be used.
'';
};
home.activation = mkOption {
internal = true;
default = {};
@@ -210,27 +237,50 @@ in
type = types.package;
description = "The package containing the complete activation script.";
};
home.extraBuilderCommands = mkOption {
type = types.lines;
default = "";
internal = true;
description = ''
Extra commands to run in the Home Manager generation builder.
'';
};
home.extraProfileCommands = mkOption {
type = types.lines;
default = "";
internal = true;
description = ''
Extra commands to run in the Home Manager profile builder.
'';
};
};
config = {
assertions = [
(let
badFiles =
filter (f: hasPrefix "." (baseNameOf f))
(map (v: toString v.source)
(attrValues cfg.file));
badFilesStr = toString badFiles;
in
{
assertion = badFiles == [];
message = "Source file names must not start with '.': ${badFilesStr}";
})
{
assertion = config.home.username != "";
message = "Username could not be determined";
}
{
assertion = config.home.homeDirectory != "";
message = "Home directory could not be determined";
}
];
home.username = mkDefault (builtins.getEnv "USER");
home.homeDirectory = mkDefault (builtins.getEnv "HOME");
home.profileDirectory =
if config.submoduleSupport.enable
&& config.submoduleSupport.externalPackageInstall
then config.home.path
else cfg.homeDirectory + "/.nix-profile";
home.sessionVariables =
let
maybeSet = name: value:
listToAttrs (optional (value != null) { inherit name value; });
maybeSet = n: v: optionalAttrs (v != null) { ${n} = v; };
in
(maybeSet "LANG" cfg.language.base)
//
@@ -242,132 +292,63 @@ in
//
(maybeSet "LC_TIME" cfg.language.time);
home.packages = [
# Provide a file holding all session variables.
(
pkgs.writeTextFile {
name = "hm-session-vars.sh";
destination = "/etc/profile.d/hm-session-vars.sh";
text = ''
# Only source this once.
if [ -n "$__HM_SESS_VARS_SOURCED" ]; then return; fi
export __HM_SESS_VARS_SOURCED=1
${config.lib.shell.exportAll cfg.sessionVariables}
'';
}
)
];
# A dummy entry acting as a boundary between the activation
# script's "check" and the "write" phases.
home.activation.writeBoundary = dagEntryAnywhere "";
home.activation.writeBoundary = dag.entryAnywhere "";
# This verifies that the links we are about to create will not
# overwrite an existing file.
home.activation.checkLinkTargets = dagEntryBefore ["writeBoundary"] (
let
pattern = "-home-manager-files/";
check = pkgs.writeText "check" ''
. ${./lib-bash/color-echo.sh}
newGenFiles="$1"
shift
for sourcePath in "$@" ; do
relativePath="''${sourcePath#$newGenFiles/}"
targetPath="$HOME/$relativePath"
if [[ -e "$targetPath" \
&& ! "$(readlink -e "$targetPath")" =~ "${pattern}" ]] ; then
errorEcho "Existing file '$targetPath' is in the way"
collision=1
fi
done
if [[ -v collision ]] ; then
errorEcho "Please move the above files and try again"
exit 1
fi
'';
in
''
function checkNewGenCollision() {
local newGenFiles
newGenFiles="$(readlink -e "$newGenPath/home-files")"
find "$newGenFiles" -type f -print0 -or -type l -print0 \
| xargs -0 bash ${check} "$newGenFiles"
}
checkNewGenCollision || exit 1
''
);
home.activation.linkGeneration = dagEntryAfter ["writeBoundary"] (
let
pattern = "-home-manager-files/";
link = pkgs.writeText "link" ''
newGenFiles="$1"
shift
for sourcePath in "$@" ; do
relativePath="''${sourcePath#$newGenFiles/}"
targetPath="$HOME/$relativePath"
$DRY_RUN_CMD mkdir -p $VERBOSE_ARG "$(dirname "$targetPath")"
$DRY_RUN_CMD ln -nsf $VERBOSE_ARG "$sourcePath" "$targetPath"
done
'';
cleanup = pkgs.writeText "cleanup" ''
. ${./lib-bash/color-echo.sh}
newGenFiles="$1"
oldGenFiles="$2"
shift 2
for sourcePath in "$@" ; do
relativePath="''${sourcePath#$oldGenFiles/}"
targetPath="$HOME/$relativePath"
if [[ -e "$newGenFiles/$relativePath" ]] ; then
$VERBOSE_ECHO "Checking $targetPath exists"
elif [[ ! "$(readlink -e "$targetPath")" =~ "${pattern}" ]] ; then
warnEcho "Path '$targetPath' not link into Home Manager generation. Skipping delete."
else
echo "Checking $targetPath gone (deleting)"
$DRY_RUN_CMD rm $VERBOSE_ARG "$targetPath"
$DRY_RUN_CMD rmdir --ignore-fail-on-non-empty \
$VERBOSE_ARG -p "$(dirname "$targetPath")"
fi
done
'';
in
# Install packages to the user environment.
#
# Note, sometimes our target may not allow modification of the Nix
# store and then we cannot rely on `nix-env -i`. This is the case,
# for example, if we are running as a NixOS module and building a
# virtual machine. Then we must instead rely on an external
# mechanism for installing packages, which in NixOS is provided by
# the `users.users.<name?>.packages` option. The activation
# command is still needed since some modules need to run their
# activation commands after the packages are guaranteed to be
# installed.
#
# 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"] (
if config.submoduleSupport.externalPackageInstall
then
''
function linkNewGen() {
local newGenFiles
newGenFiles="$(readlink -e "$newGenPath/home-files")"
find "$newGenFiles" -type f -print0 -or -type l -print0 \
| xargs -0 bash ${link} "$newGenFiles"
}
function cleanOldGen() {
if [[ ! -v oldGenPath ]] ; then
return
fi
echo "Cleaning up orphan links from $HOME"
local newGenFiles oldGenFiles
newGenFiles="$(readlink -e "$newGenPath/home-files")"
oldGenFiles="$(readlink -e "$oldGenPath/home-files")"
find "$oldGenFiles" -type f -print0 -or -type l -print0 \
| xargs -0 bash ${cleanup} "$newGenFiles" "$oldGenFiles"
}
if [[ ! -v oldGenPath || "$oldGenPath" != "$newGenPath" ]] ; then
echo "Creating profile generation $newGenNum"
$DRY_RUN_CMD ln -Tsf $VERBOSE_ARG "$newGenPath" "$newGenProfilePath"
$DRY_RUN_CMD ln -Tsf $VERBOSE_ARG "$newGenProfilePath" "$genProfilePath"
$DRY_RUN_CMD ln -Tsf $VERBOSE_ARG "$newGenPath" "$newGenGcPath"
else
echo "No change so reusing latest profile generation $oldGenNum"
if nix-env -q | grep '^home-manager-path$'; then
$DRY_RUN_CMD nix-env -e home-manager-path
fi
linkNewGen
cleanOldGen
''
else
''
$DRY_RUN_CMD nix-env -i ${cfg.path}
''
);
home.activation.installPackages = dagEntryAfter ["writeBoundary"] ''
$DRY_RUN_CMD nix-env -i ${cfg.path}
'';
home.activationPackage =
let
mkCmd = res: ''
noteEcho Activating ${res.name}
${res.data}
'';
sortedCommands = dagTopoSort cfg.activation;
sortedCommands = dag.topoSort cfg.activation;
activationCmds =
if sortedCommands ? result then
concatStringsSep "\n" (map mkCmd sortedCommands.result)
@@ -375,16 +356,28 @@ in
abort ("Dependency cycle in activation script: "
+ builtins.toJSON sortedCommands);
sf = pkgs.writeText "activation-script" ''
# Programs that always should be available on the activation
# script's PATH.
activationBinPaths = lib.makeBinPath [
pkgs.bash
pkgs.coreutils
pkgs.diffutils # For `cmp` and `diff`.
pkgs.findutils
pkgs.gnugrep
pkgs.gnused
pkgs.ncurses # For `tput`.
]
+ optionalString (!cfg.emptyActivationPath) "\${PATH:+:}$PATH";
activationScript = pkgs.writeScript "activation-script" ''
#!${pkgs.stdenv.shell}
set -eu
set -o pipefail
# This code explicitly requires GNU Core Utilities and Bash.
# We therefore need to ensure they are prioritized over any
# other similarly named tools on the system.
export PATH="${pkgs.coreutils}/bin:${pkgs.bash}/bin:$PATH"
cd $HOME
export PATH="${activationBinPaths}"
. ${./lib-bash/color-echo.sh}
@@ -392,47 +385,34 @@ in
${activationCmds}
'';
home-files = pkgs.stdenv.mkDerivation {
name = "home-manager-files";
phases = [ "installPhase" ];
installPhase =
"mkdir -p $out\n" +
concatStringsSep "\n" (
mapAttrsToList (n: v:
''
if [ -d "${v.source}" ]; then
mkdir -pv "$(dirname "$out/${v.target}")"
ln -sv "${v.source}" "$out/${v.target}"
else
install -D -m${v.mode} "${v.source}" "$out/${v.target}"
fi
''
) cfg.file
);
};
in
pkgs.stdenv.mkDerivation {
name = "home-manager-generation";
pkgs.runCommand
"home-manager-generation"
{
preferLocalBuild = true;
allowSubstitutes = false;
}
''
mkdir -p $out
phases = [ "installPhase" ];
installPhase = ''
install -D -m755 ${sf} $out/activate
cp ${activationScript} $out/activate
substituteInPlace $out/activate \
--subst-var-by GENERATION_DIR $out
ln -s ${home-files} $out/home-files
ln -s ${config.home-files} $out/home-files
ln -s ${cfg.path} $out/home-path
${cfg.extraBuilderCommands}
'';
};
home.path = pkgs.buildEnv {
name = "home-manager-path";
paths = cfg.packages;
inherit (cfg) extraOutputsToInstall;
postBuild = cfg.extraProfileCommands;
meta = {
description = "Environment of packages installed through home-manager";

View File

@@ -1,3 +1,5 @@
#!/usr/bin/env bash
function setupVars() {
local profilesPath="/nix/var/nix/profiles/per-user/$USER"
local gcPath="/nix/var/nix/gcroots/per-user/$USER"
@@ -9,27 +11,38 @@ function setupVars() {
| sort -rn \
| head -1)
if [[ -n "$greatestGenNum" ]] ; then
if [[ -n $greatestGenNum ]] ; then
oldGenNum=$greatestGenNum
newGenNum=$((oldGenNum + 1))
else
newGenNum=1
fi
if [[ -e "$gcPath/current-home" ]] ; then
if [[ -e $gcPath/current-home ]] ; then
oldGenPath="$(readlink -e "$gcPath/current-home")"
fi
$VERBOSE_ECHO "Sanity checking oldGenNum and oldGenPath"
if [[ -v oldGenNum && ! -v oldGenPath
|| ! -v oldGenNum && -v oldGenPath ]]; then
errorEcho "Invalid profile number and GC root values! These must be"
errorEcho "either both empty or both set but are now set to"
errorEcho " '${oldGenNum:-}' and '${oldGenPath:-}'"
errorEcho "If you don't mind losing previous profile generations then"
errorEcho "the easiest solution is probably to run"
errorEcho " rm $profilesPath/home-manager*"
errorEcho " rm $gcPath/current-home"
errorEcho "and trying home-manager switch again. Good luck!"
exit 1
fi
genProfilePath="$profilesPath/home-manager"
newGenPath="@GENERATION_DIR@";
newGenProfilePath="$profilesPath/home-manager-$newGenNum-link"
newGenGcPath="$gcPath/current-home"
}
setupVars
echo "Starting home manager activation"
if [[ -v VERBOSE ]]; then
export VERBOSE_ECHO=echo
export VERBOSE_ARG="--verbose"
@@ -38,14 +51,23 @@ else
export VERBOSE_ARG=""
fi
echo "Starting home manager activation"
setupVars
if [[ -v DRY_RUN ]] ; then
$VERBOSE_ECHO "This is a dry run"
echo "This is a dry run"
export DRY_RUN_CMD=echo
else
$VERBOSE_ECHO "This is a live run"
export DRY_RUN_CMD=""
fi
if [[ -v VERBOSE ]]; then
echo -n "Using Nix version: "
nix-env --version
fi
$VERBOSE_ECHO "Activation variables:"
if [[ -v oldGenNum ]] ; then
$VERBOSE_ECHO " oldGenNum=$oldGenNum"

View File

@@ -7,9 +7,9 @@
# - the addition of the function `dagEntryBefore` indicating a
# "wanted by" relationship.
with import <nixpkgs/lib/strings.nix>;
with import <nixpkgs/lib/attrsets.nix>;
with import <nixpkgs/lib/lists.nix>;
{ lib }:
with lib;
rec {

23
modules/lib/default.nix Normal file
View File

@@ -0,0 +1,23 @@
{ lib }:
{
dag =
let
d = import ./dag.nix { inherit lib; };
in
{
empty = d.emptyDag;
isDag = d.isDag;
topoSort = d.dagTopoSort;
map = d.dagMap;
entryAnywhere = d.dagEntryAnywhere;
entryBetween = d.dagEntryBetween;
entryAfter = d.dagEntryAfter;
entryBefore = d.dagEntryBefore;
};
strings = import ./strings.nix { inherit lib; };
shell = import ./shell.nix { inherit lib; };
zsh = import ./zsh.nix { inherit lib; };
}

102
modules/lib/file-type.nix Normal file
View File

@@ -0,0 +1,102 @@
{ homeDirectory, lib, pkgs }:
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
# is relative the `basePath` argument (which itself must be an
# absolute path).
#
# Arguments:
# - basePathDesc docbook compatible description of the base path
# - basePath the file base path
fileType = basePathDesc: basePath: types.loaOf (types.submodule (
{ name, config, ... }: {
options = {
target = mkOption {
type = types.str;
apply = p:
let
absPath = if hasPrefix "/" p then p else "${basePath}/${p}";
in
removePrefix (homeDirectory + "/") absPath;
description = ''
Path to target file relative to ${basePathDesc}.
'';
};
text = mkOption {
default = null;
type = types.nullOr types.lines;
description = "Text of the file.";
};
source = mkOption {
type = types.path;
description = ''
Path of the source file. The file name must not start
with a period since Nix will not allow such names in
the Nix store.
</para><para>
This may refer to a directory.
'';
};
executable = mkOption {
type = types.nullOr types.bool;
default = null;
description = ''
Set the execute bit. If <literal>null</literal>, defaults to the mode
of the <varname>source</varname> file or to <literal>false</literal>
for files created through the <varname>text</varname> option.
'';
};
recursive = mkOption {
type = types.bool;
default = false;
description = ''
If the file source is a directory, then this option
determines whether the directory should be recursively
linked to the target location. This option has no effect
if the source is a file.
</para><para>
If <literal>false</literal> (the default) then the target
will be a symbolic link to the source directory. If
<literal>true</literal> then the target will be a
directory structure matching the source's but whose leafs
are symbolic links to the files of the source directory.
'';
};
onChange = mkOption {
type = types.lines;
default = "";
description = ''
Shell commands to run when file has changed between
generations. The script will be run
<emphasis>after</emphasis> the new files have been linked
into place.
'';
};
};
config = {
target = mkDefault name;
source = mkIf (config.text != null) (
mkDefault (pkgs.writeTextFile {
inherit (config) executable text;
name = stringsExtra.storeFileName name;
})
);
};
}
));
}

View File

@@ -1,93 +0,0 @@
/* Functions that generate widespread file
* formats from nix data structures.
*
* They all follow a similar interface:
* generator { config-attrs } data
*
* Tests can be found in ./tests.nix
* Documentation in the manual, #sec-generators
*/
with import <nixpkgs/lib/trivial.nix>;
let
libStr = import <nixpkgs/lib/strings.nix>;
libAttr = import <nixpkgs/lib/attrsets.nix>;
flipMapAttrs = flip libAttr.mapAttrs;
in
rec {
/* Generate a line of key k and value v, separated by
* character sep. If sep appears in k, it is escaped.
* Helper for synaxes with different separators.
*
* mkKeyValueDefault ":" "f:oo" "bar"
* > "f\:oo:bar"
*/
mkKeyValueDefault = sep: k: v:
"${libStr.escape [sep] k}${sep}${toString v}";
/* Generate a key-value-style config file from an attrset.
*
* mkKeyValue is the same as in toINI.
*/
toKeyValue = {
mkKeyValue ? mkKeyValueDefault "="
}: attrs:
let mkLine = k: v: mkKeyValue k v + "\n";
in libStr.concatStrings (libAttr.mapAttrsToList mkLine attrs);
/* Generate an INI-style config file from an
* attrset of sections to an attrset of key-value pairs.
*
* generators.toINI {} {
* foo = { hi = "${pkgs.hello}"; ciao = "bar"; };
* baz = { "also, integers" = 42; };
* }
*
*> [baz]
*> also, integers=42
*>
*> [foo]
*> ciao=bar
*> hi=/nix/store/y93qql1p5ggfnaqjjqhxcw0vqw95rlz0-hello-2.10
*
* The mk* configuration attributes can generically change
* the way sections and key-value strings are generated.
*
* For more examples see the test cases in ./tests.nix.
*/
toINI = {
# apply transformations (e.g. escapes) to section names
mkSectionName ? (name: libStr.escape [ "[" "]" ] name),
# format a setting line from key and value
mkKeyValue ? mkKeyValueDefault "="
}: attrsOfAttrs:
let
# map function to string for each key val
mapAttrsToStringsSep = sep: mapFn: attrs:
libStr.concatStringsSep sep
(libAttr.mapAttrsToList mapFn attrs);
mkSection = sectName: sectValues: ''
[${mkSectionName sectName}]
'' + toKeyValue { inherit mkKeyValue; } sectValues;
in
# map input to ini sections
mapAttrsToStringsSep "\n" mkSection attrsOfAttrs;
/* Generates JSON from an arbitrary (non-function) value.
* For more information see the documentation of the builtin.
*/
toJSON = {}: builtins.toJSON;
/* YAML has been a strict superset of JSON since 1.2, so we
* use toJSON. Before it only had a few differences referring
* to implicit typing rules, so it should work with older
* parsers as well.
*/
toYAML = {}@args: toJSON args;
}

11
modules/lib/shell.nix Normal file
View File

@@ -0,0 +1,11 @@
{ lib }:
rec {
# Produces a Bourne shell like variable export statement.
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
# statement for each set entry.
exportAll = vars: lib.concatStringsSep "\n" (lib.mapAttrsToList export vars);
}

27
modules/lib/strings.nix Normal file
View File

@@ -0,0 +1,27 @@
{ lib }:
with lib;
{
# Figures out a valid Nix store name for the given path.
storeFileName = path:
let
# All characters that are considered safe. Note "-" is not
# included to avoid "-" followed by digit being interpreted as a
# version.
safeChars =
[ "+" "." "_" "?" "=" ]
++ lowerChars
++ upperChars
++ stringToCharacters "0123456789";
empties = l: genList (x: "") (length l);
unsafeInName = stringToCharacters (
replaceStrings safeChars (empties safeChars) path
);
safeName = replaceStrings unsafeInName (empties unsafeInName) path;
in
"hm_" + safeName;
}

28
modules/lib/zsh.nix Normal file
View File

@@ -0,0 +1,28 @@
{ lib }:
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}\"";
# Produces a Zsh shell like definition statement
define = n: v: "${n}=${toZshValue v}";
# Given an attribute set containing shell variable names and their
# assignments, this function produces a string containing a definition
# statement for each set entry.
defineAll = vars: lib.concatStringsSep "\n" (lib.mapAttrsToList define vars);
# Produces a Zsh shell like export statement
export = n: v: "export ${define n v}";
# Given an attribute set containing shell variable names and their
# assignments, this function produces a string containing an export
# statement for each set entry.
exportAll = vars: lib.concatStringsSep "\n" (lib.mapAttrsToList export vars);
}

View File

@@ -4,19 +4,21 @@ with lib;
let
cfg = config.manual;
/* For the purpose of generating docs, evaluate options with each derivation
in `pkgs` (recursively) replaced by a fake with path "\${pkgs.attribute.path}".
It isn't perfect, but it seems to cover a vast majority of use cases.
Caveat: even if the package is reached by a different means,
the path above will be shown and not e.g. `${config.services.foo.package}`. */
nixosManual = import <nixpkgs/nixos/doc/manual> {
homeManagerManual = import ../doc {
inherit pkgs config;
version = "0.1";
revision = "release-0.1";
revision = "master";
options =
let
scrubbedEval = evalModules {
modules = [ { nixpkgs.system = pkgs.stdenv.system; } ] ++ baseModules;
modules = [ { nixpkgs.localSystem = config.nixpkgs.localSystem; } ] ++ baseModules;
args = (config._module.args) // { modules = [ ]; };
specialArgs = { pkgs = scrubDerivations "pkgs" pkgs; };
};
@@ -32,18 +34,42 @@ let
in scrubbedEval.options;
};
homeEnvironmentManPages = pkgs.runCommand "home-environment-manpages" {
allowedReferences = [ "out" ];
} ''
install -v -D -m444 \
${nixosManual.manpages}/share/man/man5/configuration.nix.5 \
$out/share/man/man5/home-configuration.nix.5
'';
manualHtmlRoot = "${homeManagerManual.manual}/share/doc/home-manager/index.html";
helpScript = pkgs.writeShellScriptBin "home-manager-help" ''
#!${pkgs.bash}/bin/bash -e
if [ -z "$BROWSER" ]; then
for candidate in xdg-open open w3m; do
BROWSER="$(type -P $candidate || true)"
if [ -x "$BROWSER" ]; then
break;
fi
done
fi
if [ -z "$BROWSER" ]; then
echo "$0: unable to start a web browser; please set \$BROWSER"
exit 1
fi
exec "$BROWSER" ${manualHtmlRoot}
'';
in
{
options = {
manual.html.enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to install the HTML manual. This also installs the
<command>home-manager-help</command> tool, which opens a local
copy of the Home Manager manual in the system web browser.
'';
};
manual.manpages.enable = mkOption {
type = types.bool;
default = true;
@@ -59,10 +85,17 @@ in
};
};
config = mkIf config.manual.manpages.enable {
# To fix error during manpage build.
meta.doc = builtins.toFile "nothingness" "<para></para>";
config = {
home.packages = mkMerge [
(mkIf cfg.html.enable [ helpScript homeManagerManual.manual ])
home.packages = [ homeEnvironmentManPages ];
(mkIf cfg.manpages.enable [ homeManagerManual.manpages ])
];
};
# To fix error during manpage build.
meta = {
maintainers = [ maintainers.rycee ];
doc = builtins.toFile "nothingness" "";
};
}

83
modules/misc/dconf.nix Normal file
View File

@@ -0,0 +1,83 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.dconf;
dag = config.lib.dag;
toDconfIni = generators.toINI { mkKeyValue = mkIniKeyValue; };
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}";
primitive = with types; either bool (either int str);
in
{
meta.maintainers = [ maintainers.gnidorah maintainers.rycee ];
options = {
dconf = {
enable = mkOption {
type = types.bool;
default = true;
visible = false;
description = ''
Whether to enable dconf settings.
'';
};
settings = mkOption {
type = with types;
attrsOf (attrsOf (either primitive (listOf primitive)));
default = {};
example = literalExample ''
{
"org/gnome/calculator" = {
button-mode = "programming";
show-thousands = true;
base = 10;
word-size = 64;
};
}
'';
description = ''
Settings to write to the dconf configuration system.
'';
};
};
};
config = mkIf (cfg.enable && cfg.settings != {}) {
home.activation.dconfSettings = dag.entryAfter ["installPackages"] (
let
iniFile = pkgs.writeText "hm-dconf.ini" (toDconfIni cfg.settings);
in
''
if [[ -v DBUS_SESSION_BUS_ADDRESS ]]; then
DCONF_DBUS_RUN_SESSION=""
else
DCONF_DBUS_RUN_SESSION="${pkgs.dbus}/bin/dbus-run-session"
fi
if [[ -v DRY_RUN ]]; then
echo $DCONF_DBUS_RUN_SESSION ${pkgs.gnome3.dconf}/bin/dconf load / "<" ${iniFile}
else
$DCONF_DBUS_RUN_SESSION ${pkgs.gnome3.dconf}/bin/dconf load / < ${iniFile}
fi
unset DCONF_DBUS_RUN_SESSION
''
);
};
}

View File

@@ -0,0 +1,41 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.fonts.fontconfig;
in
{
meta.maintainers = [ maintainers.rycee ];
options = {
fonts.fontconfig = {
enableProfileFonts = mkOption {
type = types.bool;
default = false;
example = true;
description = ''
Configure fontconfig to discover fonts installed through
<varname>home.packages</varname> and
<command>nix-env</command>.
</para><para>
Note, this is only necessary on non-NixOS systems.
'';
};
};
};
config = mkIf cfg.enableProfileFonts {
xdg.configFile."fontconfig/conf.d/10-nix-profile-fonts.conf".text = ''
<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
<dir>${config.home.profileDirectory}/lib/X11/fonts</dir>
<dir>${config.home.profileDirectory}/share/fonts</dir>
</fontconfig>
'';
};
}

View File

@@ -8,7 +8,7 @@ let
cfg2 = config.gtk.gtk2;
cfg3 = config.gtk.gtk3;
toGtk3Ini = (import ../lib/generators.nix).toINI {
toGtk3Ini = generators.toINI {
mkKeyValue = key: value:
let
value' =
@@ -27,78 +27,115 @@ let
in
"${n} = ${v'}";
fontType = types.submodule {
options = {
package = mkOption {
type = types.nullOr types.package;
default = null;
example = literalExample "pkgs.dejavu_fonts";
description = ''
Package providing the font. This package will be installed
to your profile. If <literal>null</literal> then the font
is assumed to already be available in your profile.
'';
};
name = mkOption {
type = types.str;
example = "DejaVu Sans 8";
description = ''
The family name and size of the font within the package.
'';
};
};
};
themeType = types.submodule {
options = {
package = mkOption {
type = types.nullOr types.package;
default = null;
example = literalExample "pkgs.gnome3.gnome_themes_standard";
description = ''
Package providing the theme. This package will be installed
to your profile. If <literal>null</literal> then the theme
is assumed to already be available in your profile.
'';
};
name = mkOption {
type = types.str;
example = "Adwaita";
description = "The name of the theme within the package.";
};
};
};
in
{
meta.maintainers = [ maintainers.rycee ];
imports = [
(mkRemovedOptionModule ["gtk" "gtk3" "waylandSupport"] ''
This options is not longer needed and can be removed.
'')
];
options = {
gtk = {
enable = mkEnableOption "GTK 2/3 configuration";
fontName = mkOption {
type = types.nullOr types.str;
font = mkOption {
type = types.nullOr fontType;
default = null;
example = "DejaVu Sans 8";
description = ''
The font to use in GTK+ 2/3 applications.
'';
};
themeName = mkOption {
type = types.nullOr types.str;
iconTheme = mkOption {
type = types.nullOr themeType;
default = null;
example = "Vertex-Dark";
description = "The name of the GTK+2/3 theme to use.";
description = "The icon theme to use.";
};
iconThemeName = mkOption {
type = types.nullOr types.str;
theme = mkOption {
type = types.nullOr themeType;
default = null;
example = "Tango";
description = "The name of the icon theme to use.";
description = "The GTK+2/3 theme to use.";
};
gtk2 = mkOption {
description = "Options specific to GTK+ 2";
default = {};
type = types.submodule {
options = {
extraConfig = mkOption {
type = types.lines;
default = "";
example = "gtk-can-change-accels = 1";
description = ''
Extra configuration lines to add verbatim to
<filename>~/.gtkrc-2.0</filename>.
'';
};
};
gtk2 = {
extraConfig = mkOption {
type = types.lines;
default = "";
example = "gtk-can-change-accels = 1";
description = ''
Extra configuration lines to add verbatim to
<filename>~/.gtkrc-2.0</filename>.
'';
};
};
gtk3 = mkOption {
description = "Options specific to GTK+ 3";
default = {};
type = types.submodule {
options = {
extraConfig = mkOption {
type = types.attrs;
default = {};
example = { gtk-cursor-blink = false; gtk-recent-files-limit = 20; };
description = ''
Extra configuration options to add to
<filename>~/.config/gtk-3.0/settings.ini</filename>.
'';
};
gtk3 = {
extraConfig = mkOption {
type = types.attrs;
default = {};
example = { gtk-cursor-blink = false; gtk-recent-files-limit = 20; };
description = ''
Extra configuration options to add to
<filename>~/.config/gtk-3.0/settings.ini</filename>.
'';
};
extraCss = mkOption {
type = types.lines;
default = "";
description = ''
Extra configuration lines to add verbatim to
<filename>~/.config/gtk-3.0/gtk.css</filename>.
'';
};
};
extraCss = mkOption {
type = types.lines;
default = "";
description = ''
Extra configuration lines to add verbatim to
<filename>~/.config/gtk-3.0/gtk.css</filename>.
'';
};
};
};
@@ -107,25 +144,45 @@ in
config = mkIf cfg.enable (
let
ini =
optionalAttrs (cfg.fontName != null)
{ gtk-font-name = cfg.fontName; }
optionalAttrs (cfg.font != null)
{ gtk-font-name = cfg.font.name; }
//
optionalAttrs (cfg.themeName != null)
{ gtk-theme-name = cfg.themeName; }
optionalAttrs (cfg.theme != null)
{ gtk-theme-name = cfg.theme.name; }
//
optionalAttrs (cfg.iconThemeName != null)
{ gtk-icon-theme-name = cfg.iconThemeName; };
optionalAttrs (cfg.iconTheme != null)
{ gtk-icon-theme-name = cfg.iconTheme.name; };
dconfIni =
optionalAttrs (cfg.font != null)
{ font-name = cfg.font.name; }
//
optionalAttrs (cfg.theme != null)
{ gtk-theme = cfg.theme.name; }
//
optionalAttrs (cfg.iconTheme != null)
{ icon-theme = cfg.iconTheme.name; };
optionalPackage = opt:
optional (opt != null && opt.package != null) opt.package;
in
{
home.packages =
optionalPackage cfg.font
++ optionalPackage cfg.theme
++ optionalPackage cfg.iconTheme;
home.file.".gtkrc-2.0".text =
concatStringsSep "\n" (
mapAttrsToList formatGtk2Option ini
) + "\n" + cfg2.extraConfig;
home.file.".config/gtk-3.0/settings.ini".text =
xdg.configFile."gtk-3.0/settings.ini".text =
toGtk3Ini { Settings = ini // cfg3.extraConfig; };
home.file.".config/gtk-3.0/gtk.css".text = cfg3.extraCss;
xdg.configFile."gtk-3.0/gtk.css".text = cfg3.extraCss;
dconf.settings."org/gnome/desktop/interface" = dconfIni;
}
);
}

14
modules/misc/lib.nix Normal file
View File

@@ -0,0 +1,14 @@
{ lib, ... }:
{
options = {
lib = lib.mkOption {
type = lib.types.attrsOf lib.types.attrs;
default = {};
description = ''
This option allows modules to define helper functions,
constants, etc.
'';
};
};
}

1002
modules/misc/news.nix Normal file

File diff suppressed because it is too large Load Diff

153
modules/misc/nixpkgs.nix Normal file
View File

@@ -0,0 +1,153 @@
# Adapted from Nixpkgs.
{ config, lib, pkgs, ... }:
with lib;
let
isConfig = x:
builtins.isAttrs x || builtins.isFunction x;
optCall = f: x:
if builtins.isFunction f
then f x
else f;
mergeConfig = lhs_: rhs_:
let
lhs = optCall lhs_ { inherit pkgs; };
rhs = optCall rhs_ { inherit pkgs; };
in
lhs // rhs //
optionalAttrs (lhs ? packageOverrides) {
packageOverrides = pkgs:
optCall lhs.packageOverrides pkgs //
optCall (attrByPath ["packageOverrides"] ({}) rhs) pkgs;
} //
optionalAttrs (lhs ? perlPackageOverrides) {
perlPackageOverrides = pkgs:
optCall lhs.perlPackageOverrides pkgs //
optCall (attrByPath ["perlPackageOverrides"] ({}) rhs) pkgs;
};
configType = mkOptionType {
name = "nixpkgs-config";
description = "nixpkgs config";
check = x:
let traceXIfNot = c:
if c x then true
else lib.traceSeqN 1 x false;
in traceXIfNot isConfig;
merge = args: fold (def: mergeConfig def.value) {};
};
overlayType = mkOptionType {
name = "nixpkgs-overlay";
description = "nixpkgs overlay";
check = builtins.isFunction;
merge = lib.mergeOneOption;
};
_pkgs = import <nixpkgs> (
filterAttrs (n: v: v != null) config.nixpkgs
);
in
{
options.nixpkgs = {
config = mkOption {
default = null;
example = { allowBroken = true; };
type = types.nullOr configType;
description = ''
The configuration of the Nix Packages collection. (For
details, see the Nixpkgs documentation.) It allows you to set
package configuration options.
</para><para>
If <literal>null</literal>, then configuration is taken from
the fallback location, for example,
<filename>~/.config/nixpkgs/config.nix</filename>.
</para><para>
Note, this option will not apply outside your Home Manager
configuration like when installing manually through
<command>nix-env</command>. If you want to apply it both
inside and outside Home Manager you can put it in a separate
file and include something like
<programlisting language="nix">
nixpkgs.config = import ./nixpkgs-config.nix;
xdg.configFile."nixpkgs/config.nix".source =
./nixpkgs-config.nix;
</programlisting>
in your Home Manager configuration.
'';
};
overlays = mkOption {
default = null;
example = literalExample
''
[ (self: super: {
openssh = super.openssh.override {
hpnSupport = true;
withKerberos = true;
kerberos = self.libkrb5;
};
};
) ]
'';
type = types.nullOr (types.listOf overlayType);
description = ''
List of overlays to use with the Nix Packages collection. (For
details, see the Nixpkgs documentation.) It allows you to
override packages globally. This is a function that takes as
an argument the <emphasis>original</emphasis> Nixpkgs. The
first argument should be used for finding dependencies, and
the second should be used for overriding recipes.
</para><para>
If <literal>null</literal>, then the overlays are taken from
the fallback location, for example,
<filename>~/.config/nixpkgs/overlays</filename>.
</para><para>
Like <varname>nixpkgs.config</varname> this option only
applies within the Home Manager configuration. See
<varname>nixpkgs.config</varname> for a suggested setup that
works both internally and externally.
'';
};
system = mkOption {
type = types.str;
example = "i686-linux";
internal = true;
description = ''
Specifies the Nix platform type for which the user environment
should be built. If unset, it defaults to the platform type of
your host system. Specifying this option is useful when doing
distributed multi-platform deployment, or when building
virtual machines.
'';
};
};
config = {
_module.args = {
pkgs = _pkgs;
pkgs_i686 =
if _pkgs.stdenv.isLinux && _pkgs.stdenv.hostPlatform.isx86
then _pkgs.pkgsi686Linux
else { };
};
};
}

View File

@@ -4,17 +4,33 @@ with lib;
let
homeCfg = config.home;
vars = config.pam.sessionVariables;
in
{
options = {};
meta.maintainers = [ maintainers.rycee ];
config = mkIf (homeCfg.sessionVariableSetter == "pam") {
options = {
pam.sessionVariables = mkOption {
default = {};
type = types.attrs;
example = { EDITOR = "vim"; };
description = ''
Environment variables that will be set for the PAM session.
The variable values must be as described in
<citerefentry>
<refentrytitle>pam_env.conf</refentrytitle>
<manvolnum>5</manvolnum>
</citerefentry>.
'';
};
};
config = mkIf (vars != {}) {
home.file.".pam_environment".text =
concatStringsSep "\n" (
mapAttrsToList (n: v: "${n} OVERRIDE=${v}") homeCfg.sessionVariables
mapAttrsToList (n: v: "${n} OVERRIDE=\"${toString v}\"") vars
) + "\n";
};
}

41
modules/misc/qt.nix Normal file
View File

@@ -0,0 +1,41 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.qt;
dag = config.lib.dag;
in
{
meta.maintainers = [ maintainers.rycee ];
options = {
qt = {
enable = mkEnableOption "Qt 4 and 5 configuration";
useGtkTheme = mkOption {
type = types.bool;
default = false;
description = ''
Whether Qt 4 and 5 should be set up to use the GTK theme
settings.
'';
};
};
};
config = mkIf (cfg.enable && cfg.useGtkTheme) {
home.sessionVariables.QT_QPA_PLATFORMTHEME = "gtk2";
home.packages = [ pkgs.libsForQt5.qtstyleplugins ];
xsession.profileExtra =
"systemctl --user import-environment QT_QPA_PLATFORMTHEME";
home.activation.useGtkThemeInQt4 = dag.entryAfter ["writeBoundary"] ''
$DRY_RUN_CMD ${pkgs.crudini}/bin/crudini $VERBOSE_ARG \
--set "${config.xdg.configHome}/Trolltech.conf" Qt style GTK+
'';
};
}

View File

@@ -0,0 +1,32 @@
{ lib, ... }:
with lib;
{
meta.maintainers = [ maintainers.rycee ];
options.submoduleSupport = {
enable = mkOption {
type = types.bool;
default = false;
internal = true;
description = ''
Whether the Home Manager module system is used as a submodule
in, for example, NixOS or nix-darwin.
'';
};
externalPackageInstall = mkOption {
type = types.bool;
default = false;
internal = true;
description = ''
Whether the packages of <option>home.packages</option> are
installed separately from the Home Manager activation script.
In NixOS, for example, this may be accomplished by installing
the packages through
<option>users.users.&lt;name?&gt;.packages</option>.
'';
};
};
}

24
modules/misc/version.nix Normal file
View File

@@ -0,0 +1,24 @@
{ config, lib, ... }:
with lib;
{
options = {
home.stateVersion = mkOption {
type = types.enum [ "18.09" "19.03" ];
default = "18.09";
description = ''
It is occasionally necessary for Home Manager to change
configuration defaults in a way that is incompatible with
stateful data. This could, for example, include switching the
default data format or location of a file.
</para><para>
The <emphasis>state version</emphasis> indicates which default
settings are in effect and will therefore help avoid breaking
program configurations. Switching to a higher state version
typically requires performing some manual steps, such as data
conversion or moving files.
'';
};
};
}

101
modules/misc/xdg.nix Normal file
View File

@@ -0,0 +1,101 @@
{ options, config, lib, pkgs, ... }:
with lib;
let
cfg = config.xdg;
dag = config.lib.dag;
fileType = (import ../lib/file-type.nix {
inherit (config.home) homeDirectory;
inherit lib pkgs;
}).fileType;
defaultCacheHome = "${config.home.homeDirectory}/.cache";
defaultConfigHome = "${config.home.homeDirectory}/.config";
defaultDataHome = "${config.home.homeDirectory}/.local/share";
getXdgDir = name: fallback:
let
value = builtins.getEnv name;
in
if value != "" then value else fallback;
in
{
options.xdg = {
enable = mkEnableOption "management of XDG base directories";
cacheHome = mkOption {
type = types.path;
defaultText = "~/.cache";
description = ''
Absolute path to directory holding application caches.
'';
};
configFile = mkOption {
type = fileType "<varname>xdg.configHome</varname>" cfg.configHome;
default = {};
description = ''
Attribute set of files to link into the user's XDG
configuration home.
'';
};
configHome = mkOption {
type = types.path;
defaultText = "~/.config";
description = ''
Absolute path to directory holding application configurations.
'';
};
dataFile = mkOption {
type = fileType "<varname>xdg.dataHome</varname>" cfg.dataHome;
default = {};
description = ''
Attribute set of files to link into the user's XDG
data home.
'';
};
dataHome = mkOption {
type = types.path;
defaultText = "~/.local/share";
description = ''
Absolute path to directory holding application data.
'';
};
};
config = mkMerge [
(mkIf cfg.enable {
xdg.cacheHome = mkDefault defaultCacheHome;
xdg.configHome = mkDefault defaultConfigHome;
xdg.dataHome = mkDefault defaultDataHome;
home.sessionVariables = {
XDG_CACHE_HOME = cfg.cacheHome;
XDG_CONFIG_HOME = cfg.configHome;
XDG_DATA_HOME = cfg.dataHome;
};
})
(mkIf (!cfg.enable) {
xdg.cacheHome = getXdgDir "XDG_CACHE_HOME" defaultCacheHome;
xdg.configHome = getXdgDir "XDG_CONFIG_HOME" defaultConfigHome;
xdg.dataHome = getXdgDir "XDG_DATA_HOME" defaultDataHome;
})
{
home.file = mkMerge [ cfg.configFile cfg.dataFile ];
home.activation.xdgCreateCache = dag.entryAfter [ "writeBoundary" ] ''
$DRY_RUN_CMD mkdir $VERBOSE_ARG -m0700 -p "${config.xdg.cacheHome}"
'';
}
];
}

139
modules/modules.nix Normal file
View File

@@ -0,0 +1,139 @@
{ pkgs
, lib
# Whether to enable module type checking.
, check ? true
}:
with lib;
let
hostPlatform = pkgs.stdenv.hostPlatform;
checkPlatform = any (meta.platformMatch pkgs.stdenv.hostPlatform);
loadModule = file: { condition ? true }: {
inherit file condition;
};
allModules = [
(loadModule ./accounts/email.nix { })
(loadModule ./files.nix { })
(loadModule ./home-environment.nix { })
(loadModule ./manual.nix { })
(loadModule ./misc/dconf.nix { })
(loadModule ./misc/fontconfig.nix { })
(loadModule ./misc/gtk.nix { })
(loadModule ./misc/lib.nix { })
(loadModule ./misc/news.nix { })
(loadModule ./misc/nixpkgs.nix { })
(loadModule ./misc/pam.nix { })
(loadModule ./misc/qt.nix { })
(loadModule ./misc/submodule-support.nix { })
(loadModule ./misc/version.nix { })
(loadModule ./misc/xdg.nix { })
(loadModule ./programs/afew.nix { })
(loadModule ./programs/alot.nix { })
(loadModule ./programs/astroid.nix { })
(loadModule ./programs/autorandr.nix { })
(loadModule ./programs/bash.nix { })
(loadModule ./programs/beets.nix { })
(loadModule ./programs/browserpass.nix { })
(loadModule ./programs/chromium.nix { condition = hostPlatform.isLinux; })
(loadModule ./programs/command-not-found/command-not-found.nix { })
(loadModule ./programs/direnv.nix { })
(loadModule ./programs/eclipse.nix { })
(loadModule ./programs/emacs.nix { })
(loadModule ./programs/feh.nix { })
(loadModule ./programs/firefox.nix { })
(loadModule ./programs/fish.nix { })
(loadModule ./programs/fzf.nix { })
(loadModule ./programs/git.nix { })
(loadModule ./programs/gnome-terminal.nix { })
(loadModule ./programs/go.nix { })
(loadModule ./programs/home-manager.nix { })
(loadModule ./programs/htop.nix { })
(loadModule ./programs/info.nix { })
(loadModule ./programs/irssi.nix { })
(loadModule ./programs/jq.nix { })
(loadModule ./programs/lesspipe.nix { })
(loadModule ./programs/man.nix { })
(loadModule ./programs/matplotlib.nix { })
(loadModule ./programs/mbsync.nix { })
(loadModule ./programs/mercurial.nix { })
(loadModule ./programs/msmtp.nix { })
(loadModule ./programs/neovim.nix { })
(loadModule ./programs/newsboat.nix { })
(loadModule ./programs/noti.nix { })
(loadModule ./programs/notmuch.nix { })
(loadModule ./programs/obs-studio.nix { })
(loadModule ./programs/offlineimap.nix { })
(loadModule ./programs/opam.nix { })
(loadModule ./programs/pidgin.nix { })
(loadModule ./programs/rofi.nix { })
(loadModule ./programs/ssh.nix { })
(loadModule ./programs/taskwarrior.nix { })
(loadModule ./programs/termite.nix { })
(loadModule ./programs/texlive.nix { })
(loadModule ./programs/tmux.nix { })
(loadModule ./programs/urxvt.nix { })
(loadModule ./programs/vim.nix { })
(loadModule ./programs/vscode.nix { })
(loadModule ./programs/zathura.nix { })
(loadModule ./programs/zsh.nix { })
(loadModule ./services/blueman-applet.nix { })
(loadModule ./services/compton.nix { })
(loadModule ./services/dunst.nix { })
(loadModule ./services/emacs.nix { condition = hostPlatform.isLinux; })
(loadModule ./services/flameshot.nix { })
(loadModule ./services/gnome-keyring.nix { })
(loadModule ./services/gpg-agent.nix { })
(loadModule ./services/kbfs.nix { })
(loadModule ./services/kdeconnect.nix { })
(loadModule ./services/keepassx.nix { })
(loadModule ./services/keybase.nix { })
(loadModule ./services/mbsync.nix { })
(loadModule ./services/mpd.nix { })
(loadModule ./services/network-manager-applet.nix { })
(loadModule ./services/nextcloud-client.nix { })
(loadModule ./services/owncloud-client.nix { })
(loadModule ./services/parcellite.nix { })
(loadModule ./services/pasystray.nix { })
(loadModule ./services/polybar.nix { })
(loadModule ./services/random-background.nix { })
(loadModule ./services/redshift.nix { })
(loadModule ./services/screen-locker.nix { })
(loadModule ./services/stalonetray.nix { })
(loadModule ./services/status-notifier-watcher.nix { })
(loadModule ./services/syncthing.nix { })
(loadModule ./services/taffybar.nix { })
(loadModule ./services/tahoe-lafs.nix { })
(loadModule ./services/udiskie.nix { })
(loadModule ./services/unclutter.nix { })
(loadModule ./services/window-managers/awesome.nix { })
(loadModule ./services/window-managers/i3.nix { })
(loadModule ./services/window-managers/xmonad.nix { })
(loadModule ./services/xembed-sni-proxy.nix { condition = hostPlatform.isLinux; })
(loadModule ./services/xscreensaver.nix { })
(loadModule ./systemd.nix { })
(loadModule ./xcursor.nix { })
(loadModule ./xresources.nix { })
(loadModule ./xsession.nix { })
(loadModule <nixpkgs/nixos/modules/misc/assertions.nix> { })
(loadModule <nixpkgs/nixos/modules/misc/meta.nix> { })
];
modules = map (getAttr "file") (filter (getAttr "condition") allModules);
pkgsModule = {
config._module.args.baseModules = modules;
config._module.args.pkgs = lib.mkDefault pkgs;
config._module.check = check;
config.lib = import ./lib { inherit lib; };
config.nixpkgs.system = mkDefault pkgs.system;
};
in
modules ++ [ pkgsModule ]

52
modules/programs/afew.nix Normal file
View File

@@ -0,0 +1,52 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.afew;
in
{
options.programs.afew = {
enable = mkEnableOption "the afew initial tagging script for Notmuch";
extraConfig = mkOption {
type = types.lines;
default = ''
[SpamFilter]
[KillThreadsFilter]
[ListMailsFilter]
[ArchiveSentMailsFilter]
[InboxFilter]
'';
example = ''
[SpamFilter]
[Filter.0]
query = from:pointyheaded@boss.com
tags = -new;+boss
message = Message from above
[InboxFilter]
'';
description = ''
Extra lines added to afew configuration file. Available
configuration options are described in the afew manual:
<link xlink:href="https://afew.readthedocs.io/en/latest/configuration.html" />.
'';
};
};
config = mkIf cfg.enable {
home.packages = [ pkgs.afew ];
xdg.configFile."afew/config".text = ''
# Generated by Home Manager.
# See https://afew.readthedocs.io/
${cfg.extraConfig}
'';
};
}

View File

@@ -0,0 +1,32 @@
{ config, lib, ... }:
with lib;
{
options.alot = {
sendMailCommand = mkOption {
type = types.nullOr types.str;
description = ''
Command to send a mail. If msmtp is enabled for the account,
then this is set to
<command>msmtpq --read-envelope-from --read-recipients</command>.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Extra settings to add to this Alot account configuration.
'';
};
};
config = mkIf config.notmuch.enable {
alot.sendMailCommand = mkOptionDefault (
if config.msmtp.enable
then "msmtpq --read-envelope-from --read-recipients"
else null
);
};
}

167
modules/programs/alot.nix Normal file
View File

@@ -0,0 +1,167 @@
# alot config loader is sensitive to leading space !
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.alot;
alotAccounts = filter (a: a.notmuch.enable)
(attrValues config.accounts.email.accounts);
boolStr = v: if v then "True" else "False";
accountStr = account: with account;
concatStringsSep "\n" (
[ "[[${name}]]" ]
++ mapAttrsToList (n: v: n + "=" + v) (
{
address = address;
realname = realName;
sendmail_command =
optionalString (alot.sendMailCommand != null) alot.sendMailCommand;
}
// optionalAttrs (gpg != null) {
gpg_key = gpg.key;
encrypt_by_default = if gpg.encryptByDefault then "all" else "none";
sign_by_default = boolStr gpg.signByDefault;
}
// optionalAttrs (signature.showSignature != "none") {
signature = pkgs.writeText "signature.txt" signature.text;
signature_as_attachment =
boolStr (signature.showSignature == "attach");
}
)
)
+ "\n"
+ alot.extraConfig;
configFile =
let
bindingsToStr = attrSet:
concatStringsSep "\n" (mapAttrsToList (n: v: "${n} = ${v}") attrSet);
in
''
# Generated by Home Manager.
# See http://alot.readthedocs.io/en/latest/configuration/config_options.html
${cfg.extraConfig}
[bindings]
${bindingsToStr cfg.bindings.global}
[[bufferlist]]
${bindingsToStr cfg.bindings.bufferlist}
[[search]]
${bindingsToStr cfg.bindings.search}
[[envelope]]
${bindingsToStr cfg.bindings.envelope}
[[taglist]]
${bindingsToStr cfg.bindings.taglist}
[[thread]]
${bindingsToStr cfg.bindings.thread}
[accounts]
${concatStringsSep "\n\n" (map accountStr alotAccounts)}
'';
in
{
options.programs.alot = {
enable = mkOption {
type = types.bool;
default = false;
example = true;
description = ''
Whether to enable the Alot mail user agent. Alot uses the
Notmuch email system and will therefore be automatically
enabled for each email account that is managed by Notmuch.
'';
};
hooks = mkOption {
type = types.lines;
default = "";
description = ''
Content of the hooks file.
'';
};
bindings = mkOption {
type = types.submodule {
options = {
global = mkOption {
type = types.attrsOf types.str;
default = {};
description = "Global keybindings.";
};
bufferlist = mkOption {
type = types.attrsOf types.str;
default = {};
description = "Bufferlist mode keybindings.";
};
search = mkOption {
type = types.attrsOf types.str;
default = {};
description = "Search mode keybindings.";
};
envelope = mkOption {
type = types.attrsOf types.str;
default = {};
description = "Envelope mode keybindings.";
};
taglist = mkOption {
type = types.attrsOf types.str;
default = {};
description = "Taglist mode keybindings.";
};
thread = mkOption {
type = types.attrsOf types.str;
default = {};
description = "Thread mode keybindings.";
};
};
};
default = {};
description = ''
Keybindings.
'';
};
extraConfig = mkOption {
type = types.lines;
default = ''
auto_remove_unread = True
ask_subject = False
handle_mouse = True
initial_command = "search tag:inbox AND NOT tag:killed"
input_timeout = 0.3
prefer_plaintext = True
thread_indent_replies = 4
'';
description = ''
Extra lines added to alot configuration file.
'';
};
};
config = mkIf cfg.enable {
home.packages = [ pkgs.alot ];
xdg.configFile."alot/config".text = configFile;
xdg.configFile."alot/hooks.py".text =
''
# Generated by Home Manager.
''
+ cfg.hooks;
};
}

View File

@@ -0,0 +1,33 @@
{ config, lib, ... }:
with lib;
{
options.astroid = {
enable = mkEnableOption "Astroid";
sendMailCommand = mkOption {
type = types.str;
description = ''
Command to send a mail. If msmtp is enabled for the account,
then this is set to
<command>msmtpq --read-envelope-from --read-recipients</command>.
'';
};
extraConfig = mkOption {
type = types.attrs;
default = {};
example = { select_query = ""; };
description = ''
Extra settings to add to this astroid account configuration.
'';
};
};
config = mkIf config.notmuch.enable {
astroid.sendMailCommand = mkIf config.msmtp.enable (
mkOptionDefault "msmtpq --read-envelope-from --read-recipients"
);
};
}

View File

@@ -0,0 +1,113 @@
{
"astroid": {
"config": {
"version": "11"
},
"debug": {
"dryrun_sending": "false"
},
"hints": {
"level": "0"
},
"log": {
"syslog": "false",
"stdout": "true",
"level": "info"
}
},
"startup": {
"queries": {
"inbox": "tag:inbox"
}
},
"terminal": {
"height": "10",
"font_description": "default"
},
"thread_index": {
"page_jump_rows": "6",
"sort_order": "newest",
"cell": {
"font_description": "default",
"line_spacing": "2",
"date_length": "10",
"message_count_length": "4",
"authors_length": "20",
"subject_color": "#807d74",
"subject_color_selected": "#000000",
"background_color_selected": "",
"background_color_marked": "#fff584",
"background_color_marked_selected": "#bcb559",
"tags_length": "80",
"tags_upper_color": "#e5e5e5",
"tags_lower_color": "#333333",
"tags_alpha": "0.5",
"hidden_tags": "attachment,flagged,unread"
}
},
"general": {
"time": {
"clock_format": "local",
"same_year": "%b %-e",
"diff_year": "%x"
}
},
"editor": {
"charset": "utf-8",
"save_draft_on_force_quit": "true",
"attachment_words": "attach",
"attachment_directory": "~",
"markdown_processor": "marked"
},
"mail": {
"reply": {
"quote_line": "Excerpts from %1's message of %2:",
"mailinglist_reply_to_sender": "true"
},
"forward": {
"quote_line": "Forwarding %1's message of %2:",
"disposition": "inline"
},
"sent_tags": "sent",
"message_id_fqdn": "",
"message_id_user": "",
"user_agent": "default",
"send_delay": "2",
"close_on_success": "false",
"format_flowed": "false"
},
"poll": {
"interval": "60",
"always_full_refresh": "false"
},
"attachment": {
"external_open_cmd": "xdg-open"
},
"thread_view": {
"open_html_part_external": "false",
"preferred_type": "plain",
"preferred_html_only": "false",
"allow_remote_when_encrypted": "false",
"open_external_link": "xdg-open",
"default_save_directory": "~",
"indent_messages": "false",
"gravatar": {
"enable": "true"
},
"mark_unread_delay": "0.5",
"expand_flagged": "true"
},
"crypto": {
"gpg": {
"path": "gpg2",
"always_trust": "true",
"enabled": "true"
}
},
"saved_searches": {
"show_on_startup": "false",
"save_history": "true",
"history_lines_to_show": "15",
"history_lines": "1000"
}
}

View File

@@ -0,0 +1,139 @@
{ config, lib, pkgs, ... }:
with lib;
with builtins;
let
cfg = config.programs.astroid;
astroidAccounts =
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;
# See https://github.com/astroidmail/astroid/wiki/Configuration-Reference
configFile = mailAccounts:
let
template = fromJSON (readFile ./astroid-config-template.json);
astroidConfig = foldl' recursiveUpdate template [
{
astroid.notmuch_config = "${config.xdg.configHome}/notmuch/notmuchrc";
accounts = mapAttrs (n: accountAttr) astroidAccounts;
crypto.gpg.path = "${pkgs.gnupg}/bin/gpg";
}
cfg.extraConfig
cfg.externalEditor
];
in
builtins.toJSON astroidConfig;
in
{
options = {
programs.astroid = {
enable = mkEnableOption "Astroid";
pollScript = mkOption {
type = types.str;
default = "";
example = "mbsync gmail";
description = ''
Script to run to fetch/update mails.
'';
};
externalEditor = mkOption {
type = types.nullOr types.str;
default = null;
# Converts it into JSON that can be merged into the configuration.
apply = cmd:
optionalAttrs (cmd != null) {
editor = {
"external_editor" = "true";
"cmd" = cmd;
};
};
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:
<orderedlist numeration="arabic">
<listitem><para>file name</para></listitem>
<listitem><para>server name</para></listitem>
<listitem><para>socket ID</para></listitem>
</orderedlist>
See <link xlink:href='https://github.com/astroidmail/astroid/wiki/Customizing-editor' />.
'';
};
extraConfig = mkOption {
type = types.attrs;
default = {};
example = { poll.interval = 0; };
description = ''
JSON config that will override the default Astroid configuration.
'';
};
};
};
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
'';
xdg.configFile."astroid/poll.sh" = {
executable = true;
text = ''
# Generated by Home Manager
${cfg.pollScript}
'';
};
};
}

View File

@@ -0,0 +1,277 @@
{ config, lib, pkgs, ... }:
with lib;
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; };
};
profileModule = types.submodule {
options = {
fingerprint = mkOption {
type = types.attrsOf types.str;
description = ''
Output name to EDID mapping.
Use <code>autorandr --fingerprint</code> to get current setup values.
'';
default = {};
};
config = mkOption {
type = types.attrsOf configModule;
description = "Per output profile configuration.";
default = {};
};
hooks = mkOption {
type = profileHooksModule;
description = "Profile hook scripts.";
default = {};
};
};
};
configModule = types.submodule {
options = {
enable = mkOption {
type = types.bool;
description = "Whether to enable the output.";
default = true;
};
primary = mkOption {
type = types.bool;
description = "Whether output should be marked as primary";
default = false;
};
position = mkOption {
type = types.str;
description = "Output position";
default = "";
example = "5760x0";
};
mode = mkOption {
type = types.str;
description = "Output resolution.";
default = "";
example = "3840x2160";
};
rate = mkOption {
type = types.str;
description = "Output framerate.";
default = "";
example = "60.00";
};
gamma = mkOption {
type = types.str;
description = "Output gamma configuration.";
default = "";
example = "1.0:0.909:0.833";
};
rotate = mkOption {
type = types.nullOr (types.enum ["normal" "left" "right" "inverted"]);
description = "Output rotate configuration.";
default = null;
example = "left";
};
transform = mkOption {
type = types.nullOr (matrixOf 3 3 types.float);
default = null;
example = literalExample ''
[
[ 0.6 0.0 0.0 ]
[ 0.0 0.6 0.0 ]
[ 0.0 0.0 1.0 ]
]
'';
description = ''
Refer to
<citerefentry>
<refentrytitle>xrandr</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>
for the documentation of the transform matrix.
'';
};
};
};
hookType = types.lines;
globalHooksModule = types.submodule {
options = {
postswitch = mkOption {
type = types.attrsOf hookType;
description = "Postswitch hook executed after mode switch.";
default = {};
};
preswitch = mkOption {
type = types.attrsOf hookType;
description = "Preswitch hook executed before mode switch.";
default = {};
};
predetect = mkOption {
type = types.attrsOf hookType;
description = "Predetect hook executed before autorandr attempts to run xrandr.";
default = {};
};
};
};
profileHooksModule = types.submodule {
options = {
postswitch = mkOption {
type = hookType;
description = "Postswitch hook executed after mode switch.";
default = "";
};
preswitch = mkOption {
type = hookType;
description = "Preswitch hook executed before mode switch.";
default = "";
};
predetect = mkOption {
type = hookType;
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) ]))
]);
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.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.transform != null) (
"transform " + concatMapStringsSep "," toString (flatten config.transform)
)}
'' else ''
output ${name}
off
'';
in
{
options = {
programs.autorandr = {
enable = mkEnableOption "Autorandr";
hooks = mkOption {
type = globalHooksModule;
description = "Global hook scripts";
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
'''
};
}
'';
};
profiles = mkOption {
type = types.attrsOf profileModule;
description = "Autorandr profiles specification.";
default = {};
example = literalExample ''
{
"work" = {
fingerprint = {
eDP1 = "<EDID>";
DP1 = "<EDID>";
};
config = {
eDP1.enable = false;
DP1 = {
enable = true;
primary = true;
position = "0x0";
mode = "3840x2160";
gamma = "1.0:0.909:0.833";
rate = "60.00";
rotate = "left";
};
};
hooks.postswitch = readFile ./work-postswitch.sh;
};
}
'';
};
};
};
config = mkIf cfg.enable {
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)
(mkMerge (mapAttrsToList profileToFiles cfg.profiles))
]);
};
meta.maintainers = [ maintainers.uvnikita ];
}

View File

@@ -9,6 +9,8 @@ let
in
{
meta.maintainers = [ maintainers.rycee ];
options = {
programs.bash = {
enable = mkEnableOption "GNU Bourne-Again SHell";
@@ -19,6 +21,12 @@ in
description = "Number of history lines to keep in memory.";
};
historyFile = mkOption {
type = types.str;
default = "$HOME/.bash_history";
description = "Location of the bash history file.";
};
historyFileSize = mkOption {
type = types.int;
default = 100000;
@@ -62,13 +70,21 @@ in
description = "Shell options to set.";
};
sessionVariables = mkOption {
default = {};
type = types.attrs;
example = { MAILCHECK = 30; };
description = ''
Environment variables that will be set for the Bash session.
'';
};
shellAliases = mkOption {
default = {};
example = { ll = "ls -l"; ".." = "cd .."; };
description = ''
An attribute set that maps aliases (the top level attribute names in
this option) to command strings or directly to build outputs. The
aliases are added to all users' shells.
this option) to command strings or directly to build outputs.
'';
type = types.attrs;
};
@@ -82,13 +98,30 @@ in
profileExtra = mkOption {
default = "";
type = types.lines;
description = "Extra commands that should be added to .profile.";
description = ''
Extra commands that should be run when initializing a login
shell.
'';
};
bashrcExtra = mkOption {
# Hide for now, may want to rename in the future.
visible = false;
default = "";
type = types.lines;
description = ''
Extra commands that should be added to
<filename>~/.bashrc</filename>.
'';
};
initExtra = mkOption {
default = "";
type = types.lines;
description = "Extra commands that should be added to .bashrc.";
description = ''
Extra commands that should be run when initializing an
interactive shell.
'';
};
};
};
@@ -96,24 +129,46 @@ in
config = (
let
aliasesStr = concatStringsSep "\n" (
mapAttrsToList (k: v: "alias ${k}='${v}'") cfg.shellAliases
mapAttrsToList (k: v: "alias ${k}=${escapeShellArg v}") cfg.shellAliases
);
shoptsStr = concatStringsSep "\n" (
map (v: "shopt -s ${v}") cfg.shellOptions
);
export = n: v: "export ${n}=\"${toString v}\"";
exportIfNonNull = n: v: optionalString (v != null) (export n v);
exportIfNonEmpty = n: v: optionalString (v != "") (export n v);
sessionVarsStr = config.lib.shell.exportAll cfg.sessionVariables;
histControlStr = concatStringsSep ":" cfg.historyControl;
histIgnoreStr = concatStringsSep ":" cfg.historyIgnore;
envVarsStr = concatStringsSep "\n" (
mapAttrsToList export config.home.sessionVariables
);
historyControlStr =
concatStringsSep "\n" (mapAttrsToList (n: v: "${n}=${v}") (
{
HISTFILE = "\"${cfg.historyFile}\"";
HISTFILESIZE = toString cfg.historyFileSize;
HISTSIZE = toString cfg.historySize;
}
// optionalAttrs (cfg.historyControl != []) {
HISTCONTROL = concatStringsSep ":" cfg.historyControl;
}
// optionalAttrs (cfg.historyIgnore != []) {
HISTIGNORE = concatStringsSep ":" cfg.historyIgnore;
}
));
in mkIf cfg.enable {
programs.bash.bashrcExtra = ''
# Commands that should be applied only for interactive shells.
if [[ $- == *i* ]]; then
${historyControlStr}
${shoptsStr}
${aliasesStr}
${cfg.initExtra}
${optionalString cfg.enableAutojump
". ${pkgs.autojump}/share/autojump/autojump.bash"}
fi
'';
home.file.".bash_profile".text = ''
# -*- mode: sh -*-
@@ -127,8 +182,9 @@ in
home.file.".profile".text = ''
# -*- mode: sh -*-
${optionalString (config.home.sessionVariableSetter == "bash")
envVarsStr}
. "${config.home.profileDirectory}/etc/profile.d/hm-session-vars.sh"
${sessionVarsStr}
${cfg.profileExtra}
'';
@@ -136,22 +192,7 @@ in
home.file.".bashrc".text = ''
# -*- mode: sh -*-
# Skip if not running interactively.
[ -z "$PS1" ] && return
${export "HISTSIZE" cfg.historySize}
${export "HISTFILESIZE" cfg.historyFileSize}
${exportIfNonEmpty "HISTCONTROL" histControlStr}
${exportIfNonEmpty "HISTIGNORE" histIgnoreStr}
${shoptsStr}
${aliasesStr}
${cfg.initExtra}
${optionalString cfg.enableAutojump
". ${pkgs.autojump}/share/autojump/autojump.bash"}
${cfg.bashrcExtra}
'';
home.packages =

View File

@@ -9,8 +9,25 @@ let
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 != {};
defaultText = "false";
description = ''
Whether to enable the beets music library manager. This
defaults to <literal>false</literal> for state
version  19.03. For earlier versions beets is enabled if
<option>programs.beets.settings</option> is non-empty.
'';
};
settings = mkOption {
type = types.attrs;
default = {};
@@ -22,10 +39,10 @@ in
};
};
config = mkIf (cfg.settings != {}) {
config = mkIf cfg.enable {
home.packages = [ pkgs.beets ];
home.file.".config/beets/config.yaml".text =
xdg.configFile."beets/config.yaml".text =
builtins.toJSON config.programs.beets.settings;
};
}

View File

@@ -0,0 +1,80 @@
{ config, lib, pkgs, ... }:
with lib;
let
browsers = [
"chrome"
"chromium"
"firefox"
"vivaldi"
];
in {
options = {
programs.browserpass = {
enable = mkEnableOption "the browserpass extension host application";
browsers = mkOption {
type = types.listOf (types.enum browsers);
default = browsers;
example = [ "firefox" ];
description = "Which browsers to install browserpass for";
};
};
};
config = mkIf config.programs.browserpass.enable {
home.file = builtins.concatLists (with pkgs.stdenv; map (x:
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}/etc/chrome-host.json";
}
{
target = "${dir}/../policies/managed/com.github.browserpass.native.json";
source = "${pkgs.browserpass}/etc/chrome-policy.json";
}
]
else if x == "chromium" then
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}/etc/chrome-host.json";
}
{
target = "${dir}/../policies/managed/com.github.browserpass.native.json";
source = "${pkgs.browserpass}/etc/chrome-policy.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/mozilla/native-messaging-hosts/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}/etc/chrome-host.json";
}
{
target = "${dir}/../policies/managed/com.github.browserpass.native.json";
source = "${pkgs.browserpass}/etc/chrome-policy.json";
}
]
else throw "unknown browser ${x}") config.programs.browserpass.browsers);
};
}

View File

@@ -0,0 +1,93 @@
{ config, lib, pkgs, ... }:
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;
};
package = mkOption {
inherit visible;
type = types.package;
default = defaultPkg;
defaultText = "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>.
'';
};
};
browserConfig = cfg:
let
browser = (builtins.parseDrvName cfg.package.name).name;
darwinDirs = {
chromium = "Chromium";
google-chrome = "Google/Chrome";
google-chrome-beta = "Google/Chrome Beta";
google-chrome-dev = "Google/Chrome Dev";
};
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";
};
};
in
mkIf cfg.enable {
home.packages = [ cfg.package ];
home.file = 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;
};
config = mkMerge [
(browserConfig config.programs.chromium)
(browserConfig config.programs.google-chrome)
(browserConfig config.programs.google-chrome-beta)
(browserConfig config.programs.google-chrome-dev)
];
}

View File

@@ -0,0 +1,57 @@
# Adapted from Nixpkgs.
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.command-not-found;
commandNotFound = pkgs.substituteAll {
name = "command-not-found";
dir = "bin";
src = ./command-not-found.pl;
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 ]);
};
shInit = commandNotFoundHandlerName: ''
# This function is called whenever a command is not found.
${commandNotFoundHandlerName}() {
local p=${commandNotFound}/bin/command-not-found
if [ -x $p -a -f ${cfg.dbPath} ]; then
# Run the helper program.
$p "$@"
else
echo "$1: command not found" >&2
return 127
fi
}
'';
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" ;
description = ''
Absolute path to <filename>programs.sqlite</filename>. By
default this file will be provided by your channel
(nixexprs.tar.xz).
'';
type = types.path;
};
};
config = mkIf cfg.enable {
programs.bash.initExtra = shInit "command_not_found_handle";
programs.zsh.initExtra = shInit "command_not_found_handler";
home.packages = [ commandNotFound ];
};
}

View File

@@ -0,0 +1,44 @@
#! @perl@/bin/perl -w @perlFlags@
use strict;
use DBI;
use DBD::SQLite;
use String::ShellQuote;
use Config;
my $program = $ARGV[0];
my $dbPath = "@dbPath@";
my $dbh = DBI->connect("dbi:SQLite:dbname=$dbPath", "", "")
or die "cannot open database `$dbPath'";
$dbh->{RaiseError} = 0;
$dbh->{PrintError} = 0;
my $system = $ENV{"NIX_SYSTEM"} // $Config{myarchname};
my $res = $dbh->selectall_arrayref(
"select package from Programs where system = ? and name = ?",
{ Slice => {} }, $system, $program);
if (!defined $res || scalar @$res == 0) {
print STDERR "$program: command not found\n";
} elsif (scalar @$res == 1) {
my $package = @$res[0]->{package};
if ($ENV{"NIX_AUTO_RUN"} // "") {
exec("nix-shell", "-p", $package, "--run", shell_quote("exec", @ARGV));
} else {
print STDERR <<EOF;
The program $program is currently not installed. You can install it by typing:
nix-env -iA nixos.$package
EOF
}
} else {
print STDERR <<EOF;
The program $program is currently not installed. It is provided by
several packages. You can install it by typing one of the following:
EOF
print STDERR " nix-env -iA nixos.$_->{package}\n" foreach @$res;
}
exit 127;

107
modules/programs/direnv.nix Normal file
View File

@@ -0,0 +1,107 @@
{ config, lib, pkgs, ... }:
with lib;
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
{
meta.maintainers = [ maintainers.rycee ];
options.programs.direnv = {
enable = mkEnableOption "direnv, the environment switcher";
config = mkOption {
type = types.attrs;
default = {};
description = ''
Configuration written to
<filename>~/.config/direnv/config.toml</filename>.
</para><para>
See
<citerefentry>
<refentrytitle>direnv.toml</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>.
for the full list of options.
'';
};
stdlib = mkOption {
type = types.lines;
default = "";
description = ''
Custom stdlib written to
<filename>~/.config/direnv/direnvrc</filename>.
'';
};
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.direnv ];
xdg.configFile."direnv/config.toml" = mkIf (cfg.config != {}) {
source = configFile cfg.config;
};
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.zsh.initExtra = mkIf cfg.enableZshIntegration ''
eval "$(${pkgs.direnv}/bin/direnv hook zsh)"
'';
programs.fish.shellInit = mkIf cfg.enableFishIntegration ''
eval (${pkgs.direnv}/bin/direnv hook fish)
'';
};
}

View File

@@ -9,10 +9,22 @@ let
in
{
meta.maintainers = [ maintainers.rycee ];
options = {
programs.eclipse = {
enable = mkEnableOption "Eclipse";
enableLombok = mkOption {
type = types.bool;
default = false;
example = true;
description = ''
Whether to enable the Lombok Java Agent in Eclipse. This is
necessary to use the Lombok class annotations.
'';
};
jvmArgs = mkOption {
type = types.listOf types.str;
default = [];
@@ -31,7 +43,10 @@ in
home.packages = [
(pkgs.eclipses.eclipseWithPlugins {
eclipse = pkgs.eclipses.eclipse-platform;
jvmArgs = cfg.jvmArgs;
jvmArgs =
cfg.jvmArgs
++ optional cfg.enableLombok
"-javaagent:${pkgs.lombok}/share/java/lombok.jar";
plugins = cfg.plugins;
})
];

View File

@@ -6,24 +6,66 @@ let
cfg = config.programs.emacs;
# Copied from all-packages.nix, with modifications to support
# overrides.
emacsPackages =
let
epkgs = pkgs.emacsPackagesNgGen cfg.package;
in
epkgs.overrideScope' cfg.overrides;
emacsWithPackages = emacsPackages.emacsWithPackages;
in
{
meta.maintainers = [ maintainers.rycee ];
options = {
programs.emacs = {
enable = mkEnableOption "Emacs";
package = mkOption {
type = types.package;
default = pkgs.emacs;
defaultText = "pkgs.emacs";
example = literalExample "pkgs.emacs25-nox";
description = "The Emacs package to use.";
};
extraPackages = mkOption {
default = self: [];
example = literalExample ''
epkgs: [ epkgs.emms epkgs.magit ]
'';
defaultText = "epkgs: []";
example = literalExample "epkgs: [ epkgs.emms epkgs.magit ]";
description = "Extra packages available to Emacs.";
};
overrides = mkOption {
default = self: super: {};
defaultText = "self: super: {}";
example = literalExample ''
self: super: rec {
haskell-mode = self.melpaPackages.haskell-mode;
# ...
};
'';
description = ''
Allows overriding packages within the Emacs package set.
'';
};
finalPackage = mkOption {
type = types.package;
visible = false;
readOnly = true;
description = ''
The Emacs package including any overrides and extra packages.
'';
};
};
};
config = mkIf cfg.enable {
home.packages = [ (pkgs.emacsWithPackages cfg.extraPackages) ];
home.packages = [ cfg.finalPackage ];
programs.emacs.finalPackage = emacsWithPackages cfg.extraPackages;
};
}

41
modules/programs/feh.nix Normal file
View File

@@ -0,0 +1,41 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.feh;
disableBinding = func: key: func;
enableBinding = func: key: "${func} ${key}";
in
{
options.programs.feh = {
enable = mkEnableOption "feh - a fast and light image viewer";
keybindings = mkOption {
default = {};
type = types.attrs;
example = { zoom_in = "plus"; zoom_out = "minus"; };
description = ''
Set keybindings.
See <link xlink:href="https://man.finalrewind.org/1/feh/#x4b455953"/> for
default bindings and available commands.
'';
};
};
config = mkIf cfg.enable {
home.packages = [ pkgs.feh ];
xdg.configFile."feh/keys".text = ''
# Disable default keybindings
${concatStringsSep "\n" (mapAttrsToList disableBinding cfg.keybindings)}
# Enable new keybindings
${concatStringsSep "\n" (mapAttrsToList enableBinding cfg.keybindings)}
'';
};
}

View File

@@ -6,9 +6,13 @@ let
cfg = config.programs.firefox;
extensionPath = "extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
in
{
meta.maintainers = [ maintainers.rycee ];
options = {
programs.firefox = {
enable = mkEnableOption "Firefox";
@@ -20,6 +24,22 @@ in
description = "The unwrapped Firefox package to use.";
};
extensions = mkOption {
type = types.listOf types.package;
default = [];
example = literalExample ''
with pkgs.nur.repos.rycee.firefox-addons; [
https-everywhere
privacy-badger
]
'';
description = ''
List of Firefox add-on packages to install. Note, it is
necessary to manually enable these extensions inside Firefox
after the first installation.
'';
};
enableAdobeFlash = mkOption {
type = types.bool;
default = false;
@@ -31,6 +51,12 @@ in
default = false;
description = "Whether to enable the unfree Google Talk plugin.";
};
enableIcedTea = mkOption {
type = types.bool;
default = false;
description = "Whether to enable the Java applet plugin.";
};
};
};
@@ -44,6 +70,7 @@ in
fcfg = setAttrByPath [browserName] {
enableAdobeFlash = cfg.enableAdobeFlash;
enableGoogleTalkPlugin = cfg.enableGoogleTalk;
icedtea = cfg.enableIcedTea;
};
wrapper = pkgs.wrapFirefox.override {
@@ -51,5 +78,18 @@ in
};
in
[ (wrapper cfg.package { }) ];
home.file.".mozilla/${extensionPath}" = mkIf (cfg.extensions != []) (
let
extensionsEnv = pkgs.buildEnv {
name = "hm-firefox-extensions";
paths = cfg.extensions;
};
in
{
source = "${extensionsEnv}/share/mozilla/${extensionPath}";
recursive = true;
}
);
};
}

191
modules/programs/fish.nix Normal file
View File

@@ -0,0 +1,191 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.fish;
abbrsStr = concatStringsSep "\n" (
mapAttrsToList (k: v: "abbr --add ${k} '${v}'") cfg.shellAbbrs
);
aliasesStr = concatStringsSep "\n" (
mapAttrsToList (k: v: "alias ${k}='${v}'") cfg.shellAliases
);
in
{
options = {
programs.fish = {
enable = mkEnableOption "fish friendly interactive shell";
package = mkOption {
default = pkgs.fish;
defaultText = "pkgs.fish";
description = ''
The fish package to install. May be used to change the version.
'';
type = types.package;
};
shellAliases = mkOption {
default = {};
description = ''
Set of aliases for fish shell. See
<option>environment.shellAliases</option> for an option
format description.
'';
type = types.attrs;
};
shellAbbrs = mkOption {
default = {};
description = ''
Set of abbreviations for fish shell.
'';
type = types.attrs;
};
shellInit = mkOption {
default = "";
description = ''
Shell script code called during fish shell initialisation.
'';
type = types.lines;
};
loginShellInit = mkOption {
default = "";
description = ''
Shell script code called during fish login shell initialisation.
'';
type = types.lines;
};
interactiveShellInit = mkOption {
default = "";
description = ''
Shell script code called during interactive fish shell initialisation.
'';
type = types.lines;
};
promptInit = mkOption {
default = "";
description = ''
Shell script code used to initialise fish prompt.
'';
type = types.lines;
};
};
};
config = mkIf cfg.enable {
home.packages = [ cfg.package ];
xdg.dataFile."fish/home-manager_generated_completions".source =
let
# paths later in the list will overwrite those already linked
destructiveSymlinkJoin =
args_@{ name
, paths
, preferLocalBuild ? true
, allowSubstitutes ? false
, postBuild ? ""
, ...
}:
let
args = removeAttrs args_ [ "name" "postBuild" ]
// { inherit preferLocalBuild allowSubstitutes; }; # pass the defaults
in pkgs.runCommand name args
''
mkdir -p $out
for i in $paths; do
if [ -z "$(find $i -prune -empty)" ]; then
cp -srf $i/* $out
fi
done
${postBuild}
'';
generateCompletions = package: pkgs.runCommand
"${package.name}-fish-completions"
{
src = package;
nativeBuildInputs = [ pkgs.python2 ];
buildInputs = [ cfg.package ];
preferLocalBuild = true;
allowSubstitutes = false;
}
''
mkdir -p $out
if [ -d $src/share/man ]; then
find $src/share/man -type f \
| xargs python ${cfg.package}/share/fish/tools/create_manpage_completions.py --directory $out \
> /dev/null
fi
'';
in
destructiveSymlinkJoin {
name = "${config.home.username}-fish-completions";
paths =
let
cmp = (a: b: (a.meta.priority or 0) > (b.meta.priority or 0));
in
map generateCompletions (sort cmp config.home.packages);
};
programs.fish.interactiveShellInit = ''
# add completions generated by Home Manager to $fish_complete_path
begin
set -l joined (string join " " $fish_complete_path)
set -l prev_joined (string replace --regex "[^\s]*generated_completions.*" "" $joined)
set -l post_joined (string replace $prev_joined "" $joined)
set -l prev (string split " " (string trim $prev_joined))
set -l post (string split " " (string trim $post_joined))
set fish_complete_path $prev "${config.xdg.dataHome}/fish/home-manager_generated_completions" $post
end
'';
xdg.configFile."fish/config.fish".text = ''
# ~/.config/fish/config.fish: DO NOT EDIT -- this file has been generated automatically.
# if we haven't sourced the general config, do it
if not set -q __fish_general_config_sourced
set fish_function_path ${pkgs.fish-foreign-env}/share/fish-foreign-env/functions $fish_function_path
fenv source ${config.home.profileDirectory}/etc/profile.d/hm-session-vars.sh > /dev/null
set -e fish_function_path[1]
${cfg.shellInit}
# and leave a note so we don't source this config section again from
# this very shell (children will source the general config anew)
set -g __fish_general_config_sourced 1
end
# if we haven't sourced the login config, do it
status --is-login; and not set -q __fish_login_config_sourced
and begin
${cfg.loginShellInit}
# and leave a note so we don't source this config section again from
# this very shell (children will source the general config anew)
set -g __fish_login_config_sourced 1
end
# if we haven't sourced the interactive config, do it
status --is-interactive; and not set -q __fish_interactive_config_sourced
and begin
# Abbrs
${abbrsStr}
# Aliases
${aliasesStr}
${cfg.promptInit}
${cfg.interactiveShellInit}
# and leave a note so we don't source this config section again from
# this very shell (children will source the general config anew,
# allowing configuration changes in, e.g, aliases, to propagate)
set -g __fish_interactive_config_sourced 1
end
'';
};
}

138
modules/programs/fzf.nix Normal file
View File

@@ -0,0 +1,138 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.fzf;
in
{
options.programs.fzf = {
enable = mkEnableOption "fzf - a command-line fuzzy finder";
defaultCommand = mkOption {
type = types.nullOr types.str;
default = null;
example = "fd --type f";
description = ''
The command that gets executed as the default source for fzf
when running.
'';
};
defaultOptions = mkOption {
type = types.listOf types.str;
default = [];
example = [ "--height 40%" "--border" ];
description = ''
Extra command line options given to fzf by default.
'';
};
fileWidgetCommand = mkOption {
type = types.nullOr types.str;
default = null;
example = "fd --type f";
description = ''
The command that gets executed as the source for fzf for the
CTRL-T keybinding.
'';
};
fileWidgetOptions = mkOption {
type = types.listOf types.str;
default = [];
example = [ "--preview 'head {}'" ];
description = ''
Command line options for the CTRL-T keybinding.
'';
};
changeDirWidgetCommand = mkOption {
type = types.nullOr types.str;
default = null;
example = "fd --type d" ;
description = ''
The command that gets executed as the source for fzf for the
ALT-C keybinding.
'';
};
changeDirWidgetOptions = mkOption {
type = types.listOf types.str;
default = [];
example = [ "--preview 'tree -C {} | head -200'" ];
description = ''
Command line options for the ALT-C keybinding.
'';
};
historyWidgetCommand = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
The command that gets executed as the source for fzf for the
CTRL-R keybinding.
'';
};
historyWidgetOptions = mkOption {
type = types.listOf types.str;
default = [];
example = [ "--sort" "--exact" ];
description = ''
Command line options for the CTRL-R keybinding.
'';
};
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.
'';
};
};
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;
}
);
programs.bash.initExtra = mkIf cfg.enableBashIntegration ''
if [[ :$SHELLOPTS: =~ :(vi|emacs): ]]; then
. ${pkgs.fzf}/share/fzf/completion.bash
. ${pkgs.fzf}/share/fzf/key-bindings.bash
fi
'';
programs.zsh.initExtra = mkIf cfg.enableZshIntegration ''
if [[ $options[zle] = on ]]; then
. ${pkgs.fzf}/share/fzf/completion.zsh
. ${pkgs.fzf}/share/fzf/key-bindings.zsh
fi
'';
};
}

View File

@@ -6,35 +6,73 @@ let
cfg = config.programs.git;
toINI = (import ../lib/generators.nix).toINI {};
gitIniType = with types;
let
primitiveType = either bool (either int str);
in
attrsOf (attrsOf primitiveType);
signModule = types.submodule (
{ ... }: {
options = {
key = mkOption {
type = types.str;
description = "The default GPG signing key fingerprint.";
};
signByDefault = mkOption {
type = types.bool;
default = false;
description = "Whether commits should be signed by default.";
};
gpgPath = mkOption {
type = types.str;
default = "${pkgs.gnupg}/bin/gpg2";
defaultText = "\${pkgs.gnupg}/bin/gpg2";
description = "Path to GnuPG binary to use.";
};
signModule = types.submodule {
options = {
key = mkOption {
type = types.str;
description = "The default GPG signing key fingerprint.";
};
}
);
signByDefault = mkOption {
type = types.bool;
default = false;
description = "Whether commits should be signed by default.";
};
gpgPath = mkOption {
type = types.str;
default = "${pkgs.gnupg}/bin/gpg2";
defaultText = "\${pkgs.gnupg}/bin/gpg2";
description = "Path to GnuPG binary to use.";
};
};
};
includeModule = types.submodule ({ config, ... }: {
options = {
condition = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Include this configuration only when <varname>condition</varname>
matches. Allowed conditions are described in
<citerefentry>
<refentrytitle>git-config</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>.
'';
};
path = mkOption {
type = with types; either str path;
description = "Path of the configuration file to include.";
};
contents = mkOption {
type = types.attrs;
default = {};
description = ''
Configuration to include. If empty then a path must be given.
'';
};
};
config.path = mkIf (config.contents != {}) (
mkDefault (pkgs.writeText "contents" (generators.toINI {} config.contents))
);
});
in
{
meta.maintainers = [ maintainers.rycee ];
options = {
programs.git = {
enable = mkEnableOption "Git";
@@ -43,22 +81,28 @@ in
type = types.package;
default = pkgs.git;
defaultText = "pkgs.git";
description = "Git package to install.";
description = ''
Git package to install. Use <varname>pkgs.gitAndTools.gitFull</varname>
to gain access to <command>git send-email</command> for instance.
'';
};
userName = mkOption {
type = types.str;
type = types.nullOr types.str;
default = null;
description = "Default user name to use.";
};
userEmail = mkOption {
type = types.str;
type = types.nullOr types.str;
default = null;
description = "Default user email to use.";
};
aliases = mkOption {
type = types.attrs;
type = types.attrsOf types.str;
default = {};
example = { co = "checkout"; };
description = "Git aliases to define.";
};
@@ -69,33 +113,144 @@ in
};
extraConfig = mkOption {
type = types.lines;
default = "";
type = types.either types.lines gitIniType;
default = {};
example = {
core = { whitespace = "trailing-space,space-before-tab"; };
};
description = "Additional configuration to add.";
};
iniContent = mkOption {
type = gitIniType;
internal = true;
};
ignores = mkOption {
type = types.listOf types.str;
default = [];
example = [ "*~" "*.swp" ];
description = "List of paths that should be globally ignored.";
};
includes = mkOption {
type = types.listOf includeModule;
default = [];
example = literalExample ''
[
{ path = "~/path/to/config.inc"; }
{
path = "~/path/to/conditional.inc";
condition = "gitdir:~/src/dir";
}
]
'';
description = "List of configuration files to include.";
};
lfs = {
enable = mkEnableOption "Git Large File Storage";
skipSmudge = mkOption {
type = types.bool;
default = false;
description = ''
Skip automatic downloading of objects on clone or pull.
This requires a manual <command>git lfs pull</command>
every time a new commit is checked out on your repository.
'';
};
};
};
};
config = mkIf cfg.enable (
let
ini = {
user = {
name = cfg.userName;
email = cfg.userEmail;
} // optionalAttrs (cfg.signing != null) {
signingKey = cfg.signing.key;
};
} // optionalAttrs (cfg.signing != null) {
commit.gpgSign = cfg.signing.signByDefault;
gpg.program = cfg.signing.gpgPath;
} // optionalAttrs (cfg.aliases != {}) {
alias = cfg.aliases;
};
in
mkMerge [
{
home.packages = [ cfg.package ];
home.file.".gitconfig".text = toINI ini + "\n" + cfg.extraConfig;
programs.git.iniContent.user = {
name = mkIf (cfg.userName != null) cfg.userName;
email = mkIf (cfg.userEmail != null) cfg.userEmail;
};
xdg.configFile = {
"git/config".text = generators.toINI {} cfg.iniContent;
"git/ignore" = mkIf (cfg.ignores != []) {
text = concatStringsSep "\n" cfg.ignores + "\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;
};
})
(mkIf (cfg.aliases != {}) {
programs.git.iniContent.alias = cfg.aliases;
})
(mkIf (lib.isAttrs cfg.extraConfig) {
programs.git.iniContent = cfg.extraConfig;
})
(mkIf (lib.isString cfg.extraConfig) {
xdg.configFile."git/config".text = cfg.extraConfig;
})
(mkIf (cfg.includes != []) {
xdg.configFile."git/config".text = mkAfter
(concatMapStringsSep "\n"
(i: with i; ''
[${if (condition == null) then "include" else "includeIf \"${condition}\""}]
path = ${path}
'')
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" ]
);
};
})
]
);
}

View File

@@ -1,12 +1,16 @@
{ config, lib, pkgs, ... }:
with lib;
with import ../lib/dag.nix;
let
cfg = config.programs.gnome-terminal;
vteInitStr = ''
# gnome-terminal: Show current directory in the terminal window title.
. ${pkgs.gnome3.vte}/etc/profile.d/vte.sh
'';
profileColorsSubModule = types.submodule (
{ ... }: {
options = {
@@ -90,19 +94,6 @@ let
}
);
toINI = (import ../lib/generators.nix).toINI { mkKeyValue = mkIniKeyValue; };
mkIniKeyValue = key: value:
let
tweakVal = v:
if isString v then "'${v}'"
else if isList v then "[" + concatStringsSep "," (map tweakVal v) + "]"
else if isBool v && v then "true"
else if isBool v && !v then "false"
else toString v;
in
"${key}=${tweakVal value}";
buildProfileSet = pcfg:
{
visible-name = pcfg.visibleName;
@@ -135,28 +126,11 @@ let
)
);
buildIniSet = cfg:
{
"/" = {
default-show-menubar = cfg.showMenubar;
schema-version = 3;
};
}
//
{
"profiles:" = {
default = head (attrNames (filterAttrs (n: v: v.default) cfg.profile));
list = attrNames cfg.profile; #mapAttrsToList (n: v: n) cfg.profile;
};
}
//
mapAttrs' (name: value:
nameValuePair ("profiles:/:${name}") (buildProfileSet value)
) cfg.profile;
in
{
meta.maintainers = [ maintainers.rycee ];
options = {
programs.gnome-terminal = {
enable = mkEnableOption "Gnome Terminal";
@@ -178,19 +152,26 @@ in
config = mkIf cfg.enable {
home.packages = [ pkgs.gnome3.gnome_terminal ];
# The dconf service needs to be installed and prepared.
home.activation.gnomeTerminal = dagEntryAfter ["installPackages"] (
dconf.settings =
let
sf = pkgs.writeText "gnome-terminal.ini" (toINI (buildIniSet cfg));
dconfPath = "/org/gnome/terminal/legacy/";
dconfPath = "org/gnome/terminal/legacy";
in
''
if [[ -v DRY_RUN ]]; then
echo ${pkgs.gnome3.dconf}/bin/dconf load ${dconfPath} "<" ${sf}
else
${pkgs.gnome3.dconf}/bin/dconf load ${dconfPath} < ${sf}
fi
''
);
{
"${dconfPath}" = {
default-show-menubar = cfg.showMenubar;
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;
};
}

75
modules/programs/go.nix Normal file
View File

@@ -0,0 +1,75 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.go;
in
{
meta.maintainers = [ maintainers.rvolosatovs ];
options = {
programs.go = {
enable = mkEnableOption "Go";
package = mkOption {
type = types.package;
default = pkgs.go;
defaultText = "pkgs.go";
description = "The Go package to use.";
};
packages = mkOption {
type = with types; attrsOf path;
default = {};
example = literalExample ''
{
"golang.org/x/text" = builtins.fetchGit "https://go.googlesource.com/text";
"golang.org/x/time" = builtins.fetchGit "https://go.googlesource.com/time";
}
'';
description = "Packages to add to GOPATH.";
};
goPath = mkOption {
type = with types; nullOr str;
default = null;
example = "go";
description = "GOPATH relative to HOME";
};
goBin = mkOption {
type = with types; nullOr str;
default = null;
example = ".local/bin.go";
description = "GOBIN relative to HOME";
};
};
};
config = mkIf cfg.enable (mkMerge [
{
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;
}
(mkIf (cfg.goPath != null) {
home.sessionVariables.GOPATH = builtins.toPath "${config.home.homeDirectory}/${cfg.goPath}";
})
(mkIf (cfg.goBin != null) {
home.sessionVariables.GOBIN = builtins.toPath "${config.home.homeDirectory}/${cfg.goBin}";
})
]);
}

View File

@@ -0,0 +1,43 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.home-manager;
dag = config.lib.dag;
in
{
meta.maintainers = [ maintainers.rycee ];
options = {
programs.home-manager = {
enable = mkEnableOption "Home Manager";
path = mkOption {
type = types.nullOr types.str;
default = null;
example = "$HOME/devel/home-manager";
description = ''
The default path to use for Home Manager. If this path does
not exist then
<filename>$HOME/.config/nixpkgs/home-manager</filename> and
<filename>$HOME/.nixpkgs/home-manager</filename> will be
attempted.
'';
};
};
};
config = mkIf (cfg.enable && !config.submoduleSupport.enable) {
home.packages = [
(import ../../home-manager {
inherit pkgs;
inherit (cfg) path;
})
];
};
}

327
modules/programs/htop.nix Normal file
View File

@@ -0,0 +1,327 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.htop;
list = xs: concatMapStrings (x: "${toString x} ") xs;
bool = b: if b then "1" else "0";
fields = {
PID = 0;
COMM = 1;
STATE = 2;
PPID = 3;
PGRP = 4;
SESSION = 5;
TTY_NR = 6;
TPGID = 7;
MINFLT = 9;
MAJFLT = 11;
PRIORITY = 17;
NICE = 18;
STARTTIME = 20;
PROCESSOR = 37;
M_SIZE = 38;
M_RESIDENT = 39;
ST_UID = 45;
PERCENT_CPU = 46;
PERCENT_MEM = 47;
USER = 48;
TIME = 49;
NLWP = 50;
TGID = 51;
CMINFLT = 10;
CMAJFLT = 12;
UTIME = 13;
STIME = 14;
CUTIME = 15;
CSTIME = 16;
M_SHARE = 40;
M_TRS = 41;
M_DRS = 42;
M_LRS = 43;
M_DT = 44;
CTID = 99;
VPID = 100;
VXID = 102;
RCHAR = 102;
WCHAR = 103;
SYSCR = 104;
SYSCW = 105;
RBYTES = 106;
WBYTES = 107;
CNCLWB = 108;
IO_READ_RATE = 109;
IO_WRITE_RATE = 110;
IO_RATE = 111;
CGROUP = 112;
OOM = 113;
IO_PRIORITY = 114;
};
# Mapping from names to defaults
meters = {
Clock = 2;
LoadAverage = 2;
Load = 2;
Memory = 1;
Swap = 1;
Tasks = 2;
Uptime = 2;
Battery = 2;
Hostname = 2;
AllCPUs = 1;
AllCPUs2 = 1;
LeftCPUs = 1;
RightCPUs = 1;
LeftCPUs2 = 1;
RightCPUs2 = 1;
Blank = 2;
CPU = 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 {
options = {
kind = mkOption {
type = types.enum (attrNames meters);
example = "AllCPUs";
description = "What kind of meter.";
};
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).";
};
};
});
meterType = types.submodule {
options = {
left = mkOption {
description = "Meters shown in the left header.";
default = [ "AllCPUs" "Memory" "Swap" ];
example = [
"Memory"
"LeftCPUs2"
"RightCPUs2"
{ kind = "CPU"; mode = 3; }
];
type = types.listOf singleMeterType;
};
right = mkOption {
description = "Meters shown in the right header.";
default = [ "Tasks" "LoadAverage" "Uptime" ];
example = [
{ kind = "Clock"; mode = 4; }
"Uptime"
"Tasks"
];
type = types.listOf singleMeterType;
};
};
};
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" ];
description = "Active fields shown in the table.";
};
sortKey = mkOption {
type = types.enum (attrNames fields);
default = "PERCENT_CPU";
example = "TIME";
description = "Which field to use for sorting.";
};
sortDescending = mkOption {
type = types.bool;
default = true;
description = "Whether to sort descending or not.";
};
hideThreads = mkOption {
type = types.bool;
default = false;
description = "Hide threads.";
};
hideKernelThreads = mkOption {
type = types.bool;
default = true;
description = "Hide kernel threads.";
};
hideUserlandThreads = mkOption {
type = types.bool;
default = false;
description = "Hide userland process threads.";
};
shadowOtherUsers = mkOption {
type = types.bool;
default = false;
description = "Shadow other users' processes.";
};
showThreadNames = mkOption {
type = types.bool;
default = false;
description = "Show custom thread names.";
};
showProgramPath = mkOption {
type = types.bool;
default = true;
description = "Show program path.";
};
highlightBaseName = mkOption {
type = types.bool;
default = false;
description = "Highlight program <quote>basename</quote>.";
};
highlightMegabytes = mkOption {
type = types.bool;
default = true;
description = "Highlight large numbers in memory counters.";
};
highlightThreads = mkOption {
type = types.bool;
default = true;
description = "Display threads in a different color.";
};
treeView = mkOption {
type = types.bool;
default = false;
description = "Tree view.";
};
headerMargin = mkOption {
type = types.bool;
default = true;
description = "Leave a margin around header.";
};
detailedCpuTime = mkOption {
type = types.bool;
default = false;
description = "Detailed CPU time (System/IO-Wait/Hard-IRQ/Soft-IRQ/Steal/Guest).";
};
cpuCountFromZero = mkOption {
type = types.bool;
default = false;
description = "Count CPUs from 0 instead of 1.";
};
updateProcessNames = mkOption {
type = types.bool;
default = false;
description = "Update process names on every refresh.";
};
accountGuestInCpuMeter = mkOption {
type = types.bool;
default = false;
description = "Add guest time in CPU meter percentage.";
};
colorScheme = mkOption {
type = types.enum [ 0 1 2 3 4 5 6 ];
default = 0;
example = 6;
description = "Which color scheme to use.";
};
delay = mkOption {
type = types.int;
default = 15;
example = 2;
description = "Set the delay between updates, in tenths of seconds.";
};
meters = mkOption {
description = "Meters shown in the header.";
default = {
left = [ "AllCPUs" "Memory" "Swap" ];
right = [ "Tasks" "LoadAverage" "Uptime" ];
};
example = {
left = [
"Memory"
"CPU"
"LeftCPUs2"
"RightCPUs2"
{ kind = "CPU"; mode = 3; }
];
right = [
{ kind = "Clock"; mode = 4; }
"Uptime"
"Tasks"
"LoadAverage"
{ kind = "Battery"; mode = 1; }
];
};
type = meterType;
};
};
config = mkIf cfg.enable {
home.packages = [ pkgs.htop ];
xdg.configFile."htop/htoprc".text = let
leftMeters = map (m: m.kind) cfg.meters.left;
leftModes = map (m: m.mode) cfg.meters.left;
rightMeters = map (m: m.kind) cfg.meters.right;
rightModes = map (m: m.mode) cfg.meters.right;
in ''
# This file is regenerated by home-manager
# when options are changed in the config
fields=${list (map (n: fields.${n}) cfg.fields)}
sort_key=${toString (fields.${cfg.sortKey})}
sort_direction=${bool cfg.sortDescending}
hide_threads=${bool cfg.hideThreads}
hide_kernel_threads=${bool cfg.hideKernelThreads}
hide_userland_threads=${bool cfg.hideUserlandThreads}
shadow_other_users=${bool cfg.shadowOtherUsers}
show_thread_names=${bool cfg.showThreadNames}
show_program_path=${bool cfg.showProgramPath}
highlight_base_name=${bool cfg.highlightBaseName}
highlight_megabytes=${bool cfg.highlightMegabytes}
highlight_threads=${bool cfg.highlightThreads}
tree_view=${bool cfg.treeView}
header_margin=${bool cfg.headerMargin}
detailed_cpu_time=${bool cfg.detailedCpuTime}
cpu_count_from_zero=${bool cfg.cpuCountFromZero}
update_process_names=${bool cfg.updateProcessNames}
account_guest_in_cpu_meter=${bool cfg.accountGuestInCpuMeter}
color_scheme=${toString cfg.colorScheme}
delay=${toString cfg.delay}
left_meters=${list leftMeters}
left_meter_modes=${list leftModes}
right_meters=${list rightMeters}
right_meter_modes=${list rightModes}
'';
};
}

View File

@@ -21,13 +21,15 @@
{ config, lib, pkgs, ... }:
with lib;
with import ../lib/dag.nix;
let
cfg = config.programs.info;
dag = config.lib.dag;
# Indexes info files found in this location
homeInfoPath = "$HOME/.nix-profile/share/info";
homeInfoPath = "${config.home.profileDirectory}/share/info";
# Installs this package -- the interactive just means that it
# includes the curses `info` program. We also use `install-info`
@@ -42,7 +44,7 @@ in
enable = mkEnableOption "GNU Info";
homeInfoDirLocation = mkOption {
default = "$HOME/.cache/info";
default = "\${XDG_CACHE_HOME:-$HOME/.cache}/info";
description = ''
Directory in which to store the info <filename>dir</filename>
file within your home.
@@ -52,17 +54,12 @@ in
};
config = mkIf cfg.enable {
assertions = [{
assertion = config.home.sessionVariableSetter != "pam";
message = ''
The info module does not work with PAM as a session variable setter.
'';
}];
home.sessionVariables.INFOPATH =
"${cfg.homeInfoDirLocation}\${INFOPATH:+:}\${INFOPATH}";
home.activation.createHomeInfoDir = dagEntryAfter ["installPackages"] ''
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
@@ -70,8 +67,12 @@ in
-exec $DRY_RUN_CMD ${infoPkg}/bin/install-info '{}' \
"${cfg.homeInfoDirLocation}/dir" \;
fi
export PATH="$oPATH"
unset oPATH
'';
home.packages = [infoPkg];
home.packages = [ infoPkg ];
home.extraOutputsToInstall = [ "info" ];
};
}

211
modules/programs/irssi.nix Normal file
View File

@@ -0,0 +1,211 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.irssi;
boolStr = b: if b then "yes" else "no";
quoteStr = s: escape ["\""] s;
assignFormat = set:
concatStringsSep "\n"
(mapAttrsToList (k: v: " ${k} = \"${quoteStr v}\";") set);
chatnetString =
concatStringsSep "\n"
(flip mapAttrsToList cfg.networks
(k: v: ''
${k} = {
type = "${v.type}";
nick = "${quoteStr v.nick}";
autosendcmd = "${concatMapStringsSep ";" quoteStr v.autoCommands}";
};
''));
serversString =
concatStringsSep ",\n"
(flip mapAttrsToList cfg.networks
(k: v: ''
{
chatnet = "${k}";
address = "${v.server.address}";
port = "${toString v.server.port}";
use_ssl = "${boolStr v.server.ssl.enable}";
ssl_verify = "${boolStr v.server.ssl.verify}";
autoconnect = "${boolStr v.server.autoConnect}";
}
''));
channelString =
concatStringsSep ",\n"
(flip mapAttrsToList cfg.networks
(k: v:
concatStringsSep ",\n"
(flip mapAttrsToList v.channels
(c: cv: ''
{
chatnet = "${k}";
name = "${c}";
autojoin = "${boolStr cv.autoJoin}";
}
''))));
channelType = types.submodule {
options = {
name = mkOption {
type = types.nullOr types.str;
visible = false;
default = null;
description = "Name of the channel.";
};
autoJoin = mkOption {
type = types.bool;
default = false;
description = "Whether to join this channel on connect.";
};
};
};
networkType = types.submodule ({ name, ...}: {
options = {
name = mkOption {
visible = false;
default = name;
type = types.str;
};
nick = mkOption {
type = types.str;
description = "Nickname in that network.";
};
type = mkOption {
type = types.str;
description = "Type of the network.";
default = "IRC";
};
autoCommands = mkOption {
type = types.listOf types.str;
default = [];
description = "List of commands to execute on connect.";
};
server = {
address = mkOption {
type = types.str;
description = "Address of the chat server.";
};
port = mkOption {
type = types.int;
default = 6667;
description = "Port of the chat server.";
};
ssl = {
enable = mkOption {
type = types.bool;
default = true;
description = "Whether SSL should be used.";
};
verify = mkOption {
type = types.bool;
default = true;
description = "Whether the SSL certificate should be verified.";
};
};
autoConnect = mkOption {
type = types.bool;
default = false;
description = "Whether Irssi connects to the server on launch.";
};
};
channels = mkOption {
description = "Channels for the given network.";
type = types.attrsOf channelType;
default = {};
};
};
});
in
{
options = {
programs.irssi = {
enable = mkEnableOption "the Irssi chat client";
extraConfig = mkOption {
default = "";
description = "These lines are appended to the Irssi configuration.";
type = types.str;
};
aliases = mkOption {
default = {};
example = { J = "join"; BYE = "quit";};
description = "An attribute set that maps aliases to commands.";
type = types.attrsOf types.str;
};
networks = mkOption {
default = {};
example = literalExample ''
{
freenode = {
nick = "hmuser";
server = {
address = "chat.freenode.net";
port = 6697;
autoConnect = true;
};
channels = {
nixos.autoJoin = true;
};
};
}
'';
description = "An attribute set of chat networks.";
type = types.attrsOf networkType;
};
};
};
config = mkIf cfg.enable {
home.packages = [ pkgs.irssi ];
home.file.".irssi/config".text = ''
settings = {
core = {
settings_autosave = "no";
};
};
aliases = {
${assignFormat cfg.aliases}
};
chatnets = {
${chatnetString}
};
servers = (
${serversString}
);
channels = (
${channelString}
);
${cfg.extraConfig}
'';
};
}

76
modules/programs/jq.nix Normal file
View File

@@ -0,0 +1,76 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.jq;
colorType = mkOption {
type = types.str;
description = "ANSI color definition";
example = "1;31";
visible = false;
};
colorsType = types.submodule {
options = {
null = colorType;
false = colorType;
true = colorType;
numbers = colorType;
strings = colorType;
arrays = colorType;
objects = colorType;
};
};
in
{
options = {
programs.jq = {
enable = mkEnableOption "the jq command-line JSON processor";
colors = mkOption {
description = ''
The colors used in colored JSON output.</para>
<para>See <link xlink:href="https://stedolan.github.io/jq/manual/#Colors"/>.
'';
example = literalExample ''
{
null = "1;30";
false = "0;31";
true = "0;32";
numbers = "0;36";
strings = "0;33";
arrays = "1;35";
objects = "1;37";
}
'';
default = {
null = "1;30";
false = "0;39";
true = "0;39";
numbers = "0;39";
strings = "0;32";
arrays = "1;39";
objects = "1;39";
};
type = colorsType;
};
};
};
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}";
};
};
}

View File

@@ -3,6 +3,8 @@
with lib;
{
meta.maintainers = [ maintainers.rycee ];
options = {
programs.lesspipe = {
enable = mkEnableOption "lesspipe preprocessor for less";

22
modules/programs/man.nix Normal file
View File

@@ -0,0 +1,22 @@
{ config, lib, pkgs, ... }:
with lib;
{
options = {
programs.man.enable = mkOption {
type = types.bool;
default = true;
description = ''
Whether to enable manual pages and the <command>man</command>
command. This also includes "man" outputs of all
<literal>home.packages</literal>.
'';
};
};
config = mkIf config.programs.man.enable {
home.packages = [ pkgs.man ];
home.extraOutputsToInstall = [ "man" ];
};
}

View File

@@ -0,0 +1,64 @@
{ config, lib, ... }:
with lib;
let
cfg = config.programs.matplotlib;
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}");
in
{
meta.maintainers = [ maintainers.rprospero ];
options.programs.matplotlib = {
enable = mkEnableOption "matplotlib, a plotting library for python";
config = mkOption {
default = { };
type = types.attrs;
description = ''
Add terms to the <filename>matplotlibrc</filename> file to
control the default matplotlib behavior.
'';
example = literalExample ''
{
backend = "Qt5Agg";
axes = {
grid = true;
facecolor = "black";
edgecolor = "FF9900";
};
grid.color = "FF9900";
}
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Additional commands for matplotlib that will be added to the
<filename>matplotlibrc</filename> file.
'';
};
};
config = mkIf cfg.enable {
xdg.configFile."matplotlib/matplotlibrc".text =
concatStringsSep "\n" ([]
++ mapAttrsToList (formatLine "") cfg.config
++ optional (cfg.extraConfig != "") cfg.extraConfig
) + "\n";
};
}

View File

@@ -0,0 +1,107 @@
{ lib, ... }:
with lib;
let
extraConfigType = with lib.types; attrsOf (either (either str int) bool);
in
{
options.mbsync = {
enable = mkEnableOption "synchronization using mbsync";
flatten = mkOption {
type = types.nullOr types.str;
default = null;
example = ".";
description = ''
If set, flattens the hierarchy within the maildir by
substituting the canonical hierarchy delimiter
<literal>/</literal> with this value.
'';
};
create = mkOption {
type = types.enum [ "none" "maildir" "imap" "both" ];
default = "none";
example = "maildir";
description = ''
Automatically create missing mailboxes within the
given mail store.
'';
};
remove = mkOption {
type = types.enum [ "none" "maildir" "imap" "both" ];
default = "none";
example = "imap";
description = ''
Propagate mailbox deletions to the given mail store.
'';
};
expunge = mkOption {
type = types.enum [ "none" "maildir" "imap" "both" ];
default = "none";
example = "both";
description = ''
Permanently remove messages marked for deletion from
the given mail store.
'';
};
patterns = mkOption {
type = types.listOf types.str;
default = [ "*" ];
description = ''
Pattern of mailboxes to synchronize.
'';
};
extraConfig.channel = mkOption {
type = extraConfigType;
default = {};
example = literalExample ''
{
MaxMessages = 10000;
MaxSize = "1m";
};
'';
description = ''
Per channel extra configuration.
'';
};
extraConfig.local = mkOption {
type = extraConfigType;
default = {};
description = ''
Local store extra configuration.
'';
};
extraConfig.remote = mkOption {
type = extraConfigType;
default = {};
description = ''
Remote store extra configuration.
'';
};
extraConfig.account = mkOption {
type = extraConfigType;
default = {};
example = literalExample ''
{
PipelineDepth = 10;
Timeout = 60;
};
'';
description = ''
Account section extra configuration.
'';
};
};
}

188
modules/programs/mbsync.nix Normal file
View File

@@ -0,0 +1,188 @@
{ config, lib, pkgs, ... }:
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) {
CertificateFile = tls.certificatesFile;
};
masterSlaveMapping = {
none = "None";
imap = "Master";
maildir = "Slave";
both = "Both";
};
genSection = header: entries:
let
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
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";
genGroupConfig = name: channels:
let
genGroupChannel = n: boxes: "Channel ${n}:${concatStringsSep "," boxes}";
in
concatStringsSep "\n" (
[ "Group ${name}" ] ++ mapAttrsToList genGroupChannel channels
);
in
{
options = {
programs.mbsync = {
enable = mkEnableOption "mbsync IMAP4 and Maildir mailbox synchronizer";
package = mkOption {
type = types.package;
default = pkgs.isync;
defaultText = "pkgs.isync";
example = literalExample "pkgs.isync";
description = "The package to use for the mbsync binary.";
};
groups = mkOption {
type = types.attrsOf (types.attrsOf (types.listOf types.str));
default = {};
example = literalExample ''
{
inboxes = {
account1 = [ "Inbox" ];
account2 = [ "Inbox" ];
};
}
'';
description = ''
Definition of groups.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Extra configuration lines to add to the mbsync configuration.
'';
};
};
};
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")
];
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" ]
++ accountsConfig
++ groupsConfig
++ optional (cfg.extraConfig != "") cfg.extraConfig
) + "\n";
home.activation.createMaildir =
dag.entryBetween [ "linkGeneration" ] [ "writeBoundary" ] ''
$DRY_RUN_CMD mkdir -m700 -p $VERBOSE_ARG ${
concatMapStringsSep " " (a: a.maildir.absPath) mbsyncAccounts
}
'';
};
}

View File

@@ -0,0 +1,102 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.mercurial;
in
{
options = {
programs.mercurial = {
enable = mkEnableOption "Mercurial";
package = mkOption {
type = types.package;
default = pkgs.mercurial;
defaultText = "pkgs.mercurial";
description = "Mercurial package to install.";
};
userName = mkOption {
type = types.str;
description = "Default user name to use.";
};
userEmail = mkOption {
type = types.str;
description = "Default user email to use.";
};
aliases = mkOption {
type = types.attrs;
default = {};
description = "Mercurial aliases to define.";
};
extraConfig = mkOption {
type = types.either types.attrs types.lines;
default = {};
description = "Additional configuration to add.";
};
iniContent = mkOption {
type = types.attrsOf types.attrs;
internal = true;
};
ignores = mkOption {
type = types.listOf types.str;
default = [];
example = [ "*~" "*.swp" ];
description = "List of globs for files to be globally ignored.";
};
ignoresRegexp = mkOption {
type = types.listOf types.str;
default = [];
example = [ "^.*~$" "^.*\\.swp$" ];
description =
"List of regular expressions for files to be globally ignored.";
};
};
};
config = mkIf cfg.enable (
mkMerge [
{
home.packages = [ cfg.package ];
programs.mercurial.iniContent.ui = {
username = cfg.userName + " <" + cfg.userEmail + ">";
};
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";
xdg.configFile."hg/hgignore_global".text =
"syntax: glob\n" + concatStringsSep "\n" cfg.ignores + "\n" +
"syntax: regexp\n" + concatStringsSep "\n" cfg.ignoresRegexp + "\n";
})
(mkIf (cfg.aliases != {}) {
programs.mercurial.iniContent.alias = cfg.aliases;
})
(mkIf (lib.isAttrs cfg.extraConfig) {
programs.mercurial.iniContent = cfg.extraConfig;
})
(mkIf (lib.isString cfg.extraConfig) {
xdg.configFile."hg/hgrc".text = cfg.extraConfig;
})
]
);
}

View File

@@ -0,0 +1,36 @@
{ config, lib, ... }:
with lib;
{
options.msmtp = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable msmtp.
</para><para>
If enabled then it is possible to use the
<parameter class="command">--account</parameter> command line
option to send a message for a given account using the
<command>msmtp</command> or <command>msmtpq</command> tool.
For example, <command>msmtp --account=private</command> would
send using the account defined in
<option>accounts.email.accounts.private</option>. If the
<parameter class="command">--account</parameter> option is not
given then the primary account will be used.
'';
};
extraConfig = mkOption {
type = types.attrsOf types.str;
default = { };
example = { auth = "login"; };
description = ''
Extra configuration options to add to <filename>~/.msmtprc</filename>.
See <link xlink:href="https://marlam.de/msmtp/msmtprc.txt"/> for
examples.
'';
};
};
}

View File

@@ -0,0 +1,76 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.msmtp;
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 (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}"
);
configFile = mailAccounts: ''
# Generated by Home Manager.
${cfg.extraConfig}
${concatStringsSep "\n\n" (map accountStr mailAccounts)}
'';
in
{
options = {
programs.msmtp = {
enable = mkEnableOption "msmtp";
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Extra configuration lines to add to <filename>~/.msmtprc</filename>.
See <link xlink:href="https://marlam.de/msmtp/msmtprc.txt"/> for examples.
'';
};
};
};
config = mkIf cfg.enable {
home.packages = [ pkgs.msmtp ];
xdg.configFile."msmtp/config".text = configFile msmtpAccounts;
home.sessionVariables = {
MSMTP_QUEUE = "${config.xdg.dataHome}/msmtp/queue";
MSMTP_LOG = "${config.xdg.dataHome}/msmtp/queue.log";
};
};
}

139
modules/programs/neovim.nix Normal file
View File

@@ -0,0 +1,139 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.neovim;
extraPythonPackageType = mkOptionType {
name = "extra-python-packages";
description = "python packages in python.withPackages format";
check = with types; (x: if isFunction x
then isList (x pkgs.pythonPackages)
else false);
merge = mergeOneOption;
};
extraPython3PackageType = mkOptionType {
name = "extra-python3-packages";
description = "python3 packages in python.withPackages format";
check = with types; (x: if isFunction x
then isList (x pkgs.python3Packages)
else false);
merge = mergeOneOption;
};
in
{
options = {
programs.neovim = {
enable = mkEnableOption "Neovim";
viAlias = mkOption {
type = types.bool;
default = false;
description = ''
Symlink `vi` to `nvim` binary.
'';
};
vimAlias = mkOption {
type = types.bool;
default = false;
description = ''
Symlink `vim` to `nvim` binary.
'';
};
withPython = mkOption {
type = types.bool;
default = true;
description = ''
Enable Python 2 provider. Set to <literal>true</literal> to
use Python 2 plugins.
'';
};
extraPythonPackages = mkOption {
type = with types; either extraPythonPackageType (listOf package);
default = (_: []);
defaultText = "ps: []";
example = literalExample "(ps: with ps; [ pandas jedi ])";
description = ''
A function in python.withPackages format, which returns a
list of Python 2 packages required for your plugins to work.
'';
};
withRuby = mkOption {
type = types.nullOr types.bool;
default = true;
description = ''
Enable ruby provider.
'';
};
withPython3 = mkOption {
type = types.bool;
default = true;
description = ''
Enable Python 3 provider. Set to <literal>true</literal> to
use Python 3 plugins.
'';
};
extraPython3Packages = mkOption {
type = with types; either extraPython3PackageType (listOf package);
default = (_: []);
defaultText = "ps: []";
example = literalExample "(ps: with ps; [ python-language-server ])";
description = ''
A function in python.withPackages format, which returns a
list of Python 3 packages required for your plugins to work.
'';
};
package = mkOption {
type = types.package;
default = pkgs.neovim-unwrapped;
defaultText = "pkgs.neovim-unwrapped";
description = "The package to use for the neovim binary.";
};
configure = mkOption {
type = types.attrs;
default = {};
example = literalExample ''
configure = {
customRC = $''''
" here your custom configuration goes!
$'''';
packages.myVimPackage = with pkgs.vimPlugins; {
# loaded on launch
start = [ fugitive ];
# manually loadable by calling `:packadd $plugin-name`
opt = [ ];
};
};
'';
description = ''
Generate your init file from your list of plugins and custom commands,
and loads it from the store via <command>nvim -u /nix/store/hash-vimrc</command>
'';
};
};
};
config = mkIf cfg.enable {
home.packages = [
(pkgs.wrapNeovim cfg.package {
inherit (cfg)
extraPython3Packages withPython3
extraPythonPackages withPython
withRuby viAlias vimAlias configure;
})
];
};
}

View File

@@ -0,0 +1,98 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.newsboat;
wrapQuote = x: "\"${x}\"";
in
{
options = {
programs.newsboat = {
enable = mkEnableOption "the Newsboat feed reader";
urls = mkOption {
type = types.listOf types.attrs;
default = [];
example = [{url = "http://example.com"; tags = ["foo" "bar"];}];
description = "List of urls and tokens.";
};
maxItems = mkOption {
type = types.int;
default = 0;
description = "Maximum number of items per feed, 0 for infinite.";
};
reloadThreads = mkOption {
type = types.int;
default = 5;
description = "How many threads to use for updating the feeds.";
};
autoReload = mkOption {
type = types.bool;
default = false;
description = "Whether to enable automatic reloading while newsboat is running.";
};
reloadTime = mkOption {
type = types.nullOr types.int;
default = 60;
description = "Time in minutes between reloads.";
};
browser = mkOption {
type = types.str;
default = "${pkgs.xdg_utils}/bin/xdg-open";
description = "External browser to use.";
};
queries = mkOption {
type = types.attrsOf types.str;
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.";
};
};
};
config = mkIf cfg.enable {
home.packages = [ pkgs.newsboat ];
home.file.".newsboat/urls".text =
let
urls = builtins.concatStringsSep "\n" (
map (u: builtins.concatStringsSep " " ([u.url] ++ (map wrapQuote u.tags)))
cfg.urls);
queries = builtins.concatStringsSep "\n" (
mapAttrsToList (n: v: "\"query:${n}:${escape ["\""] v}\"") cfg.queries);
in
''
${urls}
${queries}
'';
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}")}
prepopulate-query-feeds yes
${cfg.extraConfig}
'';
};
}

53
modules/programs/noti.nix Normal file
View File

@@ -0,0 +1,53 @@
{ config, lib, pkgs, ...}:
with lib;
let
cfg = config.programs.noti;
in
{
meta.maintainers = [ maintainers.marsam ];
options.programs.noti = {
enable = mkEnableOption "Noti";
settings = mkOption {
type = types.attrsOf (types.attrsOf types.str);
default = {};
description = ''
Configuration written to
<filename>~/.config/noti/noti.yaml</filename>.
</para><para>
See
<citerefentry>
<refentrytitle>noti.yaml</refentrytitle>
<manvolnum>5</manvolnum>
</citerefentry>.
for the full list of options.
'';
example = literalExample ''
{
say = {
voice = "Alex";
};
slack = {
token = "1234567890abcdefg";
channel = "@jaime";
};
}
'';
};
};
config = mkIf cfg.enable {
home.packages = [ pkgs.noti ];
xdg.configFile."noti/noti.yaml" = mkIf (cfg.settings != {}) {
text = generators.toYAML {} cfg.settings;
};
};
}

View File

@@ -0,0 +1,7 @@
{ lib, ... }:
{
options.notmuch = {
enable = lib.mkEnableOption "notmuch indexing";
};
}

View File

@@ -0,0 +1,196 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.notmuch;
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 "address" secondaries;
};
search = {
exclude_tags = [ "deleted" "spam" ];
};
}
cfg.extraConfig;
in
{
options = {
programs.notmuch = {
enable = mkEnableOption "Notmuch mail indexer";
new = mkOption {
type = types.submodule {
options = {
ignore = mkOption {
type = types.listOf types.str;
default = [];
description = ''
A list to specify files and directories that will not be
searched for messages by <command>notmuch new</command>.
'';
};
tags = mkOption {
type = types.listOf types.str;
default = [ "unread" "inbox" ];
example = [ "new" ];
description = ''
A list of tags that will be added to all messages
incorporated by <command>notmuch new</command>.
'';
};
};
};
default = {};
description = ''
Options related to email processing performed by
<command>notmuch new</command>.
'';
};
extraConfig = mkOption {
type = types.attrsOf (types.attrsOf types.str);
default = {};
description = ''
Options that should be appended to the notmuch configuration file.
'';
};
hooks = {
preNew = mkOption {
type = types.lines;
default = "";
example = "mbsync --all";
description = ''
Bash statements run before scanning or importing new
messages into the database.
'';
};
postNew = mkOption {
type = types.lines;
default = "";
example = ''
notmuch tag +nixos -- tag:new and from:nixos1@discoursemail.com
'';
description = ''
Bash statements run after new messages have been imported
into the database and initial tags have been applied.
'';
};
postInsert = mkOption {
type = types.lines;
default = "";
description = ''
Bash statements run after a message has been inserted
into the database and initial tags have been applied.
'';
};
};
maildir = {
synchronizeFlags = mkOption {
type = types.bool;
default = true;
description = ''
Whether to synchronize Maildir flags.
'';
};
};
};
};
config = mkIf cfg.enable {
assertions = [
{
assertion = notmuchIni.user.name != [];
message = "notmuch: Must have a user name set.";
}
{
assertion = notmuchIni.user.primary_email != [];
message = "notmuch: Must have a user primary email address set.";
}
];
home.packages = [ pkgs.notmuch ];
home.sessionVariables = {
NOTMUCH_CONFIG = "${config.xdg.configHome}/notmuch/notmuchrc";
NMBGIT = "${config.xdg.dataHome}/notmuch/nmbug";
};
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.stdenv.shell}
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);
};
}

View File

@@ -0,0 +1,53 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.obs-studio;
package = pkgs.obs-studio;
mkPluginEnv = packages:
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
{
meta.maintainers = [ maintainers.adisbladis ];
options = {
programs.obs-studio = {
enable = mkEnableOption "obs-studio";
plugins = mkOption {
default = [];
example = literalExample "[ pkgs.obs-linuxbrowser ]";
description = "Optional OBS plugins.";
type = types.listOf types.package;
};
};
};
config = mkIf cfg.enable {
home.packages = [ package ];
xdg.configFile."obs-studio/plugins" = mkIf (cfg.plugins != []) {
source = mkPluginEnv cfg.plugins;
};
};
}

View File

@@ -0,0 +1,57 @@
{ config, lib, ... }:
with lib;
let
extraConfigType = with types; attrsOf (either (either str int) bool);
in
{
options.offlineimap = {
enable = mkEnableOption "OfflineIMAP";
extraConfig.account = mkOption {
type = extraConfigType;
default = {};
example = {
autorefresh = 20;
};
description = ''
Extra configuration options to add to the account section.
'';
};
extraConfig.local = mkOption {
type = extraConfigType;
default = {};
example = {
sync_deletes = true;
};
description = ''
Extra configuration options to add to the local account
section.
'';
};
extraConfig.remote = mkOption {
type = extraConfigType;
default = {};
example = {
maxconnections = 2;
expunge = false;
};
description = ''
Extra configuration options to add to the remote account
section.
'';
};
postSyncHookCommand = mkOption {
type = types.lines;
default = "";
description = "Command to run after fetching new mails.";
};
};
}

View File

@@ -0,0 +1,207 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.offlineimap;
accounts = filter (a: a.offlineimap.enable)
(attrValues config.accounts.email.accounts);
toIni = generators.toINI {
mkKeyValue = key: value:
let
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.
#
# Note, these scripts are not actually created and installed at the
# moment. It will need some thinking on whether this is a good idea
# and whether other modules should have some similar functionality.
#
# Perhaps have a single tool `email` that wraps the command?
# Something like
#
# $ email <account name> <program name> <program args>
genOfflineImapScript = account: with account;
pkgs.writeShellScriptBin "offlineimap-${name}" ''
exec ${pkgs.offlineimap}/bin/offlineimap -a${account.name} "$@"
'';
accountStr = account: with account;
let
postSyncHook = optionalAttrs (offlineimap.postSyncHookCommand != "") {
postsynchook =
pkgs.writeShellScriptBin
"postsynchook"
offlineimap.postSyncHookCommand
+ "/bin/postsynchook";
};
localType =
if account.flavor == "gmail.com"
then "GmailMaildir"
else "Maildir";
remoteType =
if account.flavor == "gmail.com"
then "Gmail"
else "IMAP";
remoteHost = optionalAttrs (imap.host != null) {
remotehost = imap.host;
};
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;
};
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
// offlineimap.extraConfig.remote;
};
extraConfigType = with types; attrsOf (either (either str int) bool);
in
{
options = {
programs.offlineimap = {
enable = mkEnableOption "OfflineIMAP";
pythonFile = mkOption {
type = types.lines;
default = ''
import subprocess
def get_pass(service, cmd):
return subprocess.check_output(cmd, )
'';
description = ''
Python code that can then be used in other parts of the
configuration.
'';
};
extraConfig.general = mkOption {
type = extraConfigType;
default = {};
example = {
maxage = 30;
ui = "blinkenlights";
};
description = ''
Extra configuration options added to the
<option>general</option> section.
'';
};
extraConfig.default = mkOption {
type = extraConfigType;
default = {};
example = {
gmailtrashfolder = "[Gmail]/Papierkorb";
};
description = ''
Extra configuration options added to the
<option>DEFAULT</option> section.
'';
};
extraConfig.mbnames = mkOption {
type = extraConfigType;
default = {};
example = literalExample ''
{
filename = "~/.config/mutt/mailboxes";
header = "'mailboxes '";
peritem = "'+%(accountname)s/%(foldername)s'";
sep = "' '";
footer = "'\\n'";
}
'';
description = ''
Extra configuration options added to the
<code>mbnames</code> section.
'';
};
};
};
config = mkIf cfg.enable {
home.packages = [ pkgs.offlineimap ];
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);
};
}

52
modules/programs/opam.nix Normal file
View File

@@ -0,0 +1,52 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.opam;
in
{
meta.maintainers = [ maintainers.marsam ];
options.programs.opam = {
enable = mkEnableOption "Opam";
package = mkOption {
type = types.package;
default = pkgs.opam;
defaultText = "pkgs.opam";
description = "Opam package to install.";
};
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.
'';
};
};
config = mkIf cfg.enable {
home.packages = [ cfg.package ];
programs.bash.initExtra = mkIf cfg.enableBashIntegration ''
eval "$(${cfg.package}/bin/opam env --shell=bash)"
'';
programs.zsh.initExtra = mkIf cfg.enableZshIntegration ''
eval "$(${cfg.package}/bin/opam env --shell=zsh)"
'';
};
}

View File

@@ -0,0 +1,36 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.pidgin;
in
{
meta.maintainers = [ maintainers.rycee ];
options = {
programs.pidgin = {
enable = mkEnableOption "Pidgin messaging client";
package = mkOption {
type = types.package;
default = pkgs.pidgin;
defaultText = "pkgs.pidgin";
description = "The Pidgin package to use.";
};
plugins = mkOption {
default = [];
example = literalExample "[ pkgs.pidgin-otr pkgs.pidgin-osd ]";
description = "Plugins that should be available to Pidgin.";
};
};
};
config = mkIf cfg.enable {
home.packages = [ (cfg.package.override { inherit (cfg) plugins; }) ];
};
}

339
modules/programs/rofi.nix Normal file
View File

@@ -0,0 +1,339 @@
{ config, lib, pkgs, ... }:
with lib;
with builtins;
let
cfg = config.programs.rofi;
colorOption = description: mkOption {
type = types.str;
description = description;
};
rowColorSubmodule = types.submodule {
options = {
background = colorOption "Background color";
foreground = colorOption "Foreground color";
backgroundAlt = colorOption "Alternative background color";
highlight = mkOption {
type = types.submodule {
options = {
background = colorOption "Highlight background color";
foreground = colorOption "Highlight foreground color";
};
};
description = "Color settings for highlighted row.";
};
};
};
windowColorSubmodule = types.submodule {
options = {
background = colorOption "Window background color";
border = colorOption "Window border color";
separator = colorOption "Separator color";
};
};
colorsSubmodule = types.submodule {
options = {
window = mkOption {
default = null;
type = windowColorSubmodule;
description = "Window color settings.";
};
rows = mkOption {
default = null;
type = types.submodule {
options = {
normal = mkOption {
default = null;
type = types.nullOr rowColorSubmodule;
description = "Normal row color settings.";
};
active = mkOption {
default = null;
type = types.nullOr rowColorSubmodule;
description = "Active row color settings.";
};
urgent = mkOption {
default = null;
type = types.nullOr rowColorSubmodule;
description = "Urgent row color settings.";
};
};
};
description = "Rows color settings.";
};
};
};
valueToString = value:
if isBool value
then (if value then "true" else "else")
else toString value;
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))}
'';
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)}
'';
locationsMap = {
center = 0;
top-left = 1;
top = 2;
top-right = 3;
right = 4;
bottom-right = 5;
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);
themePath = if (lib.isString cfg.theme) then null else cfg.theme;
in
{
options.programs.rofi = {
enable = mkEnableOption "Rofi: A window switcher, application launcher and dmenu replacement";
width = mkOption {
default = null;
type = types.nullOr types.int;
description = "Window width";
example = 100;
};
lines = mkOption {
default = null;
type = types.nullOr types.int;
description = "Number of lines";
example = 10;
};
borderWidth = mkOption {
default = null;
type = types.nullOr types.int;
description = "Border width";
example = 1;
};
rowHeight = mkOption {
default = null;
type = types.nullOr types.int;
description = "Row height (in chars)";
example = 1;
};
padding = mkOption {
default = null;
type = types.nullOr types.int;
description = "Padding";
example = 400;
};
font = mkOption {
default = null;
type = types.nullOr types.str;
example = "Droid Sans Mono 14";
description = "Font to use.";
};
scrollbar = mkOption {
default = null;
type = types.nullOr types.bool;
description = "Whether to show a scrollbar.";
};
terminal = mkOption {
default = null;
type = types.nullOr types.str;
description = ''
Path to the terminal which will be used to run console applications
'';
example = "\${pkgs.gnome3.gnome_terminal}/bin/gnome-terminal";
};
separator = mkOption {
default = null;
type = types.nullOr (types.enum [ "none" "dash" "solid" ]);
description = "Separator style";
example = "solid";
};
cycle = mkOption {
default = null;
type = types.nullOr types.bool;
description = "Whether to cycle through the results list.";
};
fullscreen = mkOption {
default = null;
type = types.nullOr types.bool;
description = "Whether to run rofi fullscreen.";
};
location = mkOption {
default = "center";
type = types.enum (builtins.attrNames locationsMap);
description = "The location rofi appears on the screen.";
};
xoffset = mkOption {
default = 0;
type = types.int;
description = ''
Offset in the x-axis in pixels relative to the chosen location.
'';
};
yoffset = mkOption {
default = 0;
type = types.int;
description = ''
Offset in the y-axis in pixels relative to the chosen location.
'';
};
colors = mkOption {
default = null;
type = types.nullOr colorsSubmodule;
description = ''
Color scheme settings. Colors can be specified in CSS color
formats. This option may become deprecated in the future and
therefore the <varname>programs.rofi.theme</varname> option
should be used whenever possible.
'';
example = literalExample ''
colors = {
window = {
background = "argb:583a4c54";
border = "argb:582a373e";
separator = "#c3c6c8";
};
rows = {
normal = {
background = "argb:58455a64";
foreground = "#fafbfc";
backgroundAlt = "argb:58455a64";
highlight = {
background = "#00bcd4";
foreground = "#fafbfc";
};
};
};
};
'';
};
theme = mkOption {
default = null;
type = with types; nullOr (either string path);
example = "Arc";
description = ''
Name of theme or path to theme file in rasi format. Available
named themes can be viewed using the
<command>rofi-theme-selector</command> tool.
'';
};
configPath = mkOption {
default = "${config.xdg.configHome}/rofi/config";
defaultText = "$XDG_CONFIG_HOME/rofi/config";
type = types.str;
description = "Path where to put generated configuration file.";
};
extraConfig = mkOption {
default = "";
type = types.lines;
description = "Additional configuration to add.";
};
};
config = mkIf cfg.enable {
assertions = [
{
assertion = cfg.theme == null || cfg.colors == null;
message = ''
Cannot use the rofi options 'theme' and 'colors' simultaneously.
'';
}
];
home.packages = [ pkgs.rofi ];
home.file."${cfg.configPath}".text = ''
${setOption "width" cfg.width}
${setOption "lines" cfg.lines}
${setOption "font" cfg.font}
${setOption "bw" cfg.borderWidth}
${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 "terminal" cfg.terminal}
${setOption "cycle" cfg.cycle}
${setOption "fullscreen" cfg.fullscreen}
${setOption "location" (builtins.getAttr cfg.location locationsMap)}
${setOption "xoffset" cfg.xoffset}
${setOption "yoffset" cfg.yoffset}
${setColorScheme cfg.colors}
${setOption "theme" themeName}
${cfg.extraConfig}
'';
xdg.dataFile = mkIf (themePath != null) {
"rofi/themes/${themeName}.rasi".source = themePath;
};
};
}

View File

@@ -8,7 +8,9 @@ let
yn = flag: if flag then "yes" else "no";
matchBlockModule = types.submodule {
unwords = builtins.concatStringsSep " ";
matchBlockModule = types.submodule ({ name, ... }: {
options = {
host = mkOption {
type = types.str;
@@ -24,6 +26,15 @@ let
description = "Specifies port number to connect on remote host.";
};
forwardAgent = mkOption {
default = null;
type = types.nullOr types.bool;
description = ''
Whether the connection to the authentication agent (if any)
will be forwarded to the remote machine.
'';
};
forwardX11 = mkOption {
type = types.bool;
default = false;
@@ -55,10 +66,15 @@ let
};
identityFile = mkOption {
type = types.nullOr types.str;
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 identity is read.
Specifies files from which the user identity is read.
Identities will be tried in the given order.
'';
};
@@ -81,6 +97,24 @@ let
"Set timeout in seconds after which response will be requested.";
};
sendEnv = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Environment variables to send from the local host to the
server.
'';
};
compression = mkOption {
type = types.nullOr types.bool;
default = null;
description = ''
Specifies whether to use compression. Omitted from the host
block when <literal>null</literal>.
'';
};
checkHostIP = mkOption {
type = types.bool;
default = true;
@@ -95,27 +129,66 @@ let
default = null;
description = "The command to use to connect to the server.";
};
proxyJump = mkOption {
type = types.nullOr types.str;
default = null;
description = "The proxy host to use to connect to the server.";
};
certificateFile = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
Specifies a file from which the user certificate is read.
'';
};
addressFamily = mkOption {
default = null;
type = types.nullOr (types.enum ["any" "inet" "inet6"]);
description = ''
Specifies which address family to use when connecting.
'';
};
extraOptions = mkOption {
type = types.attrsOf types.str;
default = {};
description = "Extra configuration options for the host.";
};
};
};
config.host = mkDefault name;
});
matchBlockStr = cf: concatStringsSep "\n" (
["Host ${cf.host}"]
++ optional (cf.port != null) " Port ${toString cf.port}"
++ optional cf.forwardX11 " ForwardX11 yes"
++ optional cf.forwardX11Trusted " ForwardX11Trusted yes"
++ optional cf.identitiesOnly " IdentitiesOnly yes"
++ optional (cf.user != null) " User ${cf.user}"
++ optional (cf.identityFile != null) " IdentityFile ${cf.identityFile}"
++ optional (cf.hostname != null) " HostName ${cf.hostname}"
++ optional (cf.port != null) " Port ${toString cf.port}"
++ optional (cf.forwardAgent != null) " ForwardAgent ${yn cf.forwardAgent}"
++ optional cf.forwardX11 " ForwardX11 yes"
++ 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}"
++ optional (cf.serverAliveInterval != 0)
" ServerAliveInterval ${toString cf.serverAliveInterval}"
++ optional (!cf.checkHostIP) " CheckHostIP no"
++ optional (cf.proxyCommand != null) " ProxyCommand ${cf.proxyCommand}"
++ optional (cf.compression != null) " Compression ${yn cf.compression}"
++ optional (!cf.checkHostIP) " CheckHostIP no"
++ optional (cf.proxyCommand != null) " ProxyCommand ${cf.proxyCommand}"
++ optional (cf.proxyJump != null) " ProxyJump ${cf.proxyJump}"
++ map (file: " IdentityFile ${file}") cf.identityFile
++ mapAttrsToList (n: v: " ${n} ${v}") cf.extraOptions
);
in
{
meta.maintainers = [ maintainers.rycee ];
options.programs.ssh = {
enable = mkEnableOption "SSH client configuration";
@@ -123,8 +196,46 @@ in
default = false;
type = types.bool;
description = ''
Whether connection to authentication agent (if any) will be forwarded
to remote machine.
Whether the connection to the authentication agent (if any)
will be forwarded to the remote machine.
'';
};
compression = mkOption {
default = false;
type = types.bool;
description = "Specifies whether to use compression.";
};
serverAliveInterval = mkOption {
type = types.int;
default = 0;
description = ''
Set default timeout in seconds after which response will be requested.
'';
};
hashKnownHosts = mkOption {
default = false;
type = types.bool;
description = ''
Indicates that
<citerefentry>
<refentrytitle>ssh</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>
should hash host names and addresses when they are added to
the known hosts file.
'';
};
userKnownHostsFile = mkOption {
type = types.str;
default = "~/.ssh/known_hosts";
description = ''
Specifies one or more files to use for the user host key
database, separated by whitespace. The default is
<filename>~/.ssh/known_hosts</filename>.
'';
};
@@ -138,28 +249,84 @@ in
controlPath = mkOption {
type = types.str;
default = "~/.ssh/master-%r@%h:%p";
default = "~/.ssh/master-%r@%n:%p";
description = ''
Specify path to the control socket used for connection sharing.
'';
};
matchBlocks = mkOption {
type = types.listOf matchBlockModule;
default = [];
controlPersist = mkOption {
type = types.str;
default = "no";
example = "10m";
description = ''
Specify per-host settings.
Whether control socket should remain open in the background.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Extra configuration.
'';
};
extraOptionOverrides = mkOption {
type = types.attrsOf types.str;
default = {};
description = ''
Extra SSH configuration options that take precedence over any
host specific configuration.
'';
};
matchBlocks = mkOption {
type = types.loaOf matchBlockModule;
default = {};
example = literalExample ''
{
"john.example.com" = {
hostname = "example.com";
user = "john";
};
foo = {
hostname = "example.com";
identityFile = "/home/john/.ssh/foo_rsa";
};
};
'';
description = ''
Specify per-host settings. Note, if the order of rules matter
then this must be a list. See
<citerefentry>
<refentrytitle>ssh_config</refentrytitle>
<manvolnum>5</manvolnum>
</citerefentry>.
'';
};
};
config = mkIf cfg.enable {
home.file.".ssh/config".text = ''
ForwardAgent ${yn cfg.forwardAgent}
ControlMaster ${cfg.controlMaster}
ControlPath ${cfg.controlPath}
${concatStringsSep "\n" (
mapAttrsToList (n: v: "${n} ${v}") cfg.extraOptionOverrides)}
${concatStringsSep "\n\n" (map matchBlockStr cfg.matchBlocks)}
${concatStringsSep "\n\n" (
map matchBlockStr (
builtins.attrValues cfg.matchBlocks))}
Host *
ForwardAgent ${yn cfg.forwardAgent}
Compression ${yn cfg.compression}
ServerAliveInterval ${toString cfg.serverAliveInterval}
HashKnownHosts ${yn cfg.hashKnownHosts}
UserKnownHostsFile ${cfg.userKnownHostsFile}
ControlMaster ${cfg.controlMaster}
ControlPath ${cfg.controlPath}
ControlPersist ${cfg.controlPersist}
${replaceStrings ["\n"] ["\n "] cfg.extraConfig}
'';
};
}

View File

@@ -0,0 +1,112 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.taskwarrior;
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}";
formatValue = 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}";
formatSet = key: values:
(concatStringsSep "\n"
(mapAttrsToList
(subKey: subValue: formatPair "${key}.${subKey}" subValue)
values));
formatPair = key: value:
if isAttrs value then formatSet key value
else formatLine key value;
in
{
options = {
programs.taskwarrior = {
enable = mkEnableOption "Task Warrior";
config = mkOption {
type = types.attrs;
default = {};
example = literalExample ''
{
confirmation = false;
report.minimal.filter = "status:pending";
report.active.columns = [ "id" "start" "entry.age" "priority" "project" "due" "description" ];
report.active.labels = [ "ID" "Started" "Age" "Priority" "Project" "Due" "Description" ];
taskd = {
certificate = "/path/to/cert";
key = "/path/to/key";
ca = "/path/to/ca";
server = "host.domain:53589";
credentials = "Org/First Last/cf31f287-ee9e-43a8-843e-e8bbd5de4294";
};
}
'';
description = ''
Key-value configuration written to
<filename>~/.taskrc</filename>.
'';
};
dataLocation = mkOption {
type = types.str;
default = "${config.xdg.dataHome}/task";
defaultText = "$XDG_DATA_HOME/task";
description = ''
Location where Task Warrior will store its data.
</para><para>
Home Manager will attempt to create this directory.
'';
};
colorTheme = mkOption {
type = with types; nullOr (either str path);
default = null;
example = "dark-blue-256";
description = ''
Either one of the default provided theme as string, or a
path to a theme configuration file.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Additional content written at the end of
<filename>~/.taskrc</filename>.
'';
};
};
};
config = mkIf cfg.enable {
home.packages = [ pkgs.taskwarrior ];
home.file."${cfg.dataLocation}/.keep".text = "";
home.file.".taskrc".text = ''
data.location=${cfg.dataLocation}
${includeTheme cfg.colorTheme}
${concatStringsSep "\n" (
mapAttrsToList formatPair cfg.config)}
${cfg.extraConfig}
'';
};
}

View File

@@ -0,0 +1,378 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.termite;
vteInitStr = ''
# See https://github.com/thestinger/termite#id1
if [[ $TERM == xterm-termite ]]; then
. ${pkgs.gnome3.vte-ng}/etc/profile.d/vte.sh
fi
'';
in
{
options = {
programs.termite = {
enable = mkEnableOption "Termite VTE-based terminal";
allowBold = mkOption {
default = null;
type = types.nullOr types.bool;
description = ''
Allow the output of bold characters when the bold escape sequence appears.
'';
};
audibleBell = mkOption {
default = null;
type = types.nullOr types.bool;
description = "Have the terminal beep on the terminal bell.";
};
clickableUrl = mkOption {
default = null;
type = types.nullOr types.bool;
description = ''
Auto-detected URLs can be clicked on to open them in your browser.
Only enabled if a browser is configured or detected.
'';
};
dynamicTitle = mkOption {
default = null;
type = types.nullOr types.bool;
description = ''
Settings dynamic title allows the terminal and the shell to
update the terminal's title.
'';
};
fullscreen = mkOption {
default = null;
type = types.nullOr types.bool;
description = "Enables entering fullscreen mode by pressing F11.";
};
mouseAutohide = mkOption {
default = null;
type = types.nullOr types.bool;
description = "Automatically hide the mouse pointer when you start typing.";
};
scrollOnOutput = mkOption {
default = null;
type = types.nullOr types.bool;
description = "Scroll to the bottom when the shell generates output.";
};
scrollOnKeystroke = mkOption {
default = null;
type = types.nullOr types.bool;
description = "Scroll to the bottom automatically when a key is pressed.";
};
searchWrap = mkOption {
default = null;
type = types.nullOr types.bool;
description = "Search from top again when you hit the bottom.";
};
urgentOnBell = mkOption {
default = null;
type = types.nullOr types.bool;
description = "Sets the window as urgent on the terminal bell.";
};
font = mkOption {
default = null;
example = "Monospace 12";
type = types.nullOr types.str;
description = "The font description for the terminal's font.";
};
geometry = mkOption {
default = null;
example = "640x480";
type = types.nullOr types.str;
description = "The default window geometry for new terminal windows.";
};
iconName = mkOption {
default = null;
example = "terminal";
type = types.nullOr types.str;
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.";
};
browser = mkOption {
default = null;
type = types.nullOr types.str;
example = "${pkgs.xdg_utils}/xdg-open";
description = ''
Set the default browser for opening links. If its not set, $BROWSER is read.
If that's not set, url hints will be disabled.
'';
};
cursorBlink = mkOption {
default = null;
example = "system";
type = types.nullOr (types.enum [ "system" "on" "off" ]);
description = ''
Specify the how the terminal's cursor should behave.
Accepts system to respect the gtk global configuration,
on and off to explicitly enable or disable them.
'';
};
cursorShape = mkOption {
default = null;
example = "block";
type = types.nullOr (types.enum [ "block" "underline" "ibeam" ]);
description = ''
Specify how the cursor should look. Accepts block, ibeam and underline.
'';
};
filterUnmatchedUrls = mkOption {
default = null;
type = types.nullOr types.bool;
description = "Whether to hide url hints not matching input in url hints mode.";
};
modifyOtherKeys = mkOption {
default = null;
type = types.nullOr types.bool;
description = ''
Emit escape sequences for extra keys,
like the modifyOtherKeys resource for
<citerefentry>
<refentrytitle>xterm</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>.
'';
};
sizeHints = mkOption {
default = null;
type = types.nullOr types.bool;
description = ''
Enable size hints. Locks the terminal resizing
to increments of the terminal's cell size.
Requires a window manager that respects scroll hints.
'';
};
scrollbar = mkOption {
default = null;
type = types.nullOr (types.enum [ "off" "left" "right" ]);
description = "Scroll to the bottom when the shell generates output.";
};
backgroundColor = mkOption {
default = null;
example = "rgba(63, 63, 63, 0.8)";
type = types.nullOr types.str;
description = "Background color value.";
};
cursorColor = mkOption {
default = null;
example = "#dcdccc";
type = types.nullOr types.str;
description = "Cursor color value.";
};
cursorForegroundColor = mkOption {
default = null;
example = "#dcdccc";
type = types.nullOr types.str;
description = "Cursor foreground color value.";
};
foregroundColor = mkOption {
default = null;
example = "#dcdccc";
type = types.nullOr types.str;
description = "Foreground color value.";
};
foregroundBoldColor = mkOption {
default = null;
example = "#ffffff";
type = types.nullOr types.str;
description = "Foreground bold color value.";
};
highlightColor = mkOption {
default = null;
example = "#2f2f2f";
type = types.nullOr types.str;
description = "highlight color value.";
};
hintsActiveBackgroundColor = mkOption {
default = null;
example = "#3f3f3f";
type = types.nullOr types.str;
description = "Hints active background color value.";
};
hintsActiveForegroundColor = mkOption {
default = null;
example = "#e68080";
type = types.nullOr types.str;
description = "Hints active foreground color value.";
};
hintsBackgroundColor = mkOption {
default = null;
example = "#3f3f3f";
type = types.nullOr types.str;
description = "Hints background color value.";
};
hintsForegroundColor = mkOption {
default = null;
example = "#dcdccc";
type = types.nullOr types.str;
description = "Hints foreground color value.";
};
hintsBorderColor = mkOption {
default = null;
example = "#3f3f3f";
type = types.nullOr types.str;
description = "Hints border color value.";
};
hintsBorderWidth = mkOption {
default = null;
example = "0.5";
type = types.nullOr types.str;
description = "Hints border width.";
};
hintsFont = mkOption {
default = null;
example = "Monospace 12";
type = types.nullOr types.str;
description = "The font description for the hints font.";
};
hintsPadding = mkOption {
default = null;
example = 2;
type = types.nullOr types.int;
description = "Hints padding.";
};
hintsRoundness = mkOption {
default = null;
example = "0.2";
type = types.nullOr types.str;
description = "Hints roundness.";
};
optionsExtra = mkOption {
default = "";
example = "fullscreen = true";
type = types.lines;
description = "Extra options that should be added to [options] section.";
};
colorsExtra = mkOption {
default = "";
example = ''
color0 = #3f3f3f
color1 = #705050
color2 = #60b48a
'';
type = types.lines;
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.";
};
};
};
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;
}
);
}

View File

@@ -6,27 +6,45 @@ let
cfg = config.programs.texlive;
texlivePkgs = cfg.extraPackages pkgs.texlive;
in
{
meta.maintainers = [ maintainers.rycee ];
options = {
programs.texlive = {
enable = mkEnableOption "Texlive";
extraPackages = mkOption {
default = self: {};
default = tpkgs: { inherit (tpkgs) collection-basic; };
defaultText = "tpkgs: { inherit (tpkgs) collection-basic; }";
example = literalExample ''
tpkgs: { inherit (tpkgs) collection-fontsrecommended algorithms; }
'';
description = "Extra packages available to Texlive.";
};
package = mkOption {
type = types.package;
description = "Resulting customized Texlive package.";
readOnly = true;
};
};
};
config = mkIf cfg.enable {
home.packages = [
(pkgs.texlive.combine (cfg.extraPackages pkgs.texlive))
assertions = [
{
assertion = texlivePkgs != {};
message = "Must provide at least one extra package in"
+ " 'programs.texlive.extraPackages'.";
}
];
home.packages = [ cfg.package ];
programs.texlive.package = pkgs.texlive.combine texlivePkgs;
};
}

Some files were not shown because too many files have changed in this diff Show More