aboutsummaryrefslogtreecommitdiff
path: root/home-manager/modules/programs
diff options
context:
space:
mode:
authorKaiden Fey <kookie@spacekookie.de>2020-09-21 14:12:32 +0200
committerKatharina Fey <kookie@spacekookie.de>2020-09-21 14:12:32 +0200
commitf80843dd45d7acd563d0a5b014cec3a2ea686fc2 (patch)
tree87189d873d6f932d85f9c1a480462b37d96cd6a5 /home-manager/modules/programs
parente0800985dab8f8ebb4cebdfd7e361fd1fafdb2a7 (diff)
parent9b1b55ba0264a55add4b7b4e022bdc2832b531f6 (diff)
Merge commit '9b1b55ba0264a55add4b7b4e022bdc2832b531f6'
Diffstat (limited to 'home-manager/modules/programs')
-rw-r--r--home-manager/modules/programs/abook.nix40
-rw-r--r--home-manager/modules/programs/alacritty.nix9
-rw-r--r--home-manager/modules/programs/alot.nix342
-rw-r--r--home-manager/modules/programs/aria2.nix61
-rw-r--r--home-manager/modules/programs/astroid.nix4
-rw-r--r--home-manager/modules/programs/autorandr.nix39
-rw-r--r--home-manager/modules/programs/bash.nix11
-rw-r--r--home-manager/modules/programs/bat.nix29
-rw-r--r--home-manager/modules/programs/broot.nix6
-rw-r--r--home-manager/modules/programs/dircolors.nix223
-rw-r--r--home-manager/modules/programs/direnv.nix16
-rw-r--r--home-manager/modules/programs/eclipse.nix12
-rw-r--r--home-manager/modules/programs/emacs.nix16
-rw-r--r--home-manager/modules/programs/firefox.nix112
-rw-r--r--home-manager/modules/programs/fish.nix497
-rw-r--r--home-manager/modules/programs/fzf.nix12
-rw-r--r--home-manager/modules/programs/getmail.nix6
-rw-r--r--home-manager/modules/programs/git.nix63
-rw-r--r--home-manager/modules/programs/gnome-terminal.nix42
-rw-r--r--home-manager/modules/programs/go.nix16
-rw-r--r--home-manager/modules/programs/htop.nix46
-rw-r--r--home-manager/modules/programs/i3status.nix208
-rw-r--r--home-manager/modules/programs/info.nix78
-rw-r--r--home-manager/modules/programs/kakoune.nix70
-rw-r--r--home-manager/modules/programs/kitty.nix91
-rw-r--r--home-manager/modules/programs/lf.nix219
-rw-r--r--home-manager/modules/programs/lieer-accounts.nix69
-rw-r--r--home-manager/modules/programs/lieer.nix93
-rw-r--r--home-manager/modules/programs/man.nix66
-rw-r--r--home-manager/modules/programs/mbsync.nix4
-rw-r--r--home-manager/modules/programs/mcfly.nix79
-rw-r--r--home-manager/modules/programs/mpv.nix2
-rw-r--r--home-manager/modules/programs/msmtp.nix4
-rw-r--r--home-manager/modules/programs/ncmpcpp.nix135
-rw-r--r--home-manager/modules/programs/ne.nix95
-rw-r--r--home-manager/modules/programs/neomutt-accounts.nix18
-rw-r--r--home-manager/modules/programs/neomutt.nix36
-rw-r--r--home-manager/modules/programs/neovim.nix16
-rw-r--r--home-manager/modules/programs/newsboat.nix6
-rw-r--r--home-manager/modules/programs/notmuch.nix4
-rw-r--r--home-manager/modules/programs/nushell.nix68
-rw-r--r--home-manager/modules/programs/offlineimap.nix5
-rw-r--r--home-manager/modules/programs/powerline-go.nix123
-rw-r--r--home-manager/modules/programs/qutebrowser.nix268
-rw-r--r--home-manager/modules/programs/rofi.nix13
-rw-r--r--home-manager/modules/programs/ssh.nix55
-rw-r--r--home-manager/modules/programs/starship.nix23
-rw-r--r--home-manager/modules/programs/termite.nix2
-rw-r--r--home-manager/modules/programs/tmux.nix98
-rw-r--r--home-manager/modules/programs/vim.nix2
-rw-r--r--home-manager/modules/programs/vscode.nix66
-rw-r--r--home-manager/modules/programs/waybar.nix363
-rw-r--r--home-manager/modules/programs/zoxide.nix79
-rw-r--r--home-manager/modules/programs/zplug.nix60
-rw-r--r--home-manager/modules/programs/zsh.nix54
55 files changed, 3645 insertions, 529 deletions
diff --git a/home-manager/modules/programs/abook.nix b/home-manager/modules/programs/abook.nix
new file mode 100644
index 00000000000..4ddc080ad51
--- /dev/null
+++ b/home-manager/modules/programs/abook.nix
@@ -0,0 +1,40 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.programs.abook;
+
+in {
+ options.programs.abook = {
+ enable = mkEnableOption "Abook";
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ example = ''
+ field pager = Pager
+ view CONTACT = name, email
+ set autosave=true
+ '';
+ description = ''
+ Extra lines added to <filename>$HOME/.config/abook/abookrc</filename>.
+ Available configuration options are described in the abook repository:
+ <link xlink:href="https://sourceforge.net/p/abook/git/ci/master/tree/sample.abookrc" />.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ home.packages = [ pkgs.abook ];
+ xdg.configFile."abook/abookrc" = mkIf (cfg.extraConfig != "") {
+ text = ''
+ # Generated by Home Manager.
+ # See http://abook.sourceforge.net/
+
+ ${cfg.extraConfig}
+ '';
+ };
+ };
+}
diff --git a/home-manager/modules/programs/alacritty.nix b/home-manager/modules/programs/alacritty.nix
index 69b9ea9673d..ea908f2b056 100644
--- a/home-manager/modules/programs/alacritty.nix
+++ b/home-manager/modules/programs/alacritty.nix
@@ -11,6 +11,13 @@ in {
programs.alacritty = {
enable = mkEnableOption "Alacritty";
+ package = mkOption {
+ type = types.package;
+ default = pkgs.alacritty;
+ defaultText = literalExample "pkgs.alacritty";
+ description = "The Alacritty package to install.";
+ };
+
settings = mkOption {
type = types.attrs;
default = { };
@@ -41,7 +48,7 @@ in {
config = mkMerge [
(mkIf cfg.enable {
- home.packages = [ pkgs.alacritty ];
+ home.packages = [ cfg.package ];
xdg.configFile."alacritty/alacritty.yml" = mkIf (cfg.settings != { }) {
text =
diff --git a/home-manager/modules/programs/alot.nix b/home-manager/modules/programs/alot.nix
index 2b28f34caa3..e907cd3e0ac 100644
--- a/home-manager/modules/programs/alot.nix
+++ b/home-manager/modules/programs/alot.nix
@@ -7,167 +7,231 @@ let
cfg = config.programs.alot;
- alotAccounts = filter (a: a.notmuch.enable)
- (attrValues config.accounts.email.accounts);
+ 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;
- sent_box = "maildir" + "://" + maildir.absPath + "/" + folders.sent;
- draft_box = "maildir" + "://"+ maildir.absPath + "/" + folders.drafts;
- }
- // optionalAttrs (aliases != []) {
- aliases = concatStringsSep "," aliases;
- }
- // 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");
- }
- )
- ++ [ alot.extraConfig ]
- ++ [ "[[[abook]]]" ]
- ++ mapAttrsToList (n: v: n + "=" + v) alot.contactCompletion
- );
-
- 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.
- '';
- };
+ mkKeyValue = key: value:
+ let value' = if isBool value then boolStr value else toString value;
+ in "${key} = ${value'}";
+
+ mk2ndLevelSectionName = name: "[" + name + "]";
+
+ tagSubmodule = types.submodule {
+ options = {
+ translated = mkOption {
+ type = types.nullOr types.str;
+ description = ''
+ Fixed string representation for this tag. The tag can be
+ hidden from view, if the key translated is set to
+ <literal>""</literal>, the empty string.
+ '';
+ };
- hooks = mkOption {
- type = types.lines;
- default = "";
- description = ''
- Content of the hooks file.
- '';
- };
+ translation = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description = ''
+ A pair of strings that define a regular substitution to
+ compute the string representation on the fly using
+ <literal>re.sub</literal>.
+ '';
+ };
- bindings = mkOption {
- type = types.submodule {
- options = {
- global = mkOption {
- type = types.attrsOf types.str;
- default = {};
- description = "Global keybindings.";
- };
+ normal = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "'','', 'white','light red', 'white','#d66'";
+ description = ''
+ How to display the tag when unfocused.
+ See <link xlink:href="https://alot.readthedocs.io/en/latest/configuration/theming.html#tagstring-formatting"/>.
+ '';
+ };
- bufferlist = mkOption {
- type = types.attrsOf types.str;
- default = {};
- description = "Bufferlist mode keybindings.";
- };
+ focus = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description = "How to display the tag when focused.";
+ };
+ };
+ };
- search = mkOption {
- type = types.attrsOf types.str;
- default = {};
- description = "Search mode keybindings.";
- };
+ accountStr = account:
+ with account;
+ concatStringsSep "\n" ([ "[[${name}]]" ]
+ ++ mapAttrsToList (n: v: n + "=" + v) ({
+ address = address;
+ realname = realName;
+ sendmail_command =
+ optionalString (alot.sendMailCommand != null) alot.sendMailCommand;
+ sent_box = "maildir" + "://" + maildir.absPath + "/" + folders.sent;
+ draft_box = "maildir" + "://" + maildir.absPath + "/" + folders.drafts;
+ } // optionalAttrs (aliases != [ ]) {
+ aliases = concatStringsSep "," aliases;
+ } // 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");
+ }) ++ [ alot.extraConfig ] ++ [ "[[[abook]]]" ]
+ ++ mapAttrsToList (n: v: n + "=" + v) alot.contactCompletion);
+
+ 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
+
+ ${generators.toKeyValue { inherit mkKeyValue; } cfg.settings}
+ ${cfg.extraConfig}
+ [tags]
+ '' + (let
+ submoduleToAttrs = m:
+ filterAttrs (name: v: name != "_module" && v != null) m;
+ in generators.toINI { mkSectionName = mk2ndLevelSectionName; }
+ (mapAttrs (name: x: submoduleToAttrs x) cfg.tags)) + ''
+ [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.
+ '';
+ };
- envelope = mkOption {
- type = types.attrsOf types.str;
- default = {};
- description = "Envelope mode keybindings.";
- };
+ hooks = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Content of the hooks file.
+ '';
+ };
- taglist = mkOption {
- type = types.attrsOf types.str;
- default = {};
- description = "Taglist mode keybindings.";
+ 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.
+ '';
+ };
- thread = mkOption {
- type = types.attrsOf types.str;
- default = {};
- description = "Thread mode keybindings.";
- };
+ tags = mkOption {
+ type = types.attrsOf tagSubmodule;
+ default = { };
+ description = "How to display the tags.";
+ };
+
+ settings = mkOption {
+ type = with types;
+ let primitive = either (either (either str int) bool) float;
+ in attrsOf primitive;
+ default = {
+ initial_command = "search tag:inbox AND NOT tag:killed";
+ auto_remove_unread = true;
+ handle_mouse = true;
+ prefer_plaintext = true;
};
+ example = literalExample ''
+ {
+ auto_remove_unread = true;
+ ask_subject = false;
+ thread_indent_replies = 2;
+ }
+ '';
+ description = ''
+ Configuration options added to alot configuration file.
+ '';
+ };
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Extra lines added to alot configuration file.
+ '';
};
- 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.
- '';
+ accounts.email.accounts = mkOption {
+ type = with types; attrsOf (submodule (import ./alot-accounts.nix pkgs));
};
};
config = mkIf cfg.enable {
- home.packages = [ pkgs.alot ];
+ home.packages = [ pkgs.alot ];
xdg.configFile."alot/config".text = configFile;
- xdg.configFile."alot/hooks.py".text =
- ''
+ xdg.configFile."alot/hooks.py" = mkIf (cfg.hooks != "") {
+ text = ''
# Generated by Home Manager.
- ''
- + cfg.hooks;
+ '' + cfg.hooks;
+ };
};
}
diff --git a/home-manager/modules/programs/aria2.nix b/home-manager/modules/programs/aria2.nix
new file mode 100644
index 00000000000..d1317ff7616
--- /dev/null
+++ b/home-manager/modules/programs/aria2.nix
@@ -0,0 +1,61 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.programs.aria2;
+
+ formatLine = n: v:
+ let
+ formatValue = v:
+ if builtins.isBool v then
+ (if v then "true" else "false")
+ else
+ toString v;
+ in "${n}=${formatValue v}";
+in {
+ meta.maintainers = [ hm.maintainers.justinlovinger ];
+
+ options.programs.aria2 = {
+ enable = mkEnableOption "aria2";
+
+ settings = mkOption {
+ type = with types; attrsOf (oneOf [ bool float int str ]);
+ default = { };
+ description = ''
+ Options to add to <filename>aria2.conf</filename> file.
+ See
+ <citerefentry>
+ <refentrytitle>aria2c</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </citerefentry>
+ for options.
+ '';
+ example = literalExample ''
+ {
+ listen-port = 60000;
+ dht-listen-port = 60000;
+ seed-ratio = 1.0;
+ max-upload-limit = "50K";
+ ftp-pasv = true;
+ }
+ '';
+ };
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Extra lines added to <filename>aria2.conf</filename> file.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ home.packages = [ pkgs.aria2 ];
+
+ xdg.configFile."aria2/aria2.conf".text = concatStringsSep "\n" ([ ]
+ ++ mapAttrsToList formatLine cfg.settings
+ ++ optional (cfg.extraConfig != "") cfg.extraConfig);
+ };
+}
diff --git a/home-manager/modules/programs/astroid.nix b/home-manager/modules/programs/astroid.nix
index 8b3762fac0b..af12b10edbb 100644
--- a/home-manager/modules/programs/astroid.nix
+++ b/home-manager/modules/programs/astroid.nix
@@ -98,6 +98,10 @@ in {
'';
};
};
+
+ accounts.email.accounts = mkOption {
+ type = with types; attrsOf (submodule (import ./astroid-accounts.nix));
+ };
};
config = mkIf cfg.enable {
diff --git a/home-manager/modules/programs/autorandr.nix b/home-manager/modules/programs/autorandr.nix
index 02fc77c1e58..40cad704db9 100644
--- a/home-manager/modules/programs/autorandr.nix
+++ b/home-manager/modules/programs/autorandr.nix
@@ -55,6 +55,13 @@ let
default = true;
};
+ crtc = mkOption {
+ type = types.nullOr types.ints.unsigned;
+ description = "Output video display controller.";
+ default = null;
+ example = 0;
+ };
+
primary = mkOption {
type = types.bool;
description = "Whether output should be marked as primary";
@@ -244,21 +251,22 @@ let
]);
fingerprintToString = name: edid: "${name} ${edid}";
configToString = name: config:
- if config.enable then ''
- output ${name}
- ${optionalString (config.position != "") "pos ${config.position}"}
- ${optionalString config.primary "primary"}
- ${optionalString (config.dpi != null) "dpi ${toString config.dpi}"}
- ${optionalString (config.gamma != "") "gamma ${config.gamma}"}
- ${optionalString (config.mode != "") "mode ${config.mode}"}
- ${optionalString (config.rate != "") "rate ${config.rate}"}
- ${optionalString (config.rotate != null) "rotate ${config.rotate}"}
- ${optionalString (config.scale != null)
- ((if config.scale.method == "factor" then "scale" else "scale-from")
- + " ${toString config.scale.x}x${toString config.scale.y}")}
- ${optionalString (config.transform != null) ("transform "
- + concatMapStringsSep "," toString (flatten config.transform))}
- '' else ''
+ if config.enable then
+ concatStringsSep "\n" ([ "output ${name}" ]
+ ++ optional (config.position != "") "pos ${config.position}"
+ ++ optional (config.crtc != null) "crtc ${toString config.crtc}"
+ ++ optional config.primary "primary"
+ ++ optional (config.dpi != null) "dpi ${toString config.dpi}"
+ ++ optional (config.gamma != "") "gamma ${config.gamma}"
+ ++ optional (config.mode != "") "mode ${config.mode}"
+ ++ optional (config.rate != "") "rate ${config.rate}"
+ ++ optional (config.rotate != null) "rotate ${config.rotate}"
+ ++ optional (config.transform != null) ("transform "
+ + concatMapStringsSep "," toString (flatten config.transform))
+ ++ optional (config.scale != null)
+ ((if config.scale.method == "factor" then "scale" else "scale-from")
+ + " ${toString config.scale.x}x${toString config.scale.y}"))
+ else ''
output ${name}
off
'';
@@ -315,6 +323,7 @@ in {
eDP1.enable = false;
DP1 = {
enable = true;
+ crtc = 0;
primary = true;
position = "0x0";
mode = "3840x2160";
diff --git a/home-manager/modules/programs/bash.nix b/home-manager/modules/programs/bash.nix
index 82a9fbe8f8b..45fe368bddc 100644
--- a/home-manager/modules/programs/bash.nix
+++ b/home-manager/modules/programs/bash.nix
@@ -82,7 +82,12 @@ in
shellAliases = mkOption {
default = {};
type = types.attrsOf types.str;
- example = { ll = "ls -l"; ".." = "cd .."; };
+ example = literalExample ''
+ {
+ 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.
@@ -171,10 +176,10 @@ in
${aliasesStr}
- ${cfg.initExtra}
-
${optionalString cfg.enableAutojump
". ${pkgs.autojump}/share/autojump/autojump.bash"}
+
+ ${cfg.initExtra}
fi
'';
diff --git a/home-manager/modules/programs/bat.nix b/home-manager/modules/programs/bat.nix
index aa0df9abd45..e2b30ea9333 100644
--- a/home-manager/modules/programs/bat.nix
+++ b/home-manager/modules/programs/bat.nix
@@ -24,14 +24,35 @@ in {
'';
};
+ themes = mkOption {
+ type = types.attrsOf types.lines;
+ default = { };
+ example = literalExample ''
+ {
+ dracula = builtins.readFile (pkgs.fetchFromGitHub {
+ owner = "dracula";
+ repo = "sublime"; # Bat uses sublime syntax for its themes
+ rev = "26c57ec282abcaa76e57e055f38432bd827ac34e";
+ sha256 = "019hfl4zbn4vm4154hh3bwk6hm7bdxbr1hdww83nabxwjn99ndhv";
+ } + "/Dracula.tmTheme");
+ }
+ '';
+ description = ''
+ Additional themes to provide.
+ '';
+ };
+
};
config = mkIf cfg.enable {
home.packages = [ pkgs.bat ];
- xdg.configFile."bat/config" = mkIf (cfg.config != { }) {
- text = concatStringsSep "\n"
- (mapAttrsToList (n: v: ''--${n}="${v}"'') cfg.config);
- };
+ xdg.configFile = mkMerge ([{
+ "bat/config" = mkIf (cfg.config != { }) {
+ text = concatStringsSep "\n"
+ (mapAttrsToList (n: v: ''--${n}="${v}"'') cfg.config);
+ };
+ }] ++ flip mapAttrsToList cfg.themes
+ (name: body: { "bat/themes/${name}.tmTheme" = { text = body; }; }));
};
}
diff --git a/home-manager/modules/programs/broot.nix b/home-manager/modules/programs/broot.nix
index eac31b56801..6951e035d32 100644
--- a/home-manager/modules/programs/broot.nix
+++ b/home-manager/modules/programs/broot.nix
@@ -172,11 +172,11 @@ in {
xdg.configFile."broot/conf.toml".source = configFile brootConf;
# Dummy file to prevent broot from trying to reinstall itself
- xdg.configFile."broot/launcher/installed".text = "";
+ xdg.configFile."broot/launcher/installed-v1".text = "";
programs.bash.initExtra = mkIf cfg.enableBashIntegration (
- # Using mkAfter to make it more likely to appear after other
- # manipulations of the prompt.
+ # Using mkAfter to make it more likely to appear after other
+ # manipulations of the prompt.
mkAfter ''
# This script was automatically generated by the broot function
# More information can be found in https://github.com/Canop/broot
diff --git a/home-manager/modules/programs/dircolors.nix b/home-manager/modules/programs/dircolors.nix
new file mode 100644
index 00000000000..026de72d711
--- /dev/null
+++ b/home-manager/modules/programs/dircolors.nix
@@ -0,0 +1,223 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.programs.dircolors;
+
+ formatLine = n: v: "${n} ${toString v}";
+in {
+ meta.maintainers = [ hm.maintainers.justinlovinger ];
+
+ options.programs.dircolors = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to manage <filename>.dir_colors</filename>
+ and set <code>LS_COLORS</code>.
+ '';
+ };
+
+ enableBashIntegration = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether to enable Bash integration.
+ '';
+ };
+
+ enableFishIntegration = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether to enable Fish integration.
+ '';
+ };
+
+ enableZshIntegration = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether to enable Zsh integration.
+ '';
+ };
+
+ settings = mkOption {
+ type = with types; attrsOf str;
+ default = { };
+ description = ''
+ Options to add to <filename>.dir_colors</filename> file.
+ See <command>dircolors --print-database</command>
+ for options.
+ '';
+ example = literalExample ''
+ {
+ OTHER_WRITABLE = "30;46";
+ ".sh" = "01;32";
+ ".csh" = "01;32";
+ }
+ '';
+ };
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Extra lines added to <filename>.dir_colors</filename> file.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ # Add default settings from `dircolors --print-database`.
+ programs.dircolors.settings = {
+ RESET = mkDefault "0";
+ DIR = mkDefault "01;34";
+ LINK = mkDefault "01;36";
+ MULTIHARDLINK = mkDefault "00";
+ FIFO = mkDefault "40;33";
+ SOCK = mkDefault "01;35";
+ DOOR = mkDefault "01;35";
+ BLK = mkDefault "40;33;01";
+ CHR = mkDefault "40;33;01";
+ ORPHAN = mkDefault "40;31;01";
+ MISSING = mkDefault "00";
+ SETUID = mkDefault "37;41";
+ SETGID = mkDefault "30;43";
+ CAPABILITY = mkDefault "30;41";
+ STICKY_OTHER_WRITABLE = mkDefault "30;42";
+ OTHER_WRITABLE = mkDefault "34;42";
+ STICKY = mkDefault "37;44";
+ EXEC = mkDefault "01;32";
+ ".tar" = mkDefault "01;31";
+ ".tgz" = mkDefault "01;31";
+ ".arc" = mkDefault "01;31";
+ ".arj" = mkDefault "01;31";
+ ".taz" = mkDefault "01;31";
+ ".lha" = mkDefault "01;31";
+ ".lz4" = mkDefault "01;31";
+ ".lzh" = mkDefault "01;31";
+ ".lzma" = mkDefault "01;31";
+ ".tlz" = mkDefault "01;31";
+ ".txz" = mkDefault "01;31";
+ ".tzo" = mkDefault "01;31";
+ ".t7z" = mkDefault "01;31";
+ ".zip" = mkDefault "01;31";
+ ".z" = mkDefault "01;31";
+ ".dz" = mkDefault "01;31";
+ ".gz" = mkDefault "01;31";
+ ".lrz" = mkDefault "01;31";
+ ".lz" = mkDefault "01;31";
+ ".lzo" = mkDefault "01;31";
+ ".xz" = mkDefault "01;31";
+ ".zst" = mkDefault "01;31";
+ ".tzst" = mkDefault "01;31";
+ ".bz2" = mkDefault "01;31";
+ ".bz" = mkDefault "01;31";
+ ".tbz" = mkDefault "01;31";
+ ".tbz2" = mkDefault "01;31";
+ ".tz" = mkDefault "01;31";
+ ".deb" = mkDefault "01;31";
+ ".rpm" = mkDefault "01;31";
+ ".jar" = mkDefault "01;31";
+ ".war" = mkDefault "01;31";
+ ".ear" = mkDefault "01;31";
+ ".sar" = mkDefault "01;31";
+ ".rar" = mkDefault "01;31";
+ ".alz" = mkDefault "01;31";
+ ".ace" = mkDefault "01;31";
+ ".zoo" = mkDefault "01;31";
+ ".cpio" = mkDefault "01;31";
+ ".7z" = mkDefault "01;31";
+ ".rz" = mkDefault "01;31";
+ ".cab" = mkDefault "01;31";
+ ".wim" = mkDefault "01;31";
+ ".swm" = mkDefault "01;31";
+ ".dwm" = mkDefault "01;31";
+ ".esd" = mkDefault "01;31";
+ ".jpg" = mkDefault "01;35";
+ ".jpeg" = mkDefault "01;35";
+ ".mjpg" = mkDefault "01;35";
+ ".mjpeg" = mkDefault "01;35";
+ ".gif" = mkDefault "01;35";
+ ".bmp" = mkDefault "01;35";
+ ".pbm" = mkDefault "01;35";
+ ".pgm" = mkDefault "01;35";
+ ".ppm" = mkDefault "01;35";
+ ".tga" = mkDefault "01;35";
+ ".xbm" = mkDefault "01;35";
+ ".xpm" = mkDefault "01;35";
+ ".tif" = mkDefault "01;35";
+ ".tiff" = mkDefault "01;35";
+ ".png" = mkDefault "01;35";
+ ".svg" = mkDefault "01;35";
+ ".svgz" = mkDefault "01;35";
+ ".mng" = mkDefault "01;35";
+ ".pcx" = mkDefault "01;35";
+ ".mov" = mkDefault "01;35";
+ ".mpg" = mkDefault "01;35";
+ ".mpeg" = mkDefault "01;35";
+ ".m2v" = mkDefault "01;35";
+ ".mkv" = mkDefault "01;35";
+ ".webm" = mkDefault "01;35";
+ ".ogm" = mkDefault "01;35";
+ ".mp4" = mkDefault "01;35";
+ ".m4v" = mkDefault "01;35";
+ ".mp4v" = mkDefault "01;35";
+ ".vob" = mkDefault "01;35";
+ ".qt" = mkDefault "01;35";
+ ".nuv" = mkDefault "01;35";
+ ".wmv" = mkDefault "01;35";
+ ".asf" = mkDefault "01;35";
+ ".rm" = mkDefault "01;35";
+ ".rmvb" = mkDefault "01;35";
+ ".flc" = mkDefault "01;35";
+ ".avi" = mkDefault "01;35";
+ ".fli" = mkDefault "01;35";
+ ".flv" = mkDefault "01;35";
+ ".gl" = mkDefault "01;35";
+ ".dl" = mkDefault "01;35";
+ ".xcf" = mkDefault "01;35";
+ ".xwd" = mkDefault "01;35";
+ ".yuv" = mkDefault "01;35";
+ ".cgm" = mkDefault "01;35";
+ ".emf" = mkDefault "01;35";
+ ".ogv" = mkDefault "01;35";
+ ".ogx" = mkDefault "01;35";
+ ".aac" = mkDefault "00;36";
+ ".au" = mkDefault "00;36";
+ ".flac" = mkDefault "00;36";
+ ".m4a" = mkDefault "00;36";
+ ".mid" = mkDefault "00;36";
+ ".midi" = mkDefault "00;36";
+ ".mka" = mkDefault "00;36";
+ ".mp3" = mkDefault "00;36";
+ ".mpc" = mkDefault "00;36";
+ ".ogg" = mkDefault "00;36";
+ ".ra" = mkDefault "00;36";
+ ".wav" = mkDefault "00;36";
+ ".oga" = mkDefault "00;36";
+ ".opus" = mkDefault "00;36";
+ ".spx" = mkDefault "00;36";
+ ".xspf" = mkDefault "00;36";
+ };
+
+ home.file.".dir_colors".text = concatStringsSep "\n" ([ ]
+ ++ optional (cfg.extraConfig != "") cfg.extraConfig
+ ++ mapAttrsToList formatLine cfg.settings) + "\n";
+
+ programs.bash.initExtra = mkIf cfg.enableBashIntegration ''
+ eval $(${pkgs.coreutils}/bin/dircolors -b ~/.dir_colors)
+ '';
+
+ programs.fish.shellInit = mkIf cfg.enableFishIntegration ''
+ eval (${pkgs.coreutils}/bin/dircolors -c ~/.dir_colors)
+ '';
+
+ # Set `LS_COLORS` before Oh My Zsh and `initExtra`.
+ programs.zsh.initExtraBeforeCompInit = mkIf cfg.enableZshIntegration ''
+ eval $(${pkgs.coreutils}/bin/dircolors -b ~/.dir_colors)
+ '';
+ };
+}
diff --git a/home-manager/modules/programs/direnv.nix b/home-manager/modules/programs/direnv.nix
index beb40a96261..1d1374b8e26 100644
--- a/home-manager/modules/programs/direnv.nix
+++ b/home-manager/modules/programs/direnv.nix
@@ -70,6 +70,11 @@ in {
Whether to enable Fish integration.
'';
};
+
+ enableNixDirenvIntegration = mkEnableOption ''
+ <link
+ xlink:href="https://github.com/nix-community/nix-direnv">nix-direnv</link>,
+ a fast, persistent use_nix implementation for direnv'';
};
config = mkIf cfg.enable {
@@ -78,12 +83,15 @@ in {
xdg.configFile."direnv/config.toml" =
mkIf (cfg.config != { }) { source = configFile cfg.config; };
- xdg.configFile."direnv/direnvrc" =
- mkIf (cfg.stdlib != "") { text = cfg.stdlib; };
+ xdg.configFile."direnv/direnvrc" = let
+ text = concatStringsSep "\n" (optional (cfg.stdlib != "") cfg.stdlib
+ ++ optional cfg.enableNixDirenvIntegration
+ "source ${pkgs.nix-direnv}/share/nix-direnv/direnvrc");
+ in mkIf (text != "") { inherit text; };
programs.bash.initExtra = mkIf cfg.enableBashIntegration (
- # Using mkAfter to make it more likely to appear after other
- # manipulations of the prompt.
+ # Using mkAfter to make it more likely to appear after other
+ # manipulations of the prompt.
mkAfter ''
eval "$(${pkgs.direnv}/bin/direnv hook bash)"
'');
diff --git a/home-manager/modules/programs/eclipse.nix b/home-manager/modules/programs/eclipse.nix
index 8ce605b106a..21973ab937e 100644
--- a/home-manager/modules/programs/eclipse.nix
+++ b/home-manager/modules/programs/eclipse.nix
@@ -13,6 +13,16 @@ in {
programs.eclipse = {
enable = mkEnableOption "Eclipse";
+ package = mkOption {
+ type = types.package;
+ default = pkgs.eclipses.eclipse-platform;
+ defaultText = literalExample "pkgs.eclipses.eclipse-platform";
+ example = literalExample "pkgs.eclipses.eclipse-java";
+ description = ''
+ The Eclipse package to install.
+ '';
+ };
+
enableLombok = mkOption {
type = types.bool;
default = false;
@@ -40,7 +50,7 @@ in {
config = mkIf cfg.enable {
home.packages = [
(pkgs.eclipses.eclipseWithPlugins {
- eclipse = pkgs.eclipses.eclipse-platform;
+ eclipse = cfg.package;
jvmArgs = cfg.jvmArgs ++ optional cfg.enableLombok
"-javaagent:${pkgs.lombok}/share/java/lombok.jar";
plugins = cfg.plugins;
diff --git a/home-manager/modules/programs/emacs.nix b/home-manager/modules/programs/emacs.nix
index 987a9f2431e..b785f71358c 100644
--- a/home-manager/modules/programs/emacs.nix
+++ b/home-manager/modules/programs/emacs.nix
@@ -8,16 +8,12 @@ let
# Copied from all-packages.nix, with modifications to support
# overrides.
- emacsPackages =
- let
- epkgs = pkgs.emacsPackagesGen cfg.package;
- in
- epkgs.overrideScope' cfg.overrides;
- emacsWithPackages = emacsPackages.emacsWithPackages;
+ emacsPackages = let epkgs = pkgs.emacsPackagesFor cfg.package;
+ in epkgs.overrideScope' cfg.overrides;
-in
+ emacsWithPackages = emacsPackages.emacsWithPackages;
-{
+in {
meta.maintainers = [ maintainers.rycee ];
options = {
@@ -33,7 +29,7 @@ in
};
extraPackages = mkOption {
- default = self: [];
+ default = self: [ ];
type = hm.types.selectorFunction;
defaultText = "epkgs: []";
example = literalExample "epkgs: [ epkgs.emms epkgs.magit ]";
@@ -45,7 +41,7 @@ in
};
overrides = mkOption {
- default = self: super: {};
+ default = self: super: { };
type = hm.types.overlayFunction;
defaultText = "self: super: {}";
example = literalExample ''
diff --git a/home-manager/modules/programs/firefox.nix b/home-manager/modules/programs/firefox.nix
index 17c64752d66..d5003f59edc 100644
--- a/home-manager/modules/programs/firefox.nix
+++ b/home-manager/modules/programs/firefox.nix
@@ -23,8 +23,15 @@ let
then "${firefoxConfigPath}/Profiles"
else firefoxConfigPath;
+ # The extensions path shared by all profiles; will not be supported
+ # by future Firefox versions.
extensionPath = "extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
+ extensionsEnvPkg = pkgs.buildEnv {
+ name = "hm-firefox-extensions";
+ paths = cfg.extensions;
+ };
+
profiles =
flip mapAttrs' cfg.profiles (_: profile:
nameValuePair "Profile${toString profile.id}" {
@@ -59,6 +66,13 @@ in
{
meta.maintainers = [ maintainers.rycee ];
+ imports = [
+ (mkRemovedOptionModule ["programs" "firefox" "enableGoogleTalk"]
+ "Support for this option has been removed.")
+ (mkRemovedOptionModule ["programs" "firefox" "enableIcedTea"]
+ "Support for this option has been removed.")
+ ];
+
options = {
programs.firefox = {
enable = mkEnableOption "Firefox";
@@ -87,9 +101,29 @@ in
]
'';
description = ''
- List of Firefox add-on packages to install. Note, it is
- necessary to manually enable these extensions inside Firefox
- after the first installation.
+ List of Firefox add-on packages to install. Some
+ pre-packaged add-ons are accessible from NUR,
+ <link xlink:href="https://github.com/nix-community/NUR"/>.
+ Once you have NUR installed run
+
+ <screen language="console">
+ <prompt>$</prompt> <userinput>nix-env -f '&lt;nixpkgs&gt;' -qaP -A nur.repos.rycee.firefox-addons</userinput>
+ </screen>
+
+ to list the available Firefox add-ons.
+
+ </para><para>
+
+ Note that it is necessary to manually enable these
+ extensions inside Firefox after the first installation.
+
+ </para><para>
+
+ Extensions listed here will only be available in Firefox
+ profiles managed through the
+ <link linkend="opt-programs.firefox.profiles">programs.firefox.profiles</link>
+ option. This is due to recent changes in the way Firefox
+ handles extension side-loading.
'';
};
@@ -137,7 +171,7 @@ in
userChrome = mkOption {
type = types.lines;
default = "";
- description = "Custom Firefox CSS.";
+ description = "Custom Firefox user chrome CSS.";
example = ''
/* Hide tab bar in FF Quantum */
@-moz-document url("chrome://browser/content/browser.xul") {
@@ -153,6 +187,16 @@ in
'';
};
+ userContent = mkOption {
+ type = types.lines;
+ default = "";
+ description = "Custom Firefox user content CSS.";
+ example = ''
+ /* Hide scrollbar in FF Quantum */
+ *{scrollbar-width:none !important}
+ '';
+ };
+
path = mkOption {
type = types.str;
default = name;
@@ -176,38 +220,6 @@ in
default = false;
description = "Whether to enable the unfree Adobe Flash plugin.";
};
-
- enableGoogleTalk = mkOption {
- type = types.bool;
- default = false;
- description = ''
- Whether to enable the unfree Google Talk plugin. This option
- is <emphasis>deprecated</emphasis> and will only work if
-
- <programlisting language="nix">
- programs.firefox.package = pkgs.firefox-esr-52-unwrapped;
- </programlisting>
-
- and the <option>plugin.load_flash_only</option> Firefox
- option has been disabled.
- '';
- };
-
- enableIcedTea = mkOption {
- type = types.bool;
- default = false;
- description = ''
- Whether to enable the Java applet plugin. This option is
- <emphasis>deprecated</emphasis> and will only work if
-
- <programlisting language="nix">
- programs.firefox.package = pkgs.firefox-esr-52-unwrapped;
- </programlisting>
-
- and the <option>plugin.load_flash_only</option> Firefox
- option has been disabled.
- '';
- };
};
};
@@ -250,8 +262,6 @@ in
# The configuration expected by the Firefox wrapper.
fcfg = {
enableAdobeFlash = cfg.enableAdobeFlash;
- enableGoogleTalkPlugin = cfg.enableGoogleTalk;
- icedtea = cfg.enableIcedTea;
};
# A bit of hackery to force a config into the wrapper.
@@ -273,17 +283,10 @@ in
home.file = mkMerge (
[{
- "${mozillaConfigPath}/${extensionPath}" = mkIf (cfg.extensions != []) (
- let
- extensionsEnv = pkgs.buildEnv {
- name = "hm-firefox-extensions";
- paths = cfg.extensions;
- };
- in {
- source = "${extensionsEnv}/share/mozilla/${extensionPath}";
- recursive = true;
- }
- );
+ "${mozillaConfigPath}/${extensionPath}" = mkIf (cfg.extensions != []) {
+ source = "${extensionsEnvPkg}/share/mozilla/${extensionPath}";
+ recursive = true;
+ };
"${firefoxConfigPath}/profiles.ini" = mkIf (cfg.profiles != {}) {
text = profilesIni;
@@ -295,10 +298,21 @@ in
text = profile.userChrome;
};
+ "${profilesPath}/${profile.path}/chrome/userContent.css" =
+ mkIf (profile.userContent != "") {
+ text = profile.userContent;
+ };
+
"${profilesPath}/${profile.path}/user.js" =
mkIf (profile.settings != {} || profile.extraConfig != "") {
text = mkUserJs profile.settings profile.extraConfig;
};
+
+ "${profilesPath}/${profile.path}/extensions" = mkIf (cfg.extensions != []) {
+ source = "${extensionsEnvPkg}/share/mozilla/${extensionPath}";
+ recursive = true;
+ force = true;
+ };
})
);
};
diff --git a/home-manager/modules/programs/fish.nix b/home-manager/modules/programs/fish.nix
index 87a17b85507..730afa79262 100644
--- a/home-manager/modules/programs/fish.nix
+++ b/home-manager/modules/programs/fish.nix
@@ -6,119 +6,310 @@ let
cfg = config.programs.fish;
- abbrsStr = concatStringsSep "\n" (
- mapAttrsToList (k: v: "abbr --add --global ${k} '${v}'") cfg.shellAbbrs
- );
+ pluginModule = types.submodule ({ config, ... }: {
+ options = {
+ src = mkOption {
+ type = types.path;
+ description = ''
+ Path to the plugin folder.
+ </para><para>
+ Relevant pieces will be added to the fish function path and
+ the completion path. The <filename>init.fish</filename> and
+ <filename>key_binding.fish</filename> files are sourced if
+ they exist.
+ '';
+ };
- aliasesStr = concatStringsSep "\n" (
- mapAttrsToList (k: v: "alias ${k}='${v}'") cfg.shellAliases
- );
+ name = mkOption {
+ type = types.str;
+ description = ''
+ The name of the plugin.
+ '';
+ };
+ };
+ });
-in
+ functionModule = types.submodule {
+ options = {
+ body = mkOption {
+ type = types.lines;
+ description = ''
+ The function body.
+ '';
+ };
+
+ argumentNames = mkOption {
+ type = with types; nullOr (either str (listOf str));
+ default = null;
+ description = ''
+ Assigns the value of successive command line arguments to the names
+ given.
+ '';
+ };
-{
+ description = mkOption {
+ type = with types; nullOr str;
+ default = null;
+ description = ''
+ A description of what the function does, suitable as a completion
+ description.
+ '';
+ };
+
+ wraps = mkOption {
+ type = with types; nullOr str;
+ default = null;
+ description = ''
+ Causes the function to inherit completions from the given wrapped
+ command.
+ '';
+ };
+
+ onEvent = mkOption {
+ type = with types; nullOr str;
+ default = null;
+ description = ''
+ Tells fish to run this function when the specified named event is
+ emitted. Fish internally generates named events e.g. when showing the
+ prompt.
+ '';
+ };
+
+ onVariable = mkOption {
+ type = with types; nullOr str;
+ default = null;
+ description = ''
+ Tells fish to run this function when the specified variable changes
+ value.
+ '';
+ };
+
+ onJobExit = mkOption {
+ type = with types; nullOr (either str int);
+ default = null;
+ description = ''
+ Tells fish to run this function when the job with the specified group
+ ID exits. Instead of a PID, the stringer <literal>caller</literal> can
+ be specified. This is only legal when in a command substitution, and
+ will result in the handler being triggered by the exit of the job
+ which created this command substitution.
+ '';
+ };
+
+ onProcessExit = mkOption {
+ type = with types; nullOr (either str int);
+ default = null;
+ example = "$fish_pid";
+ description = ''
+ Tells fish to run this function when the fish child process with the
+ specified process ID exits. Instead of a PID, for backwards
+ compatibility, <literal>%self</literal> can be specified as an alias
+ for <literal>$fish_pid</literal>, and the function will be run when
+ the current fish instance exits.
+ '';
+ };
+
+ onSignal = mkOption {
+ type = with types; nullOr (either str int);
+ default = null;
+ example = [ "SIGHUP" "HUP" 1 ];
+ description = ''
+ Tells fish to run this function when the specified signal is
+ delievered. The signal can be a signal number or signal name.
+ '';
+ };
+
+ noScopeShadowing = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Allows the function to access the variables of calling functions.
+ '';
+ };
+
+ inheritVariable = mkOption {
+ type = with types; nullOr str;
+ default = null;
+ description = ''
+ Snapshots the value of the specified variable and defines a local
+ variable with that same name and value when the function is defined.
+ '';
+ };
+ };
+ };
+
+ abbrsStr = concatStringsSep "\n"
+ (mapAttrsToList (k: v: "abbr --add --global -- ${k} ${escapeShellArg v}")
+ cfg.shellAbbrs);
+
+ aliasesStr = concatStringsSep "\n"
+ (mapAttrsToList (k: v: "alias ${k} ${escapeShellArg v}") cfg.shellAliases);
+
+in {
options = {
programs.fish = {
- enable = mkEnableOption "fish friendly interactive shell";
+ enable = mkEnableOption "fish, the friendly interactive shell";
package = mkOption {
+ type = types.package;
default = pkgs.fish;
defaultText = literalExample "pkgs.fish";
description = ''
The fish package to install. May be used to change the version.
'';
- type = types.package;
};
shellAliases = mkOption {
- default = {};
+ type = with types; attrsOf str;
+ default = { };
+ example = literalExample ''
+ {
+ ll = "ls -l";
+ ".." = "cd ..";
+ }
+ '';
description = ''
- Set of aliases for fish shell. See
- <option>environment.shellAliases</option> for an option
- format description.
+ An attribute set that maps aliases (the top level attribute names
+ in this option) to command strings or directly to build outputs.
'';
- type = types.attrs;
};
shellAbbrs = mkOption {
- default = {};
+ type = with types; attrsOf str;
+ default = { };
+ example = {
+ l = "less";
+ gco = "git checkout";
+ };
description = ''
- Set of abbreviations for fish shell.
+ An attribute set that maps aliases (the top level attribute names
+ in this option) to abbreviations. Abbreviations are expanded with
+ the longer phrase after they are entered.
'';
- type = types.attrs;
};
shellInit = mkOption {
+ type = types.lines;
default = "";
description = ''
- Shell script code called during fish shell initialisation.
+ Shell script code called during fish shell
+ initialisation.
'';
- type = types.lines;
};
loginShellInit = mkOption {
+ type = types.lines;
default = "";
description = ''
- Shell script code called during fish login shell initialisation.
+ Shell script code called during fish login shell
+ initialisation.
'';
- type = types.lines;
};
interactiveShellInit = mkOption {
+ type = types.lines;
default = "";
description = ''
- Shell script code called during interactive fish shell initialisation.
+ Shell script code called during interactive fish shell
+ initialisation.
'';
- type = types.lines;
};
promptInit = mkOption {
+ type = types.lines;
default = "";
description = ''
Shell script code used to initialise fish prompt.
'';
- type = types.lines;
};
};
+
+ programs.fish.plugins = mkOption {
+ type = types.listOf pluginModule;
+ default = [ ];
+ example = literalExample ''
+ [
+ {
+ name = "z";
+ src = pkgs.fetchFromGitHub {
+ owner = "jethrokuan";
+ repo = "z";
+ rev = "ddeb28a7b6a1f0ec6dae40c636e5ca4908ad160a";
+ sha256 = "0c5i7sdrsp0q3vbziqzdyqn4fmp235ax4mn4zslrswvn8g3fvdyh";
+ };
+ }
+
+ # oh-my-fish plugins are stored in their own repositories, which
+ # makes them simple to import into home-manager.
+ {
+ name = "fasd";
+ src = pkgs.fetchFromGitHub {
+ owner = "oh-my-fish";
+ repo = "plugin-fasd";
+ rev = "38a5b6b6011106092009549e52249c6d6f501fba";
+ sha256 = "06v37hqy5yrv5a6ssd1p3cjd9y3hnp19d3ab7dag56fs1qmgyhbs";
+ };
+ }
+ ]
+ '';
+ description = ''
+ The plugins to source in
+ <filename>conf.d/99plugins.fish</filename>.
+ '';
+ };
+
+ programs.fish.functions = mkOption {
+ type = with types; attrsOf (either lines functionModule);
+ default = { };
+ example = literalExample ''
+ {
+ __fish_command_not_found_handler = {
+ body = "__fish_default_command_not_found_handler $argv[1]";
+ onEvent = "fish_command_not_found";
+ };
+
+ gitignore = "curl -sL https://www.gitignore.io/api/$argv";
+ }
+ '';
+ description = ''
+ Basic functions to add to fish. For more information see
+ <link xlink:href="https://fishshell.com/docs/current/cmds/function.html"/>.
+ '';
+ };
+
};
- config = mkIf cfg.enable {
- home.packages = [ cfg.package ];
+ config = mkIf cfg.enable (mkMerge [
+ {
+ home.packages = [ cfg.package ];
- xdg.dataFile."fish/home-manager_generated_completions".source =
- let
+ 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 ? ""
- , ...
- }:
+ 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"
- {
+ args = removeAttrs args_ [ "name" "postBuild" ] // {
+ # pass the defaults
+ inherit preferLocalBuild allowSubstitutes;
+ };
+ 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 \
@@ -126,66 +317,144 @@ in
> /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);
+ 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 by home-manager.
+
+ # if we haven't sourced the general config, do it
+ if not set -q __fish_general_config_sourced
+
+ set -p fish_function_path ${pkgs.fish-foreign-env}/share/fish-foreign-env/functions
+ 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
+
+ # Login shell initialisation
+ ${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
+
+ # Abbreviations
+ ${abbrsStr}
+
+ # Aliases
+ ${aliasesStr}
+
+ # Prompt initialisation
+ ${cfg.promptInit}
+
+ # Interactive shell intialisation
+ ${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
+ '';
+ }
+ {
+ xdg.configFile = mapAttrs' (name: def: {
+ name = "fish/functions/${name}.fish";
+ value = {
+ text = let
+ modifierStr = n: v: optional (v != null) ''--${n}="${toString v}"'';
+ modifierStrs = n: v: optional (v != null) "--${n}=${toString v}";
+ modifierBool = n: v: optional (v != null && v) "--${n}";
+
+ mods = with def;
+ modifierStr "description" description ++ modifierStr "wraps" wraps
+ ++ modifierStr "on-event" onEvent
+ ++ modifierStr "on-variable" onVariable
+ ++ modifierStr "on-job-exit" onJobExit
+ ++ modifierStr "on-process-exit" onProcessExit
+ ++ modifierStr "on-signal" onSignal
+ ++ modifierBool "no-scope-shadowing" noScopeShadowing
+ ++ modifierStr "inherit-variable" inheritVariable
+ ++ modifierStrs "argument-names" argumentNames;
+
+ modifiers = if isAttrs def then " ${toString mods}" else "";
+ body = if isAttrs def then def.body else def;
+ in ''
+ function ${name}${modifiers}
+ ${body}
+ end
+ '';
};
+ }) cfg.functions;
+ }
- 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
- '';
- };
+ # Each plugin gets a corresponding conf.d/plugin-NAME.fish file to load
+ # in the paths and any initialization scripts.
+ (mkIf (length cfg.plugins > 0) {
+ xdg.configFile = mkMerge ((map (plugin: {
+ "fish/conf.d/plugin-${plugin.name}.fish".text = ''
+ # Plugin ${plugin.name}
+ set -l plugin_dir ${plugin.src}
+
+ # Set paths to import plugin components
+ if test -d $plugin_dir/functions
+ set fish_function_path $fish_function_path[1] $plugin_dir/functions $fish_function_path[2..-1]
+ end
+
+ if test -d $plugin_dir/completions
+ set fish_complete_path $fish_complete_path[1] $plugin_dir/completions $fish_complete_path[2..-1]
+ end
+
+ # Source initialization code if it exists.
+ if test -d $plugin_dir/conf.d
+ for f in $plugin_dir/conf.d/*.fish
+ source $f
+ end
+ end
+
+ if test -f $plugin_dir/key_bindings.fish
+ source $plugin_dir/key_bindings.fish
+ end
+
+ if test -f $plugin_dir/init.fish
+ source $plugin_dir/init.fish
+ end
+ '';
+ }) cfg.plugins));
+ })
+ ]);
}
diff --git a/home-manager/modules/programs/fzf.nix b/home-manager/modules/programs/fzf.nix
index 36eb3a1cdba..3aee57768ea 100644
--- a/home-manager/modules/programs/fzf.nix
+++ b/home-manager/modules/programs/fzf.nix
@@ -100,6 +100,14 @@ in {
Whether to enable Zsh integration.
'';
};
+
+ enableFishIntegration = mkOption {
+ default = true;
+ type = types.bool;
+ description = ''
+ Whether to enable Fish integration.
+ '';
+ };
};
config = mkIf cfg.enable {
@@ -130,5 +138,9 @@ in {
. ${pkgs.fzf}/share/fzf/key-bindings.zsh
fi
'';
+
+ programs.fish.shellInit = mkIf cfg.enableFishIntegration ''
+ source ${pkgs.fzf}/share/fzf/key-bindings.fish && fzf_key_bindings
+ '';
};
}
diff --git a/home-manager/modules/programs/getmail.nix b/home-manager/modules/programs/getmail.nix
index 2c3919dcf2f..f83c469ff24 100644
--- a/home-manager/modules/programs/getmail.nix
+++ b/home-manager/modules/programs/getmail.nix
@@ -49,6 +49,12 @@ let
".getmail/getmail${if a.primary then "rc" else a.name}";
in {
+ options = {
+ accounts.email.accounts = mkOption {
+ type = with types; attrsOf (submodule (import ./getmail-accounts.nix));
+ };
+ };
+
config = mkIf getmailEnabled {
home.file = foldl' (a: b: a // b) { }
(map (a: { "${renderConfigFilepath a}".text = renderAccountConfig a; })
diff --git a/home-manager/modules/programs/git.nix b/home-manager/modules/programs/git.nix
index a56aa10d50e..312269de316 100644
--- a/home-manager/modules/programs/git.nix
+++ b/home-manager/modules/programs/git.nix
@@ -19,10 +19,20 @@ let
else
''${section} "${subsection}"'';
+ mkValueString = v:
+ let
+ escapedV = ''
+ "${
+ replaceStrings [ "\n" " " ''"'' "\\" ] [ "\\n" "\\t" ''\"'' "\\\\" ] v
+ }"'';
+ in generators.mkValueStringDefault { } (if isString v then escapedV else v);
+
# generation for multiple ini values
mkKeyValue = k: v:
- let mkKeyValue = generators.mkKeyValueDefault { } "=" k;
- in concatStringsSep "\n" (map mkKeyValue (toList v));
+ let
+ mkKeyValue =
+ generators.mkKeyValueDefault { inherit mkValueString; } " = " k;
+ in concatStringsSep "\n" (map (kv: " " + mkKeyValue kv) (toList v));
# converts { a.b.c = 5; } to { "a.b".c = 5; } for toINI
gitFlattenAttrs = let
@@ -205,6 +215,36 @@ in {
'';
};
};
+
+ delta = {
+ enable = mkEnableOption "" // {
+ description = ''
+ Whether to enable the <command>delta</command> syntax highlighter.
+ See <link xlink:href="https://github.com/dandavison/delta" />.
+ '';
+ };
+
+ options = mkOption {
+ type = with types;
+ let
+ primitiveType = either str (either bool int);
+ sectionType = attrsOf primitiveType;
+ in attrsOf (either primitiveType sectionType);
+ default = { };
+ example = {
+ features = "decorations";
+ whitespace-error-style = "22 reverse";
+ decorations = {
+ commit-decoration-style = "bold yellow box ul";
+ file-style = "bold yellow ul";
+ file-decoration-style = "none";
+ };
+ };
+ description = ''
+ Options to configure delta.
+ '';
+ };
+ };
};
};
@@ -237,7 +277,14 @@ in {
genIdentity = name: account:
with account;
nameValuePair "sendemail.${name}" ({
- smtpEncryption = if smtp.tls.enable then "tls" else "";
+ smtpEncryption = if smtp.tls.enable then
+ (if smtp.tls.useStartTls
+ || versionOlder config.home.stateVersion "20.09" then
+ "tls"
+ else
+ "ssl")
+ else
+ "";
smtpServer = smtp.host;
smtpUser = userName;
from = address;
@@ -299,5 +346,15 @@ in {
([ "git-lfs" "smudge" ] ++ skipArg ++ [ "--" "%f" ]);
};
})
+
+ (mkIf cfg.delta.enable {
+ programs.git.iniContent =
+ let deltaCommand = "${pkgs.gitAndTools.delta}/bin/delta";
+ in {
+ core.pager = deltaCommand;
+ interactive.diffFilter = "${deltaCommand} --color-only";
+ delta = cfg.delta.options;
+ };
+ })
]);
}
diff --git a/home-manager/modules/programs/gnome-terminal.nix b/home-manager/modules/programs/gnome-terminal.nix
index 570a1fc7df0..f1b15862130 100644
--- a/home-manager/modules/programs/gnome-terminal.nix
+++ b/home-manager/modules/programs/gnome-terminal.nix
@@ -6,11 +6,6 @@ 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
- '';
-
backForeSubModule = types.submodule ({ ... }: {
options = {
foreground = mkOption {
@@ -81,6 +76,12 @@ let
description = "The terminal colors, null to use system default.";
};
+ cursorBlinkMode = mkOption {
+ default = "system";
+ type = types.enum [ "system" "on" "off" ];
+ description = "The cursor blink mode.";
+ };
+
cursorShape = mkOption {
default = "block";
type = types.enum [ "block" "ibeam" "underline" ];
@@ -121,6 +122,20 @@ let
The number of scrollback lines to keep, null for infinite.
'';
};
+
+ customCommand = mkOption {
+ default = null;
+ type = types.nullOr types.str;
+ description = ''
+ The command to use to start the shell, or null for default shell.
+ '';
+ };
+
+ loginShell = mkOption {
+ default = false;
+ type = types.bool;
+ description = "Run command as a login shell.";
+ };
};
});
@@ -130,7 +145,14 @@ let
scrollbar-policy = if pcfg.showScrollbar then "always" else "never";
scrollback-lines = pcfg.scrollbackLines;
cursor-shape = pcfg.cursorShape;
- } // (if (pcfg.font == null) then {
+ cursor-blink-mode = pcfg.cursorBlinkMode;
+ login-shell = pcfg.loginShell;
+ } // (if (pcfg.customCommand != null) then {
+ use-custom-command = true;
+ custom-command = pcfg.customCommand;
+ } else {
+ use-custom-command = false;
+ }) // (if (pcfg.font == null) then {
use-system-font = true;
} else {
use-system-font = false;
@@ -179,7 +201,7 @@ in {
themeVariant = mkOption {
default = "default";
- type = types.enum [ "default" "light" "dark" ];
+ type = types.enum [ "default" "light" "dark" "system" ];
description = "The theme variation to request";
};
@@ -192,7 +214,7 @@ in {
};
config = mkIf cfg.enable {
- home.packages = [ pkgs.gnome3.gnome_terminal ];
+ home.packages = [ pkgs.gnome3.gnome-terminal ];
dconf.settings = let dconfPath = "org/gnome/terminal/legacy";
in {
@@ -210,7 +232,7 @@ in {
(n: v: nameValuePair ("${dconfPath}/profiles:/:${n}") (buildProfileSet v))
cfg.profile;
- programs.bash.initExtra = mkBefore vteInitStr;
- programs.zsh.initExtra = vteInitStr;
+ programs.bash.enableVteIntegration = true;
+ programs.zsh.enableVteIntegration = true;
};
}
diff --git a/home-manager/modules/programs/go.nix b/home-manager/modules/programs/go.nix
index 983769d26af..4b85ec854ad 100644
--- a/home-manager/modules/programs/go.nix
+++ b/home-manager/modules/programs/go.nix
@@ -62,6 +62,18 @@ in {
example = ".local/bin.go";
description = "GOBIN relative to HOME";
};
+
+ goPrivate = mkOption {
+ type = with types; listOf str;
+ default = [ ];
+ example = [ "*.corp.example.com" "rsc.io/private" ];
+ description = ''
+ The <envar>GOPRIVATE</envar> environment variable controls
+ which modules the go command considers to be private (not
+ available publicly) and should therefore not use the proxy
+ or checksum database.
+ '';
+ };
};
};
@@ -85,5 +97,9 @@ in {
home.sessionVariables.GOBIN =
builtins.toPath "${config.home.homeDirectory}/${cfg.goBin}";
})
+
+ (mkIf (cfg.goPrivate != [ ]) {
+ home.sessionVariables.GOPRIVATE = concatStringsSep "," cfg.goPrivate;
+ })
]);
}
diff --git a/home-manager/modules/programs/htop.nix b/home-manager/modules/programs/htop.nix
index 84966040534..1fb397cdc38 100644
--- a/home-manager/modules/programs/htop.nix
+++ b/home-manager/modules/programs/htop.nix
@@ -61,6 +61,9 @@ let
CGROUP = 112;
OOM = 113;
IO_PRIORITY = 114;
+ M_PSS = 118;
+ M_SWAP = 119;
+ M_PSSWP = 120;
};
# Mapping from names to defaults
@@ -76,16 +79,32 @@ let
Hostname = 2;
AllCPUs = 1;
AllCPUs2 = 1;
+ AllCPUs4 = 1;
LeftCPUs = 1;
RightCPUs = 1;
+ Right = 1;
+ CPUs = 1;
LeftCPUs2 = 1;
RightCPUs2 = 1;
+ LeftCPUs4 = 1;
+ RightCPUs4 = 1;
Blank = 2;
+ PressureStallCPUSome = 2;
+ PressureStallIOSome = 2;
+ PressureStallIOFull = 2;
+ PressureStallMemorySome = 2;
+ PressureStallMemoryFull = 2;
+ ZFSARC = 2;
+ ZFSCARC = 2;
CPU = 1;
"CPU(1)" = 1;
"CPU(2)" = 1;
"CPU(3)" = 1;
"CPU(4)" = 1;
+ "CPU(5)" = 1;
+ "CPU(6)" = 1;
+ "CPU(7)" = 1;
+ "CPU(8)" = 1;
};
singleMeterType = let
@@ -268,6 +287,18 @@ in {
description = "Count CPUs from 0 instead of 1.";
};
+ showCpuUsage = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Show CPU usage frequency.";
+ };
+
+ showCpuFrequency = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Show CPU frequency.";
+ };
+
updateProcessNames = mkOption {
type = types.bool;
default = false;
@@ -287,6 +318,12 @@ in {
description = "Which color scheme to use.";
};
+ enableMouse = mkOption {
+ type = types.bool;
+ default = true;
+ description = "Enable mouse support.";
+ };
+
delay = mkOption {
type = types.int;
default = 15;
@@ -328,6 +365,11 @@ in {
type = meterType;
};
+ vimMode = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Vim key bindings.";
+ };
};
config = mkIf cfg.enable {
@@ -357,14 +399,18 @@ in {
header_margin=${bool cfg.headerMargin}
detailed_cpu_time=${bool cfg.detailedCpuTime}
cpu_count_from_zero=${bool cfg.cpuCountFromZero}
+ show_cpu_usage=${bool cfg.showCpuUsage}
+ show_cpu_frequency=${bool cfg.showCpuFrequency}
update_process_names=${bool cfg.updateProcessNames}
account_guest_in_cpu_meter=${bool cfg.accountGuestInCpuMeter}
color_scheme=${toString cfg.colorScheme}
+ enable_mouse=${bool cfg.enableMouse}
delay=${toString cfg.delay}
left_meters=${list leftMeters}
left_meter_modes=${list leftModes}
right_meters=${list rightMeters}
right_meter_modes=${list rightModes}
+ vim_mode=${bool cfg.vimMode}
'';
};
}
diff --git a/home-manager/modules/programs/i3status.nix b/home-manager/modules/programs/i3status.nix
new file mode 100644
index 00000000000..c1e12fe71d7
--- /dev/null
+++ b/home-manager/modules/programs/i3status.nix
@@ -0,0 +1,208 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.programs.i3status;
+
+ enabledModules = filterAttrs (n: v: v.enable) cfg.modules;
+
+ formatOrder = n: ''order += "${n}"'';
+
+ formatModule = n: v:
+ let
+ formatLine = n: v:
+ let
+ formatValue = v:
+ if isBool v then
+ (if v then "true" else "false")
+ else if isString v then
+ ''"${v}"''
+ else
+ toString v;
+ in "${n} = ${formatValue v}";
+ in ''
+ ${n} {
+ ${concatStringsSep "\n " (mapAttrsToList formatLine v)}
+ }
+ '';
+
+ settingsType = with types; attrsOf (oneOf [ bool int str ]);
+
+ sortAttrNamesByPosition = comparator: set:
+ let pos = n: set."${n}".position;
+ in sort (a: b: comparator (pos a) (pos b)) (attrNames set);
+in {
+ meta.maintainers = [ hm.maintainers.justinlovinger ];
+
+ options.programs.i3status = {
+ enable = mkEnableOption "i3status";
+
+ enableDefault = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether or not to enable
+ the default configuration.
+ '';
+ };
+
+ general = mkOption {
+ type = settingsType;
+ default = { };
+ description = ''
+ Configuration to add to i3status <filename>config</filename>
+ <code>general</code> section.
+ See
+ <citerefentry>
+ <refentrytitle>i3status</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </citerefentry>
+ for options.
+ '';
+ example = literalExample ''
+ {
+ colors = true;
+ color_good = "#e0e0e0";
+ color_degraded = "#d7ae00";
+ color_bad = "#f69d6a";
+ interval = 1;
+ }
+ '';
+ };
+
+ modules = mkOption {
+ type = types.attrsOf (types.submodule {
+ options = {
+ enable = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether or not to enable this module.
+ '';
+ };
+ position = mkOption {
+ type = with types; either int float;
+ description = ''
+ Position of this module in i3status <code>order</code>.
+ '';
+ };
+ settings = mkOption {
+ type = settingsType;
+ default = { };
+ description = ''
+ Configuration to add to this i3status module.
+ See
+ <citerefentry>
+ <refentrytitle>i3status</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </citerefentry>
+ for options.
+ '';
+ example = literalExample ''
+ {
+ format = "♪ %volume";
+ format_muted = "♪ muted (%volume)";
+ device = "pulse:1";
+ }
+ '';
+ };
+ };
+ });
+ default = { };
+ description = ''
+ Modules to add to i3status <filename>config</filename> file.
+ See
+ <citerefentry>
+ <refentrytitle>i3status</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </citerefentry>
+ for options.
+ '';
+ example = literalExample ''
+ {
+ "volume master" = {
+ position = 1;
+ settings = {
+ format = "♪ %volume";
+ format_muted = "♪ muted (%volume)";
+ device = "pulse:1";
+ };
+ };
+ "disk /" = {
+ position = 2;
+ settings = {
+ format = "/ %avail";
+ };
+ };
+ }
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ programs.i3status = mkIf cfg.enableDefault {
+ general = {
+ colors = mkDefault true;
+ interval = mkDefault 5;
+ };
+
+ modules = {
+ ipv6 = { position = mkDefault 1; };
+
+ "wireless _first_" = {
+ position = mkDefault 2;
+ settings = {
+ format_up = mkDefault "W: (%quality at %essid) %ip";
+ format_down = mkDefault "W: down";
+ };
+ };
+
+ "ethernet _first_" = {
+ position = mkDefault 3;
+ settings = {
+ format_up = mkDefault "E: %ip (%speed)";
+ format_down = mkDefault "E: down";
+ };
+ };
+
+ "battery all" = {
+ position = mkDefault 4;
+ settings = { format = mkDefault "%status %percentage %remaining"; };
+ };
+
+ "disk /" = {
+ position = mkDefault 5;
+ settings = { format = mkDefault "%avail"; };
+ };
+
+ load = {
+ position = mkDefault 6;
+ settings = { format = mkDefault "%1min"; };
+ };
+
+ memory = {
+ position = mkDefault 7;
+ settings = {
+ format = mkDefault "%used | %available";
+ threshold_degraded = mkDefault "1G";
+ format_degraded = mkDefault "MEMORY < %available";
+ };
+ };
+
+ "tztime local" = {
+ position = mkDefault 8;
+ settings = { format = mkDefault "%Y-%m-%d %H:%M:%S"; };
+ };
+ };
+ };
+
+ home.packages = [ pkgs.i3status ];
+
+ xdg.configFile."i3status/config".text = concatStringsSep "\n" ([ ]
+ ++ optional (cfg.general != { }) (formatModule "general" cfg.general)
+ ++ map formatOrder (sortAttrNamesByPosition lessThan enabledModules)
+ ++ mapAttrsToList formatModule
+ (mapAttrs (n: v: v.settings) enabledModules));
+ };
+}
diff --git a/home-manager/modules/programs/info.nix b/home-manager/modules/programs/info.nix
index 9e4a5d4aaff..a7d2692b515 100644
--- a/home-manager/modules/programs/info.nix
+++ b/home-manager/modules/programs/info.nix
@@ -1,22 +1,21 @@
-# info.nix -- install texinfo, set INFOPATH, create `dir` file
+# info.nix -- install texinfo and create `dir` file
# This is a helper for the GNU info documentation system. By default,
# the `info` command (and the Info subsystem within Emacs) gives easy
# access to the info files stored system-wide, but not info files in
# your ~/.nix-profile.
-# We set $INFOPATH to include `/run/current-system/sw/share/info` and
-# `~/.nix-profile/share/info` but it's not enough. Although info can
-# then find files when you explicitly ask for them, it doesn't show
-# them to you in the table of contents on startup. To do that requires
-# a `dir` file. NixOS keeps the system-wide `dir` file up to date, but
-# ignores home-installed packages.
+# Specifically, although info can then find files when you explicitly
+# ask for them, it doesn't show them to you in the table of contents
+# on startup. To do that requires a `dir` file. NixOS keeps the
+# system-wide `dir` file up to date, but ignores files installed in
+# user profiles.
-# So this module contains an activation script that generates the
-# `dir` for your home profile. Then when you start info (and both
-# `dir` files are in your $INFOPATH), it will *merge* the contents of
-# the two files, showing you a unified table of contents for all
-# packages. This is really nice.
+# This module contains extra profile commands that generate the `dir`
+# for your home profile. Then when you start info (and both `dir`
+# files are in your $INFOPATH), it will *merge* the contents of the
+# two files, showing you a unified table of contents for all packages.
+# This is really nice.
{ config, lib, pkgs, ... }:
@@ -26,50 +25,39 @@ let
cfg = config.programs.info;
- # Indexes info files found in this location
- 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`
# from this package in the activation script.
infoPkg = pkgs.texinfoInteractive;
in {
- options = {
- programs.info = {
- enable = mkEnableOption "GNU Info";
+ imports = [
+ (mkRemovedOptionModule [ "programs" "info" "homeInfoDirLocation" ] ''
+ The `dir` file is now generated as part of the Home Manager profile and
+ will no longer be placed in your home directory.
+ '')
+ ];
- homeInfoDirLocation = mkOption {
- default = "\${XDG_CACHE_HOME:-$HOME/.cache}/info";
- description = ''
- Directory in which to store the info <filename>dir</filename>
- file within your home.
- '';
- };
- };
- };
+ options.programs.info.enable = mkEnableOption "GNU Info";
config = mkIf cfg.enable {
- home.sessionVariables.INFOPATH =
- "${cfg.homeInfoDirLocation}\${INFOPATH:+:}\${INFOPATH}";
+ home.packages = [
+ infoPkg
- home.activation.createHomeInfoDir =
- hm.dag.entryAfter [ "installPackages" ] ''
- oPATH=$PATH
- export PATH="${lib.makeBinPath [ pkgs.gzip ]}''${PATH:+:}$PATH"
- $DRY_RUN_CMD mkdir -p "${cfg.homeInfoDirLocation}"
- $DRY_RUN_CMD rm -f "${cfg.homeInfoDirLocation}/dir"
- if [[ -d "${homeInfoPath}" ]]; then
- find -L "${homeInfoPath}" \( -name '*.info' -o -name '*.info.gz' \) \
- -exec $DRY_RUN_CMD ${infoPkg}/bin/install-info '{}' \
- "${cfg.homeInfoDirLocation}/dir" \;
- fi
- export PATH="$oPATH"
- unset oPATH
- '';
-
- home.packages = [ infoPkg ];
+ # Make sure the target directory is a real directory.
+ (pkgs.runCommandLocal "dummy-info-dir1" { } "mkdir -p $out/share/info")
+ (pkgs.runCommandLocal "dummy-info-dir2" { } "mkdir -p $out/share/info")
+ ];
home.extraOutputsToInstall = [ "info" ];
+
+ home.extraProfileCommands = let infoPath = "$out/share/info";
+ in ''
+ if [[ -w "${infoPath}" && ! -e "${infoPath}/dir" ]]; then
+ PATH="${lib.makeBinPath [ pkgs.gzip infoPkg ]}''${PATH:+:}$PATH" \
+ find -L "${infoPath}" \( -name '*.info' -o -name '*.info.gz' \) \
+ -exec install-info '{}' "${infoPath}/dir" ';'
+ fi
+ '';
};
}
diff --git a/home-manager/modules/programs/kakoune.nix b/home-manager/modules/programs/kakoune.nix
index faf2542dc70..6db311a1376 100644
--- a/home-manager/modules/programs/kakoune.nix
+++ b/home-manager/modules/programs/kakoune.nix
@@ -49,6 +49,7 @@ let
"InsertCompletionShow"
"InsertCompletionHide"
"InsertCompletionSelect"
+ "ModuleLoaded"
];
example = "SetOption";
description = ''
@@ -96,16 +97,7 @@ let
keyMapping = types.submodule {
options = {
mode = mkOption {
- type = types.enum [
- "insert"
- "normal"
- "prompt"
- "menu"
- "user"
- "goto"
- "view"
- "object"
- ];
+ type = types.str;
example = "user";
description = ''
The mode in which the mapping takes effect.
@@ -497,6 +489,10 @@ let
};
};
+ kakouneWithPlugins = pkgs.wrapKakoune pkgs.kakoune-unwrapped {
+ configure = { plugins = cfg.plugins; };
+ };
+
configFile = let
wrapOptions = with cfg.config.wrapLines;
concatStrings [
@@ -513,6 +509,25 @@ let
"${optionalString (separator != null) " -separator ${separator}"}"
];
+ showWhitespaceOptions = with cfg.config.showWhitespace;
+ let
+ quoteSep = sep:
+ if sep == "'" then
+ ''"'"''
+ else if lib.strings.stringLength sep == 1 then
+ "'${sep}'"
+ else
+ sep; # backwards compat, in case sep == "' '", etc.
+
+ in concatStrings [
+ (optionalString (tab != null) " -tab ${quoteSep tab}")
+ (optionalString (tabStop != null) " -tabpad ${quoteSep tabStop}")
+ (optionalString (space != null) " -spc ${quoteSep space}")
+ (optionalString (nonBreakingSpace != null)
+ " -nbsp ${quoteSep nonBreakingSpace}")
+ (optionalString (lineFeed != null) " -lf ${quoteSep lineFeed}")
+ ];
+
uiOptions = with cfg.config.ui;
concatStringsSep " " [
"ncurses_set_title=${if setTitle then "true" else "false"}"
@@ -533,6 +548,21 @@ let
}"
];
+ userModeString = mode:
+ optionalString (!builtins.elem mode [
+ "insert"
+ "normal"
+ "prompt"
+ "menu"
+ "user"
+ "goto"
+ "view"
+ "object"
+ ]) "try %{declare-user-mode ${mode}}";
+
+ userModeStrings = map userModeString
+ (lists.unique (map (km: km.mode) cfg.config.keyMappings));
+
keyMappingString = km:
concatStringsSep " " [
"map global"
@@ -566,12 +596,14 @@ let
++ optional (autoComplete != null)
"set-option global autocomplete ${concatStringsSep "|" autoComplete}"
++ optional (autoReload != null)
- "set-option global/ autoreload ${autoReload}"
+ "set-option global autoreload ${autoReload}"
++ optional (wrapLines != null && wrapLines.enable)
"add-highlighter global/ wrap${wrapOptions}"
++ optional (numberLines != null && numberLines.enable)
"add-highlighter global/ number-lines${numberLinesOptions}"
++ optional showMatching "add-highlighter global/ show-matching"
+ ++ optional (showWhitespace != null && showWhitespace.enable)
+ "add-highlighter global/ show-whitespaces${showWhitespaceOptions}"
++ optional (scrollOff != null)
"set-option global scrolloff ${toString scrollOff.lines},${
toString scrollOff.columns
@@ -580,7 +612,8 @@ let
++ [ "# UI options" ]
++ optional (ui != null) "set-option global ui_options ${uiOptions}"
- ++ [ "# Key mappings" ] ++ map keyMappingString keyMappings
+ ++ [ "# User modes" ] ++ userModeStrings ++ [ "# Key mappings" ]
+ ++ map keyMappingString keyMappings
++ [ "# Hooks" ] ++ map hookString hooks);
in pkgs.writeText "kakrc"
@@ -605,11 +638,22 @@ in {
<filename>~/.config/kak/kakrc</filename>.
'';
};
+
+ plugins = mkOption {
+ type = with types; listOf package;
+ default = [ ];
+ example = literalExample "[ pkgs.kakounePlugins.kak-fzf ]";
+ description = ''
+ List of kakoune plugins to install. To get a list of
+ supported plugins run:
+ <command>nix-env -f '&lt;nixpkgs&gt;' -qaP -A kakounePlugins</command>.
+ '';
+ };
};
};
config = mkIf cfg.enable {
- home.packages = [ pkgs.kakoune ];
+ home.packages = [ kakouneWithPlugins ];
xdg.configFile."kak/kakrc".source = configFile;
};
}
diff --git a/home-manager/modules/programs/kitty.nix b/home-manager/modules/programs/kitty.nix
new file mode 100644
index 00000000000..313a0bfadd7
--- /dev/null
+++ b/home-manager/modules/programs/kitty.nix
@@ -0,0 +1,91 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.programs.kitty;
+
+ eitherStrBoolInt = with types; either str (either bool int);
+
+ optionalPackage = opt:
+ optional (opt != null && opt.package != null) opt.package;
+
+ toKittyConfig = generators.toKeyValue {
+ mkKeyValue = key: value:
+ let
+ value' = if isBool value then
+ (if value then "yes" else "no")
+ else
+ toString value;
+ in "${key} ${value'}";
+ };
+
+ toKittyKeybindings = generators.toKeyValue {
+ mkKeyValue = key: command: "map ${key} ${command}";
+ };
+
+in {
+ options.programs.kitty = {
+ enable = mkEnableOption "Kitty terminal emulator";
+
+ settings = mkOption {
+ type = types.attrsOf eitherStrBoolInt;
+ default = { };
+ example = literalExample ''
+ {
+ scrollback_lines = 10000;
+ enable_audio_bell = false;
+ update_check_interval = 0;
+ }
+ '';
+ description = ''
+ Configuration written to
+ <filename>~/.config/kitty/kitty.conf</filename>. See
+ <link xlink:href="https://sw.kovidgoyal.net/kitty/conf.html" />
+ for the documentation.
+ '';
+ };
+
+ font = mkOption {
+ type = types.nullOr hm.types.fontType;
+ default = null;
+ description = "The font to use.";
+ };
+
+ keybindings = mkOption {
+ type = types.attrsOf types.str;
+ default = { };
+ description = "Mapping of keybindings to actions.";
+ example = literalExample ''
+ {
+ "ctrl+c" = "copy_or_interrupt";
+ "ctrl+f>2" = "set_font_size 20";
+ }
+ '';
+ };
+
+ extraConfig = mkOption {
+ default = "";
+ type = types.lines;
+ description = "Additional configuration to add.";
+ };
+ };
+
+ config = mkIf cfg.enable {
+ home.packages = [ pkgs.kitty ] ++ optionalPackage cfg.font;
+
+ xdg.configFile."kitty/kitty.conf".text = ''
+ # Generated by Home Manager.
+ # See https://sw.kovidgoyal.net/kitty/conf.html
+
+ ${optionalString (cfg.font != null) "font_family ${cfg.font.name}"}
+
+ ${toKittyConfig cfg.settings}
+
+ ${toKittyKeybindings cfg.keybindings}
+
+ ${cfg.extraConfig}
+ '';
+ };
+}
diff --git a/home-manager/modules/programs/lf.nix b/home-manager/modules/programs/lf.nix
new file mode 100644
index 00000000000..ee4e9b5bfce
--- /dev/null
+++ b/home-manager/modules/programs/lf.nix
@@ -0,0 +1,219 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.programs.lf;
+
+ knownSettings = {
+ anchorfind = types.bool;
+ color256 = types.bool;
+ dircounts = types.bool;
+ dirfirst = types.bool;
+ drawbox = types.bool;
+ globsearch = types.bool;
+ icons = types.bool;
+ hidden = types.bool;
+ ignorecase = types.bool;
+ ignoredia = types.bool;
+ incsearch = types.bool;
+ preview = types.bool;
+ reverse = types.bool;
+ smartcase = types.bool;
+ smartdia = types.bool;
+ wrapscan = types.bool;
+ wrapscroll = types.bool;
+ number = types.bool;
+ relativenumber = types.bool;
+ findlen = types.int;
+ period = types.int;
+ scrolloff = types.int;
+ tabstop = types.int;
+ errorfmt = types.str;
+ filesep = types.str;
+ ifs = types.str;
+ promptfmt = types.str;
+ shell = types.str;
+ sortby = types.str;
+ timefmt = types.str;
+ ratios = types.str;
+ info = types.str;
+ shellopts = types.str;
+ };
+
+ lfSettingsType = types.submodule {
+ options = let
+ opt = name: type:
+ mkOption {
+ type = types.nullOr type;
+ default = null;
+ visible = false;
+ };
+ in mapAttrs opt knownSettings;
+ };
+in {
+ meta.maintainers = [ hm.maintainers.owm111 ];
+
+ options = {
+ programs.lf = {
+ enable = mkEnableOption "lf";
+
+ settings = mkOption {
+ type = lfSettingsType;
+ default = { };
+ example = {
+ tabstop = 4;
+ number = true;
+ ratios = "1:1:2";
+ };
+ description = ''
+ An attribute set of lf settings. The attribute names and corresponding
+ values must be among the following supported options.
+
+ <informaltable frame="none"><tgroup cols="1"><tbody>
+ ${concatStringsSep "\n" (mapAttrsToList (n: v: ''
+ <row>
+ <entry><varname>${n}</varname></entry>
+ <entry>${v.description}</entry>
+ </row>
+ '') knownSettings)}
+ </tbody></tgroup></informaltable>
+
+ See the lf documentation for detailed descriptions of these options.
+ Note, use <varname>previewer</varname> to set lf's
+ <varname>previewer</varname> option, and
+ <varname>extraConfig</varname> for any other option not listed above.
+ All string options are quoted with double quotes.
+ '';
+ };
+
+ commands = mkOption {
+ type = with types; attrsOf (nullOr str);
+ default = { };
+ example = {
+ get-mime-type = ''%xdg-mime query filetype "$f"'';
+ open = "$$OPENER $f";
+ };
+ description = ''
+ Commands to declare. Commands set to null or an empty string are
+ deleted.
+ '';
+ };
+
+ keybindings = mkOption {
+ type = with types; attrsOf (nullOr str);
+ default = { };
+ example = {
+ gh = "cd ~";
+ D = "trash";
+ i = "$less $f";
+ U = "!du -sh";
+ gg = null;
+ };
+ description =
+ "Keys to bind. Keys set to null or an empty string are deleted.";
+ };
+
+ cmdKeybindings = mkOption {
+ type = with types; attrsOf (nullOr str);
+ default = { };
+ example = literalExample ''{ "<c-g>" = "cmd-escape"; }'';
+ description = ''
+ Keys to bind to command line commands which can only be one of the
+ builtin commands. Keys set to null or an empty string are deleted.
+ '';
+ };
+
+ previewer.source = mkOption {
+ type = with types; nullOr path;
+ default = null;
+ example = literalExample ''
+ pkgs.writeShellScript "pv.sh" '''
+ #!/bin/sh
+
+ case "$1" in
+ *.tar*) tar tf "$1";;
+ *.zip) unzip -l "$1";;
+ *.rar) unrar l "$1";;
+ *.7z) 7z l "$1";;
+ *.pdf) pdftotext "$1" -;;
+ *) highlight -O ansi "$1" || cat "$1";;
+ esac
+ '''
+ '';
+ description = ''
+ Script or executable to use to preview files. Sets lf's
+ <varname>previewer</varname> option.
+ '';
+ };
+
+ previewer.keybinding = mkOption {
+ type = with types; nullOr str;
+ default = null;
+ example = "i";
+ description = ''
+ Key to bind to the script at <varname>previewer.source</varname> and
+ pipe through less. Setting to null will not bind any key.
+ '';
+ };
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ example = ''
+ $mkdir -p ~/.trash
+ '';
+ description = "Custom lfrc lines.";
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ home.packages = [ pkgs.lf ];
+
+ xdg.configFile."lf/lfrc".text = let
+ fmtSetting = k: v:
+ optionalString (v != null) "set ${
+ if isBool v then
+ "${optionalString (!v) "no"}${k}"
+ else
+ "${k} ${if isInt v then toString v else ''"${v}"''}"
+ }";
+
+ settingsStr = concatStringsSep "\n" (filter (x: x != "")
+ (mapAttrsToList fmtSetting
+ (builtins.intersectAttrs knownSettings cfg.settings)));
+
+ fmtCmdMap = before: k: v:
+ "${before} ${k}${optionalString (v != null && v != "") " ${v}"}";
+ fmtCmd = fmtCmdMap "cmd";
+ fmtMap = fmtCmdMap "map";
+ fmtCmap = fmtCmdMap "cmap";
+
+ commandsStr = concatStringsSep "\n" (mapAttrsToList fmtCmd cfg.commands);
+ keybindingsStr =
+ concatStringsSep "\n" (mapAttrsToList fmtMap cfg.keybindings);
+ cmdKeybindingsStr =
+ concatStringsSep "\n" (mapAttrsToList fmtCmap cfg.cmdKeybindings);
+
+ previewerStr = optionalString (cfg.previewer.source != null) ''
+ set previewer ${cfg.previewer.source}
+ ${optionalString (cfg.previewer.keybinding != null) ''
+ map ${cfg.previewer.keybinding} ''$${cfg.previewer.source} "$f" | less -R
+ ''}
+ '';
+ in ''
+ ${settingsStr}
+
+ ${commandsStr}
+
+ ${keybindingsStr}
+
+ ${cmdKeybindingsStr}
+
+ ${previewerStr}
+
+ ${cfg.extraConfig}
+ '';
+ };
+}
diff --git a/home-manager/modules/programs/lieer-accounts.nix b/home-manager/modules/programs/lieer-accounts.nix
new file mode 100644
index 00000000000..238049065b3
--- /dev/null
+++ b/home-manager/modules/programs/lieer-accounts.nix
@@ -0,0 +1,69 @@
+{ lib, ... }:
+
+with lib;
+
+{
+ options.lieer = {
+ enable = mkEnableOption "lieer Gmail synchronization for notmuch";
+
+ timeout = mkOption {
+ type = types.ints.unsigned;
+ default = 0;
+ description = ''
+ HTTP timeout in seconds. 0 means forever or system timeout.
+ '';
+ };
+
+ replaceSlashWithDot = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Replace '/' with '.' in Gmail labels.
+ '';
+ };
+
+ dropNonExistingLabels = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Allow missing labels on the Gmail side to be dropped.
+ '';
+ };
+
+ ignoreTagsLocal = mkOption {
+ type = types.listOf types.str;
+ default = [ ];
+ description = ''
+ Set custom tags to ignore when syncing from local to
+ remote (after translations).
+ '';
+ };
+
+ ignoreTagsRemote = mkOption {
+ type = types.listOf types.str;
+ default = [
+ "CATEGORY_FORUMS"
+ "CATEGORY_PROMOTIONS"
+ "CATEGORY_UPDATES"
+ "CATEGORY_SOCIAL"
+ "CATEGORY_PERSONAL"
+ ];
+ description = ''
+ Set custom tags to ignore when syncing from remote to
+ local (before translations).
+ '';
+ };
+
+ notmuchSetupWarning = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Warn if Notmuch is not also enabled for this account.
+ </para><para>
+ This can safely be disabled if <command>notmuch init</command>
+ has been used to configure this account outside of Home
+ Manager.
+ '';
+ };
+ };
+}
diff --git a/home-manager/modules/programs/lieer.nix b/home-manager/modules/programs/lieer.nix
new file mode 100644
index 00000000000..e34a247af46
--- /dev/null
+++ b/home-manager/modules/programs/lieer.nix
@@ -0,0 +1,93 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.programs.lieer;
+
+ lieerAccounts =
+ filter (a: a.lieer.enable) (attrValues config.accounts.email.accounts);
+
+ nonGmailAccounts =
+ map (a: a.name) (filter (a: a.flavor != "gmail.com") lieerAccounts);
+
+ nonGmailConfigHelp =
+ map (name: ''accounts.email.accounts.${name}.flavor = "gmail.com";'')
+ nonGmailAccounts;
+
+ missingNotmuchAccounts = map (a: a.name)
+ (filter (a: !a.notmuch.enable && a.lieer.notmuchSetupWarning)
+ lieerAccounts);
+
+ notmuchConfigHelp =
+ map (name: "accounts.email.accounts.${name}.notmuch.enable = true;")
+ missingNotmuchAccounts;
+
+ configFile = account: {
+ name = "${account.maildir.absPath}/.gmailieer.json";
+ value = {
+ text = builtins.toJSON {
+ inherit (account.lieer) timeout;
+ account = account.address;
+ replace_slash_with_dot = account.lieer.replaceSlashWithDot;
+ drop_non_existing_label = account.lieer.dropNonExistingLabels;
+ ignore_tags = account.lieer.ignoreTagsLocal;
+ ignore_remote_labels = account.lieer.ignoreTagsRemote;
+ } + "\n";
+ };
+ };
+
+in {
+ meta.maintainers = [ maintainers.tadfisher ];
+
+ options = {
+ programs.lieer.enable =
+ mkEnableOption "lieer Gmail synchronization for notmuch";
+
+ accounts.email.accounts = mkOption {
+ type = with types; attrsOf (submodule (import ./lieer-accounts.nix));
+ };
+ };
+
+ config = mkIf cfg.enable (mkMerge [
+ (mkIf (missingNotmuchAccounts != [ ]) {
+ warnings = [''
+ lieer is enabled for the following email accounts, but notmuch is not:
+
+ ${concatStringsSep "\n " missingNotmuchAccounts}
+
+ Notmuch can be enabled with:
+
+ ${concatStringsSep "\n " notmuchConfigHelp}
+
+ If you have configured notmuch outside of Home Manager, you can suppress this
+ warning with:
+
+ programs.lieer.notmuchSetupWarning = false;
+ ''];
+ })
+
+ {
+ assertions = [{
+ assertion = nonGmailAccounts == [ ];
+ message = ''
+ lieer is enabled for non-Gmail accounts:
+
+ ${concatStringsSep "\n " nonGmailAccounts}
+
+ If these accounts are actually Gmail accounts, you can
+ fix this error with:
+
+ ${concatStringsSep "\n " nonGmailConfigHelp}
+ '';
+ }];
+
+ home.packages = [ pkgs.gmailieer ];
+
+ # Notmuch should ignore non-mail files created by lieer.
+ programs.notmuch.new.ignore = [ "/.*[.](json|lock|bak)$/" ];
+
+ home.file = listToAttrs (map configFile lieerAccounts);
+ }
+ ]);
+}
diff --git a/home-manager/modules/programs/man.nix b/home-manager/modules/programs/man.nix
index 0ed376780d4..b235b02fe2d 100644
--- a/home-manager/modules/programs/man.nix
+++ b/home-manager/modules/programs/man.nix
@@ -4,19 +4,69 @@ 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>.
- '';
+ 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>.
+ '';
+ };
+
+ generateCaches = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to generate the manual page index caches using
+ <citerefentry>
+ <refentrytitle>mandb</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>. This allows searching for a page or
+ keyword using utilities like <citerefentry>
+ <refentrytitle>apropos</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </citerefentry>.
+ </para><para>
+ This feature is disabled by default because it slows down
+ building. If you don't mind waiting a few more seconds when
+ Home Manager builds a new generation, you may safely enable
+ this option.
+ '';
+ };
};
};
config = mkIf config.programs.man.enable {
home.packages = [ pkgs.man ];
home.extraOutputsToInstall = [ "man" ];
+
+ # This is mostly copy/pasted/adapted from NixOS' documentation.nix.
+ home.file = mkIf config.programs.man.generateCaches {
+ ".manpath".text = let
+ # Generate a directory containing installed packages' manpages.
+ manualPages = pkgs.buildEnv {
+ name = "man-paths";
+ paths = config.home.packages;
+ pathsToLink = [ "/share/man" ];
+ extraOutputsToInstall = [ "man" ];
+ ignoreCollisions = true;
+ };
+
+ # Generate a database of all manpages in ${manualPages}.
+ manualCache = pkgs.runCommandLocal "man-cache" { } ''
+ # Generate a temporary man.conf so mandb knows where to
+ # write cache files.
+ echo "MANDB_MAP ${manualPages}/share/man $out" > man.conf
+
+ # Run mandb to generate cache files:
+ ${pkgs.man-db}/bin/mandb -C man.conf --no-straycats --create \
+ ${manualPages}/share/man
+ '';
+ in ''
+ MANDB_MAP ${config.home.profileDirectory}/share/man ${manualCache}
+ '';
+ };
};
}
diff --git a/home-manager/modules/programs/mbsync.nix b/home-manager/modules/programs/mbsync.nix
index 6ade10986fe..f2814b393d0 100644
--- a/home-manager/modules/programs/mbsync.nix
+++ b/home-manager/modules/programs/mbsync.nix
@@ -122,6 +122,10 @@ in {
'';
};
};
+
+ accounts.email.accounts = mkOption {
+ type = with types; attrsOf (submodule (import ./mbsync-accounts.nix));
+ };
};
config = mkIf cfg.enable {
diff --git a/home-manager/modules/programs/mcfly.nix b/home-manager/modules/programs/mcfly.nix
new file mode 100644
index 00000000000..1206f9da566
--- /dev/null
+++ b/home-manager/modules/programs/mcfly.nix
@@ -0,0 +1,79 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+
+ cfg = config.programs.mcfly;
+
+in {
+ meta.maintainers = [ maintainers.marsam ];
+
+ options.programs.mcfly = {
+ enable = mkEnableOption "mcfly";
+
+ keyScheme = mkOption {
+ type = types.enum [ "emacs" "vim" ];
+ default = "emacs";
+ description = ''
+ Key scheme to use.
+ '';
+ };
+
+ enableLightTheme = mkOption {
+ default = false;
+ type = types.bool;
+ description = ''
+ Whether to enable light mode theme.
+ '';
+ };
+
+ 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 (mkMerge [
+ {
+ home.packages = [ pkgs.mcfly ];
+
+ programs.bash.initExtra = mkIf cfg.enableBashIntegration ''
+ source "${pkgs.mcfly}/share/mcfly/mcfly.bash"
+ '';
+
+ programs.zsh.initExtra = mkIf cfg.enableZshIntegration ''
+ source "${pkgs.mcfly}/share/mcfly/mcfly.zsh"
+ '';
+
+ programs.fish.shellInit = mkIf cfg.enableFishIntegration ''
+ source "${pkgs.mcfly}/share/mcfly/mcfly.fish"
+ if status is-interactive
+ mcfly_key_bindings
+ end
+ '';
+
+ home.sessionVariables.MCFLY_KEY_SCHEME = cfg.keyScheme;
+ }
+
+ (mkIf cfg.enableLightTheme { home.sessionVariables.MCFLY_LIGHT = "TRUE"; })
+ ]);
+}
diff --git a/home-manager/modules/programs/mpv.nix b/home-manager/modules/programs/mpv.nix
index 3a4e5092f9a..a5b0517fe0a 100644
--- a/home-manager/modules/programs/mpv.nix
+++ b/home-manager/modules/programs/mpv.nix
@@ -125,7 +125,7 @@ in {
(if cfg.scripts == [ ] then
pkgs.mpv
else
- pkgs.mpv-with-scripts.override { scripts = cfg.scripts; })
+ pkgs.wrapMpv pkgs.mpv-unwrapped { scripts = cfg.scripts; })
];
}
(mkIf (cfg.config != { } || cfg.profiles != { }) {
diff --git a/home-manager/modules/programs/msmtp.nix b/home-manager/modules/programs/msmtp.nix
index f34fd72f8b1..7b6704860e0 100644
--- a/home-manager/modules/programs/msmtp.nix
+++ b/home-manager/modules/programs/msmtp.nix
@@ -56,6 +56,10 @@ in {
'';
};
};
+
+ accounts.email.accounts = mkOption {
+ type = with types; attrsOf (submodule (import ./msmtp-accounts.nix));
+ };
};
config = mkIf cfg.enable {
diff --git a/home-manager/modules/programs/ncmpcpp.nix b/home-manager/modules/programs/ncmpcpp.nix
new file mode 100644
index 00000000000..a39baab6ca5
--- /dev/null
+++ b/home-manager/modules/programs/ncmpcpp.nix
@@ -0,0 +1,135 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.programs.ncmpcpp;
+
+ renderSettings = settings:
+ concatStringsSep "\n" (mapAttrsToList renderSetting settings);
+
+ renderSetting = name: value: "${name}=${renderValue value}";
+
+ renderValue = option:
+ {
+ int = toString option;
+ bool = if option then "yes" else "no";
+ string = option;
+ }.${builtins.typeOf option};
+
+ renderBindings = bindings: concatStringsSep "\n" (map renderBinding bindings);
+
+ renderBinding = { key, command }:
+ concatStringsSep "\n " ([ ''def_key "${key}"'' ] ++ maybeWrapList command);
+
+ maybeWrapList = xs: if isList xs then xs else [ xs ];
+
+ valueType = with types; oneOf [ bool int str ];
+
+ bindingType = types.submodule ({ name, config, ... }: {
+ options = {
+ key = mkOption {
+ type = types.str;
+ description = "Key to bind.";
+ example = "j";
+ };
+
+ command = mkOption {
+ type = with types; either str (listOf str);
+ description = "Command or sequence of commands to be executed.";
+ example = "scroll_down";
+ };
+ };
+ });
+
+in {
+ meta.maintainers = with maintainers; [ olmokramer ];
+
+ options.programs.ncmpcpp = {
+ enable =
+ mkEnableOption "ncmpcpp - an ncurses Music Player Daemon (MPD) client";
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.ncmpcpp;
+ defaultText = literalExample "pkgs.ncmpcpp";
+ description = ''
+ Package providing the <code>ncmpcpp</code> command.
+ '';
+ example =
+ literalExample "pkgs.ncmpcpp.override { visualizerSupport = true; }";
+ };
+
+ mpdMusicDir = mkOption {
+ type = types.nullOr types.path;
+ default = let mpdCfg = config.services.mpd;
+ in if pkgs.stdenv.hostPlatform.isLinux && mpdCfg.enable then
+ mpdCfg.musicDirectory
+ else
+ null;
+ defaultText = literalExample ''
+ if pkgs.stdenv.hostPlatform.isLinux && config.services.mpd.enable then
+ config.services.mpd.musicDirectory
+ else
+ null
+ '';
+ description = ''
+ Value of the <code>mpd_music_dir</code> setting. On Linux platforms the
+ value of <varname>services.mpd.musicDirectory</varname> is used as the
+ default if <varname>services.mpd.enable</varname> is
+ <literal>true</literal>.
+ '';
+ example = "~/music";
+ };
+
+ settings = mkOption {
+ type = types.attrsOf valueType;
+ default = { };
+ description = ''
+ Attribute set from name of a setting to its value. For available options
+ see
+ <citerefentry>
+ <refentrytitle>ncmpcpp</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </citerefentry>.
+ '';
+ example = { ncmpcpp_directory = "~/.local/share/ncmpcpp"; };
+ };
+
+ bindings = mkOption {
+ type = types.listOf bindingType;
+ default = [ ];
+ description = "List of keybindings.";
+ example = literalExample ''
+ [
+ { key = "j"; command = "scroll_down"; }
+ { key = "k"; command = "scroll_up"; }
+ { key = "J"; command = [ "select_item" "scroll_down" ]; }
+ { key = "K"; command = [ "select_item" "scroll_up" ]; }
+ ]
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ warnings = mkIf (cfg.settings ? mpd_music_dir && cfg.mpdMusicDir != null) [
+ ("programs.ncmpcpp.settings.mpd_music_dir will be overridden by"
+ + " programs.ncmpcpp.mpdMusicDir.")
+ ];
+
+ home.packages = [ cfg.package ];
+
+ xdg.configFile = {
+ "ncmpcpp/config" = let
+ settings = cfg.settings // optionalAttrs (cfg.mpdMusicDir != null) {
+ mpd_music_dir = toString cfg.mpdMusicDir;
+ };
+ in mkIf (settings != { }) { text = renderSettings settings + "\n"; };
+
+ "ncmpcpp/bindings" = mkIf (cfg.bindings != [ ]) {
+ text = renderBindings cfg.bindings + "\n";
+ };
+ };
+ };
+}
diff --git a/home-manager/modules/programs/ne.nix b/home-manager/modules/programs/ne.nix
new file mode 100644
index 00000000000..a88d23d9133
--- /dev/null
+++ b/home-manager/modules/programs/ne.nix
@@ -0,0 +1,95 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.programs.ne;
+
+ autoPrefFiles = let
+ autoprefs = cfg.automaticPreferences
+ // optionalAttrs (cfg.defaultPreferences != "") {
+ ".default" = cfg.defaultPreferences;
+ };
+
+ gen = fileExtension: configText:
+ nameValuePair ".ne/${fileExtension}#ap" {
+ text = configText;
+ }; # Generates [path].text format expected by home.file.
+ in mapAttrs' gen autoprefs;
+
+in {
+ meta.maintainers = [ hm.maintainers.cwyc ];
+
+ options.programs.ne = {
+ enable = mkEnableOption "ne";
+
+ keybindings = mkOption {
+ type = types.lines;
+ default = "";
+ example = ''
+ KEY 7f BS
+ SEQ "\x1b[1;5D" 7f
+ '';
+ description = ''
+ Keybinding file for ne.
+ '';
+ };
+
+ defaultPreferences = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Default preferences for ne.
+ </para><para>
+ Equivalent to <literal>programs.ne.automaticPreferences.".default"</literal>.
+ '';
+ };
+
+ automaticPreferences = mkOption {
+ type = types.attrsOf types.lines;
+ default = { };
+ example = literalExample ''
+ {
+ nix = '''
+ TAB 0
+ TS 2
+ ''';
+ js = '''
+ TS 4
+ ''';
+ }
+ '';
+ description = ''
+ Automatic preferences files for ne.
+ '';
+ };
+
+ menus = mkOption {
+ type = types.lines;
+ default = "";
+ description = "Menu configuration file for ne.";
+ };
+
+ virtualExtensions = mkOption {
+ type = types.lines;
+ default = "";
+ example = ''
+ sh 1 ^#!\s*/.*\b(bash|sh|ksh|zsh)\s*
+ csh 1 ^#!\s*/.*\b(csh|tcsh)\s*
+ '';
+ description = "Virtual extensions configuration file for ne.";
+ };
+ };
+
+ config = mkIf cfg.enable {
+ home.packages = [ pkgs.ne ];
+
+ home.file = {
+ ".ne/.keys" = mkIf (cfg.keybindings != "") { text = cfg.keybindings; };
+ ".ne/.extensions" =
+ mkIf (cfg.virtualExtensions != "") { text = cfg.virtualExtensions; };
+ ".ne/.menus" = mkIf (cfg.menus != "") { text = cfg.menus; };
+ } // autoPrefFiles;
+ };
+}
diff --git a/home-manager/modules/programs/neomutt-accounts.nix b/home-manager/modules/programs/neomutt-accounts.nix
index 033db38eb0a..009cf1fa7e8 100644
--- a/home-manager/modules/programs/neomutt-accounts.nix
+++ b/home-manager/modules/programs/neomutt-accounts.nix
@@ -8,7 +8,16 @@ with lib;
sendMailCommand = mkOption {
type = types.nullOr types.str;
- default = null;
+ default = if config.msmtp.enable then
+ "msmtpq --read-envelope-from --read-recipients"
+ else
+ null;
+ defaultText = literalExample ''
+ if config.msmtp.enable then
+ "msmtpq --read-envelope-from --read-recipients"
+ else
+ null
+ '';
example = "msmtpq --read-envelope-from --read-recipients";
description = ''
Command to send a mail. If not set, neomutt will be in charge of sending mails.
@@ -24,11 +33,4 @@ with lib;
'';
};
};
-
- config = mkIf config.neomutt.enable {
- neomutt.sendMailCommand = mkOptionDefault (if config.msmtp.enable then
- "msmtpq --read-envelope-from --read-recipients"
- else
- null);
- };
}
diff --git a/home-manager/modules/programs/neomutt.nix b/home-manager/modules/programs/neomutt.nix
index 85af0353b6c..f2a6bbfff08 100644
--- a/home-manager/modules/programs/neomutt.nix
+++ b/home-manager/modules/programs/neomutt.nix
@@ -38,6 +38,19 @@ let
};
};
+ sortOptions = [
+ "date"
+ "date-received"
+ "from"
+ "mailbox-order"
+ "score"
+ "size"
+ "spam"
+ "subject"
+ "threads"
+ "to"
+ ];
+
bindModule = types.submodule {
options = {
map = mkOption {
@@ -98,7 +111,9 @@ let
} else
let
smtpProto = if smtp.tls.enable then "smtps" else "smtp";
- smtpBaseUrl = "${smtpProto}://${escape userName}@${smtp.host}";
+ smtpPort = if smtp.port != null then ":${toString smtp.port}" else "";
+ smtpBaseUrl =
+ "${smtpProto}://${escape userName}@${smtp.host}${smtpPort}";
in {
smtp_url = "'${smtpBaseUrl}'";
smtp_pass = "'`${passCmd}`'";
@@ -211,18 +226,9 @@ in {
};
sort = mkOption {
- type = types.enum [
- "date"
- "date-received"
- "from"
- "mailbox-order"
- "score"
- "size"
- "spam"
- "subject"
- "threads"
- "to"
- ];
+ # allow users to choose any option from sortOptions, or any option prefixed with "reverse-"
+ type = types.enum
+ (sortOptions ++ (map (option: "reverse-" + option) sortOptions));
default = "threads";
description = "Sorting method on messages.";
};
@@ -258,6 +264,10 @@ in {
description = "Extra configuration appended to the end.";
};
};
+
+ accounts.email.accounts = mkOption {
+ type = with types; attrsOf (submodule (import ./neomutt-accounts.nix));
+ };
};
config = mkIf cfg.enable {
diff --git a/home-manager/modules/programs/neovim.nix b/home-manager/modules/programs/neovim.nix
index 4101dc0f4e7..858f5576ad1 100644
--- a/home-manager/modules/programs/neovim.nix
+++ b/home-manager/modules/programs/neovim.nix
@@ -43,7 +43,7 @@ in
type = types.bool;
default = false;
description = ''
- Symlink `vi` to `nvim` binary.
+ Symlink <command>vi</command> to <command>nvim</command> binary.
'';
};
@@ -51,7 +51,15 @@ in
type = types.bool;
default = false;
description = ''
- Symlink `vim` to `nvim` binary.
+ Symlink <command>vim</command> to <command>nvim</command> binary.
+ '';
+ };
+
+ vimdiffAlias = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Alias <command>vimdiff</command> to <command>nvim -d</command>.
'';
};
@@ -203,5 +211,9 @@ in
configure = cfg.configure // moduleConfigure;
};
+
+ programs.bash.shellAliases = mkIf cfg.vimdiffAlias { vimdiff = "nvim -d"; };
+ programs.fish.shellAliases = mkIf cfg.vimdiffAlias { vimdiff = "nvim -d"; };
+ programs.zsh.shellAliases = mkIf cfg.vimdiffAlias { vimdiff = "nvim -d"; };
};
}
diff --git a/home-manager/modules/programs/newsboat.nix b/home-manager/modules/programs/newsboat.nix
index 6b59ed713d8..793b30680bf 100644
--- a/home-manager/modules/programs/newsboat.nix
+++ b/home-manager/modules/programs/newsboat.nix
@@ -102,7 +102,11 @@ in {
mkQueryEntry = n: v: ''"query:${n}:${escape [ ''"'' ] v}"'';
queries = mapAttrsToList mkQueryEntry cfg.queries;
- in concatStringsSep "\n" (urls ++ queries) + "\n";
+ in concatStringsSep "\n"
+ (if versionAtLeast config.home.stateVersion "20.03" then
+ queries ++ urls
+ else
+ urls ++ queries) + "\n";
home.file.".newsboat/config".text = ''
max-items ${toString cfg.maxItems}
diff --git a/home-manager/modules/programs/notmuch.nix b/home-manager/modules/programs/notmuch.nix
index 7e7a140b20c..9070d755671 100644
--- a/home-manager/modules/programs/notmuch.nix
+++ b/home-manager/modules/programs/notmuch.nix
@@ -143,6 +143,10 @@ in {
};
};
};
+
+ accounts.email.accounts = mkOption {
+ type = with types; attrsOf (submodule (import ./notmuch-accounts.nix));
+ };
};
config = mkIf cfg.enable {
diff --git a/home-manager/modules/programs/nushell.nix b/home-manager/modules/programs/nushell.nix
new file mode 100644
index 00000000000..1eb42f9515c
--- /dev/null
+++ b/home-manager/modules/programs/nushell.nix
@@ -0,0 +1,68 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.programs.nushell;
+
+ 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.Philipp-M ];
+
+ options.programs.nushell = {
+ enable = mkEnableOption "nushell";
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.nushell;
+ defaultText = literalExample "pkgs.nushell";
+ description = "The package to use for nushell.";
+ };
+
+ settings = mkOption {
+ type = with types;
+ let
+ prim = oneOf [ bool int str ];
+ primOrPrimAttrs = either prim (attrsOf prim);
+ entry = either prim (listOf primOrPrimAttrs);
+ entryOrAttrsOf = t: either entry (attrsOf t);
+ entries = entryOrAttrsOf (entryOrAttrsOf entry);
+ in attrsOf entries // { description = "Nushell configuration"; };
+ default = { };
+ example = literalExample ''
+ {
+ edit_mode = "vi";
+ startup = [ "alias la [] { ls -a }" "alias e [msg] { echo $msg }" ];
+ key_timeout = 10;
+ completion_mode = "circular";
+ no_auto_pivot = true;
+ }
+ '';
+ description = ''
+ Configuration written to
+ <filename>~/.config/nushell/config.toml</filename>.
+ </para><para>
+ See <link xlink:href="https://www.nushell.sh/book/en/configuration.html" /> for the full list
+ of options.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ home.packages = [ cfg.package ];
+
+ xdg.configFile."nu/config.toml" =
+ mkIf (cfg.settings != { }) { source = configFile cfg.settings; };
+ };
+}
diff --git a/home-manager/modules/programs/offlineimap.nix b/home-manager/modules/programs/offlineimap.nix
index 4ce12ec0a61..b6ba847e9b7 100644
--- a/home-manager/modules/programs/offlineimap.nix
+++ b/home-manager/modules/programs/offlineimap.nix
@@ -147,6 +147,11 @@ in {
'';
};
};
+
+ accounts.email.accounts = mkOption {
+ type = with types;
+ attrsOf (submodule (import ./offlineimap-accounts.nix));
+ };
};
config = mkIf cfg.enable {
diff --git a/home-manager/modules/programs/powerline-go.nix b/home-manager/modules/programs/powerline-go.nix
new file mode 100644
index 00000000000..a4cd233cf70
--- /dev/null
+++ b/home-manager/modules/programs/powerline-go.nix
@@ -0,0 +1,123 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.programs.powerline-go;
+
+ # Convert an option value to a string to be passed as argument to
+ # powerline-go:
+ valueToString = value:
+ if builtins.isList value then
+ builtins.concatStringsSep "," (builtins.map valueToString value)
+ else if builtins.isAttrs value then
+ valueToString
+ (mapAttrsToList (key: val: "${valueToString key}=${valueToString val}")
+ value)
+ else
+ builtins.toString value;
+
+ modulesArgument = optionalString (cfg.modules != null)
+ "-modules ${valueToString cfg.modules}";
+
+ newlineArgument = optionalString cfg.newline "-newline";
+
+ pathAliasesArgument = optionalString (cfg.pathAliases != null)
+ "-path-aliases ${valueToString cfg.pathAliases}";
+
+ otherSettingPairArgument = name: value:
+ if value == true then "-${name}" else "-${name} ${valueToString value}";
+
+ otherSettingsArgument = optionalString (cfg.settings != { })
+ (concatStringsSep " "
+ (mapAttrsToList otherSettingPairArgument cfg.settings));
+
+ commandLineArguments = ''
+ ${modulesArgument} ${newlineArgument} ${pathAliasesArgument} ${otherSettingsArgument}
+ '';
+
+in {
+ meta.maintainers = [ maintainers.DamienCassou ];
+
+ options = {
+ programs.powerline-go = {
+ enable = mkEnableOption
+ "Powerline-go, a beautiful and useful low-latency prompt for your shell";
+
+ modules = mkOption {
+ default = null;
+ type = types.nullOr (types.listOf types.str);
+ description = ''
+ List of module names to load. The list of all available
+ modules as well as the choice of default ones are at
+ <link xlink:href="https://github.com/justjanne/powerline-go"/>.
+ '';
+ example = [ "host" "ssh" "cwd" "gitlite" "jobs" "exit" ];
+ };
+
+ newline = mkOption {
+ default = false;
+ type = types.bool;
+ description = ''
+ Set to true if the prompt should be on a line of its own.
+ '';
+ example = true;
+ };
+
+ pathAliases = mkOption {
+ default = null;
+ type = types.nullOr (types.attrsOf types.str);
+ description = ''
+ Pairs of full-path and corresponding desired short name. You
+ may use '~' to represent your home directory but you should
+ protect it to avoid shell substitution.
+ '';
+ example = literalExample ''
+ { "\\~/projects/home-manager" = "prj:home-manager"; }
+ '';
+ };
+
+ settings = mkOption {
+ default = { };
+ type = with types; attrsOf (oneOf [ bool int str (listOf str) ]);
+ description = ''
+ This can be any key/value pair as described in
+ <link xlink:href="https://github.com/justjanne/powerline-go"/>.
+ '';
+ example = literalExample ''
+ {
+ hostname-only-if-ssh = true;
+ numeric-exit-codes = true;
+ cwd-max-depth = 7;
+ ignore-repos = [ "/home/me/big-project" "/home/me/huge-project" ];
+ }
+ '';
+ };
+
+ extraUpdatePS1 = mkOption {
+ default = "";
+ description = "Shell code to execute after the prompt is set.";
+ example = ''
+ PS1=$PS1"NixOS> ";
+ '';
+ type = types.str;
+ };
+ };
+ };
+
+ config = mkIf (cfg.enable && config.programs.bash.enable) {
+ programs.bash.initExtra = ''
+ function _update_ps1() {
+ local old_exit_status=$?
+ PS1="$(${pkgs.powerline-go}/bin/powerline-go -error $old_exit_status ${commandLineArguments})"
+ ${cfg.extraUpdatePS1}
+ return $old_exit_status
+ }
+
+ if [ "$TERM" != "linux" ]; then
+ PROMPT_COMMAND="_update_ps1;$PROMPT_COMMAND"
+ fi
+ '';
+ };
+}
diff --git a/home-manager/modules/programs/qutebrowser.nix b/home-manager/modules/programs/qutebrowser.nix
new file mode 100644
index 00000000000..798363fb187
--- /dev/null
+++ b/home-manager/modules/programs/qutebrowser.nix
@@ -0,0 +1,268 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.programs.qutebrowser;
+
+ formatLine = o: n: v:
+ let
+ formatValue = v:
+ if builtins.isNull v then
+ "None"
+ else if builtins.isBool v then
+ (if v then "True" else "False")
+ else if builtins.isString v then
+ ''"${v}"''
+ else if builtins.isList v then
+ "[${concatStringsSep ", " (map formatValue v)}]"
+ else
+ builtins.toString v;
+ in if builtins.isAttrs v then
+ concatStringsSep "\n" (mapAttrsToList (formatLine "${o}${n}.") v)
+ else
+ "${o}${n} = ${formatValue v}";
+
+ formatDictLine = o: n: v: ''${o}['${n}'] = "${v}"'';
+
+ formatKeyBindings = m: b:
+ let
+ formatKeyBinding = m: k: c:
+ ''config.bind("${k}", "${escape [ ''"'' ] c}", mode="${m}")'';
+ in concatStringsSep "\n" (mapAttrsToList (formatKeyBinding m) b);
+
+in {
+ options.programs.qutebrowser = {
+ enable = mkEnableOption "qutebrowser";
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.qutebrowser;
+ defaultText = literalExample "pkgs.qutebrowser";
+ description = "Qutebrowser package to install.";
+ };
+
+ aliases = mkOption {
+ type = types.attrsOf types.str;
+ default = { };
+ description = ''
+ Aliases for commands.
+ '';
+ };
+
+ searchEngines = mkOption {
+ type = types.attrsOf types.str;
+ default = { };
+ description = ''
+ Search engines that can be used via the address bar. Maps a search
+ engine name (such as <literal>DEFAULT</literal>, or
+ <literal>ddg</literal>) to a URL with a <literal>{}</literal>
+ placeholder. The placeholder will be replaced by the search term, use
+ <literal>{{</literal> and <literal>}}</literal> for literal
+ <literal>{/}</literal> signs. The search engine named
+ <literal>DEFAULT</literal> is used when
+ <literal>url.auto_search</literal> is turned on and something else than
+ a URL was entered to be opened. Other search engines can be used by
+ prepending the search engine name to the search term, for example
+ <literal>:open google qutebrowser</literal>.
+ '';
+ example = literalExample ''
+ {
+ w = "https://en.wikipedia.org/wiki/Special:Search?search={}&go=Go&ns0=1";
+ aw = "https://wiki.archlinux.org/?search={}";
+ nw = "https://nixos.wiki/index.php?search={}";
+ g = "https://www.google.com/search?hl=en&q={}";
+ }
+ '';
+ };
+
+ settings = mkOption {
+ type = types.attrs;
+ default = { };
+ description = ''
+ Options to add to qutebrowser <filename>config.py</filename> file.
+ See <link xlink:href="https://qutebrowser.org/doc/help/settings.html"/>
+ for options.
+ '';
+ example = literalExample ''
+ {
+ colors = {
+ hints = {
+ bg = "#000000";
+ fg = "#ffffff";
+ };
+ tabs.bar.bg = "#000000";
+ };
+ tabs.tabs_are_windows = true;
+ }
+ '';
+ };
+
+ keyMappings = mkOption {
+ type = types.attrsOf types.str;
+ default = { };
+ description = ''
+ This setting can be used to map keys to other keys. When the key used
+ as dictionary-key is pressed, the binding for the key used as
+ dictionary-value is invoked instead. This is useful for global
+ remappings of keys, for example to map Ctrl-[ to Escape. Note that when
+ a key is bound (via <literal>bindings.default</literal> or
+ <literal>bindings.commands</literal>), the mapping is ignored.
+ '';
+ };
+
+ enableDefaultBindings = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Disable to prevent loading default key bindings.
+ '';
+ };
+
+ keyBindings = mkOption {
+ type = types.attrsOf (types.attrsOf types.str);
+ default = { };
+ description = ''
+ Key bindings mapping keys to commands in different modes. This setting
+ is a dictionary containing mode names and dictionaries mapping keys to
+ commands: <literal>{mode: {key: command}}</literal> If you want to map
+ a key to another key, check the <literal>keyMappings</literal> setting
+ instead. For modifiers, you can use either <literal>-</literal> or
+ <literal>+</literal> as delimiters, and these names:
+
+ <itemizedlist>
+ <listitem><para>
+ Control: <literal>Control</literal>, <literal>Ctrl</literal>
+ </para></listitem>
+ <listitem><para>
+ Meta: <literal>Meta</literal>, <literal>Windows</literal>,
+ <literal>Mod4</literal>
+ </para></listitem>
+ <listitem><para>
+ Alt: <literal>Alt</literal>, <literal>Mod1</literal>
+ </para></listitem>
+ <listitem><para>
+ Shift: <literal>Shift</literal>
+ </para></listitem>
+ </itemizedlist>
+
+ For simple keys (no <literal>&lt;&gt;</literal>-signs), a capital
+ letter means the key is pressed with Shift. For special keys (with
+ <literal>&lt;&gt;</literal>-signs), you need to explicitly add
+ <literal>Shift-</literal> to match a key pressed with shift. If you
+ want a binding to do nothing, bind it to the <literal>nop</literal>
+ command. If you want a default binding to be passed through to the
+ website, bind it to null. Note that some commands which are only useful
+ for bindings (but not used interactively) are hidden from the command
+ completion. See <literal>:</literal>help for a full list of available
+ commands. The following modes are available:
+
+ <variablelist>
+ <varlistentry>
+ <term><literal>normal</literal></term>
+ <listitem><para>
+ Default mode, where most commands are invoked.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>insert</literal></term>
+ <listitem><para>
+ Entered when an input field is focused on a website, or by
+ pressing i in normal mode. Passes through almost all keypresses
+ to the website, but has some bindings like
+ <literal>&lt;Ctrl-e&gt;</literal> to open an external editor.
+ Note that single keys can’t be bound in this mode.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>hint</literal></term>
+ <listitem><para>
+ Entered when f is pressed to select links with the keyboard. Note
+ that single keys can’t be bound in this mode.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>passthrough</literal></term>
+ <listitem><para>
+ Similar to insert mode, but passes through all keypresses except
+ <literal>&lt;Escape&gt;</literal> to leave the mode. It might be
+ useful to bind <literal>&lt;Escape&gt;</literal> to some other
+ key in this mode if you want to be able to send an Escape key to
+ the website as well. Note that single keys can’t be bound in this
+ mode.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>command</literal></term>
+ <listitem><para>
+ Entered when pressing the : key in order to enter a command. Note
+ that single keys can’t be bound in this mode.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>prompt</literal></term>
+ <listitem><para>
+ Entered when there’s a prompt to display, like for download
+ locations or when invoked from JavaScript.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>yesno</literal></term>
+ <listitem><para>
+ Entered when there’s a yes/no prompt displayed.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>caret</literal></term>
+ <listitem><para>
+ Entered when pressing the v mode, used to select text using the
+ keyboard.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>register</literal></term>
+ <listitem><para>
+ Entered when qutebrowser is waiting for a register name/key for
+ commands like <literal>:set-mark</literal>.
+ </para></listitem>
+ </varlistentry>
+ </variablelist>
+ '';
+ example = literalExample ''
+ {
+ normal = {
+ "<Ctrl-v>" = "spawn mpv {url}";
+ ",p" = "spawn --userscript qute-pass";
+ ",l" = '''config-cycle spellcheck.languages ["en-GB"] ["en-US"]''';
+ };
+ prompt = {
+ "<Ctrl-y>" = "prompt-yes";
+ };
+ }
+ '';
+ };
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Extra lines added to qutebrowser <filename>config.py</filename> file.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ home.packages = [ cfg.package ];
+
+ xdg.configFile."qutebrowser/config.py".text = concatStringsSep "\n" ([ ]
+ ++ mapAttrsToList (formatLine "c.") cfg.settings
+ ++ mapAttrsToList (formatDictLine "c.aliases") cfg.aliases
+ ++ mapAttrsToList (formatDictLine "c.url.searchengines") cfg.searchEngines
+ ++ mapAttrsToList (formatDictLine "c.bindings.key_mappings")
+ cfg.keyMappings
+ ++ optional (!cfg.enableDefaultBindings) "c.bindings.default = {}"
+ ++ mapAttrsToList formatKeyBindings cfg.keyBindings
+ ++ optional (cfg.extraConfig != "") cfg.extraConfig);
+ };
+}
diff --git a/home-manager/modules/programs/rofi.nix b/home-manager/modules/programs/rofi.nix
index f344e88e2ff..734bcc423e6 100644
--- a/home-manager/modules/programs/rofi.nix
+++ b/home-manager/modules/programs/rofi.nix
@@ -131,6 +131,17 @@ in {
enable = mkEnableOption
"Rofi: A window switcher, application launcher and dmenu replacement";
+ package = mkOption {
+ default = pkgs.rofi;
+ type = types.package;
+ description = ''
+ Package providing the <command>rofi</command> binary.
+ '';
+ example = literalExample ''
+ pkgs.rofi.override { plugins = [ pkgs.rofi-emoji ]; };
+ '';
+ };
+
width = mkOption {
default = null;
type = types.nullOr types.int;
@@ -295,7 +306,7 @@ in {
'';
}];
- home.packages = [ pkgs.rofi ];
+ home.packages = [ cfg.package ];
home.file."${cfg.configPath}".text = ''
${setOption "width" cfg.width}
diff --git a/home-manager/modules/programs/ssh.nix b/home-manager/modules/programs/ssh.nix
index 6b0747dd9b1..ae1f221803c 100644
--- a/home-manager/modules/programs/ssh.nix
+++ b/home-manager/modules/programs/ssh.nix
@@ -56,7 +56,7 @@ let
};
};
- matchBlockModule = types.submodule ({ name, ... }: {
+ matchBlockModule = types.submodule ({ dagName, ... }: {
options = {
host = mkOption {
type = types.str;
@@ -143,6 +143,15 @@ let
"Set timeout in seconds after which response will be requested.";
};
+ serverAliveCountMax = mkOption {
+ type = types.ints.positive;
+ default = 3;
+ description = ''
+ Sets the number of server alive messages which may be sent
+ without SSH receiving any messages back from the server.
+ '';
+ };
+
sendEnv = mkOption {
type = types.listOf types.str;
default = [];
@@ -266,7 +275,7 @@ let
};
};
- config.host = mkDefault name;
+ config.host = mkDefault dagName;
});
matchBlockStr = cf: concatStringsSep "\n" (
@@ -281,7 +290,9 @@ let
++ optional (cf.addressFamily != null) " AddressFamily ${cf.addressFamily}"
++ optional (cf.sendEnv != []) " SendEnv ${unwords cf.sendEnv}"
++ optional (cf.serverAliveInterval != 0)
- " ServerAliveInterval ${toString cf.serverAliveInterval}"
+ " ServerAliveInterval ${toString cf.serverAliveInterval}"
+ ++ optional (cf.serverAliveCountMax != 3)
+ " ServerAliveCountMax ${toString cf.serverAliveCountMax}"
++ optional (cf.compression != null) " Compression ${yn cf.compression}"
++ optional (!cf.checkHostIP) " CheckHostIP no"
++ optional (cf.proxyCommand != null) " ProxyCommand ${cf.proxyCommand}"
@@ -325,6 +336,15 @@ in
'';
};
+ serverAliveCountMax = mkOption {
+ type = types.ints.positive;
+ default = 3;
+ description = ''
+ Sets the default number of server alive messages which may be
+ sent without SSH receiving any messages back from the server.
+ '';
+ };
+
hashKnownHosts = mkOption {
default = false;
type = types.bool;
@@ -392,7 +412,7 @@ in
};
matchBlocks = mkOption {
- type = types.loaOf matchBlockModule;
+ type = hm.types.listOrDagOf matchBlockModule;
default = {};
example = literalExample ''
{
@@ -400,7 +420,7 @@ in
hostname = "example.com";
user = "john";
};
- foo = {
+ foo = lib.hm.dag.entryBefore ["john.example.com"] {
hostname = "example.com";
identityFile = "/home/john/.ssh/foo_rsa";
};
@@ -408,11 +428,15 @@ in
'';
description = ''
Specify per-host settings. Note, if the order of rules matter
- then this must be a list. See
+ then use the DAG functions to express the dependencies as
+ shown in the example.
+ </para><para>
+ See
<citerefentry>
<refentrytitle>ssh_config</refentrytitle>
<manvolnum>5</manvolnum>
- </citerefentry>.
+ </citerefentry>
+ for more information.
'';
};
};
@@ -432,23 +456,30 @@ in
checkLocal = block: any' checkBindAndHost block.localForwards;
checkRemote = block: any' checkBindAndHost block.remoteForwards;
checkMatchBlock = block: all (fn: fn block) [ checkLocal checkRemote checkDynamic ];
- in any' checkMatchBlock (builtins.attrValues cfg.matchBlocks);
+ in any' checkMatchBlock (map (block: block.data) (builtins.attrValues cfg.matchBlocks));
message = "Forwarded paths cannot have ports.";
}
];
- home.file.".ssh/config".text = ''
+ home.file.".ssh/config".text =
+ let
+ sortedMatchBlocks = hm.dag.topoSort cfg.matchBlocks;
+ sortedMatchBlocksStr = builtins.toJSON sortedMatchBlocks;
+ matchBlocks =
+ if sortedMatchBlocks ? result
+ then sortedMatchBlocks.result
+ else abort "Dependency cycle in SSH match blocks: ${sortedMatchBlocksStr}";
+ in ''
${concatStringsSep "\n" (
mapAttrsToList (n: v: "${n} ${v}") cfg.extraOptionOverrides)}
- ${concatStringsSep "\n\n" (
- map matchBlockStr (
- builtins.attrValues cfg.matchBlocks))}
+ ${concatStringsSep "\n\n" (map (block: matchBlockStr block.data) matchBlocks)}
Host *
ForwardAgent ${yn cfg.forwardAgent}
Compression ${yn cfg.compression}
ServerAliveInterval ${toString cfg.serverAliveInterval}
+ ServerAliveCountMax ${toString cfg.serverAliveCountMax}
HashKnownHosts ${yn cfg.hashKnownHosts}
UserKnownHostsFile ${cfg.userKnownHostsFile}
ControlMaster ${cfg.controlMaster}
diff --git a/home-manager/modules/programs/starship.nix b/home-manager/modules/programs/starship.nix
index 7c7819865f7..8462d331501 100644
--- a/home-manager/modules/programs/starship.nix
+++ b/home-manager/modules/programs/starship.nix
@@ -31,8 +31,23 @@ in {
};
settings = mkOption {
- type = types.attrs;
+ type = with types;
+ let
+ prim = either bool (either int str);
+ primOrPrimAttrs = either prim (attrsOf prim);
+ entry = either prim (listOf primOrPrimAttrs);
+ entryOrAttrsOf = t: either entry (attrsOf t);
+ entries = entryOrAttrsOf (entryOrAttrsOf entry);
+ in attrsOf entries // { description = "Starship configuration"; };
default = { };
+ example = literalExample ''
+ {
+ add_newline = false;
+ prompt_order = [ "line_break" "package" "line_break" "character" ];
+ scan_timeout = 10;
+ character.symbol = "➜";
+ }
+ '';
description = ''
Configuration written to
<filename>~/.config/starship.toml</filename>.
@@ -74,7 +89,7 @@ in {
mkIf (cfg.settings != { }) { source = configFile cfg.settings; };
programs.bash.initExtra = mkIf cfg.enableBashIntegration ''
- if [[ -z $INSIDE_EMACS ]]; then
+ if [[ $TERM != "dumb" && (-z $INSIDE_EMACS || $INSIDE_EMACS == "vterm") ]]; then
eval "$(${cfg.package}/bin/starship init bash)"
fi
'';
@@ -85,8 +100,8 @@ in {
fi
'';
- programs.fish.shellInit = mkIf cfg.enableFishIntegration ''
- if test -z "$INSIDE_EMACS"
+ programs.fish.promptInit = mkIf cfg.enableFishIntegration ''
+ if test "$TERM" != "dumb" -a \( -z "$INSIDE_EMACS" -o "$INSIDE_EMACS" = "vterm" \)
eval (${cfg.package}/bin/starship init fish)
end
'';
diff --git a/home-manager/modules/programs/termite.nix b/home-manager/modules/programs/termite.nix
index 8a05db03558..e3d704424e8 100644
--- a/home-manager/modules/programs/termite.nix
+++ b/home-manager/modules/programs/termite.nix
@@ -362,7 +362,7 @@ in {
${optionalString "cursor" cfg.cursorColor}
${optionalString "cursor_foreground" cfg.cursorForegroundColor}
${optionalString "foreground" cfg.foregroundColor}
- ${optionalString "foregroundBold" cfg.foregroundBoldColor}
+ ${optionalString "foreground_bold" cfg.foregroundBoldColor}
${optionalString "highlight" cfg.highlightColor}
${cfg.colorsExtra}
diff --git a/home-manager/modules/programs/tmux.nix b/home-manager/modules/programs/tmux.nix
index 766bc6238ba..a71c302ac6f 100644
--- a/home-manager/modules/programs/tmux.nix
+++ b/home-manager/modules/programs/tmux.nix
@@ -6,7 +6,7 @@ let
cfg = config.programs.tmux;
- pluginName = p: if types.package.check p then p.name else p.plugin.name;
+ pluginName = p: if types.package.check p then p.pname else p.plugin.pname;
pluginModule = types.submodule {
options = {
@@ -31,6 +31,13 @@ let
boolToStr = value: if value then "on" else "off";
tmuxConf = ''
+ ${optionalString cfg.sensibleOnTop ''
+ # ============================================= #
+ # Start with defaults from the Sensible plugin #
+ # --------------------------------------------- #
+ run-shell ${pkgs.tmuxPlugins.sensible.rtp}
+ # ============================================= #
+ ''}
set -g default-terminal "${cfg.terminal}"
set -g base-index ${toString cfg.baseIndex}
setw -g pane-base-index ${toString cfg.baseIndex}
@@ -74,10 +81,40 @@ let
setw -g clock-mode-style ${if cfg.clock24 then "24" else "12"}
set -s escape-time ${toString cfg.escapeTime}
set -g history-limit ${toString cfg.historyLimit}
-
- ${cfg.extraConfig}
'';
+ configPlugins = {
+ assertions = [(
+ let
+ hasBadPluginName = p: !(hasPrefix "tmuxplugin" (pluginName p));
+ badPlugins = filter hasBadPluginName cfg.plugins;
+ in
+ {
+ assertion = badPlugins == [];
+ message =
+ "Invalid tmux plugin (not prefixed with \"tmuxplugins\"): "
+ + concatMapStringsSep ", " pluginName badPlugins;
+ }
+ )];
+
+ home.file.".tmux.conf".text = ''
+ # ============================================= #
+ # Load plugins with Home Manager #
+ # --------------------------------------------- #
+
+ ${(concatMapStringsSep "\n\n" (p: ''
+ # ${pluginName p}
+ # ---------------------
+ ${p.extraConfig or ""}
+ run-shell ${
+ if types.package.check p
+ then p.rtp
+ else p.plugin.rtp
+ }
+ '') cfg.plugins)}
+ # ============================================= #
+ '';
+ };
in
{
@@ -214,7 +251,7 @@ in
};
secureSocket = mkOption {
- default = true;
+ default = pkgs.stdenv.isLinux;
type = types.bool;
description = ''
Store tmux socket under <filename>/run</filename>, which is more
@@ -258,63 +295,22 @@ in
};
config = mkIf cfg.enable (
- mkMerge [
+ mkMerge ([
{
home.packages = [ cfg.package ]
++ optional cfg.tmuxinator.enable pkgs.tmuxinator
++ optional cfg.tmuxp.enable pkgs.tmuxp;
-
- home.file.".tmux.conf".text = tmuxConf;
}
-
- (mkIf cfg.sensibleOnTop {
- home.file.".tmux.conf".text = mkBefore ''
- # ============================================= #
- # Start with defaults from the Sensible plugin #
- # --------------------------------------------- #
- run-shell ${pkgs.tmuxPlugins.sensible.rtp}
- # ============================================= #
- '';
- })
-
(mkIf cfg.secureSocket {
home.sessionVariables = {
TMUX_TMPDIR = ''''${XDG_RUNTIME_DIR:-"/run/user/\$(id -u)"}'';
};
})
- (mkIf (cfg.plugins != []) {
- assertions = [(
- let
- hasBadPluginName = p: !(hasPrefix "tmuxplugin" (pluginName p));
- badPlugins = filter hasBadPluginName cfg.plugins;
- in
- {
- assertion = badPlugins == [];
- message =
- "Invalid tmux plugin (not prefixed with \"tmuxplugins\"): "
- + concatMapStringsSep ", " pluginName badPlugins;
- }
- )];
-
- home.file.".tmux.conf".text = mkAfter ''
- # ============================================= #
- # Load plugins with Home Manager #
- # --------------------------------------------- #
-
- ${(concatMapStringsSep "\n\n" (p: ''
- # ${pluginName p}
- # ---------------------
- ${p.extraConfig or ""}
- run-shell ${
- if types.package.check p
- then p.rtp
- else p.plugin.rtp
- }
- '') cfg.plugins)}
- # ============================================= #
- '';
- })
- ]
+ # config file ~/.tmux.conf
+ { home.file.".tmux.conf".text = mkBefore tmuxConf; }
+ (mkIf (cfg.plugins != []) configPlugins)
+ { home.file.".tmux.conf".text = mkAfter cfg.extraConfig; }
+ ])
);
}
diff --git a/home-manager/modules/programs/vim.nix b/home-manager/modules/programs/vim.nix
index 39826a9a5d6..3325bf22516 100644
--- a/home-manager/modules/programs/vim.nix
+++ b/home-manager/modules/programs/vim.nix
@@ -5,7 +5,7 @@ with lib;
let
cfg = config.programs.vim;
- defaultPlugins = [ pkgs.vimPlugins.sensible ];
+ defaultPlugins = [ pkgs.vimPlugins.vim-sensible ];
knownSettings = {
background = types.enum [ "dark" "light" ];
diff --git a/home-manager/modules/programs/vscode.nix b/home-manager/modules/programs/vscode.nix
index cf7ac722210..099760c834a 100644
--- a/home-manager/modules/programs/vscode.nix
+++ b/home-manager/modules/programs/vscode.nix
@@ -20,11 +20,14 @@ let
"vscodium" = "vscode-oss";
}.${vscodePname};
- configFilePath =
+ userDir =
if pkgs.stdenv.hostPlatform.isDarwin then
- "Library/Application Support/${configDir}/User/settings.json"
+ "Library/Application Support/${configDir}/User"
else
- "${config.xdg.configHome}/${configDir}/User/settings.json";
+ "${config.xdg.configHome}/${configDir}/User";
+
+ configFilePath = "${userDir}/settings.json";
+ keybindingsFilePath = "${userDir}/keybindings.json";
# TODO: On Darwin where are the extensions?
extensionPath = ".${extensionDir}/extensions";
@@ -59,6 +62,45 @@ in
'';
};
+ keybindings = mkOption {
+ type = types.listOf (types.submodule {
+ options = {
+ key = mkOption {
+ type = types.str;
+ example = "ctrl+c";
+ description = "The key or key-combination to bind.";
+ };
+
+ command = mkOption {
+ type = types.str;
+ example = "editor.action.clipboardCopyAction";
+ description = "The VS Code command to execute.";
+ };
+
+ when = mkOption {
+ type = types.str;
+ default = "";
+ example = "textInputFocus";
+ description = "Optional context filter.";
+ };
+ };
+ });
+ default = [];
+ example = literalExample ''
+ [
+ {
+ key = "ctrl+c";
+ command = "editor.action.clipboardCopyAction";
+ when = "textInputFocus";
+ }
+ ]
+ '';
+ description = ''
+ Keybindings written to Visual Studio Code's
+ <filename>keybindings.json</filename>.
+ '';
+ };
+
extensions = mkOption {
type = types.listOf types.package;
default = [];
@@ -77,15 +119,13 @@ in
# Adapted from https://discourse.nixos.org/t/vscode-extensions-setup/1801/2
home.file =
let
+ subDir = "share/vscode/extensions";
toPaths = path:
- let
- p = "${path}/share/vscode/extensions";
- in
- # Links every dir in p to the extension path.
- mapAttrsToList (k: v:
- {
- "${extensionPath}/${k}".source = "${p}/${k}";
- }) (builtins.readDir p);
+ # Links every dir in path to the extension path.
+ mapAttrsToList (k: _:
+ {
+ "${extensionPath}/${k}".source = "${path}/${subDir}/${k}";
+ }) (builtins.readDir (path + "/${subDir}"));
toSymlink = concatMap toPaths cfg.extensions;
in
foldr
@@ -95,6 +135,10 @@ in
mkIf (cfg.userSettings != {}) {
text = builtins.toJSON cfg.userSettings;
};
+ "${keybindingsFilePath}" =
+ mkIf (cfg.keybindings != []) {
+ text = builtins.toJSON cfg.keybindings;
+ };
}
toSymlink;
};
diff --git a/home-manager/modules/programs/waybar.nix b/home-manager/modules/programs/waybar.nix
new file mode 100644
index 00000000000..369f6e32aba
--- /dev/null
+++ b/home-manager/modules/programs/waybar.nix
@@ -0,0 +1,363 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+ cfg = config.programs.waybar;
+
+ # Used when generating warnings
+ modulesPath = "programs.waybar.settings.[].modules";
+
+ # Taken from <https://github.com/Alexays/Waybar/blob/adaf84304865e143e4e83984aaea6f6a7c9d4d96/src/factory.cpp>
+ defaultModuleNames = [
+ "sway/mode"
+ "sway/workspaces"
+ "sway/window"
+ "wlr/taskbar"
+ "idle_inhibitor"
+ "memory"
+ "cpu"
+ "clock"
+ "disk"
+ "tray"
+ "network"
+ "backlight"
+ "pulseaudio"
+ "mpd"
+ "temperature"
+ "bluetooth"
+ "battery"
+ ];
+
+ isValidCustomModuleName = x:
+ elem x defaultModuleNames || (hasPrefix "custom/" x && stringLength x > 7);
+
+ margins = let
+ mkMargin = name: {
+ "margin-${name}" = mkOption {
+ type = types.nullOr types.int;
+ default = null;
+ example = 10;
+ description = "Margins value without unit.";
+ };
+ };
+ margins = map mkMargin [ "top" "left" "bottom" "right" ];
+ in foldl' mergeAttrs { } margins;
+
+ waybarBarConfig = with lib.types;
+ submodule {
+ options = {
+ layer = mkOption {
+ type = nullOr (enum [ "top" "bottom" ]);
+ default = null;
+ description = ''
+ Decide if the bar is displayed in front (<code>"top"</code>)
+ of the windows or behind (<code>"bottom"</code>).
+ '';
+ example = "top";
+ };
+
+ output = mkOption {
+ type = nullOr (either str (listOf str));
+ default = null;
+ example = literalExample ''
+ [ "DP-1" "!DP-2" "!DP-3" ]
+ '';
+ description = ''
+ Specifies on which screen this bar will be displayed.
+ Exclamation mark(!) can be used to exclude specific output.
+ '';
+ };
+
+ position = mkOption {
+ type = nullOr (enum [ "top" "bottom" "left" "right" ]);
+ default = null;
+ example = "right";
+ description = "Bar position relative to the output.";
+ };
+
+ height = mkOption {
+ type = nullOr ints.unsigned;
+ default = null;
+ example = 5;
+ description =
+ "Height to be used by the bar if possible. Leave blank for a dynamic value.";
+ };
+
+ width = mkOption {
+ type = nullOr ints.unsigned;
+ default = null;
+ example = 5;
+ description =
+ "Width to be used by the bar if possible. Leave blank for a dynamic value.";
+ };
+
+ modules-left = mkOption {
+ type = nullOr (listOf str);
+ default = null;
+ description = "Modules that will be displayed on the left.";
+ example = literalExample ''
+ [ "sway/workspaces" "sway/mode" "wlr/taskbar" ]
+ '';
+ };
+
+ modules-center = mkOption {
+ type = nullOr (listOf str);
+ default = null;
+ description = "Modules that will be displayed in the center.";
+ example = literalExample ''
+ [ "sway/window" ]
+ '';
+ };
+
+ modules-right = mkOption {
+ type = nullOr (listOf str);
+ default = null;
+ description = "Modules that will be displayed on the right.";
+ example = literalExample ''
+ [ "mpd" "custom/mymodule#with-css-id" "temperature" ]
+ '';
+ };
+
+ modules = mkOption {
+ type = attrsOf unspecified;
+ default = { };
+ description = "Modules configuration.";
+ example = literalExample ''
+ {
+ "sway/window" = {
+ max-length = 50;
+ };
+ "clock" = {
+ format-alt = "{:%a, %d. %b %H:%M}";
+ };
+ }
+ '';
+ };
+
+ margin = mkOption {
+ type = nullOr str;
+ default = null;
+ description = "Margins value using the CSS format without units.";
+ example = "20 5";
+ };
+
+ inherit (margins) margin-top margin-left margin-bottom margin-right;
+
+ name = mkOption {
+ type = nullOr str;
+ default = null;
+ description =
+ "Optional name added as a CSS class, for styling multiple waybars.";
+ example = "waybar-1";
+ };
+
+ gtk-layer-shell = mkOption {
+ type = nullOr bool;
+ default = null;
+ example = false;
+ description =
+ "Option to disable the use of gtk-layer-shell for popups.";
+ };
+ };
+ };
+in {
+ meta.maintainers = [ hm.maintainers.berbiche ];
+
+ options.programs.waybar = with lib.types; {
+ enable = mkEnableOption "Waybar";
+
+ package = mkOption {
+ type = package;
+ default = pkgs.waybar;
+ defaultText = literalExample "${pkgs.waybar}";
+ description = ''
+ Waybar package to use. Set to <code>null</code> to use the default module.
+ '';
+ };
+
+ settings = mkOption {
+ type = listOf waybarBarConfig;
+ default = [ ];
+ description = ''
+ Configuration for Waybar, see <link
+ xlink:href="https://github.com/Alexays/Waybar/wiki/Configuration"/>
+ for supported values.
+ '';
+ example = literalExample ''
+ [
+ {
+ layer = "top";
+ position = "top";
+ height = 30;
+ output = [
+ "eDP-1"
+ "HDMI-A-1"
+ ];
+ modules-left = [ "sway/workspaces" "sway/mode" "wlr/taskbar" ];
+ modules-center = [ "sway/window" "custom/hello-from-waybar" ];
+ modules-right = [ "mpd" "custom/mymodule#with-css-id" "temperature" ];
+ modules = {
+ "sway/workspaces" = {
+ disable-scroll = true;
+ all-outputs = true;
+ };
+ "custom/hello-from-waybar" = {
+ format = "hello {}";
+ max-length = 40;
+ interval = "once";
+ exec = pkgs.writeShellScript "hello-from-waybar" '''
+ echo "from within waybar"
+ ''';
+ };
+ };
+ }
+ ]
+ '';
+ };
+
+ systemd.enable = mkEnableOption "Waybar systemd integration";
+
+ style = mkOption {
+ type = nullOr str;
+ default = null;
+ description = ''
+ CSS style of the bar.
+ See <link xlink:href="https://github.com/Alexays/Waybar/wiki/Configuration"/>
+ for the documentation.
+ '';
+ example = ''
+ * {
+ border: none;
+ border-radius: 0;
+ font-family: Source Code Pro;
+ }
+ window#waybar {
+ background: #16191C;
+ color: #AAB2BF;
+ }
+ #workspaces button {
+ padding: 0 5px;
+ }
+ '';
+ };
+ };
+
+ config = let
+ # Inspired by https://github.com/NixOS/nixpkgs/pull/89781
+ writePrettyJSON = name: x:
+ pkgs.runCommandLocal name { } ''
+ ${pkgs.jq}/bin/jq . > $out <<<${escapeShellArg (builtins.toJSON x)}
+ '';
+
+ configSource = let
+ # Removes nulls because Waybar ignores them for most values
+ removeNulls = filterAttrs (_: v: v != null);
+
+ # Makes the actual valid configuration Waybar accepts
+ # (strips our custom settings before converting to JSON)
+ makeConfiguration = configuration:
+ let
+ # The "modules" option is not valid in the JSON
+ # as its descendants have to live at the top-level
+ settingsWithoutModules =
+ filterAttrs (n: _: n != "modules") configuration;
+ settingsModules =
+ optionalAttrs (configuration.modules != { }) configuration.modules;
+ in removeNulls (settingsWithoutModules // settingsModules);
+ # The clean list of configurations
+ finalConfiguration = map makeConfiguration cfg.settings;
+ in writePrettyJSON "waybar-config.json" finalConfiguration;
+
+ warnings = let
+ mkUnreferencedModuleWarning = name:
+ "The module '${name}' defined in '${modulesPath}' is not referenced "
+ + "in either `modules-left`, `modules-center` or `modules-right` of Waybar's options";
+ mkUndefinedModuleWarning = settings: name:
+ let
+ # Locations where the module is undefined (a combination modules-{left,center,right})
+ locations = flip filter [ "left" "center" "right" ]
+ (x: elem name settings."modules-${x}");
+ mkPath = loc: "'${modulesPath}-${loc}'";
+ # The modules-{left,center,right} configuration that includes
+ # an undefined module
+ path = concatMapStringsSep " and " mkPath locations;
+ in "The module '${name}' defined in ${path} is neither "
+ + "a default module or a custom module declared in '${modulesPath}'";
+ mkInvalidModuleNameWarning = name:
+ "The custom module '${name}' defined in '${modulesPath}' is not a valid "
+ + "module name. A custom module's name must start with 'custom/' "
+ + "like 'custom/mymodule' for instance";
+
+ # Find all modules in `modules-{left,center,right}` and `modules` not declared/referenced.
+ # `cfg.settings` is a list of Waybar configurations
+ # and we need to preserve the index for appropriate warnings
+ allFaultyModules = flip map cfg.settings (settings:
+ let
+ allModules = unique
+ (concatMap (x: attrByPath [ "modules-${x}" ] [ ] settings) [
+ "left"
+ "center"
+ "right"
+ ]);
+ declaredModules = attrNames settings.modules;
+ # Modules declared in `modules` but not referenced in `modules-{left,center,right}`
+ unreferencedModules = subtractLists allModules declaredModules;
+ # Modules listed in modules-{left,center,right} that are not default modules
+ nonDefaultModules = subtractLists defaultModuleNames allModules;
+ # Modules referenced in `modules-{left,center,right}` but not declared in `modules`
+ undefinedModules = subtractLists declaredModules nonDefaultModules;
+ # Check for invalid module names
+ invalidModuleNames =
+ filter (m: !isValidCustomModuleName m) (attrNames settings.modules);
+ in {
+ # The Waybar bar configuration (since config.settings is a list)
+ settings = settings;
+ undef = undefinedModules;
+ unref = unreferencedModules;
+ invalidName = invalidModuleNames;
+ });
+
+ allWarnings = flip concatMap allFaultyModules
+ ({ settings, undef, unref, invalidName }:
+ let
+ unreferenced = map mkUnreferencedModuleWarning unref;
+ undefined = map (mkUndefinedModuleWarning settings) undef;
+ invalid = map mkInvalidModuleNameWarning invalidName;
+ in undefined ++ unreferenced ++ invalid);
+ in allWarnings;
+
+ in mkIf cfg.enable (mkMerge [
+ { home.packages = [ cfg.package ]; }
+ (mkIf (cfg.settings != [ ]) {
+ # Generate warnings about defined but unreferenced modules
+ inherit warnings;
+
+ xdg.configFile."waybar/config".source = configSource;
+ })
+ (mkIf (cfg.style != null) {
+ xdg.configFile."waybar/style.css".text = cfg.style;
+ })
+ (mkIf cfg.systemd.enable {
+ systemd.user.services.waybar = {
+ Unit = {
+ Description =
+ "Highly customizable Wayland bar for Sway and Wlroots based compositors.";
+ Documentation = "https://github.com/Alexays/Waybar/wiki";
+ PartOf = [ "graphical-session.target" ];
+ Requisite = [ "dbus.service" ];
+ After = [ "dbus.service" ];
+ };
+
+ Service = {
+ Type = "dbus";
+ BusName = "fr.arouillard.waybar";
+ ExecStart = "${cfg.package}/bin/waybar";
+ Restart = "always";
+ RestartSec = "1sec";
+ };
+
+ Install = { WantedBy = [ "graphical-session.target" ]; };
+ };
+ })
+ ]);
+}
diff --git a/home-manager/modules/programs/zoxide.nix b/home-manager/modules/programs/zoxide.nix
new file mode 100644
index 00000000000..842ff109294
--- /dev/null
+++ b/home-manager/modules/programs/zoxide.nix
@@ -0,0 +1,79 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.programs.zoxide;
+
+in {
+ meta.maintainers = [ maintainers.marsam ];
+
+ options.programs.zoxide = {
+ enable = mkEnableOption "zoxide";
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.zoxide;
+ defaultText = literalExample "pkgs.zoxide";
+ description = ''
+ Zoxide package to install.
+ '';
+ };
+
+ options = mkOption {
+ type = types.listOf types.str;
+ default = [ ];
+ example = [ "--no-aliases" ];
+ description = ''
+ List of options to pass to zoxide.
+ '';
+ };
+
+ 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 = [ cfg.package ];
+
+ programs.bash.initExtra = mkIf cfg.enableBashIntegration ''
+ eval "$(${cfg.package}/bin/zoxide init bash ${
+ concatStringsSep " " cfg.options
+ })"
+ '';
+
+ programs.zsh.initExtra = mkIf cfg.enableZshIntegration ''
+ eval "$(${cfg.package}/bin/zoxide init zsh ${
+ concatStringsSep " " cfg.options
+ })"
+ '';
+
+ programs.fish.shellInit = mkIf cfg.enableFishIntegration ''
+ ${cfg.package}/bin/zoxide init fish ${
+ concatStringsSep " " cfg.options
+ } | source
+ '';
+ };
+}
diff --git a/home-manager/modules/programs/zplug.nix b/home-manager/modules/programs/zplug.nix
new file mode 100644
index 00000000000..6cb5e98e313
--- /dev/null
+++ b/home-manager/modules/programs/zplug.nix
@@ -0,0 +1,60 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.programs.zsh.zplug;
+
+ pluginModule = types.submodule ({ config, ... }: {
+ options = {
+ name = mkOption {
+ type = types.str;
+ description = "The name of the plugin.";
+ };
+
+ tags = mkOption {
+ type = types.listOf types.str;
+ default = [ ];
+ description = "The plugin tags.";
+ };
+ };
+
+ });
+
+in {
+ options.programs.zsh.zplug = {
+ enable = mkEnableOption "zplug - a zsh plugin manager";
+
+ plugins = mkOption {
+ default = [ ];
+ type = types.listOf pluginModule;
+ description = "List of zplug plugins.";
+ };
+ };
+
+ config = mkIf cfg.enable {
+ home.packages = [ pkgs.zplug ];
+
+ programs.zsh.initExtraBeforeCompInit = ''
+ source ${pkgs.zplug}/init.zsh
+
+ ${optionalString (cfg.plugins != [ ]) ''
+ ${concatStrings (map (plugin: ''
+ zplug "${plugin.name}"${
+ optionalString (plugin.tags != [ ]) ''
+ ${concatStrings (map (tag: ", ${tag}") plugin.tags)}
+ ''
+ }
+ '') cfg.plugins)}
+ ''}
+
+ if ! zplug check; then
+ zplug install
+ fi
+
+ zplug load
+ '';
+
+ };
+}
diff --git a/home-manager/modules/programs/zsh.nix b/home-manager/modules/programs/zsh.nix
index c5694e1f704..ed65d5fe487 100644
--- a/home-manager/modules/programs/zsh.nix
+++ b/home-manager/modules/programs/zsh.nix
@@ -18,6 +18,10 @@ let
mapAttrsToList (k: v: "alias ${k}=${lib.escapeShellArg v}") cfg.shellAliases
);
+ globalAliasesStr = concatStringsSep "\n" (
+ mapAttrsToList (k: v: "alias -g ${k}=${lib.escapeShellArg v}") cfg.shellGlobalAliases
+ );
+
zdotdir = "$HOME/" + cfg.dotDir;
bindkeyCommands = {
@@ -152,6 +156,17 @@ let
Name of the theme to be used by oh-my-zsh.
'';
};
+
+ extraConfig = mkOption {
+ default = "";
+ example = ''
+ zstyle :omz:plugins:ssh-agent identities id_rsa id_rsa2 id_github
+ '';
+ type = types.lines;
+ description = ''
+ Extra settings for plugins.
+ '';
+ };
};
};
@@ -170,6 +185,14 @@ in
type = types.nullOr types.bool;
};
+ cdpath = mkOption {
+ default = [];
+ description = ''
+ List of paths to autocomplete calls to `cd`.
+ '';
+ type = types.listOf types.str;
+ };
+
dotDir = mkOption {
default = null;
example = ".config/zsh";
@@ -183,7 +206,12 @@ in
shellAliases = mkOption {
default = {};
- example = { ll = "ls -l"; ".." = "cd .."; };
+ example = literalExample ''
+ {
+ 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.
@@ -191,6 +219,21 @@ in
type = types.attrsOf types.str;
};
+ shellGlobalAliases = mkOption {
+ default = {};
+ example = literalExample ''
+ {
+ UUID = "$(uuidgen | tr -d \\n)";
+ G = "| grep";
+ }
+ '';
+ description = ''
+ Similar to <varname><link linkend="opt-programs.zsh.shellAliases">opt-programs.zsh.shellAliases</link></varname>,
+ but are substituted anywhere on a line.
+ '';
+ type = types.attrsOf types.str;
+ };
+
enableCompletion = mkOption {
default = true;
description = ''
@@ -357,6 +400,10 @@ in
home.file."${relToDotDir ".zshrc"}".text = ''
typeset -U path cdpath fpath manpath
+ ${optionalString (cfg.cdpath != []) ''
+ cdpath+=(${concatStringsSep " " cfg.cdpath})
+ ''}
+
for profile in ''${(z)NIX_PROFILES}; do
fpath+=($profile/share/zsh/site-functions $profile/share/zsh/$ZSH_VERSION/functions $profile/share/zsh/vendor-completions)
done
@@ -393,6 +440,8 @@ in
${envVarsStr}
${optionalString cfg.oh-my-zsh.enable ''
+ # oh-my-zsh extra settings for plugins
+ ${cfg.oh-my-zsh.extraConfig}
# oh-my-zsh configuration generated by NixOS
${optionalString (cfg.oh-my-zsh.plugins != [])
"plugins=(${concatStringsSep " " cfg.oh-my-zsh.plugins})"
@@ -433,6 +482,9 @@ in
# Aliases
${aliasesStr}
+
+ # Global Aliases
+ ${globalAliasesStr}
'';
}