1
0
Fork 0
mirror of https://github.com/nix-community/home-manager.git synced 2025-12-05 16:41:04 +01:00

treewide: reformat nixfmt-rfc-style

Reformat repository using new nixfmt-rfc-style.
This commit is contained in:
Austin Horstman 2025-04-07 16:11:29 -05:00
parent 5df48c4255
commit cba2f9ce95
1051 changed files with 37028 additions and 26594 deletions

View file

@ -1,6 +1,13 @@
{ config, lib, pkgs, ... }:
let cfg = config.programs.abook;
in {
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.abook;
in
{
options.programs.abook = {
enable = lib.mkEnableOption "Abook";

View file

@ -1,17 +1,29 @@
{ config, lib, confSections, confSection, ... }:
{
config,
lib,
confSections,
confSection,
...
}:
let
inherit (lib) literalExpression mkOption types;
mapAttrNames = f: attr:
lib.listToAttrs (lib.attrValues (lib.mapAttrs (k: v: {
name = f k;
value = v;
}) attr));
mapAttrNames =
f: attr:
lib.listToAttrs (
lib.attrValues (
lib.mapAttrs (k: v: {
name = f k;
value = v;
}) attr
)
);
addAccountName = name: k: "${k}:account=${name}";
oauth2Params = mkOption {
type = with types;
type =
with types;
nullOr (submodule {
options = {
token_endpoint = mkOption {
@ -37,7 +49,9 @@ let
};
});
default = null;
example = { token_endpoint = "<token_endpoint>"; };
example = {
token_endpoint = "<token_endpoint>";
};
description = ''
Sets the oauth2 params if authentication mechanism oauthbearer or
xoauth2 is used.
@ -45,157 +59,188 @@ let
'';
};
in {
in
{
type = mkOption {
type = types.attrsOf (types.submodule {
options.aerc = {
enable = lib.mkEnableOption "aerc";
extraAccounts = mkOption {
type = confSection;
default = { };
example =
literalExpression ''{ source = "maildir://~/Maildir/example"; }'';
description = ''
Extra config added to the configuration section for this account in
{file}`$HOME/.config/aerc/accounts.conf`.
See {manpage}`aerc-accounts(5)`.
'';
type = types.attrsOf (
types.submodule {
options.aerc = {
enable = lib.mkEnableOption "aerc";
extraAccounts = mkOption {
type = confSection;
default = { };
example = literalExpression ''{ source = "maildir://~/Maildir/example"; }'';
description = ''
Extra config added to the configuration section for this account in
{file}`$HOME/.config/aerc/accounts.conf`.
See {manpage}`aerc-accounts(5)`.
'';
};
extraBinds = mkOption {
type = confSections;
default = { };
example = literalExpression ''{ messages = { d = ":move ''${folder.trash}<Enter>"; }; }'';
description = ''
Extra bindings specific to this account, added to
{file}`$HOME/.config/aerc/binds.conf`.
See {manpage}`aerc-binds(5)`.
'';
};
extraConfig = mkOption {
type = confSections;
default = { };
example = literalExpression "{ ui = { sidebar-width = 25; }; }";
description = ''
Config specific to this account, added to {file}`$HOME/.config/aerc/aerc.conf`.
Aerc only supports per-account UI configuration.
For other sections of {file}`$HOME/.config/aerc/aerc.conf`,
use `programs.aerc.extraConfig`.
See {manpage}`aerc-config(5)`.
'';
};
imapAuth = mkOption {
type =
with types;
nullOr (enum [
"oauthbearer"
"xoauth2"
]);
default = null;
example = "auth";
description = ''
Sets the authentication mechanism if imap is used as the incoming
method.
See {manpage}`aerc-imap(5)`.
'';
};
imapOauth2Params = oauth2Params;
smtpAuth = mkOption {
type =
with types;
nullOr (enum [
"none"
"plain"
"login"
"oauthbearer"
"xoauth2"
]);
default = "plain";
example = "auth";
description = ''
Sets the authentication mechanism if smtp is used as the outgoing
method.
See {manpage}`aerc-smtp(5)`.
'';
};
smtpOauth2Params = oauth2Params;
};
extraBinds = mkOption {
type = confSections;
default = { };
example = literalExpression
''{ messages = { d = ":move ''${folder.trash}<Enter>"; }; }'';
description = ''
Extra bindings specific to this account, added to
{file}`$HOME/.config/aerc/binds.conf`.
See {manpage}`aerc-binds(5)`.
'';
};
extraConfig = mkOption {
type = confSections;
default = { };
example = literalExpression "{ ui = { sidebar-width = 25; }; }";
description = ''
Config specific to this account, added to {file}`$HOME/.config/aerc/aerc.conf`.
Aerc only supports per-account UI configuration.
For other sections of {file}`$HOME/.config/aerc/aerc.conf`,
use `programs.aerc.extraConfig`.
See {manpage}`aerc-config(5)`.
'';
};
imapAuth = mkOption {
type = with types; nullOr (enum [ "oauthbearer" "xoauth2" ]);
default = null;
example = "auth";
description = ''
Sets the authentication mechanism if imap is used as the incoming
method.
See {manpage}`aerc-imap(5)`.
'';
};
imapOauth2Params = oauth2Params;
smtpAuth = mkOption {
type = with types;
nullOr (enum [ "none" "plain" "login" "oauthbearer" "xoauth2" ]);
default = "plain";
example = "auth";
description = ''
Sets the authentication mechanism if smtp is used as the outgoing
method.
See {manpage}`aerc-smtp(5)`.
'';
};
smtpOauth2Params = oauth2Params;
};
});
}
);
};
mkAccount = name: account:
mkAccount =
name: account:
let
nullOrMap = f: v: if v == null then v else f v;
optPort = port: if port != null then ":${toString port}" else "";
optAttr = k: v:
if v != null && v != [ ] && v != "" then { ${k} = v; } else { };
optAttr = k: v: if v != null && v != [ ] && v != "" then { ${k} = v; } else { };
optPwCmd = k: p:
optAttr "${k}-cred-cmd" (nullOrMap (lib.concatStringsSep " ") p);
optPwCmd = k: p: optAttr "${k}-cred-cmd" (nullOrMap (lib.concatStringsSep " ") p);
useOauth = auth: builtins.elem auth [ "oauthbearer" "xoauth2" ];
useOauth =
auth:
builtins.elem auth [
"oauthbearer"
"xoauth2"
];
oauthParams = { auth, params }:
oauthParams =
{ auth, params }:
if useOauth auth && params != null && params != { } then
"?" + builtins.concatStringsSep "&"
(lib.attrsets.mapAttrsToList (k: v: k + "=" + lib.strings.escapeURL v)
(lib.attrsets.filterAttrs (k: v: v != null) params))
"?"
+ builtins.concatStringsSep "&" (
lib.attrsets.mapAttrsToList (k: v: k + "=" + lib.strings.escapeURL v) (
lib.attrsets.filterAttrs (k: v: v != null) params
)
)
else
"";
mkConfig = {
maildir = cfg: {
source =
"maildir://${config.accounts.email.maildirBasePath}/${cfg.maildir.path}";
source = "maildir://${config.accounts.email.maildirBasePath}/${cfg.maildir.path}";
};
maildirpp = cfg: {
source =
"maildirpp://${config.accounts.email.maildirBasePath}/${cfg.maildir.path}/Inbox";
source = "maildirpp://${config.accounts.email.maildirBasePath}/${cfg.maildir.path}/Inbox";
};
imap = { userName, imap, passwordCommand, aerc, ... }@cfg:
imap =
{
userName,
imap,
passwordCommand,
aerc,
...
}@cfg:
let
loginMethod' =
if cfg.aerc.imapAuth != null then "+${cfg.aerc.imapAuth}" else "";
loginMethod' = if cfg.aerc.imapAuth != null then "+${cfg.aerc.imapAuth}" else "";
oauthParams' = oauthParams {
auth = cfg.aerc.imapAuth;
params = cfg.aerc.imapOauth2Params;
};
protocol = if imap.tls.enable then
if imap.tls.useStartTls then "imap" else "imaps${loginMethod'}"
else
"imap+insecure";
protocol =
if imap.tls.enable then
if imap.tls.useStartTls then "imap" else "imaps${loginMethod'}"
else
"imap+insecure";
port' = optPort imap.port;
in {
source =
"${protocol}://${userName}@${imap.host}${port'}${oauthParams'}";
} // optPwCmd "source" passwordCommand;
in
{
source = "${protocol}://${userName}@${imap.host}${port'}${oauthParams'}";
}
// optPwCmd "source" passwordCommand;
smtp = { userName, smtp, passwordCommand, ... }@cfg:
smtp =
{
userName,
smtp,
passwordCommand,
...
}@cfg:
let
loginMethod' =
if cfg.aerc.smtpAuth != null then "+${cfg.aerc.smtpAuth}" else "";
loginMethod' = if cfg.aerc.smtpAuth != null then "+${cfg.aerc.smtpAuth}" else "";
oauthParams' = oauthParams {
auth = cfg.aerc.smtpAuth;
params = cfg.aerc.smtpOauth2Params;
};
protocol = if smtp.tls.enable then
if smtp.tls.useStartTls then
"smtp${loginMethod'}"
protocol =
if smtp.tls.enable then
if smtp.tls.useStartTls then "smtp${loginMethod'}" else "smtps${loginMethod'}"
else
"smtps${loginMethod'}"
else
"smtp+insecure${loginMethod'}";
"smtp+insecure${loginMethod'}";
port' = optPort smtp.port;
in {
outgoing =
"${protocol}://${userName}@${smtp.host}${port'}${oauthParams'}";
} // optPwCmd "outgoing" passwordCommand;
in
{
outgoing = "${protocol}://${userName}@${smtp.host}${port'}${oauthParams'}";
}
// optPwCmd "outgoing" passwordCommand;
msmtp = cfg: {
outgoing = "msmtpq --read-envelope-from --read-recipients";
@ -203,17 +248,21 @@ in {
};
basicCfg = account:
basicCfg =
account:
{
from = "${account.realName} <${account.address}>";
} // (optAttr "copy-to" account.folders.sent)
}
// (optAttr "copy-to" account.folders.sent)
// (optAttr "default" account.folders.inbox)
// (optAttr "postpone" account.folders.drafts)
// (optAttr "aliases" account.aliases);
sourceCfg = account:
if account.mbsync.enable && account.mbsync.flatten == null
&& account.mbsync.subFolders == "Maildir++" then
sourceCfg =
account:
if
account.mbsync.enable && account.mbsync.flatten == null && account.mbsync.subFolders == "Maildir++"
then
mkConfig.maildirpp account
else if account.mbsync.enable || account.offlineimap.enable then
mkConfig.maildir account
@ -222,7 +271,8 @@ in {
else
{ };
outgoingCfg = account:
outgoingCfg =
account:
if account.msmtp.enable then
mkConfig.msmtp account
else if account.smtp != null then
@ -230,19 +280,22 @@ in {
else
{ };
gpgCfg = account:
gpgCfg =
account:
lib.optionalAttrs (account.gpg != null) {
pgp-key-id = account.gpg.key;
pgp-auto-sign = account.gpg.signByDefault;
pgp-opportunistic-encrypt = account.gpg.encryptByDefault;
};
in (basicCfg account) // (sourceCfg account) // (outgoingCfg account)
// (gpgCfg account) // account.aerc.extraAccounts;
in
(basicCfg account)
// (sourceCfg account)
// (outgoingCfg account)
// (gpgCfg account)
// account.aerc.extraAccounts;
mkAccountConfig = name: account:
mapAttrNames (addAccountName name) account.aerc.extraConfig;
mkAccountConfig = name: account: mapAttrNames (addAccountName name) account.aerc.extraConfig;
mkAccountBinds = name: account:
mapAttrNames (addAccountName name) account.aerc.extraBinds;
mkAccountBinds = name: account: mapAttrNames (addAccountName name) account.aerc.extraBinds;
}

View file

@ -1,15 +1,34 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib)
attrsets generators literalExpression mapAttrs mkIf mkOption types;
attrsets
generators
literalExpression
mapAttrs
mkIf
mkOption
types
;
cfg = config.programs.aerc;
primitive = with types;
((type: either type (listOf type)) (nullOr (oneOf [ str int bool float ])))
primitive =
with types;
((type: either type (listOf type)) (
nullOr (oneOf [
str
int
bool
float
])
))
// {
description =
"values (null, bool, int, string, or float) or a list of values, that will be joined with a comma";
description = "values (null, bool, int, string, or float) or a list of values, that will be joined with a comma";
};
confSection = types.attrsOf primitive;
@ -19,18 +38,25 @@ let
sectionsOrLines = types.either types.lines confSections;
accounts = import ./aerc-accounts.nix {
inherit config pkgs lib confSection confSections;
inherit
config
pkgs
lib
confSection
confSections
;
};
aerc-accounts =
attrsets.filterAttrs (_: v: v.aerc.enable) config.accounts.email.accounts;
aerc-accounts = attrsets.filterAttrs (_: v: v.aerc.enable) config.accounts.email.accounts;
configDir = if (pkgs.stdenv.isDarwin && !config.xdg.enable) then
"Library/Preferences/aerc"
else
"${config.xdg.configHome}/aerc";
configDir =
if (pkgs.stdenv.isDarwin && !config.xdg.enable) then
"Library/Preferences/aerc"
else
"${config.xdg.configHome}/aerc";
in {
in
{
meta.maintainers = with lib.hm.maintainers; [ lukasngl ];
options.accounts.email.accounts = accounts.type;
@ -44,8 +70,7 @@ in {
extraAccounts = mkOption {
type = sectionsOrLines;
default = { };
example = literalExpression
''{ Work = { source = "maildir://~/Maildir/work"; }; }'';
example = literalExpression ''{ Work = { source = "maildir://~/Maildir/work"; }; }'';
description = ''
Extra lines added to {file}`$HOME/.config/aerc/accounts.conf`.
@ -103,127 +128,151 @@ in {
};
};
config = let
joinCfg = cfgs: lib.concatStringsSep "\n" (lib.filter (v: v != "") cfgs);
config =
let
joinCfg = cfgs: lib.concatStringsSep "\n" (lib.filter (v: v != "") cfgs);
toINI = conf: # quirk: global section is prepended w/o section heading
let
global = conf.global or { };
local = removeAttrs conf [ "global" ];
mkValueString = v:
if lib.isList v then # join with comma
lib.concatStringsSep ","
(map (generators.mkValueStringDefault { }) v)
else
generators.mkValueStringDefault { } v;
mkKeyValue =
generators.mkKeyValueDefault { inherit mkValueString; } " = ";
in joinCfg [
(generators.toKeyValue { inherit mkKeyValue; } global)
(generators.toINI { inherit mkKeyValue; } local)
toINI =
conf: # quirk: global section is prepended w/o section heading
let
global = conf.global or { };
local = removeAttrs conf [ "global" ];
mkValueString =
v:
if lib.isList v then # join with comma
lib.concatStringsSep "," (map (generators.mkValueStringDefault { }) v)
else
generators.mkValueStringDefault { } v;
mkKeyValue = generators.mkKeyValueDefault { inherit mkValueString; } " = ";
in
joinCfg [
(generators.toKeyValue { inherit mkKeyValue; } global)
(generators.toINI { inherit mkKeyValue; } local)
];
mkINI = conf: if lib.isString conf then conf else toINI conf;
mkStyleset = attrsets.mapAttrs' (
k: v:
let
value = if lib.isString v then v else toINI { global = v; };
in
{
name = "${configDir}/stylesets/${k}";
value.text = joinCfg [
header
value
];
}
);
mkTemplates = attrsets.mapAttrs' (
k: v: {
name = "${configDir}/templates/${k}";
value.text = v;
}
);
primaryAccount = attrsets.filterAttrs (_: v: v.primary) aerc-accounts;
otherAccounts = attrsets.filterAttrs (_: v: !v.primary) aerc-accounts;
primaryAccountAccounts = mapAttrs accounts.mkAccount primaryAccount;
accountsExtraAccounts = mapAttrs accounts.mkAccount otherAccounts;
accountsExtraConfig = mapAttrs accounts.mkAccountConfig aerc-accounts;
accountsExtraBinds = mapAttrs accounts.mkAccountBinds aerc-accounts;
joinContextual = contextual: joinCfg (map mkINI (lib.attrValues contextual));
isRecursivelyEmpty =
x:
if lib.isAttrs x then lib.all (x: x == { } || isRecursivelyEmpty x) (lib.attrValues x) else false;
genAccountsConf = (
(cfg.extraAccounts != "" && cfg.extraAccounts != { })
|| !(isRecursivelyEmpty accountsExtraAccounts)
|| !(isRecursivelyEmpty primaryAccountAccounts)
);
genAercConf = (
(cfg.extraConfig != "" && cfg.extraConfig != { }) || !(isRecursivelyEmpty accountsExtraConfig)
);
genBindsConf = (
(cfg.extraBinds != "" && cfg.extraBinds != { }) || !(isRecursivelyEmpty accountsExtraBinds)
);
header = ''
# Generated by Home Manager.
'';
in
mkIf cfg.enable {
warnings =
if genAccountsConf && (cfg.extraConfig.general.unsafe-accounts-conf or false) == false then
[
''
aerc: `programs.aerc.enable` is set, but `...extraConfig.general.unsafe-accounts-conf` is set to false or unset.
This will prevent aerc from starting; see `unsafe-accounts-conf` in the man page aerc-config(5):
> By default, the file permissions of accounts.conf must be restrictive and only allow reading by the file owner (0600).
> Set this option to true to ignore this permission check. Use this with care as it may expose your credentials.
These permissions are not possible with home-manager, since the generated file is in the nix-store (permissions 0444).
Therefore, please set `programs.aerc.extraConfig.general.unsafe-accounts-conf = true`.
This option is safe; if `passwordCommand` is properly set, no credentials will be written to the nix store.
''
]
else
[ ];
assertions = [
{
assertion =
let
extraConfigSections = (
lib.unique (lib.flatten (lib.mapAttrsToList (_: v: lib.attrNames v.aerc.extraConfig) aerc-accounts))
);
in
extraConfigSections == [ ] || extraConfigSections == [ "ui" ];
message = ''
Only the ui section of $XDG_CONFIG_HOME/aerc.conf supports contextual (per-account) configuration.
Please configure it with accounts.email.accounts._.aerc.extraConfig.ui and move any other
configuration to programs.aerc.extraConfig.
'';
}
];
mkINI = conf: if lib.isString conf then conf else toINI conf;
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
mkStyleset = attrsets.mapAttrs' (k: v:
let value = if lib.isString v then v else toINI { global = v; };
in {
name = "${configDir}/stylesets/${k}";
value.text = joinCfg [ header value ];
});
home.file =
{
"${configDir}/accounts.conf" = mkIf genAccountsConf {
text = joinCfg [
header
(mkINI cfg.extraAccounts)
(mkINI primaryAccountAccounts)
(mkINI accountsExtraAccounts)
];
};
mkTemplates = attrsets.mapAttrs' (k: v: {
name = "${configDir}/templates/${k}";
value.text = v;
});
"${configDir}/aerc.conf" = mkIf genAercConf {
text = joinCfg [
header
(mkINI cfg.extraConfig)
(joinContextual accountsExtraConfig)
];
};
primaryAccount = attrsets.filterAttrs (_: v: v.primary) aerc-accounts;
otherAccounts = attrsets.filterAttrs (_: v: !v.primary) aerc-accounts;
primaryAccountAccounts = mapAttrs accounts.mkAccount primaryAccount;
accountsExtraAccounts = mapAttrs accounts.mkAccount otherAccounts;
accountsExtraConfig = mapAttrs accounts.mkAccountConfig aerc-accounts;
accountsExtraBinds = mapAttrs accounts.mkAccountBinds aerc-accounts;
joinContextual = contextual:
joinCfg (map mkINI (lib.attrValues contextual));
isRecursivelyEmpty = x:
if lib.isAttrs x then
lib.all (x: x == { } || isRecursivelyEmpty x) (lib.attrValues x)
else
false;
genAccountsConf = ((cfg.extraAccounts != "" && cfg.extraAccounts != { })
|| !(isRecursivelyEmpty accountsExtraAccounts)
|| !(isRecursivelyEmpty primaryAccountAccounts));
genAercConf = ((cfg.extraConfig != "" && cfg.extraConfig != { })
|| !(isRecursivelyEmpty accountsExtraConfig));
genBindsConf = ((cfg.extraBinds != "" && cfg.extraBinds != { })
|| !(isRecursivelyEmpty accountsExtraBinds));
header = ''
# Generated by Home Manager.
'';
in mkIf cfg.enable {
warnings = if genAccountsConf
&& (cfg.extraConfig.general.unsafe-accounts-conf or false) == false then [''
aerc: `programs.aerc.enable` is set, but `...extraConfig.general.unsafe-accounts-conf` is set to false or unset.
This will prevent aerc from starting; see `unsafe-accounts-conf` in the man page aerc-config(5):
> By default, the file permissions of accounts.conf must be restrictive and only allow reading by the file owner (0600).
> Set this option to true to ignore this permission check. Use this with care as it may expose your credentials.
These permissions are not possible with home-manager, since the generated file is in the nix-store (permissions 0444).
Therefore, please set `programs.aerc.extraConfig.general.unsafe-accounts-conf = true`.
This option is safe; if `passwordCommand` is properly set, no credentials will be written to the nix store.
''] else
[ ];
assertions = [{
assertion = let
extraConfigSections = (lib.unique (lib.flatten
(lib.mapAttrsToList (_: v: lib.attrNames v.aerc.extraConfig)
aerc-accounts)));
in extraConfigSections == [ ] || extraConfigSections == [ "ui" ];
message = ''
Only the ui section of $XDG_CONFIG_HOME/aerc.conf supports contextual (per-account) configuration.
Please configure it with accounts.email.accounts._.aerc.extraConfig.ui and move any other
configuration to programs.aerc.extraConfig.
'';
}];
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
home.file = {
"${configDir}/accounts.conf" = mkIf genAccountsConf {
text = joinCfg [
header
(mkINI cfg.extraAccounts)
(mkINI primaryAccountAccounts)
(mkINI accountsExtraAccounts)
];
};
"${configDir}/aerc.conf" = mkIf genAercConf {
text = joinCfg [
header
(mkINI cfg.extraConfig)
(joinContextual accountsExtraConfig)
];
};
"${configDir}/binds.conf" = mkIf genBindsConf {
text = joinCfg [
header
(mkINI cfg.extraBinds)
(joinContextual accountsExtraBinds)
];
};
} // (mkStyleset cfg.stylesets) // (mkTemplates cfg.templates);
};
"${configDir}/binds.conf" = mkIf genBindsConf {
text = joinCfg [
header
(mkINI cfg.extraBinds)
(joinContextual accountsExtraBinds)
];
};
}
// (mkStyleset cfg.stylesets)
// (mkTemplates cfg.templates);
};
}

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkOption types;
cfg = config.programs.aerospace;
@ -6,22 +11,29 @@ let
tomlFormat = pkgs.formats.toml { };
# filterAttrsRecursive supporting lists, as well.
filterListAndAttrsRecursive = pred: set:
lib.listToAttrs (lib.concatMap (name:
let v = set.${name};
in if pred v then
[
(lib.nameValuePair name (if lib.isAttrs v then
filterListAndAttrsRecursive pred v
else if lib.isList v then
(map (i:
if lib.isAttrs i then filterListAndAttrsRecursive pred i else i)
(lib.filter pred v))
else
v))
]
else
[ ]) (lib.attrNames set));
filterListAndAttrsRecursive =
pred: set:
lib.listToAttrs (
lib.concatMap (
name:
let
v = set.${name};
in
if pred v then
[
(lib.nameValuePair name (
if lib.isAttrs v then
filterListAndAttrsRecursive pred v
else if lib.isList v then
(map (i: if lib.isAttrs i then filterListAndAttrsRecursive pred i else i) (lib.filter pred v))
else
v
))
]
else
[ ]
) (lib.attrNames set)
);
filterNulls = filterListAndAttrsRecursive (v: v != null);
# Turns
@ -30,16 +42,22 @@ let
# {"if.foo" = "xxx"; "if.bar" = "yyy"}
# so that the correct TOML is generated for the
# on-window-detected table.
flattenConditions = attrs:
let conditions = attrs."if" or { };
in builtins.removeAttrs attrs [ "if" ]
// lib.concatMapAttrs (n: v: { "if.${n}" = v; }) conditions;
flattenConditions =
attrs:
let
conditions = attrs."if" or { };
in
builtins.removeAttrs attrs [ "if" ] // lib.concatMapAttrs (n: v: { "if.${n}" = v; }) conditions;
flattenOnWindowDetected = cfg:
let owd = cfg.on-window-detected or [ ];
in cfg // { on-window-detected = map flattenConditions owd; };
flattenOnWindowDetected =
cfg:
let
owd = cfg.on-window-detected or [ ];
in
cfg // { on-window-detected = map flattenConditions owd; };
in {
in
{
meta.maintainers = with lib.hm.maintainers; [ damidoug ];
options.programs.aerospace = {
@ -76,102 +94,122 @@ in {
enable-normalization-flatten-containers = mkOption {
type = types.bool;
default = true;
description =
''Containers that have only one child are "flattened".'';
description = ''Containers that have only one child are "flattened".'';
};
enable-normalization-opposite-orientation-for-nested-containers = mkOption {
type = types.bool;
default = true;
description = "Containers that nest into each other must have opposite orientations.";
};
enable-normalization-opposite-orientation-for-nested-containers =
mkOption {
type = types.bool;
default = true;
description =
"Containers that nest into each other must have opposite orientations.";
};
accordion-padding = mkOption {
type = types.int;
default = 30;
description = "Padding between windows in an accordion container.";
};
default-root-container-layout = mkOption {
type = types.enum [ "tiles" "accordion" ];
type = types.enum [
"tiles"
"accordion"
];
default = "tiles";
description = "Default layout for the root container.";
};
default-root-container-orientation = mkOption {
type = types.enum [ "horizontal" "vertical" "auto" ];
type = types.enum [
"horizontal"
"vertical"
"auto"
];
default = "auto";
description = "Default orientation for the root container.";
};
on-window-detected = mkOption {
type = types.listOf (types.submodule {
options = {
"if" = mkOption {
type = types.submodule {
options = {
app-id = mkOption {
type = with types; nullOr str;
default = null;
description = "The application ID to match (optional).";
};
workspace = mkOption {
type = with types; nullOr str;
default = null;
description = "The workspace name to match (optional).";
};
window-title-regex-substring = mkOption {
type = with types; nullOr str;
default = null;
description =
"Substring to match in the window title (optional).";
};
app-name-regex-substring = mkOption {
type = with types; nullOr str;
default = null;
description =
"Regex substring to match the app name (optional).";
};
during-aerospace-startup = mkOption {
type = with types; nullOr bool;
default = null;
description =
"Whether to match during aerospace startup (optional).";
type = types.listOf (
types.submodule {
options = {
"if" = mkOption {
type = types.submodule {
options = {
app-id = mkOption {
type = with types; nullOr str;
default = null;
description = "The application ID to match (optional).";
};
workspace = mkOption {
type = with types; nullOr str;
default = null;
description = "The workspace name to match (optional).";
};
window-title-regex-substring = mkOption {
type = with types; nullOr str;
default = null;
description = "Substring to match in the window title (optional).";
};
app-name-regex-substring = mkOption {
type = with types; nullOr str;
default = null;
description = "Regex substring to match the app name (optional).";
};
during-aerospace-startup = mkOption {
type = with types; nullOr bool;
default = null;
description = "Whether to match during aerospace startup (optional).";
};
};
};
default = { };
description = "Conditions for detecting a window.";
};
check-further-callbacks = mkOption {
type = with types; nullOr bool;
default = null;
description = "Whether to check further callbacks after this rule (optional).";
};
run = mkOption {
type =
with types;
oneOf [
str
(listOf str)
];
example = [
"move-node-to-workspace m"
"resize-node"
];
description = "Commands to execute when the conditions match (required).";
};
default = { };
description = "Conditions for detecting a window.";
};
check-further-callbacks = mkOption {
type = with types; nullOr bool;
default = null;
description =
"Whether to check further callbacks after this rule (optional).";
};
run = mkOption {
type = with types; oneOf [ str (listOf str) ];
example = [ "move-node-to-workspace m" "resize-node" ];
description =
"Commands to execute when the conditions match (required).";
};
};
});
}
);
default = [ ];
example = [{
"if" = {
app-id = "Another.Cool.App";
workspace = "cool-workspace";
window-title-regex-substring = "Title";
app-name-regex-substring = "CoolApp";
during-aerospace-startup = false;
};
check-further-callbacks = false;
run = [ "move-node-to-workspace m" "resize-node" ];
}];
description =
"Commands to run every time a new window is detected with optional conditions.";
example = [
{
"if" = {
app-id = "Another.Cool.App";
workspace = "cool-workspace";
window-title-regex-substring = "Title";
app-name-regex-substring = "CoolApp";
during-aerospace-startup = false;
};
check-further-callbacks = false;
run = [
"move-node-to-workspace m"
"resize-node"
];
}
];
description = "Commands to run every time a new window is detected with optional conditions.";
};
workspace-to-monitor-force-assignment = mkOption {
type = with types;
nullOr (attrsOf (oneOf [ int str (listOf str) ]));
type =
with types;
nullOr (
attrsOf (oneOf [
int
str
(listOf str)
])
);
default = null;
description = ''
Map workspaces to specific monitors.
@ -182,17 +220,18 @@ in {
"2" = "main"; # Main monitor.
"3" = "secondary"; # Secondary monitor (non-main).
"4" = "built-in"; # Built-in display.
"5" =
"^built-in retina display$"; # Regex for the built-in retina display.
"6" = [ "secondary" "dell" ]; # Match first pattern in the list.
"5" = "^built-in retina display$"; # Regex for the built-in retina display.
"6" = [
"secondary"
"dell"
]; # Match first pattern in the list.
};
};
on-focus-changed = mkOption {
type = with types; listOf str;
default = [ ];
example = [ "move-mouse monitor-lazy-center" ];
description =
"Commands to run every time focused window or workspace changes.";
description = "Commands to run every time focused window or workspace changes.";
};
on-focused-monitor-changed = mkOption {
type = with types; listOf str;
@ -210,7 +249,10 @@ in {
description = "Commands to run every time workspace changes.";
};
key-mapping.preset = mkOption {
type = types.enum [ "qwerty" "dvorak" ];
type = types.enum [
"qwerty"
"dvorak"
];
default = "qwerty";
description = "Keymapping preset.";
};
@ -243,15 +285,14 @@ in {
config = lib.mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "programs.aerospace" pkgs
lib.platforms.darwin)
(lib.hm.assertions.assertPlatform "programs.aerospace" pkgs lib.platforms.darwin)
];
home = {
packages = lib.mkIf (cfg.package != null) [ cfg.package ];
file.".config/aerospace/aerospace.toml".source =
tomlFormat.generate "aerospace"
(filterNulls (flattenOnWindowDetected cfg.userSettings));
file.".config/aerospace/aerospace.toml".source = tomlFormat.generate "aerospace" (
filterNulls (flattenOnWindowDetected cfg.userSettings)
);
};
};
}

View file

@ -1,6 +1,13 @@
{ config, lib, pkgs, ... }:
let cfg = config.programs.afew;
in {
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.afew;
in
{
options.programs.afew = {
enable = lib.mkEnableOption "the afew initial tagging script for Notmuch";

View file

@ -1,8 +1,14 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.alacritty;
tomlFormat = pkgs.formats.toml { };
in {
in
{
options = {
programs.alacritty = {
enable = lib.mkEnableOption "Alacritty";
@ -56,40 +62,45 @@ in {
};
config = lib.mkIf cfg.enable {
assertions = [{
# If using the theme option, ensure that theme exists in the
# alacritty-theme package.
assertion = let
available = lib.pipe "${pkgs.alacritty-theme}/share/alacritty-theme" [
builtins.readDir
(lib.filterAttrs
(name: type: type == "regular" && lib.hasSuffix ".toml" name))
lib.attrNames
(lib.map (lib.removeSuffix ".toml"))
];
in cfg.theme == null || (builtins.elem cfg.theme available);
message = "The alacritty theme '${cfg.theme}' does not exist.";
}];
assertions = [
{
# If using the theme option, ensure that theme exists in the
# alacritty-theme package.
assertion =
let
available = lib.pipe "${pkgs.alacritty-theme}/share/alacritty-theme" [
builtins.readDir
(lib.filterAttrs (name: type: type == "regular" && lib.hasSuffix ".toml" name))
lib.attrNames
(lib.map (lib.removeSuffix ".toml"))
];
in
cfg.theme == null || (builtins.elem cfg.theme available);
message = "The alacritty theme '${cfg.theme}' does not exist.";
}
];
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
programs.alacritty.settings = let
theme = "${pkgs.alacritty-theme}/share/alacritty-theme/${cfg.theme}.toml";
in lib.mkIf (cfg.theme != null) {
general.import =
lib.mkIf (lib.versionAtLeast cfg.package.version "0.14") [ theme ];
import = lib.mkIf (lib.versionOlder cfg.package.version "0.14") [ theme ];
};
programs.alacritty.settings =
let
theme = "${pkgs.alacritty-theme}/share/alacritty-theme/${cfg.theme}.toml";
in
lib.mkIf (cfg.theme != null) {
general.import = lib.mkIf (lib.versionAtLeast cfg.package.version "0.14") [ theme ];
import = lib.mkIf (lib.versionOlder cfg.package.version "0.14") [ theme ];
};
xdg.configFile."alacritty/alacritty.toml" = lib.mkIf (cfg.settings != { }) {
source = (tomlFormat.generate "alacritty.toml" cfg.settings).overrideAttrs
(finalAttrs: prevAttrs: {
source = (tomlFormat.generate "alacritty.toml" cfg.settings).overrideAttrs (
finalAttrs: prevAttrs: {
buildCommand = lib.concatStringsSep "\n" [
prevAttrs.buildCommand
# TODO: why is this needed? Is there a better way to retain escape sequences?
"substituteInPlace $out --replace-quiet '\\\\' '\\'"
];
});
}
);
};
};
}

View file

@ -1,7 +1,9 @@
pkgs:
{ config, lib, ... }:
let inherit (lib) mkOption types;
in {
let
inherit (lib) mkOption types;
in
{
options.alot = {
sendMailCommand = mkOption {
type = types.nullOr types.str;
@ -16,11 +18,9 @@ in {
type = types.attrsOf types.str;
default = {
type = "shellcommand";
command =
"'${pkgs.notmuch}/bin/notmuch address --format=json --output=recipients date:6M..'";
regexp = "'\\[?{" + ''
"name": "(?P<name>.*)", "address": "(?P<email>.+)", "name-addr": ".*"''
+ "}[,\\]]?'";
command = "'${pkgs.notmuch}/bin/notmuch address --format=json --output=recipients date:6M..'";
regexp =
"'\\[?{" + ''"name": "(?P<name>.*)", "address": "(?P<email>.+)", "name-addr": ".*"'' + "}[,\\]]?'";
shellcommand_external_filtering = "False";
};
example = lib.literalExpression ''
@ -48,9 +48,8 @@ in {
};
config = lib.mkIf config.notmuch.enable {
alot.sendMailCommand = lib.mkOptionDefault (if config.msmtp.enable then
"msmtpq --read-envelope-from --read-recipients"
else
null);
alot.sendMailCommand = lib.mkOptionDefault (
if config.msmtp.enable then "msmtpq --read-envelope-from --read-recipients" else null
);
};
}

View file

@ -1,22 +1,35 @@
# alot config loader is sensitive to leading space !
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib)
concatStringsSep mapAttrsToList mkOption optionalAttrs optionalString types;
concatStringsSep
mapAttrsToList
mkOption
optionalAttrs
optionalString
types
;
cfg = config.programs.alot;
enabledAccounts = lib.filter (a: a.notmuch.enable)
(lib.attrValues config.accounts.email.accounts);
enabledAccounts = lib.filter (a: a.notmuch.enable) (lib.attrValues config.accounts.email.accounts);
# sorted: primary first
alotAccounts = lib.sort (a: b: !(a.primary -> b.primary)) enabledAccounts;
boolStr = v: if v then "True" else "False";
mkKeyValue = key: value:
let value' = if lib.isBool value then boolStr value else toString value;
in "${key} = ${value'}";
mkKeyValue =
key: value:
let
value' = if lib.isBool value then boolStr value else toString value;
in
"${key} = ${value'}";
mk2ndLevelSectionName = name: "[" + name + "]";
@ -59,67 +72,95 @@ let
};
};
accountStr = account:
accountStr =
account:
let
inherit (account)
alot maildir name address realName folders aliases gpg signature;
in concatStringsSep "\n" ([ "[[${name}]]" ]
++ mapAttrsToList (n: v: n + "=" + v) ({
address = address;
realname = realName;
sendmail_command =
optionalString (alot.sendMailCommand != null) alot.sendMailCommand;
} // optionalAttrs (folders.sent != null) {
sent_box = "maildir" + "://" + maildir.absPath + "/" + folders.sent;
} // optionalAttrs (folders.drafts != null) {
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);
alot
maildir
name
address
realName
folders
aliases
gpg
signature
;
in
concatStringsSep "\n" (
[ "[[${name}]]" ]
++ mapAttrsToList (n: v: n + "=" + v) (
{
address = address;
realname = realName;
sendmail_command = optionalString (alot.sendMailCommand != null) alot.sendMailCommand;
}
// optionalAttrs (folders.sent != null) {
sent_box = "maildir" + "://" + maildir.absPath + "/" + folders.sent;
}
// optionalAttrs (folders.drafts != null) {
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
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
${lib.generators.toKeyValue { inherit mkKeyValue; } cfg.settings}
${cfg.extraConfig}
[tags]
'' + (let
submoduleToAttrs = m:
lib.filterAttrs (name: v: name != "_module" && v != null) m;
in lib.generators.toINI { mkSectionName = mk2ndLevelSectionName; }
(lib.mapAttrs (name: x: submoduleToAttrs x) cfg.tags)) + ''
[bindings]
${bindingsToStr cfg.bindings.global}
${lib.generators.toKeyValue { inherit mkKeyValue; } cfg.settings}
${cfg.extraConfig}
[tags]
''
+ (
let
submoduleToAttrs = m: lib.filterAttrs (name: v: name != "_module" && v != null) m;
in
lib.generators.toINI { mkSectionName = mk2ndLevelSectionName; } (
lib.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}
[[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]
[accounts]
${lib.concatStringsSep "\n\n" (map accountStr alotAccounts)}
'';
${lib.concatStringsSep "\n\n" (map accountStr alotAccounts)}
'';
in {
in
{
options = {
programs.alot = {
enable = mkOption {
@ -196,9 +237,12 @@ in {
};
settings = mkOption {
type = with types;
let primitive = either (either (either str int) bool) float;
in attrsOf primitive;
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;
@ -237,9 +281,11 @@ in {
xdg.configFile."alot/config".text = configFile;
xdg.configFile."alot/hooks.py" = lib.mkIf (cfg.hooks != "") {
text = ''
# Generated by Home Manager.
'' + cfg.hooks;
text =
''
# Generated by Home Manager.
''
+ cfg.hooks;
};
};
}

View file

@ -1,15 +1,25 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.zsh.antidote;
zPluginStr = (pluginNames:
lib.optionalString (pluginNames != [ ]) "${lib.concatStrings (map (name: ''
${name}
'') pluginNames)}");
zPluginStr = (
pluginNames:
lib.optionalString (pluginNames != [ ])
"${lib.concatStrings (
map (name: ''
${name}
'') pluginNames
)}"
);
parseHashId = path:
lib.elemAt (builtins.match "${builtins.storeDir}/([a-zA-Z0-9]+)-.*" path) 0;
in {
parseHashId = path: lib.elemAt (builtins.match "${builtins.storeDir}/([a-zA-Z0-9]+)-.*" path) 0;
in
{
meta.maintainers = [ lib.maintainers.hitsmaxft ];
options.programs.zsh.antidote = {
@ -30,25 +40,26 @@ in {
config = lib.mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
programs.zsh.initContent = let
configFiles = pkgs.runCommand "hm_antidote-files" { } ''
echo "${zPluginStr cfg.plugins}" > $out
'';
hashId = parseHashId "${configFiles}";
in (lib.mkOrder 550 ''
## home-manager/antidote begin :
source ${cfg.package}/share/antidote/antidote.zsh
${lib.optionalString cfg.useFriendlyNames
"zstyle ':antidote:bundle' use-friendly-names 'yes'"}
programs.zsh.initContent =
let
configFiles = pkgs.runCommand "hm_antidote-files" { } ''
echo "${zPluginStr cfg.plugins}" > $out
'';
hashId = parseHashId "${configFiles}";
in
(lib.mkOrder 550 ''
## home-manager/antidote begin :
source ${cfg.package}/share/antidote/antidote.zsh
${lib.optionalString cfg.useFriendlyNames "zstyle ':antidote:bundle' use-friendly-names 'yes'"}
bundlefile=${configFiles}
zstyle ':antidote:bundle' file $bundlefile
staticfile=/tmp/tmp_hm_zsh_plugins.zsh-${hashId}
zstyle ':antidote:static' file $staticfile
bundlefile=${configFiles}
zstyle ':antidote:bundle' file $bundlefile
staticfile=/tmp/tmp_hm_zsh_plugins.zsh-${hashId}
zstyle ':antidote:static' file $staticfile
antidote load $bundlefile $staticfile
antidote load $bundlefile $staticfile
## home-manager/antidote end
'');
## home-manager/antidote end
'');
};
}

View file

@ -1,16 +1,20 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.aria2;
formatLine = n: v:
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 {
formatValue = v: if builtins.isBool v then (if v then "true" else "false") else toString v;
in
"${n}=${formatValue v}";
in
{
meta.maintainers = [ lib.hm.maintainers.justinlovinger ];
options.programs.aria2 = {
@ -19,7 +23,14 @@ in {
package = lib.mkPackageOption pkgs "aria2" { nullable = true; };
settings = lib.mkOption {
type = with lib.types; attrsOf (oneOf [ bool float int str ]);
type =
with lib.types;
attrsOf (oneOf [
bool
float
int
str
]);
default = { };
description = ''
Options to add to {file}`aria2.conf` file.
@ -50,8 +61,10 @@ in {
config = lib.mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
xdg.configFile."aria2/aria2.conf".text = lib.concatStringsSep "\n" ([ ]
xdg.configFile."aria2/aria2.conf".text = lib.concatStringsSep "\n" (
[ ]
++ lib.mapAttrsToList formatLine cfg.settings
++ lib.optional (cfg.extraConfig != "") cfg.extraConfig);
++ lib.optional (cfg.extraConfig != "") cfg.extraConfig
);
};
}

View file

@ -1,4 +1,5 @@
{ config, lib, ... }: {
{ config, lib, ... }:
{
options.astroid = {
enable = lib.mkEnableOption "Astroid";
@ -14,7 +15,9 @@
extraConfig = lib.mkOption {
type = lib.types.attrsOf lib.types.anything;
default = { };
example = { select_query = ""; };
example = {
select_query = "";
};
description = ''
Extra settings to add to this astroid account configuration.
'';
@ -22,7 +25,8 @@
};
config = lib.mkIf config.notmuch.enable {
astroid.sendMailCommand = lib.mkIf config.msmtp.enable
(lib.mkOptionDefault "msmtpq --read-envelope-from --read-recipients");
astroid.sendMailCommand = lib.mkIf config.msmtp.enable (
lib.mkOptionDefault "msmtpq --read-envelope-from --read-recipients"
);
};
}

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkOption types;
@ -6,12 +11,12 @@ let
jsonFormat = pkgs.formats.json { };
astroidAccounts =
lib.filterAttrs (n: v: v.astroid.enable) config.accounts.email.accounts;
astroidAccounts = lib.filterAttrs (n: v: v.astroid.enable) config.accounts.email.accounts;
boolOpt = b: if b then "true" else "false";
accountAttr = account:
accountAttr =
account:
with account;
{
email = address;
@ -23,33 +28,38 @@ let
save_sent = "true";
save_sent_to = "${maildir.absPath}/${folders.sent}/cur/";
select_query = "";
} // lib.optionalAttrs (signature.showSignature != "none") {
}
// lib.optionalAttrs (signature.showSignature != "none") {
signature_attach = boolOpt (signature.showSignature == "attach");
signature_default_on = boolOpt (signature.showSignature != "none");
signature_file = pkgs.writeText "signature.txt" signature.text;
signature_file_markdown = "false";
signature_separate = "true"; # prepends '--\n' to the signature
} // lib.optionalAttrs (gpg != null) {
}
// lib.optionalAttrs (gpg != null) {
always_gpg_sign = boolOpt gpg.signByDefault;
gpgkey = gpg.key;
} // astroid.extraConfig;
}
// astroid.extraConfig;
# See https://github.com/astroidmail/astroid/wiki/Configuration-Reference
finalConfig = let
template = lib.importJSON ./astroid-config-template.json;
astroidConfig = lib.foldl' lib.recursiveUpdate template [
{
astroid.notmuch_config =
"${config.xdg.configHome}/notmuch/default/config";
accounts = lib.mapAttrs (n: accountAttr) astroidAccounts;
crypto.gpg.path = "${pkgs.gnupg}/bin/gpg";
}
cfg.extraConfig
cfg.externalEditor
];
in astroidConfig;
finalConfig =
let
template = lib.importJSON ./astroid-config-template.json;
astroidConfig = lib.foldl' lib.recursiveUpdate template [
{
astroid.notmuch_config = "${config.xdg.configHome}/notmuch/default/config";
accounts = lib.mapAttrs (n: accountAttr) astroidAccounts;
crypto.gpg.path = "${pkgs.gnupg}/bin/gpg";
}
cfg.extraConfig
cfg.externalEditor
];
in
astroidConfig;
in {
in
{
options = {
programs.astroid = {
enable = lib.mkEnableOption "Astroid";
@ -69,15 +79,15 @@ in {
type = types.nullOr types.str;
default = null;
# Converts it into JSON that can be merged into the configuration.
apply = cmd:
apply =
cmd:
lib.optionalAttrs (cmd != null) {
editor = {
"external_editor" = "true";
"cmd" = cmd;
};
};
example =
"nvim-qt -- -c 'set ft=mail' '+set fileencoding=utf-8' '+set ff=unix' '+set enc=utf-8' '+set fo+=w' %1";
example = "nvim-qt -- -c 'set ft=mail' '+set fileencoding=utf-8' '+set ff=unix' '+set enc=utf-8' '+set fo+=w' %1";
description = ''
You can use the following variables:
@ -117,8 +127,7 @@ in {
config = lib.mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
xdg.configFile."astroid/config".source =
jsonFormat.generate "astroid-config" finalConfig;
xdg.configFile."astroid/config".source = jsonFormat.generate "astroid-config" finalConfig;
xdg.configFile."astroid/poll.sh" = lib.mkIf (cfg.pollScript != "") {
executable = true;

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
let
cfg = config.programs.atuin;
daemonCfg = cfg.daemon;
@ -7,8 +12,12 @@ let
inherit (lib) mkIf mkOption types;
inherit (pkgs.stdenv) isLinux isDarwin;
in {
meta.maintainers = with lib.maintainers; [ hawkw water-sucks ];
in
{
meta.maintainers = with lib.maintainers; [
hawkw
water-sucks
];
options.programs.atuin = {
enable = lib.mkEnableOption "atuin";
@ -17,18 +26,15 @@ in {
enableBashIntegration = lib.hm.shell.mkBashIntegrationOption {
inherit config;
extraDescription =
"If enabled, this will bind `ctrl-r` to open the Atuin history.";
extraDescription = "If enabled, this will bind `ctrl-r` to open the Atuin history.";
};
enableFishIntegration = lib.hm.shell.mkFishIntegrationOption {
inherit config;
extraDescription =
"If enabled, this will bind the up-arrow key to open the Atuin history.";
extraDescription = "If enabled, this will bind the up-arrow key to open the Atuin history.";
};
enableNushellIntegration =
lib.hm.shell.mkNushellIntegrationOption { inherit config; };
enableNushellIntegration = lib.hm.shell.mkNushellIntegrationOption { inherit config; };
enableZshIntegration = lib.hm.shell.mkZshIntegrationOption {
inherit config;
@ -41,21 +47,30 @@ in {
flags = mkOption {
default = [ ];
type = types.listOf types.str;
example = [ "--disable-up-arrow" "--disable-ctrl-r" ];
example = [
"--disable-up-arrow"
"--disable-ctrl-r"
];
description = ''
Flags to append to the shell hook.
'';
};
settings = mkOption {
type = with types;
type =
with types;
let
prim = oneOf [ bool int str ];
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 = "Atuin configuration"; };
in
attrsOf entries // { description = "Atuin configuration"; };
default = { };
example = lib.literalExpression ''
{
@ -79,8 +94,15 @@ in {
logLevel = mkOption {
default = null;
type =
types.nullOr (types.enum [ "trace" "debug" "info" "warn" "error" ]);
type = types.nullOr (
types.enum [
"trace"
"debug"
"info"
"warn"
"error"
]
);
description = ''
Verbosity of Atuin daemon logging.
'';
@ -88,126 +110,145 @@ in {
};
};
config = let flagsStr = lib.escapeShellArgs cfg.flags;
in mkIf cfg.enable (lib.mkMerge [
{
# Always add the configured `atuin` package.
home.packages = [ cfg.package ];
config =
let
flagsStr = lib.escapeShellArgs cfg.flags;
in
mkIf cfg.enable (
lib.mkMerge [
{
# Always add the configured `atuin` package.
home.packages = [ cfg.package ];
# If there are user-provided settings, generate the config file.
xdg.configFile."atuin/config.toml" = mkIf (cfg.settings != { }) {
source = tomlFormat.generate "atuin-config" cfg.settings;
};
# If there are user-provided settings, generate the config file.
xdg.configFile."atuin/config.toml" = mkIf (cfg.settings != { }) {
source = tomlFormat.generate "atuin-config" cfg.settings;
};
programs.bash.initExtra = mkIf cfg.enableBashIntegration ''
if [[ :$SHELLOPTS: =~ :(vi|emacs): ]]; then
source "${pkgs.bash-preexec}/share/bash/bash-preexec.sh"
eval "$(${lib.getExe cfg.package} init bash ${flagsStr})"
fi
'';
programs.bash.initExtra = mkIf cfg.enableBashIntegration ''
if [[ :$SHELLOPTS: =~ :(vi|emacs): ]]; then
source "${pkgs.bash-preexec}/share/bash/bash-preexec.sh"
eval "$(${lib.getExe cfg.package} init bash ${flagsStr})"
fi
'';
programs.zsh.initContent = mkIf cfg.enableZshIntegration ''
if [[ $options[zle] = on ]]; then
eval "$(${lib.getExe cfg.package} init zsh ${flagsStr})"
fi
'';
programs.zsh.initContent = mkIf cfg.enableZshIntegration ''
if [[ $options[zle] = on ]]; then
eval "$(${lib.getExe cfg.package} init zsh ${flagsStr})"
fi
'';
programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration ''
${lib.getExe cfg.package} init fish ${flagsStr} | source
'';
programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration ''
${lib.getExe cfg.package} init fish ${flagsStr} | source
'';
programs.nushell = mkIf cfg.enableNushellIntegration {
extraConfig = ''
source ${
pkgs.runCommand "atuin-nushell-config.nu" {
nativeBuildInputs = [ pkgs.writableTmpDirAsHomeHook ];
} ''
${lib.getExe cfg.package} init nu ${flagsStr} >> "$out"
''
}
'';
};
}
(mkIf daemonCfg.enable (lib.mkMerge [
{
assertions = [
{
assertion = lib.versionAtLeast cfg.package.version "18.2.0";
message = ''
The Atuin daemon requires at least version 18.2.0 or later.
programs.nushell = mkIf cfg.enableNushellIntegration {
extraConfig = ''
source ${
pkgs.runCommand "atuin-nushell-config.nu"
{
nativeBuildInputs = [ pkgs.writableTmpDirAsHomeHook ];
}
''
${lib.getExe cfg.package} init nu ${flagsStr} >> "$out"
''
}
'';
}
{
assertion = isLinux || isDarwin;
message =
"The Atuin daemon can only be configured on either Linux or macOS.";
}
];
};
}
programs.atuin.settings = { daemon = { enabled = true; }; };
}
(mkIf isLinux {
programs.atuin.settings = { daemon = { systemd_socket = true; }; };
(mkIf daemonCfg.enable (
lib.mkMerge [
{
assertions = [
{
assertion = lib.versionAtLeast cfg.package.version "18.2.0";
message = ''
The Atuin daemon requires at least version 18.2.0 or later.
'';
}
{
assertion = isLinux || isDarwin;
message = "The Atuin daemon can only be configured on either Linux or macOS.";
}
];
systemd.user.services.atuin-daemon = {
Unit = {
Description = "Atuin daemon";
Requires = [ "atuin-daemon.socket" ];
};
Install = {
Also = [ "atuin-daemon.socket" ];
WantedBy = [ "default.target" ];
};
Service = {
ExecStart = "${lib.getExe cfg.package} daemon";
Environment = lib.optionals (daemonCfg.logLevel != null)
[ "ATUIN_LOG=${daemonCfg.logLevel}" ];
Restart = "on-failure";
RestartSteps = 3;
RestartMaxDelaySec = 6;
};
};
systemd.user.sockets.atuin-daemon = let
socket_dir = if lib.versionAtLeast cfg.package.version "18.4.0" then
"%t"
else
"%D/atuin";
in {
Unit = { Description = "Atuin daemon socket"; };
Install = { WantedBy = [ "sockets.target" ]; };
Socket = {
ListenStream = "${socket_dir}/atuin.sock";
SocketMode = "0600";
RemoveOnStop = true;
};
};
})
(mkIf isDarwin {
programs.atuin.settings = {
daemon = {
socket_path =
lib.mkDefault "${config.xdg.dataHome}/atuin/daemon.sock";
};
};
launchd.agents.atuin-daemon = {
enable = true;
config = {
ProgramArguments = [ "${lib.getExe cfg.package}" "daemon" ];
EnvironmentVariables =
lib.optionalAttrs (daemonCfg.logLevel != null) {
ATUIN_LOG = daemonCfg.logLevel;
programs.atuin.settings = {
daemon = {
enabled = true;
};
};
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
ProcessType = "Background";
};
};
})
]))
]);
}
(mkIf isLinux {
programs.atuin.settings = {
daemon = {
systemd_socket = true;
};
};
systemd.user.services.atuin-daemon = {
Unit = {
Description = "Atuin daemon";
Requires = [ "atuin-daemon.socket" ];
};
Install = {
Also = [ "atuin-daemon.socket" ];
WantedBy = [ "default.target" ];
};
Service = {
ExecStart = "${lib.getExe cfg.package} daemon";
Environment = lib.optionals (daemonCfg.logLevel != null) [ "ATUIN_LOG=${daemonCfg.logLevel}" ];
Restart = "on-failure";
RestartSteps = 3;
RestartMaxDelaySec = 6;
};
};
systemd.user.sockets.atuin-daemon =
let
socket_dir = if lib.versionAtLeast cfg.package.version "18.4.0" then "%t" else "%D/atuin";
in
{
Unit = {
Description = "Atuin daemon socket";
};
Install = {
WantedBy = [ "sockets.target" ];
};
Socket = {
ListenStream = "${socket_dir}/atuin.sock";
SocketMode = "0600";
RemoveOnStop = true;
};
};
})
(mkIf isDarwin {
programs.atuin.settings = {
daemon = {
socket_path = lib.mkDefault "${config.xdg.dataHome}/atuin/daemon.sock";
};
};
launchd.agents.atuin-daemon = {
enable = true;
config = {
ProgramArguments = [
"${lib.getExe cfg.package}"
"daemon"
];
EnvironmentVariables = lib.optionalAttrs (daemonCfg.logLevel != null) {
ATUIN_LOG = daemonCfg.logLevel;
};
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
ProcessType = "Background";
};
};
})
]
))
]
);
}

View file

@ -1,9 +1,15 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.autojump;
inherit (lib) mkIf;
in {
in
{
meta.maintainers = [ lib.maintainers.evanjs ];
options.programs.autojump = {
@ -11,22 +17,21 @@ in {
package = lib.mkPackageOption pkgs "autojump" { };
enableBashIntegration =
lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableBashIntegration = lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableFishIntegration =
lib.hm.shell.mkFishIntegrationOption { inherit config; };
enableFishIntegration = lib.hm.shell.mkFishIntegrationOption { inherit config; };
enableZshIntegration =
lib.hm.shell.mkZshIntegrationOption { inherit config; };
enableZshIntegration = lib.hm.shell.mkZshIntegrationOption { inherit config; };
};
config = mkIf cfg.enable {
home.packages = [ cfg.package ];
programs.bash.initExtra = mkIf cfg.enableBashIntegration (lib.mkBefore ''
. ${cfg.package}/share/autojump/autojump.bash
'');
programs.bash.initExtra = mkIf cfg.enableBashIntegration (
lib.mkBefore ''
. ${cfg.package}/share/autojump/autojump.bash
''
);
programs.zsh.initContent = mkIf cfg.enableZshIntegration ''
. ${cfg.package}/share/autojump/autojump.zsh

View file

@ -1,25 +1,49 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib)
literalExpression listToAttrs mapAttrs' mapAttrsToList mkIf mkOption
optional types;
literalExpression
listToAttrs
mapAttrs'
mapAttrsToList
mkIf
mkOption
optional
types
;
cfg = config.programs.autorandr;
matrixOf = n: m: elemType:
matrixOf =
n: m: elemType:
lib.mkOptionType rec {
name = "matrixOf";
description =
"${toString n}×${toString m} matrix of ${elemType.description}s";
check = xss:
let listOfSize = l: xs: lib.isList xs && lib.length xs == l;
in listOfSize n xss
&& lib.all (xs: listOfSize m xs && lib.all elemType.check xs) xss;
description = "${toString n}×${toString m} matrix of ${elemType.description}s";
check =
xss:
let
listOfSize = l: xs: lib.isList xs && lib.length xs == l;
in
listOfSize n xss && lib.all (xs: listOfSize m xs && lib.all elemType.check xs) xss;
merge = lib.mergeOneOption;
getSubOptions = prefix: elemType.getSubOptions (prefix ++ [ "*" "*" ]);
getSubOptions =
prefix:
elemType.getSubOptions (
prefix
++ [
"*"
"*"
]
);
getSubModules = elemType.getSubModules;
substSubModules = mod: matrixOf n m (elemType.substSubModules mod);
functor = (lib.defaultFunctor name) // { wrapped = elemType; };
functor = (lib.defaultFunctor name) // {
wrapped = elemType;
};
};
profileModule = types.submodule {
@ -97,7 +121,14 @@ let
};
rotate = mkOption {
type = types.nullOr (types.enum [ "normal" "left" "right" "inverted" ]);
type = types.nullOr (
types.enum [
"normal"
"left"
"right"
"inverted"
]
);
description = "Output rotate configuration.";
default = null;
example = "left";
@ -128,26 +159,31 @@ let
};
scale = mkOption {
type = types.nullOr (types.submodule {
options = {
method = mkOption {
type = types.enum [ "factor" "pixel" ];
description = "Output scaling method.";
default = "factor";
example = "pixel";
};
type = types.nullOr (
types.submodule {
options = {
method = mkOption {
type = types.enum [
"factor"
"pixel"
];
description = "Output scaling method.";
default = "factor";
example = "pixel";
};
x = mkOption {
type = types.either types.float types.ints.positive;
description = "Horizontal scaling factor/pixels.";
};
x = mkOption {
type = types.either types.float types.ints.positive;
description = "Horizontal scaling factor/pixels.";
};
y = mkOption {
type = types.either types.float types.ints.positive;
description = "Vertical scaling factor/pixels.";
y = mkOption {
type = types.either types.float types.ints.positive;
description = "Vertical scaling factor/pixels.";
};
};
};
});
}
);
description = ''
Output scale configuration.
@ -172,7 +208,12 @@ let
};
filter = mkOption {
type = types.nullOr (types.enum [ "bilinear" "nearest" ]);
type = types.nullOr (
types.enum [
"bilinear"
"nearest"
]
);
description = "Interpolation method to be used for scaling the output.";
default = null;
example = "nearest";
@ -242,30 +283,35 @@ let
};
};
hookToFile = folder: name: hook:
hookToFile =
folder: name: hook:
lib.nameValuePair "autorandr/${folder}/${name}" {
source = "${pkgs.writeShellScriptBin "hook" hook}/bin/hook";
};
profileToFiles = name: profile:
let inherit (profile) hooks;
in lib.mkMerge [
profileToFiles =
name: profile:
let
inherit (profile) hooks;
in
lib.mkMerge [
{
"autorandr/${name}/setup".text = lib.concatStringsSep "\n"
(mapAttrsToList fingerprintToString profile.fingerprint);
"autorandr/${name}/config".text = lib.concatStringsSep "\n"
(mapAttrsToList configToString profile.config);
"autorandr/${name}/setup".text = lib.concatStringsSep "\n" (
mapAttrsToList fingerprintToString profile.fingerprint
);
"autorandr/${name}/config".text = lib.concatStringsSep "\n" (
mapAttrsToList configToString profile.config
);
}
(mkIf (hooks.postswitch != "")
(listToAttrs [ (hookToFile name "postswitch" hooks.postswitch) ]))
(mkIf (hooks.preswitch != "")
(listToAttrs [ (hookToFile name "preswitch" hooks.preswitch) ]))
(mkIf (hooks.predetect != "")
(listToAttrs [ (hookToFile name "predetect" hooks.predetect) ]))
(mkIf (hooks.postswitch != "") (listToAttrs [ (hookToFile name "postswitch" hooks.postswitch) ]))
(mkIf (hooks.preswitch != "") (listToAttrs [ (hookToFile name "preswitch" hooks.preswitch) ]))
(mkIf (hooks.predetect != "") (listToAttrs [ (hookToFile name "predetect" hooks.predetect) ]))
];
fingerprintToString = name: edid: "${name} ${edid}";
configToString = name: config:
configToString =
name: config:
if config.enable then
lib.concatStringsSep "\n" ([ "output ${name}" ]
lib.concatStringsSep "\n" (
[ "output ${name}" ]
++ optional (config.position != "") "pos ${config.position}"
++ optional (config.crtc != null) "crtc ${toString config.crtc}"
++ optional config.primary "primary"
@ -275,18 +321,23 @@ let
++ optional (config.rate != "") "rate ${config.rate}"
++ optional (config.rotate != null) "rotate ${config.rotate}"
++ optional (config.filter != null) "filter ${config.filter}"
++ optional (config.transform != null) ("transform "
+ lib.concatMapStringsSep "," toString (lib.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}")
++ optional (config.extraConfig != "") config.extraConfig)
else ''
output ${name}
off
'';
++ optional (config.transform != null) (
"transform " + lib.concatMapStringsSep "," toString (lib.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}"
)
++ optional (config.extraConfig != "") config.extraConfig
)
else
''
output ${name}
off
'';
in {
in
{
options = {
programs.autorandr = {
enable = lib.mkEnableOption "Autorandr";
@ -358,15 +409,19 @@ in {
};
config = lib.mkIf cfg.enable {
assertions = lib.flatten (mapAttrsToList (profile:
{ config, ... }:
mapAttrsToList (output: opts: {
assertion = opts.scale == null || opts.transform == null;
message = ''
Cannot use the profile output options 'scale' and 'transform' simultaneously.
Check configuration for: programs.autorandr.profiles.${profile}.config.${output}
'';
}) config) cfg.profiles);
assertions = lib.flatten (
mapAttrsToList (
profile:
{ config, ... }:
mapAttrsToList (output: opts: {
assertion = opts.scale == null || opts.transform == null;
message = ''
Cannot use the profile output options 'scale' and 'transform' simultaneously.
Check configuration for: programs.autorandr.profiles.${profile}.config.${output}
'';
}) config
) cfg.profiles
);
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];

View file

@ -1,10 +1,16 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.awscli;
iniFormat = pkgs.formats.ini { };
in {
in
{
meta.maintainers = [ lib.maintainers.anthonyroussel ];
options.programs.awscli = {
@ -55,16 +61,12 @@ in {
config = lib.mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
home.file."${config.home.homeDirectory}/.aws/config" =
lib.mkIf (cfg.settings != { }) {
source =
iniFormat.generate "aws-config-${config.home.username}" cfg.settings;
};
home.file."${config.home.homeDirectory}/.aws/config" = lib.mkIf (cfg.settings != { }) {
source = iniFormat.generate "aws-config-${config.home.username}" cfg.settings;
};
home.file."${config.home.homeDirectory}/.aws/credentials" =
lib.mkIf (cfg.credentials != { }) {
source = iniFormat.generate "aws-credentials-${config.home.username}"
cfg.credentials;
};
home.file."${config.home.homeDirectory}/.aws/credentials" = lib.mkIf (cfg.credentials != { }) {
source = iniFormat.generate "aws-credentials-${config.home.username}" cfg.credentials;
};
};
}

View file

@ -1,16 +1,23 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.bacon;
settingsFormat = pkgs.formats.toml { };
configDir = if pkgs.stdenv.isDarwin then
"Library/Application Support/org.dystroy.bacon"
else
"${config.xdg.configHome}/bacon";
configDir =
if pkgs.stdenv.isDarwin then
"Library/Application Support/org.dystroy.bacon"
else
"${config.xdg.configHome}/bacon";
in {
in
{
meta.maintainers = [ lib.hm.maintainers.shimunn ];
options.programs.bacon = {
@ -23,7 +30,13 @@ in {
default = { };
example = {
jobs.default = {
command = [ "cargo" "build" "--all-features" "--color" "always" ];
command = [
"cargo"
"build"
"--all-features"
"--color"
"always"
];
need_stdout = true;
};
};

View file

@ -1,10 +1,21 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkIf mkOption optionalAttrs types;
inherit (lib)
mkIf
mkOption
optionalAttrs
types
;
cfg = config.programs.bash;
writeBashScript = name: text:
writeBashScript =
name: text:
pkgs.writeTextFile {
inherit name text;
checkPhase = ''
@ -12,15 +23,19 @@ let
'';
};
in {
in
{
meta.maintainers = [ lib.maintainers.rycee ];
imports = [
(lib.mkRenamedOptionModule [ "programs" "bash" "enableAutojump" ] [
"programs"
"autojump"
"enable"
])
(lib.mkRenamedOptionModule
[ "programs" "bash" "enableAutojump" ]
[
"programs"
"autojump"
"enable"
]
)
];
options = {
@ -70,8 +85,14 @@ in {
};
historyControl = mkOption {
type = types.listOf
(types.enum [ "erasedups" "ignoredups" "ignorespace" "ignoreboth" ]);
type = types.listOf (
types.enum [
"erasedups"
"ignoredups"
"ignorespace"
"ignoreboth"
]
);
default = [ ];
description = "Controlling how commands are saved on the history list.";
};
@ -79,9 +100,12 @@ in {
historyIgnore = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "ls" "cd" "exit" ];
description =
"List of commands that should not be saved to the history list.";
example = [
"ls"
"cd"
"exit"
];
description = "List of commands that should not be saved to the history list.";
};
shellOptions = mkOption {
@ -101,7 +125,10 @@ in {
# Warn if closing shell with running jobs.
"checkjobs"
];
example = [ "extglob" "-cdspell" ];
example = [
"extglob"
"-cdspell"
];
description = ''
Shell options to set. Prefix an option with
"`-`" to unset.
@ -111,7 +138,9 @@ in {
sessionVariables = mkOption {
default = { };
type = types.attrs;
example = { MAILCHECK = 30; };
example = {
MAILCHECK = 30;
};
description = ''
Environment variables that will be set for the Bash session.
'';
@ -170,77 +199,90 @@ in {
};
};
config = let
aliasesStr = lib.concatStringsSep "\n"
(lib.mapAttrsToList (k: v: "alias ${k}=${lib.escapeShellArg v}")
cfg.shellAliases);
config =
let
aliasesStr = lib.concatStringsSep "\n" (
lib.mapAttrsToList (k: v: "alias ${k}=${lib.escapeShellArg v}") cfg.shellAliases
);
shoptsStr = let switch = v: if lib.hasPrefix "-" v then "-u" else "-s";
in lib.concatStringsSep "\n"
(map (v: "shopt ${switch v} ${lib.removePrefix "-" v}") cfg.shellOptions);
shoptsStr =
let
switch = v: if lib.hasPrefix "-" v then "-u" else "-s";
in
lib.concatStringsSep "\n" (map (v: "shopt ${switch v} ${lib.removePrefix "-" v}") cfg.shellOptions);
sessionVarsStr = config.lib.shell.exportAll cfg.sessionVariables;
sessionVarsStr = config.lib.shell.exportAll cfg.sessionVariables;
historyControlStr = (lib.concatStringsSep "\n"
(lib.mapAttrsToList (n: v: "${n}=${v}")
(optionalAttrs (cfg.historyFileSize != null) {
HISTFILESIZE = toString cfg.historyFileSize;
} // optionalAttrs (cfg.historySize != null) {
HISTSIZE = toString cfg.historySize;
} // optionalAttrs (cfg.historyFile != null) {
HISTFILE = ''"${cfg.historyFile}"'';
} // optionalAttrs (cfg.historyControl != [ ]) {
HISTCONTROL = lib.concatStringsSep ":" cfg.historyControl;
} // optionalAttrs (cfg.historyIgnore != [ ]) {
HISTIGNORE =
lib.escapeShellArg (lib.concatStringsSep ":" cfg.historyIgnore);
}) ++ lib.optional (cfg.historyFile != null)
''mkdir -p "$(dirname "$HISTFILE")"''));
in mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
historyControlStr = (
lib.concatStringsSep "\n" (
lib.mapAttrsToList (n: v: "${n}=${v}") (
optionalAttrs (cfg.historyFileSize != null) {
HISTFILESIZE = toString cfg.historyFileSize;
}
// optionalAttrs (cfg.historySize != null) {
HISTSIZE = toString cfg.historySize;
}
// optionalAttrs (cfg.historyFile != null) {
HISTFILE = ''"${cfg.historyFile}"'';
}
// optionalAttrs (cfg.historyControl != [ ]) {
HISTCONTROL = lib.concatStringsSep ":" cfg.historyControl;
}
// optionalAttrs (cfg.historyIgnore != [ ]) {
HISTIGNORE = lib.escapeShellArg (lib.concatStringsSep ":" cfg.historyIgnore);
}
)
++ lib.optional (cfg.historyFile != null) ''mkdir -p "$(dirname "$HISTFILE")"''
)
);
in
mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
home.file.".bash_profile".source = writeBashScript "bash_profile" ''
# include .profile if it exists
[[ -f ~/.profile ]] && . ~/.profile
home.file.".bash_profile".source = writeBashScript "bash_profile" ''
# include .profile if it exists
[[ -f ~/.profile ]] && . ~/.profile
# include .bashrc if it exists
[[ -f ~/.bashrc ]] && . ~/.bashrc
'';
# include .bashrc if it exists
[[ -f ~/.bashrc ]] && . ~/.bashrc
'';
# If completion is enabled then make sure it is sourced very early. This
# is to avoid problems if any other initialization code attempts to set up
# completion.
programs.bash.initExtra = mkIf cfg.enableCompletion (lib.mkOrder 100 ''
if [[ ! -v BASH_COMPLETION_VERSINFO ]]; then
. "${pkgs.bash-completion}/etc/profile.d/bash_completion.sh"
fi
'');
# If completion is enabled then make sure it is sourced very early. This
# is to avoid problems if any other initialization code attempts to set up
# completion.
programs.bash.initExtra = mkIf cfg.enableCompletion (
lib.mkOrder 100 ''
if [[ ! -v BASH_COMPLETION_VERSINFO ]]; then
. "${pkgs.bash-completion}/etc/profile.d/bash_completion.sh"
fi
''
);
home.file.".profile".source = writeBashScript "profile" ''
. "${config.home.profileDirectory}/etc/profile.d/hm-session-vars.sh"
home.file.".profile".source = writeBashScript "profile" ''
. "${config.home.profileDirectory}/etc/profile.d/hm-session-vars.sh"
${sessionVarsStr}
${sessionVarsStr}
${cfg.profileExtra}
'';
${cfg.profileExtra}
'';
home.file.".bashrc".source = writeBashScript "bashrc" ''
${cfg.bashrcExtra}
home.file.".bashrc".source = writeBashScript "bashrc" ''
${cfg.bashrcExtra}
# Commands that should be applied only for interactive shells.
[[ $- == *i* ]] || return
# Commands that should be applied only for interactive shells.
[[ $- == *i* ]] || return
${historyControlStr}
${historyControlStr}
${shoptsStr}
${shoptsStr}
${aliasesStr}
${aliasesStr}
${cfg.initExtra}
'';
${cfg.initExtra}
'';
home.file.".bash_logout" = mkIf (cfg.logoutExtra != "") {
source = writeBashScript "bash_logout" cfg.logoutExtra;
home.file.".bash_logout" = mkIf (cfg.logoutExtra != "") {
source = writeBashScript "bash_logout" cfg.logoutExtra;
};
};
};
}

View file

@ -1,6 +1,13 @@
{ config, lib, pkgs, ... }:
let cfg = config.programs.bashmount;
in {
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.bashmount;
in
{
meta.maintainers = [ lib.maintainers.AndersonTorres ];
options.programs.bashmount = {
@ -24,7 +31,6 @@ in {
config = lib.mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
xdg.configFile."bashmount/config" =
lib.mkIf (cfg.extraConfig != "") { text = cfg.extraConfig; };
xdg.configFile."bashmount/config" = lib.mkIf (cfg.extraConfig != "") { text = cfg.extraConfig; };
};
}

View file

@ -1,10 +1,22 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) literalExpression mkEnableOption mkOption mkIf types;
inherit (lib)
literalExpression
mkEnableOption
mkOption
mkIf
types
;
cfg = config.programs.bat;
toConfigFile = attrs:
toConfigFile =
attrs:
let
inherit (builtins) isBool attrNames;
nonBoolFlags = lib.filterAttrs (_: v: !(isBool v)) attrs;
@ -17,20 +29,31 @@ let
switches = lib.concatMapStrings (k: ''
--${k}
'') (attrNames enabledBoolFlags);
in keyValuePairs + switches;
in {
in
keyValuePairs + switches;
in
{
meta.maintainers = with lib.maintainers; [ khaneliman ];
options.programs.bat = {
enable = mkEnableOption "bat, a cat clone with wings";
config = mkOption {
type = with types; attrsOf (oneOf [ str (listOf str) bool ]);
type =
with types;
attrsOf (oneOf [
str
(listOf str)
bool
]);
default = { };
example = {
theme = "TwoDark";
pager = "less -FR";
map-syntax = [ "*.jenkinsfile:Groovy" "*.props:Java Properties" ];
map-syntax = [
"*.jenkinsfile:Groovy"
"*.props:Java Properties"
];
};
description = ''
Bat configuration.
@ -40,8 +63,7 @@ in {
extraPackages = mkOption {
type = types.listOf types.package;
default = [ ];
example = literalExpression
"with pkgs.bat-extras; [ batdiff batman batgrep batwatch ];";
example = literalExpression "with pkgs.bat-extras; [ batdiff batman batgrep batwatch ];";
description = ''
Additional bat packages to install.
'';
@ -50,21 +72,24 @@ in {
package = lib.mkPackageOption pkgs "bat" { };
themes = mkOption {
type = types.attrsOf (types.either types.lines (types.submodule {
options = {
src = mkOption {
type = types.path;
description = "Path to the theme folder.";
};
type = types.attrsOf (
types.either types.lines (
types.submodule {
options = {
src = mkOption {
type = types.path;
description = "Path to the theme folder.";
};
file = mkOption {
type = types.nullOr types.str;
default = null;
description =
"Subpath of the theme file within the source, if needed.";
};
};
}));
file = mkOption {
type = types.nullOr types.str;
default = null;
description = "Subpath of the theme file within the source, if needed.";
};
};
}
)
);
default = { };
example = literalExpression ''
{
@ -85,20 +110,23 @@ in {
};
syntaxes = mkOption {
type = types.attrsOf (types.either types.lines (types.submodule {
options = {
src = mkOption {
type = types.path;
description = "Path to the syntax folder.";
};
file = mkOption {
type = types.nullOr types.str;
default = null;
description =
"Subpath of the syntax file within the source, if needed.";
};
};
}));
type = types.attrsOf (
types.either types.lines (
types.submodule {
options = {
src = mkOption {
type = types.path;
description = "Path to the syntax folder.";
};
file = mkOption {
type = types.nullOr types.str;
default = null;
description = "Subpath of the syntax file within the source, if needed.";
};
};
}
)
);
default = { };
example = literalExpression ''
{
@ -119,54 +147,75 @@ in {
};
};
config = mkIf cfg.enable (lib.mkMerge [
(mkIf (lib.any lib.isString (lib.attrValues cfg.themes)) {
warnings = [''
Using programs.bat.themes as a string option is deprecated and will be
removed in the future. Please change to using it as an attribute set
instead.
''];
})
(mkIf (lib.any lib.isString (lib.attrValues cfg.syntaxes)) {
warnings = [''
Using programs.bat.syntaxes as a string option is deprecated and will be
removed in the future. Please change to using it as an attribute set
instead.
''];
})
{
home.packages = [ cfg.package ] ++ cfg.extraPackages;
config = mkIf cfg.enable (
lib.mkMerge [
(mkIf (lib.any lib.isString (lib.attrValues cfg.themes)) {
warnings = [
''
Using programs.bat.themes as a string option is deprecated and will be
removed in the future. Please change to using it as an attribute set
instead.
''
];
})
(mkIf (lib.any lib.isString (lib.attrValues cfg.syntaxes)) {
warnings = [
''
Using programs.bat.syntaxes as a string option is deprecated and will be
removed in the future. Please change to using it as an attribute set
instead.
''
];
})
{
home.packages = [ cfg.package ] ++ cfg.extraPackages;
xdg.configFile = lib.mkMerge ([{
"bat/config" =
mkIf (cfg.config != { }) { text = toConfigFile cfg.config; };
}] ++ (lib.flip lib.mapAttrsToList cfg.themes (name: val: {
"bat/themes/${name}.tmTheme" = if lib.isString val then {
text = val;
} else {
source =
if isNull val.file then "${val.src}" else "${val.src}/${val.file}";
};
})) ++ (lib.flip lib.mapAttrsToList cfg.syntaxes (name: val: {
"bat/syntaxes/${name}.sublime-syntax" = if lib.isString val then {
text = val;
} else {
source =
if isNull val.file then "${val.src}" else "${val.src}/${val.file}";
};
})));
xdg.configFile = lib.mkMerge (
[
{
"bat/config" = mkIf (cfg.config != { }) { text = toConfigFile cfg.config; };
}
]
++ (lib.flip lib.mapAttrsToList cfg.themes (
name: val: {
"bat/themes/${name}.tmTheme" =
if lib.isString val then
{
text = val;
}
else
{
source = if isNull val.file then "${val.src}" else "${val.src}/${val.file}";
};
}
))
++ (lib.flip lib.mapAttrsToList cfg.syntaxes (
name: val: {
"bat/syntaxes/${name}.sublime-syntax" =
if lib.isString val then
{
text = val;
}
else
{
source = if isNull val.file then "${val.src}" else "${val.src}/${val.file}";
};
}
))
);
# NOTE: run `bat cache --build` in an empty directory to work
# around failure when ~/cache exists
# https://github.com/sharkdp/bat/issues/1726
home.activation.batCache = lib.hm.dag.entryAfter [ "linkGeneration" ] ''
(
export XDG_CACHE_HOME=${lib.escapeShellArg config.xdg.cacheHome}
verboseEcho "Rebuilding bat theme cache"
cd "${pkgs.emptyDirectory}"
run ${lib.getExe cfg.package} cache --build
)
'';
}
]);
# NOTE: run `bat cache --build` in an empty directory to work
# around failure when ~/cache exists
# https://github.com/sharkdp/bat/issues/1726
home.activation.batCache = lib.hm.dag.entryAfter [ "linkGeneration" ] ''
(
export XDG_CACHE_HOME=${lib.escapeShellArg config.xdg.cacheHome}
verboseEcho "Rebuilding bat theme cache"
cd "${pkgs.emptyDirectory}"
run ${lib.getExe cfg.package} cache --build
)
'';
}
]
);
}

View file

@ -1,22 +1,34 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) literalExpression mkIf mkOption types;
inherit (lib)
literalExpression
mkIf
mkOption
types
;
cfg = config.programs.beets;
yamlFormat = pkgs.formats.yaml { };
in {
meta.maintainers = with lib.maintainers; [ rycee Scrumplex ];
in
{
meta.maintainers = with lib.maintainers; [
rycee
Scrumplex
];
options = {
programs.beets = {
enable = mkOption {
type = types.bool;
default = if lib.versionAtLeast config.home.stateVersion "19.03" then
false
else
cfg.settings != { };
default =
if lib.versionAtLeast config.home.stateVersion "19.03" then false else cfg.settings != { };
defaultText = "false";
description = ''
Whether to enable the beets music library manager. This
@ -27,8 +39,7 @@ in {
};
package = lib.mkPackageOption pkgs "beets" {
example =
"(pkgs.beets.override { pluginOverrides = { beatport.enable = false; }; })";
example = "(pkgs.beets.override { pluginOverrides = { beatport.enable = false; }; })";
extraDescription = ''
Can be used to specify extensions.
'';
@ -70,8 +81,7 @@ in {
(mkIf cfg.enable {
home.packages = [ cfg.package ];
xdg.configFile."beets/config.yaml".source =
yamlFormat.generate "beets-config" cfg.settings;
xdg.configFile."beets/config.yaml".source = yamlFormat.generate "beets-config" cfg.settings;
})
(mkIf (cfg.mpdIntegration.enableStats || cfg.mpdIntegration.enableUpdate) {

View file

@ -1,6 +1,13 @@
{ config, lib, pkgs, ... }:
let cfg = config.programs.bemenu;
in {
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.bemenu;
in
{
meta.maintainers = [ ];
options.programs.bemenu = {
@ -9,7 +16,13 @@ in {
package = lib.mkPackageOption pkgs "bemenu" { nullable = true; };
settings = lib.mkOption {
type = with lib.types; attrsOf (oneOf [ str number bool ]);
type =
with lib.types;
attrsOf (oneOf [
str
number
bool
]);
default = { };
example = lib.literalExpression ''
{
@ -29,15 +42,13 @@ in {
width-factor = 0.3;
}
'';
description =
"Configuration options for bemenu. See {manpage}`bemenu(1)`.";
description = "Configuration options for bemenu. See {manpage}`bemenu(1)`.";
};
};
config = lib.mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "programs.bemenu" pkgs
lib.platforms.linux)
(lib.hm.assertions.assertPlatform "programs.bemenu" pkgs lib.platforms.linux)
];
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) literalExpression mkOption types;
@ -6,24 +11,33 @@ let
yamlFormat = pkgs.formats.yaml { };
mkNullableOption = args:
lib.mkOption (args // {
type = lib.types.nullOr args.type;
default = null;
});
mkNullableOption =
args:
lib.mkOption (
args
// {
type = lib.types.nullOr args.type;
default = null;
}
);
cleanRepositories = repos:
map (repo:
if builtins.isString repo then {
path = repo;
} else
removeNullValues repo) repos;
cleanRepositories =
repos:
map (
repo:
if builtins.isString repo then
{
path = repo;
}
else
removeNullValues repo
) repos;
mkRetentionOption = frequency:
mkRetentionOption =
frequency:
mkNullableOption {
type = types.int;
description =
"Number of ${frequency} archives to keep. Use -1 for no limit.";
description = "Number of ${frequency} archives to keep. Use -1 for no limit.";
example = 3;
};
@ -56,7 +70,12 @@ let
consistencyCheckModule = types.submodule {
options = {
name = mkOption {
type = types.enum [ "repository" "archives" "data" "extract" ];
type = types.enum [
"repository"
"archives"
"data"
"extract"
];
description = "Name of consistency check to run.";
example = "repository";
};
@ -69,146 +88,151 @@ let
};
};
configModule = types.submodule ({ config, ... }: {
config.location.extraConfig.exclude_from =
lib.mkIf config.location.excludeHomeManagerSymlinks
(lib.mkAfter [ (toString hmExcludeFile) ]);
options = {
location = {
sourceDirectories = mkNullableOption {
type = types.listOf types.str;
default = null;
description = ''
Directories to backup.
configModule = types.submodule (
{ config, ... }:
{
config.location.extraConfig.exclude_from = lib.mkIf config.location.excludeHomeManagerSymlinks (
lib.mkAfter [ (toString hmExcludeFile) ]
);
options = {
location = {
sourceDirectories = mkNullableOption {
type = types.listOf types.str;
default = null;
description = ''
Directories to backup.
Mutually exclusive with [](#opt-programs.borgmatic.backups._name_.location.patterns).
'';
example = literalExpression "[config.home.homeDirectory]";
Mutually exclusive with [](#opt-programs.borgmatic.backups._name_.location.patterns).
'';
example = literalExpression "[config.home.homeDirectory]";
};
patterns = mkNullableOption {
type = types.listOf types.str;
default = null;
description = ''
Patterns to include/exclude.
See the output of `borg help patterns` for the syntax. Pattern paths
are relative to `/` even when a different recursion root is set.
Mutually exclusive with [](#opt-programs.borgmatic.backups._name_.location.sourceDirectories).
'';
example = literalExpression ''
[
"R /home/user"
"- home/user/.cache"
"- home/user/Downloads"
"+ home/user/Videos/Important Video"
"- home/user/Videos"
]
'';
};
repositories = mkOption {
type = types.listOf (types.either types.str repositoryOption);
apply = cleanRepositories;
example = literalExpression ''
[
{
"path" = "ssh://myuser@myrepo.myserver.com/./repo";
"label" = "server";
}
{
"path" = "/var/lib/backups/local.borg";
"label" = "local";
}
]
'';
description = ''
List of local or remote repositories with paths and optional labels.
'';
};
excludeHomeManagerSymlinks = mkOption {
type = types.bool;
description = ''
Whether to exclude Home Manager generated symbolic links from
the backups. This facilitates restoring the whole home
directory when the Nix store doesn't contain the latest
Home Manager generation.
'';
default = false;
example = true;
};
extraConfig = extraConfigOption;
};
patterns = mkNullableOption {
type = types.listOf types.str;
default = null;
description = ''
Patterns to include/exclude.
See the output of `borg help patterns` for the syntax. Pattern paths
are relative to `/` even when a different recursion root is set.
Mutually exclusive with [](#opt-programs.borgmatic.backups._name_.location.sourceDirectories).
'';
example = literalExpression ''
[
"R /home/user"
"- home/user/.cache"
"- home/user/Downloads"
"+ home/user/Videos/Important Video"
"- home/user/Videos"
]
'';
storage = {
encryptionPasscommand = mkNullableOption {
type = types.str;
description = "Command writing the passphrase to standard output.";
example = literalExpression ''"''${pkgs.password-store}/bin/pass borg-repo"'';
};
extraConfig = extraConfigOption;
};
repositories = mkOption {
type = types.listOf (types.either types.str repositoryOption);
apply = cleanRepositories;
example = literalExpression ''
[
{
"path" = "ssh://myuser@myrepo.myserver.com/./repo";
"label" = "server";
}
{
"path" = "/var/lib/backups/local.borg";
"label" = "local";
}
]
'';
description = ''
List of local or remote repositories with paths and optional labels.
'';
retention = {
keepWithin = mkNullableOption {
type = types.strMatching "[[:digit:]]+[Hdwmy]";
description = "Keep all archives within this time interval.";
example = "2d";
};
keepSecondly = mkRetentionOption "secondly";
keepMinutely = mkRetentionOption "minutely";
keepHourly = mkRetentionOption "hourly";
keepDaily = mkRetentionOption "daily";
keepWeekly = mkRetentionOption "weekly";
keepMonthly = mkRetentionOption "monthly";
keepYearly = mkRetentionOption "yearly";
extraConfig = extraConfigOption;
};
excludeHomeManagerSymlinks = mkOption {
type = types.bool;
description = ''
Whether to exclude Home Manager generated symbolic links from
the backups. This facilitates restoring the whole home
directory when the Nix store doesn't contain the latest
Home Manager generation.
'';
default = false;
example = true;
consistency = {
checks = mkOption {
type = types.listOf consistencyCheckModule;
default = [ ];
description = "Consistency checks to run";
example = literalExpression ''
[
{
name = "repository";
frequency = "2 weeks";
}
{
name = "archives";
frequency = "4 weeks";
}
{
name = "data";
frequency = "6 weeks";
}
{
name = "extract";
frequency = "6 weeks";
}
];
'';
};
extraConfig = extraConfigOption;
};
extraConfig = extraConfigOption;
output = {
extraConfig = extraConfigOption;
};
hooks = {
extraConfig = extraConfigOption;
};
};
}
);
storage = {
encryptionPasscommand = mkNullableOption {
type = types.str;
description = "Command writing the passphrase to standard output.";
example =
literalExpression ''"''${pkgs.password-store}/bin/pass borg-repo"'';
};
extraConfig = extraConfigOption;
};
retention = {
keepWithin = mkNullableOption {
type = types.strMatching "[[:digit:]]+[Hdwmy]";
description = "Keep all archives within this time interval.";
example = "2d";
};
keepSecondly = mkRetentionOption "secondly";
keepMinutely = mkRetentionOption "minutely";
keepHourly = mkRetentionOption "hourly";
keepDaily = mkRetentionOption "daily";
keepWeekly = mkRetentionOption "weekly";
keepMonthly = mkRetentionOption "monthly";
keepYearly = mkRetentionOption "yearly";
extraConfig = extraConfigOption;
};
consistency = {
checks = mkOption {
type = types.listOf consistencyCheckModule;
default = [ ];
description = "Consistency checks to run";
example = literalExpression ''
[
{
name = "repository";
frequency = "2 weeks";
}
{
name = "archives";
frequency = "4 weeks";
}
{
name = "data";
frequency = "6 weeks";
}
{
name = "extract";
frequency = "6 weeks";
}
];
'';
};
extraConfig = extraConfigOption;
};
output = { extraConfig = extraConfigOption; };
hooks = { extraConfig = extraConfigOption; };
};
});
removeNullValues = attrSet:
lib.filterAttrs (key: value: value != null) attrSet;
removeNullValues = attrSet: lib.filterAttrs (key: value: value != null) attrSet;
hmFiles = builtins.attrValues config.home.file;
hmSymlinks = (lib.filter (file: !file.recursive) hmFiles);
@ -218,25 +242,35 @@ let
hmExcludePatterns = lib.concatMapStrings hmExcludePattern hmSymlinks;
hmExcludeFile = pkgs.writeText "hm-symlinks.txt" hmExcludePatterns;
writeConfig = config:
lib.generators.toYAML { } (removeNullValues ({
source_directories = config.location.sourceDirectories;
patterns = config.location.patterns;
repositories = config.location.repositories;
encryption_passcommand = config.storage.encryptionPasscommand;
keep_within = config.retention.keepWithin;
keep_secondly = config.retention.keepSecondly;
keep_minutely = config.retention.keepMinutely;
keep_hourly = config.retention.keepHourly;
keep_daily = config.retention.keepDaily;
keep_weekly = config.retention.keepWeekly;
keep_monthly = config.retention.keepMonthly;
keep_yearly = config.retention.keepYearly;
checks = config.consistency.checks;
} // config.location.extraConfig // config.storage.extraConfig
// config.retention.extraConfig // config.consistency.extraConfig
// config.output.extraConfig // config.hooks.extraConfig));
in {
writeConfig =
config:
lib.generators.toYAML { } (
removeNullValues (
{
source_directories = config.location.sourceDirectories;
patterns = config.location.patterns;
repositories = config.location.repositories;
encryption_passcommand = config.storage.encryptionPasscommand;
keep_within = config.retention.keepWithin;
keep_secondly = config.retention.keepSecondly;
keep_minutely = config.retention.keepMinutely;
keep_hourly = config.retention.keepHourly;
keep_daily = config.retention.keepDaily;
keep_weekly = config.retention.keepWeekly;
keep_monthly = config.retention.keepMonthly;
keep_yearly = config.retention.keepYearly;
checks = config.consistency.checks;
}
// config.location.extraConfig
// config.storage.extraConfig
// config.retention.extraConfig
// config.consistency.extraConfig
// config.output.extraConfig
// config.hooks.extraConfig
)
);
in
{
meta.maintainers = [ lib.maintainers.DamienCassou ];
options = {
@ -272,25 +306,28 @@ in {
};
config = lib.mkIf cfg.enable {
assertions = (lib.mapAttrsToList (backup: opts: {
assertion = opts.location.sourceDirectories == null
|| opts.location.patterns == null;
message = ''
Borgmatic backup configuration "${backup}" cannot specify both 'location.sourceDirectories' and 'location.patterns'.
'';
}) cfg.backups) ++ (lib.mapAttrsToList (backup: opts: {
assertion = !(opts.location.sourceDirectories == null
&& opts.location.patterns == null);
message = ''
Borgmatic backup configuration "${backup}" must specify one of 'location.sourceDirectories' or 'location.patterns'.
'';
}) cfg.backups);
assertions =
(lib.mapAttrsToList (backup: opts: {
assertion = opts.location.sourceDirectories == null || opts.location.patterns == null;
message = ''
Borgmatic backup configuration "${backup}" cannot specify both 'location.sourceDirectories' and 'location.patterns'.
'';
}) cfg.backups)
++ (lib.mapAttrsToList (backup: opts: {
assertion = !(opts.location.sourceDirectories == null && opts.location.patterns == null);
message = ''
Borgmatic backup configuration "${backup}" must specify one of 'location.sourceDirectories' or 'location.patterns'.
'';
}) cfg.backups);
xdg.configFile = with lib.attrsets;
mapAttrs' (configName: config:
xdg.configFile =
with lib.attrsets;
mapAttrs' (
configName: config:
nameValuePair ("borgmatic.d/" + configName + ".yaml") {
text = writeConfig config;
}) cfg.backups;
}
) cfg.backups;
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
};

View file

@ -1,11 +1,17 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.bottom;
tomlFormat = pkgs.formats.toml { };
in {
in
{
options = {
programs.bottom = {
enable = lib.mkEnableOption ''

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) literalExpression mkOption types;
@ -37,7 +42,10 @@ let
};
mode = mkOption {
type = types.enum [ "file" "directory" ];
type = types.enum [
"file"
"directory"
];
default = "directory";
description = ''
Does the current path redirect a file or a directory?
@ -81,7 +89,8 @@ let
};
};
};
in {
in
{
options.programs.boxxy = {
enable = lib.mkEnableOption "boxxy: Boxes in badly behaving applications";
@ -96,13 +105,11 @@ in {
config = lib.mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "programs.boxxy" pkgs
lib.platforms.linux)
(lib.hm.assertions.assertPlatform "programs.boxxy" pkgs lib.platforms.linux)
];
home.file = lib.mkIf (cfg.rules != [ ]) {
"${configPath}".source =
settingsFormat.generate "boxxy-config.yaml" { rules = cfg.rules; };
"${configPath}".source = settingsFormat.generate "boxxy-config.yaml" { rules = cfg.rules; };
};
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
@ -110,4 +117,3 @@ in {
meta.maintainers = with lib.hm.maintainers; [ nikp123 ];
}

View file

@ -1,6 +1,17 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) literalExpression mkIf mkOption mkRenamedOptionModule types;
inherit (lib)
literalExpression
mkIf
mkOption
mkRenamedOptionModule
types
;
cfg = config.programs.broot;
@ -13,7 +24,15 @@ let
modal = lib.mkEnableOption "modal (vim) mode";
verbs = mkOption {
type = with types; listOf (attrsOf (oneOf [ bool str (listOf str) ]));
type =
with types;
listOf (
attrsOf (oneOf [
bool
str
(listOf str)
])
);
default = [ ];
example = literalExpression ''
[
@ -116,53 +135,64 @@ let
};
};
shellInit = shell:
shellInit =
shell:
# Using mkAfter to make it more likely to appear after other
# manipulations of the prompt.
lib.mkAfter ''
source ${
pkgs.runCommand "br.${shell}" { nativeBuildInputs = [ cfg.package ]; }
"broot --print-shell-function ${shell} > $out"
pkgs.runCommand "br.${shell}" {
nativeBuildInputs = [ cfg.package ];
} "broot --print-shell-function ${shell} > $out"
}
'';
in {
meta.maintainers = [ lib.hm.maintainers.aheaume lib.maintainers.dermetfan ];
in
{
meta.maintainers = [
lib.hm.maintainers.aheaume
lib.maintainers.dermetfan
];
imports = [
(mkRenamedOptionModule [ "programs" "broot" "modal" ] [
"programs"
"broot"
"settings"
"modal"
])
(mkRenamedOptionModule [ "programs" "broot" "verbs" ] [
"programs"
"broot"
"settings"
"verbs"
])
(mkRenamedOptionModule [ "programs" "broot" "skin" ] [
"programs"
"broot"
"settings"
"skin"
])
(mkRenamedOptionModule
[ "programs" "broot" "modal" ]
[
"programs"
"broot"
"settings"
"modal"
]
)
(mkRenamedOptionModule
[ "programs" "broot" "verbs" ]
[
"programs"
"broot"
"settings"
"verbs"
]
)
(mkRenamedOptionModule
[ "programs" "broot" "skin" ]
[
"programs"
"broot"
"settings"
"skin"
]
)
];
options.programs.broot = {
enable = lib.mkEnableOption "Broot, a better way to navigate directories";
enableBashIntegration =
lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableBashIntegration = lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableFishIntegration =
lib.hm.shell.mkFishIntegrationOption { inherit config; };
enableFishIntegration = lib.hm.shell.mkFishIntegrationOption { inherit config; };
enableNushellIntegration =
lib.hm.shell.mkNushellIntegrationOption { inherit config; };
enableNushellIntegration = lib.hm.shell.mkNushellIntegrationOption { inherit config; };
enableZshIntegration =
lib.hm.shell.mkZshIntegrationOption { inherit config; };
enableZshIntegration = lib.hm.shell.mkZshIntegrationOption { inherit config; };
package = lib.mkPackageOption pkgs "broot" { };
@ -190,9 +220,7 @@ in {
postBuild = ''
rm $out/conf.hjson
${lib.getExe pkgs.jq} --slurp add > $out/conf.hjson \
<(${
lib.getExe pkgs.hjson-go
} -c ${cfg.package.src}/resources/default-conf/conf.hjson) \
<(${lib.getExe pkgs.hjson-go} -c ${cfg.package.src}/resources/default-conf/conf.hjson) \
${jsonFormat.generate "broot-config.json" cfg.settings}
'';
};
@ -205,8 +233,7 @@ in {
fish.shellInit = mkIf cfg.enableFishIntegration (shellInit "fish");
nushell.extraConfig =
mkIf cfg.enableNushellIntegration (shellInit "nushell");
nushell.extraConfig = mkIf cfg.enableNushellIntegration (shellInit "nushell");
};
};
}

View file

@ -1,8 +1,21 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.browserpass;
browsers = [ "brave" "chrome" "chromium" "firefox" "librewolf" "vivaldi" ];
in {
browsers = [
"brave"
"chrome"
"chromium"
"firefox"
"librewolf"
"vivaldi"
];
in
{
options = {
programs.browserpass = {
enable = lib.mkEnableOption "the browserpass extension host application";
@ -17,82 +30,108 @@ in {
};
config = lib.mkIf cfg.enable {
home.file = lib.foldl' (a: b: a // b) { } (lib.concatMap (x:
with pkgs.stdenv;
if x == "brave" then
let
dir = if isDarwin then
"Library/Application Support/BraveSoftware/Brave-Browser/NativeMessagingHosts"
else
".config/BraveSoftware/Brave-Browser/NativeMessagingHosts";
in [{
# Policies are read from `/etc/brave/policies` only
# https://github.com/brave/brave-browser/issues/19052
"${dir}/com.github.browserpass.native.json".source =
"${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json";
}]
else if x == "chrome" then
let
dir = if isDarwin then
"Library/Application Support/Google/Chrome/NativeMessagingHosts"
else
".config/google-chrome/NativeMessagingHosts";
in [{
"${dir}/com.github.browserpass.native.json".source =
"${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json";
"${dir}/../policies/managed/com.github.browserpass.native.json".source =
"${pkgs.browserpass}/lib/browserpass/policies/chromium/com.github.browserpass.native.json";
}]
else if x == "chromium" then
let
dir = if isDarwin then
"Library/Application Support/Chromium/NativeMessagingHosts"
else
".config/chromium/NativeMessagingHosts";
in [
{
"${dir}/com.github.browserpass.native.json".source =
"${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json";
}
{
"${dir}/../policies/managed/com.github.browserpass.native.json".source =
"${pkgs.browserpass}/lib/browserpass/policies/chromium/com.github.browserpass.native.json";
}
]
else if x == "firefox" then
let
dir = if isDarwin then
"Library/Application Support/Mozilla/NativeMessagingHosts"
else
".mozilla/native-messaging-hosts";
in [{
"${dir}/com.github.browserpass.native.json".source =
"${pkgs.browserpass}/lib/browserpass/hosts/firefox/com.github.browserpass.native.json";
}]
else if x == "librewolf" then
let
dir = if isDarwin then
"Library/Application Support/LibreWolf/NativeMessagingHosts"
else
".librewolf/native-messaging-hosts";
in [{
"${dir}/com.github.browserpass.native.json".source =
"${pkgs.browserpass}/lib/browserpass/hosts/firefox/com.github.browserpass.native.json";
}]
home.file = lib.foldl' (a: b: a // b) { } (
lib.concatMap (
x:
with pkgs.stdenv;
if x == "brave" then
let
dir =
if isDarwin then
"Library/Application Support/BraveSoftware/Brave-Browser/NativeMessagingHosts"
else
".config/BraveSoftware/Brave-Browser/NativeMessagingHosts";
in
[
{
# Policies are read from `/etc/brave/policies` only
# https://github.com/brave/brave-browser/issues/19052
"${dir}/com.github.browserpass.native.json".source =
"${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json";
}
]
else if x == "chrome" then
let
dir =
if isDarwin then
"Library/Application Support/Google/Chrome/NativeMessagingHosts"
else
".config/google-chrome/NativeMessagingHosts";
in
[
{
"${dir}/com.github.browserpass.native.json".source =
"${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json";
"${dir}/../policies/managed/com.github.browserpass.native.json".source =
"${pkgs.browserpass}/lib/browserpass/policies/chromium/com.github.browserpass.native.json";
}
]
else if x == "chromium" then
let
dir =
if isDarwin then
"Library/Application Support/Chromium/NativeMessagingHosts"
else
".config/chromium/NativeMessagingHosts";
in
[
{
"${dir}/com.github.browserpass.native.json".source =
"${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json";
}
{
"${dir}/../policies/managed/com.github.browserpass.native.json".source =
"${pkgs.browserpass}/lib/browserpass/policies/chromium/com.github.browserpass.native.json";
}
]
else if x == "firefox" then
let
dir =
if isDarwin then
"Library/Application Support/Mozilla/NativeMessagingHosts"
else
".mozilla/native-messaging-hosts";
in
[
{
"${dir}/com.github.browserpass.native.json".source =
"${pkgs.browserpass}/lib/browserpass/hosts/firefox/com.github.browserpass.native.json";
}
]
else if x == "librewolf" then
let
dir =
if isDarwin then
"Library/Application Support/LibreWolf/NativeMessagingHosts"
else
".librewolf/native-messaging-hosts";
in
[
{
"${dir}/com.github.browserpass.native.json".source =
"${pkgs.browserpass}/lib/browserpass/hosts/firefox/com.github.browserpass.native.json";
}
]
else if x == "vivaldi" then
let
dir = if isDarwin then
"Library/Application Support/Vivaldi/NativeMessagingHosts"
else
".config/vivaldi/NativeMessagingHosts";
in [{
"${dir}/com.github.browserpass.native.json".source =
"${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json";
"${dir}/../policies/managed/com.github.browserpass.native.json".source =
"${pkgs.browserpass}/lib/browserpass/policies/chromium/com.github.browserpass.native.json";
}]
else
throw "unknown browser ${x}") cfg.browsers);
else if x == "vivaldi" then
let
dir =
if isDarwin then
"Library/Application Support/Vivaldi/NativeMessagingHosts"
else
".config/vivaldi/NativeMessagingHosts";
in
[
{
"${dir}/com.github.browserpass.native.json".source =
"${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json";
"${dir}/../policies/managed/com.github.browserpass.native.json".source =
"${pkgs.browserpass}/lib/browserpass/policies/chromium/com.github.browserpass.native.json";
}
]
else
throw "unknown browser ${x}"
) cfg.browsers
);
};
}

View file

@ -1,26 +1,38 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.btop;
finalConfig = let
toKeyValue = lib.generators.toKeyValue {
mkKeyValue = lib.generators.mkKeyValueDefault {
mkValueString = v:
with builtins;
if isBool v then
(if v then "True" else "False")
else if isString v then
''"${v}"''
else
toString v;
} " = ";
};
in ''
${toKeyValue cfg.settings}
${lib.optionalString (cfg.extraConfig != "") cfg.extraConfig}
'';
in {
meta.maintainers = with lib.maintainers; [ GaetanLepage khaneliman ];
finalConfig =
let
toKeyValue = lib.generators.toKeyValue {
mkKeyValue = lib.generators.mkKeyValueDefault {
mkValueString =
v:
with builtins;
if isBool v then
(if v then "True" else "False")
else if isString v then
''"${v}"''
else
toString v;
} " = ";
};
in
''
${toKeyValue cfg.settings}
${lib.optionalString (cfg.extraConfig != "") cfg.extraConfig}
'';
in
{
meta.maintainers = with lib.maintainers; [
GaetanLepage
khaneliman
];
options.programs.btop = {
enable = lib.mkEnableOption "btop";
@ -28,7 +40,14 @@ in {
package = lib.mkPackageOption pkgs "btop" { nullable = true; };
settings = lib.mkOption {
type = with lib.types; attrsOf (oneOf [ bool float int str ]);
type =
with lib.types;
attrsOf (oneOf [
bool
float
int
str
]);
default = { };
example = {
color_theme = "Default";
@ -105,18 +124,24 @@ in {
config = lib.mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
xdg.configFile = let
mkThemeConfig = name: theme: {
name = "btop/themes/${name}.theme";
value = {
source = (if builtins.isPath theme || lib.isStorePath theme then
theme
else
pkgs.writeText "btop-theme.theme" theme);
xdg.configFile =
let
mkThemeConfig = name: theme: {
name = "btop/themes/${name}.theme";
value = {
source = (
if builtins.isPath theme || lib.isStorePath theme then
theme
else
pkgs.writeText "btop-theme.theme" theme
);
};
};
};
in {
"btop/btop.conf" = lib.mkIf (cfg.settings != { }) { text = finalConfig; };
} // lib.mapAttrs' mkThemeConfig cfg.themes;
in
{
"btop/btop.conf" = lib.mkIf (cfg.settings != { }) { text = finalConfig; };
}
// lib.mapAttrs' mkThemeConfig cfg.themes;
};
}

View file

@ -1,9 +1,15 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.bun;
tomlFormat = pkgs.formats.toml { };
in {
in
{
meta.maintainers = [ lib.hm.maintainers.jack5079 ];
options.programs.bun = {
@ -55,13 +61,12 @@ in {
};
# https://bun.sh/docs/install/lockfile#how-do-i-git-diff-bun-s-lockfile
programs.git.attributes =
lib.mkIf (cfg.enableGitIntegration && (cfg.package != null))
[ "*.lockb binary diff=lockb" ];
programs.git.extraConfig.diff.lockb =
lib.mkIf (cfg.enableGitIntegration && (cfg.package != null)) {
textconv = lib.getExe cfg.package;
binary = true;
};
programs.git.attributes = lib.mkIf (cfg.enableGitIntegration && (cfg.package != null)) [
"*.lockb binary diff=lockb"
];
programs.git.extraConfig.diff.lockb = lib.mkIf (cfg.enableGitIntegration && (cfg.package != null)) {
textconv = lib.getExe cfg.package;
binary = true;
};
};
}

View file

@ -1,28 +1,32 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
let
cfg = config.programs.carapace;
bin = lib.getExe cfg.package;
in {
meta.maintainers = with lib.maintainers; [ weathercold bobvanderlinden ];
in
{
meta.maintainers = with lib.maintainers; [
weathercold
bobvanderlinden
];
options.programs.carapace = {
enable = lib.mkEnableOption
"carapace, a multi-shell multi-command argument completer";
enable = lib.mkEnableOption "carapace, a multi-shell multi-command argument completer";
package = lib.mkPackageOption pkgs "carapace" { };
enableBashIntegration =
lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableBashIntegration = lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableFishIntegration =
lib.hm.shell.mkFishIntegrationOption { inherit config; };
enableFishIntegration = lib.hm.shell.mkFishIntegrationOption { inherit config; };
enableNushellIntegration =
lib.hm.shell.mkNushellIntegrationOption { inherit config; };
enableNushellIntegration = lib.hm.shell.mkNushellIntegrationOption { inherit config; };
enableZshIntegration =
lib.hm.shell.mkZshIntegrationOption { inherit config; };
enableZshIntegration = lib.hm.shell.mkZshIntegrationOption { inherit config; };
};
config = lib.mkIf cfg.enable {
@ -52,41 +56,52 @@ in {
};
};
xdg.configFile = lib.mkIf (config.programs.fish.enable
&& cfg.enableFishIntegration
&& lib.versionOlder config.programs.fish.package.version "4.0.0") (
# Convert the entries from `carapace --list` to empty
# xdg.configFile."fish/completions/NAME.fish" entries.
#
# This is to disable fish builtin completion for each of the
# carapace-supported completions.
#
# This is necessary for carapace to properly work with fish version < 4.0b1.
#
# It is in line with the instructions from
# carapace-bin:
#
# carapace --list | awk '{print $1}' | xargs -I{} touch ~/.config/fish/completions/{}.fish
#
# See https://carapace-sh.github.io/carapace-bin/setup.html#fish
let
carapaceListFile = pkgs.runCommandLocal "carapace-list" {
buildInputs = [ cfg.package ];
} ''
${bin} --list > $out
'';
in lib.pipe carapaceListFile [
lib.fileContents
(lib.splitString "\n")
(map (builtins.match "^([a-z0-9-]+) .*"))
(builtins.filter
(match: match != null && (builtins.length match) > 0))
(map (match: builtins.head match))
(map (name: {
name = "fish/completions/${name}.fish";
value = { text = ""; };
}))
builtins.listToAttrs
]);
xdg.configFile =
lib.mkIf
(
config.programs.fish.enable
&& cfg.enableFishIntegration
&& lib.versionOlder config.programs.fish.package.version "4.0.0"
)
(
# Convert the entries from `carapace --list` to empty
# xdg.configFile."fish/completions/NAME.fish" entries.
#
# This is to disable fish builtin completion for each of the
# carapace-supported completions.
#
# This is necessary for carapace to properly work with fish version < 4.0b1.
#
# It is in line with the instructions from
# carapace-bin:
#
# carapace --list | awk '{print $1}' | xargs -I{} touch ~/.config/fish/completions/{}.fish
#
# See https://carapace-sh.github.io/carapace-bin/setup.html#fish
let
carapaceListFile =
pkgs.runCommandLocal "carapace-list"
{
buildInputs = [ cfg.package ];
}
''
${bin} --list > $out
'';
in
lib.pipe carapaceListFile [
lib.fileContents
(lib.splitString "\n")
(map (builtins.match "^([a-z0-9-]+) .*"))
(builtins.filter (match: match != null && (builtins.length match) > 0))
(map (match: builtins.head match))
(map (name: {
name = "fish/completions/${name}.fish";
value = {
text = "";
};
}))
builtins.listToAttrs
]
);
};
}

View file

@ -1,9 +1,15 @@
{ pkgs, config, lib, ... }:
{
pkgs,
config,
lib,
...
}:
let
cfg = config.programs.cava;
iniFmt = pkgs.formats.ini { };
in {
in
{
meta.maintainers = [ lib.maintainers.bddvlpr ];
options.programs.cava = {

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }:
{
pkgs,
config,
lib,
...
}:
let
inherit (lib) mkIf mkOption;
@ -8,7 +13,8 @@ let
jsonFmt = pkgs.formats.json { };
in {
in
{
meta.maintainers = [ lib.hm.maintainers.bricked ];
options.programs.cavalier = {
@ -75,8 +81,7 @@ in {
config = mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "programs.cavalier" pkgs
lib.platforms.linux)
(lib.hm.assertions.assertPlatform "programs.cavalier" pkgs lib.platforms.linux)
];
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) literalExpression mkOption types;
@ -11,11 +16,13 @@ let
"vivaldi"
];
browserModule = defaultPkg: name: visible:
browserModule =
defaultPkg: name: visible:
let
browser = (builtins.parseDrvName defaultPkg.name).name;
isProprietaryChrome = lib.hasPrefix "Google Chrome" name;
in {
in
{
enable = mkOption {
inherit visible;
type = types.bool;
@ -36,7 +43,10 @@ let
inherit visible;
type = types.listOf types.str;
default = [ ];
example = [ "--enable-logging=stderr" "--ignore-gpu-blocklist" ];
example = [
"--enable-logging=stderr"
"--ignore-gpu-blocklist"
];
description = ''
List of command-line arguments to be passed to ${name}.
@ -47,12 +57,14 @@ let
[Chromium codesearch](https://source.chromium.org/search?q=file:switches.cc&ss=chromium%2Fchromium%2Fsrc).
'';
};
} // lib.optionalAttrs (!isProprietaryChrome) {
}
// lib.optionalAttrs (!isProprietaryChrome) {
# Extensions do not work with Google Chrome
# see https://github.com/nix-community/home-manager/issues/1383
extensions = mkOption {
inherit visible;
type = with types;
type =
with types;
let
extensionType = submodule {
options = {
@ -93,7 +105,8 @@ let
};
};
};
in listOf (coercedTo str (v: { id = v; }) extensionType);
in
listOf (coercedTo str (v: { id = v; }) extensionType);
default = [ ];
example = literalExpression ''
[
@ -149,7 +162,8 @@ let
};
};
browserConfig = cfg:
browserConfig =
cfg:
let
drvName = (builtins.parseDrvName cfg.package.name).name;
@ -164,23 +178,33 @@ let
brave = "BraveSoftware/Brave-Browser";
};
linuxDirs = { brave = "BraveSoftware/Brave-Browser"; };
linuxDirs = {
brave = "BraveSoftware/Brave-Browser";
};
configDir = if pkgs.stdenv.isDarwin then
"Library/Application Support/" + (darwinDirs."${browser}" or browser)
else
"${config.xdg.configHome}/" + (linuxDirs."${browser}" or browser);
configDir =
if pkgs.stdenv.isDarwin then
"Library/Application Support/" + (darwinDirs."${browser}" or browser)
else
"${config.xdg.configHome}/" + (linuxDirs."${browser}" or browser);
extensionJson = ext:
extensionJson =
ext:
assert ext.crxPath != null -> ext.version != null;
with builtins; {
with builtins;
{
name = "${configDir}/External Extensions/${ext.id}.json";
value.text = toJSON (if ext.crxPath != null then {
external_crx = ext.crxPath;
external_version = ext.version;
} else {
external_update_url = ext.updateUrl;
});
value.text = toJSON (
if ext.crxPath != null then
{
external_crx = ext.crxPath;
external_version = ext.version;
}
else
{
external_update_url = ext.updateUrl;
}
);
};
dictionary = pkg: {
@ -193,48 +217,61 @@ let
paths = cfg.nativeMessagingHosts;
};
package = if cfg.commandLineArgs != [ ] then
cfg.package.override {
commandLineArgs = lib.concatStringsSep " " cfg.commandLineArgs;
}
else
cfg.package;
package =
if cfg.commandLineArgs != [ ] then
cfg.package.override {
commandLineArgs = lib.concatStringsSep " " cfg.commandLineArgs;
}
else
cfg.package;
in lib.mkIf cfg.enable {
in
lib.mkIf cfg.enable {
home.packages = [ package ];
home.file = lib.optionalAttrs (!isProprietaryChrome) (lib.listToAttrs
((map extensionJson cfg.extensions)
++ (map dictionary cfg.dictionaries)) // {
"${configDir}/NativeMessagingHosts" =
lib.mkIf (cfg.nativeMessagingHosts != [ ]) {
source =
"${nativeMessagingHostsJoined}/etc/chromium/native-messaging-hosts";
recursive = true;
};
});
home.file = lib.optionalAttrs (!isProprietaryChrome) (
lib.listToAttrs ((map extensionJson cfg.extensions) ++ (map dictionary cfg.dictionaries))
// {
"${configDir}/NativeMessagingHosts" = lib.mkIf (cfg.nativeMessagingHosts != [ ]) {
source = "${nativeMessagingHostsJoined}/etc/chromium/native-messaging-hosts";
recursive = true;
};
}
);
};
in {
in
{
# Extensions do not work with the proprietary Google Chrome version
# see https://github.com/nix-community/home-manager/issues/1383
imports = map (lib.flip lib.mkRemovedOptionModule
"The `extensions` option does not work on Google Chrome anymore.") [
[ "programs" "google-chrome" "extensions" ]
[ "programs" "google-chrome-beta" "extensions" ]
[ "programs" "google-chrome-dev" "extensions" ]
];
imports =
map
(lib.flip lib.mkRemovedOptionModule "The `extensions` option does not work on Google Chrome anymore.")
[
[
"programs"
"google-chrome"
"extensions"
]
[
"programs"
"google-chrome-beta"
"extensions"
]
[
"programs"
"google-chrome-dev"
"extensions"
]
];
options.programs = {
chromium = browserModule pkgs.chromium "Chromium" true;
google-chrome = browserModule pkgs.google-chrome "Google Chrome" false;
google-chrome-beta =
browserModule pkgs.google-chrome-beta "Google Chrome Beta" false;
google-chrome-dev =
browserModule pkgs.google-chrome-dev "Google Chrome Dev" false;
google-chrome-beta = browserModule pkgs.google-chrome-beta "Google Chrome Beta" false;
google-chrome-dev = browserModule pkgs.google-chrome-dev "Google Chrome Dev" false;
brave = browserModule pkgs.brave "Brave Browser" false;
vivaldi = browserModule pkgs.vivaldi "Vivaldi Browser" false;
};
config = lib.mkMerge
(map (browser: browserConfig config.programs.${browser}) supportedBrowsers);
config = lib.mkMerge (map (browser: browserConfig config.programs.${browser}) supportedBrowsers);
}

View file

@ -1,6 +1,13 @@
{ config, lib, pkgs, ... }:
let cfg = config.programs.cmus;
in {
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.cmus;
in
{
meta.maintainers = [ lib.hm.maintainers.joygnu ];
options.programs.cmus = {

View file

@ -1,6 +1,11 @@
# Adapted from Nixpkgs.
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.command-not-found;
commandNotFound = pkgs.substituteAll {
@ -9,7 +14,10 @@ let
src = ./command-not-found.pl;
isExecutable = true;
inherit (cfg) dbPath;
perl = pkgs.perl.withPackages (p: [ p.DBDSQLite p.StringShellQuote ]);
perl = pkgs.perl.withPackages (p: [
p.DBDSQLite
p.StringShellQuote
]);
};
shInit = commandNotFoundHandlerName: ''
@ -26,13 +34,13 @@ let
}
'';
in {
in
{
options.programs.command-not-found = {
enable = lib.mkEnableOption "command-not-found hook for interactive shell";
dbPath = lib.mkOption {
default =
"/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite";
default = "/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite";
description = ''
Absolute path to {file}`programs.sqlite`. By
default this file will be provided by your channel

View file

@ -1,10 +1,16 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.comodoro;
tomlFormat = pkgs.formats.toml { };
in {
in
{
meta.maintainers = with lib.hm.maintainers; [ soywod ];
options.programs.comodoro = {

View file

@ -1,6 +1,13 @@
{ config, lib, pkgs, ... }:
let cfg = config.programs.darcs;
in {
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.darcs;
in
{
meta.maintainers = with lib.maintainers; [ chris-martin ];
options = {
@ -23,24 +30,28 @@ in {
boring = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "^.idea$" ".iml$" "^.stack-work$" ];
example = [
"^.idea$"
".iml$"
"^.stack-work$"
];
description = "File patterns to ignore";
};
};
};
config = lib.mkIf cfg.enable (lib.mkMerge [
{ home.packages = lib.mkIf (cfg.package != null) [ cfg.package ]; }
config = lib.mkIf cfg.enable (
lib.mkMerge [
{ home.packages = lib.mkIf (cfg.package != null) [ cfg.package ]; }
(lib.mkIf (cfg.author != [ ]) {
home.file.".darcs/author".text =
lib.concatMapStrings (x: x + "\n") cfg.author;
})
(lib.mkIf (cfg.author != [ ]) {
home.file.".darcs/author".text = lib.concatMapStrings (x: x + "\n") cfg.author;
})
(lib.mkIf (cfg.boring != [ ]) {
home.file.".darcs/boring".text =
lib.concatMapStrings (x: x + "\n") cfg.boring;
})
(lib.mkIf (cfg.boring != [ ]) {
home.file.".darcs/boring".text = lib.concatMapStrings (x: x + "\n") cfg.boring;
})
]);
]
);
}

View file

@ -1,10 +1,21 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkDefault mkIf mkOption types;
inherit (lib)
mkDefault
mkIf
mkOption
types
;
cfg = config.programs.dircolors;
formatLine = n: v: "${n} ${toString v}";
in {
in
{
meta.maintainers = [ lib.hm.maintainers.justinlovinger ];
options.programs.dircolors = {
@ -19,14 +30,11 @@ in {
package = lib.mkPackageOption pkgs "dircolors" { default = "coreutils"; };
enableBashIntegration =
lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableBashIntegration = lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableFishIntegration =
lib.hm.shell.mkFishIntegrationOption { inherit config; };
enableFishIntegration = lib.hm.shell.mkFishIntegrationOption { inherit config; };
enableZshIntegration =
lib.hm.shell.mkZshIntegrationOption { inherit config; };
enableZshIntegration = lib.hm.shell.mkZshIntegrationOption { inherit config; };
settings = mkOption {
type = with types; attrsOf str;
@ -54,169 +62,175 @@ in {
};
};
config = let
dircolorsPath = if config.home.preferXdgDirectories then
"${config.xdg.configHome}/dir_colors"
else
"~/.dir_colors";
config =
let
dircolorsPath =
if config.home.preferXdgDirectories then "${config.xdg.configHome}/dir_colors" else "~/.dir_colors";
dircolorsConfig = lib.concatStringsSep "\n" ([ ]
++ lib.mapAttrsToList formatLine cfg.settings ++ [ "" ]
++ lib.optional (cfg.extraConfig != "") cfg.extraConfig);
in mkIf cfg.enable (lib.mkMerge [
{
# 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";
};
dircolorsConfig = lib.concatStringsSep "\n" (
[ ]
++ lib.mapAttrsToList formatLine cfg.settings
++ [ "" ]
++ lib.optional (cfg.extraConfig != "") cfg.extraConfig
);
in
mkIf cfg.enable (
lib.mkMerge [
{
# 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";
};
programs.bash.initExtra = mkIf cfg.enableBashIntegration ''
eval $(${lib.getExe' cfg.package "dircolors"} -b ${dircolorsPath})
'';
programs.bash.initExtra = mkIf cfg.enableBashIntegration ''
eval $(${lib.getExe' cfg.package "dircolors"} -b ${dircolorsPath})
'';
programs.fish.shellInit = mkIf cfg.enableFishIntegration ''
eval (${lib.getExe' cfg.package "dircolors"} -c ${dircolorsPath})
'';
programs.fish.shellInit = mkIf cfg.enableFishIntegration ''
eval (${lib.getExe' cfg.package "dircolors"} -c ${dircolorsPath})
'';
# Set `LS_COLORS` before Oh My Zsh and `initExtra`.
programs.zsh.initContent = mkIf cfg.enableZshIntegration
(lib.mkOrder 550 ''
eval $(${lib.getExe' cfg.package "dircolors"} -b ${dircolorsPath})
'');
}
(mkIf (!config.home.preferXdgDirectories) {
home.file.".dir_colors".text = dircolorsConfig;
})
(mkIf config.home.preferXdgDirectories {
xdg.configFile.dir_colors.text = dircolorsConfig;
})
]);
# Set `LS_COLORS` before Oh My Zsh and `initExtra`.
programs.zsh.initContent = mkIf cfg.enableZshIntegration (
lib.mkOrder 550 ''
eval $(${lib.getExe' cfg.package "dircolors"} -b ${dircolorsPath})
''
);
}
(mkIf (!config.home.preferXdgDirectories) {
home.file.".dir_colors".text = dircolorsConfig;
})
(mkIf config.home.preferXdgDirectories {
xdg.configFile.dir_colors.text = dircolorsConfig;
})
]
);
}

View file

@ -1,25 +1,50 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib)
mkOption mkRenamedOptionModule mkRemovedOptionModule mkEnableOption types
mkPackageOption mkIf mkAfter getExe;
mkOption
mkRenamedOptionModule
mkRemovedOptionModule
mkEnableOption
types
mkPackageOption
mkIf
mkAfter
getExe
;
cfg = config.programs.direnv;
tomlFormat = pkgs.formats.toml { };
in {
in
{
imports = [
(mkRenamedOptionModule [
(mkRenamedOptionModule
[
"programs"
"direnv"
"enableNixDirenvIntegration"
]
[ "programs" "direnv" "nix-direnv" "enable" ]
)
(mkRemovedOptionModule [
"programs"
"direnv"
"enableNixDirenvIntegration"
] [ "programs" "direnv" "nix-direnv" "enable" ])
(mkRemovedOptionModule [ "programs" "direnv" "nix-direnv" "enableFlakes" ]
"Flake support is now always enabled.")
"nix-direnv"
"enableFlakes"
] "Flake support is now always enabled.")
];
meta.maintainers = with lib.maintainers; [ khaneliman rycee shikanime ];
meta.maintainers = with lib.maintainers; [
khaneliman
rycee
shikanime
];
options.programs.direnv = {
enable = mkEnableOption "direnv, the environment switcher";
@ -48,32 +73,31 @@ in {
'';
};
enableBashIntegration =
lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableBashIntegration = lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableFishIntegration = lib.hm.shell.mkFishIntegrationOption {
inherit config;
extraDescription = ''
Note, enabling the direnv module will always activate its functionality
for Fish since the direnv package automatically gets loaded in Fish.
If this is not the case try adding
enableFishIntegration =
lib.hm.shell.mkFishIntegrationOption {
inherit config;
extraDescription = ''
Note, enabling the direnv module will always activate its functionality
for Fish since the direnv package automatically gets loaded in Fish.
If this is not the case try adding
```nix
environment.pathsToLink = [ "/share/fish" ];
```
```nix
environment.pathsToLink = [ "/share/fish" ];
```
to the system configuration.
'';
} // {
default = true;
readOnly = true;
};
to the system configuration.
'';
}
// {
default = true;
readOnly = true;
};
enableNushellIntegration =
lib.hm.shell.mkNushellIntegrationOption { inherit config; };
enableNushellIntegration = lib.hm.shell.mkNushellIntegrationOption { inherit config; };
enableZshIntegration =
lib.hm.shell.mkZshIntegrationOption { inherit config; };
enableZshIntegration = lib.hm.shell.mkZshIntegrationOption { inherit config; };
nix-direnv = {
enable = mkEnableOption ''
@ -105,8 +129,7 @@ in {
source = "${cfg.nix-direnv.package}/share/nix-direnv/direnvrc";
};
xdg.configFile."direnv/direnvrc" =
lib.mkIf (cfg.stdlib != "") { text = cfg.stdlib; };
xdg.configFile."direnv/direnvrc" = lib.mkIf (cfg.stdlib != "") { text = cfg.stdlib; };
xdg.configFile."direnv/lib/hm-mise.sh" = mkIf cfg.mise.enable {
text = ''
@ -119,7 +142,8 @@ in {
# manipulations of the prompt.
mkAfter ''
eval "$(${getExe cfg.package} hook bash)"
'');
''
);
programs.zsh.initContent = mkIf cfg.enableZshIntegration ''
eval "$(${getExe cfg.package} hook zsh)"
@ -130,7 +154,8 @@ in {
# manipulations of the prompt.
mkAfter ''
${getExe cfg.package} hook fish | source
'');
''
);
# Using mkAfter to make it more likely to appear after other
# manipulations of the prompt.

View file

@ -1,12 +1,18 @@
{ config, lib, pkgs, ... }:
let cfg = config.programs.discocss;
in {
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.discocss;
in
{
meta.maintainers = with lib.maintainers; [ kranzes ];
options = {
programs.discocss = {
enable = lib.mkEnableOption
"discocss, a tiny Discord CSS injector for Linux and MacOS";
enable = lib.mkEnableOption "discocss, a tiny Discord CSS injector for Linux and MacOS";
package = lib.mkPackageOption pkgs "discocss" { nullable = true; };
@ -27,13 +33,13 @@ in {
};
config = lib.mkIf cfg.enable {
assertions = [{
assertion = cfg.discordAlias
-> !(lib.any (p: p.name == cfg.discordPackage.name)
config.home.packages);
message =
"To use discocss with discordAlias you have to remove discord from home.packages, or set discordAlias to false.";
}];
assertions = [
{
assertion =
cfg.discordAlias -> !(lib.any (p: p.name == cfg.discordPackage.name) config.home.packages);
message = "To use discocss with discordAlias you have to remove discord from home.packages, or set discordAlias to false.";
}
];
home.packages = lib.mkIf (cfg.package != null) [
(cfg.package.override {

View file

@ -1,11 +1,24 @@
{ lib, pkgs, config, ... }:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) generators types mkIf mkEnableOption mkPackageOption mkOption;
inherit (lib)
generators
types
mkIf
mkEnableOption
mkPackageOption
mkOption
;
cfg = config.programs.distrobox;
formatter = pkgs.formats.ini { listsAsDuplicateKeys = true; };
in {
in
{
meta.maintainers = with lib.hm.maintainers; [ aguirre-matteo ];
options.programs.distrobox = {
@ -57,18 +70,17 @@ in {
config = mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "programs.distrobox" pkgs
lib.platforms.linux)
(lib.hm.assertions.assertPlatform "programs.distrobox" pkgs lib.platforms.linux)
];
home.packages = [ cfg.package ];
xdg.configFile."distrobox/containers.ini".source =
(formatter.generate "containers.ini" cfg.containers);
xdg.configFile."distrobox/containers.ini".source = (
formatter.generate "containers.ini" cfg.containers
);
systemd.user.services.distrobox-home-manager = {
Unit.Description =
"Build the containers declared in ~/.config/distrobox/containers.ini";
Unit.Description = "Build the containers declared in ~/.config/distrobox/containers.ini";
Install.WantedBy = [ "default.target" ];
Service.ExecStart = "${pkgs.writeShellScript "distrobox-home-manager" ''

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
@ -6,7 +11,8 @@ let
yamlFormat = pkgs.formats.yaml { };
in {
in
{
meta.maintainers = [ lib.hm.maintainers.folliehiyuki ];
options.programs.earthly = {

View file

@ -1,9 +1,15 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkIf mkOption types;
cfg = config.programs.eclipse;
in {
in
{
meta.maintainers = [ lib.maintainers.rycee ];
options = {
@ -11,7 +17,10 @@ in {
enable = lib.mkEnableOption "Eclipse";
package = lib.mkPackageOption pkgs "eclipse" {
default = [ "eclipses" "eclipse-platform" ];
default = [
"eclipses"
"eclipse-platform"
];
example = "pkgs.eclipses.eclipse-java";
};
@ -43,8 +52,9 @@ in {
home.packages = [
(pkgs.eclipses.eclipseWithPlugins {
eclipse = cfg.package;
jvmArgs = cfg.jvmArgs ++ lib.optional cfg.enableLombok
"-javaagent:${pkgs.lombok}/share/java/lombok.jar";
jvmArgs =
cfg.jvmArgs
++ lib.optional cfg.enableLombok "-javaagent:${pkgs.lombok}/share/java/lombok.jar";
plugins = cfg.plugins;
})
];

View file

@ -1,17 +1,31 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) literalExpression mkIf mkOption types;
inherit (lib)
literalExpression
mkIf
mkOption
types
;
cfg = config.programs.emacs;
# Copied from all-packages.nix, with modifications to support
# overrides.
emacsPackages = let epkgs = pkgs.emacsPackagesFor cfg.package;
in epkgs.overrideScope cfg.overrides;
emacsPackages =
let
epkgs = pkgs.emacsPackagesFor cfg.package;
in
epkgs.overrideScope cfg.overrides;
emacsWithPackages = emacsPackages.emacsWithPackages;
extraPackages = epkgs:
extraPackages =
epkgs:
let
packages = cfg.extraPackages epkgs;
userConfig = epkgs.trivialBuild {
@ -20,17 +34,18 @@ let
version = "0.1.0";
packageRequires = packages;
};
in packages ++ lib.optional (cfg.extraConfig != "") userConfig;
in
packages ++ lib.optional (cfg.extraConfig != "") userConfig;
in {
in
{
meta.maintainers = [ lib.maintainers.rycee ];
options = {
programs.emacs = {
enable = lib.mkEnableOption "Emacs";
package =
lib.mkPackageOption pkgs "emacs" { example = "pkgs.emacs25-nox"; };
package = lib.mkPackageOption pkgs "emacs" { example = "pkgs.emacs25-nox"; };
# NOTE: The config is placed in default.el instead of ~/.emacs.d so that
# it won't conflict with Emacs configuration frameworks. Users of these

View file

@ -1,9 +1,15 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkIf;
cfg = config.programs.eww;
in {
in
{
meta.maintainers = [ lib.hm.maintainers.mainrs ];
options.programs.eww = {
@ -21,38 +27,37 @@ in {
'';
};
enableBashIntegration =
lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableBashIntegration = lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableFishIntegration =
lib.hm.shell.mkFishIntegrationOption { inherit config; };
enableFishIntegration = lib.hm.shell.mkFishIntegrationOption { inherit config; };
enableZshIntegration =
lib.hm.shell.mkZshIntegrationOption { inherit config; };
enableZshIntegration = lib.hm.shell.mkZshIntegrationOption { inherit config; };
};
config = let ewwCmd = lib.getExe cfg.package;
in mkIf cfg.enable {
home.packages = [ cfg.package ];
xdg =
mkIf (cfg.configDir != null) { configFile."eww".source = cfg.configDir; };
config =
let
ewwCmd = lib.getExe cfg.package;
in
mkIf cfg.enable {
home.packages = [ cfg.package ];
xdg = mkIf (cfg.configDir != null) { configFile."eww".source = cfg.configDir; };
programs.bash.initExtra = mkIf cfg.enableBashIntegration ''
if [[ $TERM != "dumb" ]]; then
eval "$(${ewwCmd} shell-completions --shell bash)"
fi
'';
programs.bash.initExtra = mkIf cfg.enableBashIntegration ''
if [[ $TERM != "dumb" ]]; then
eval "$(${ewwCmd} shell-completions --shell bash)"
fi
'';
programs.zsh.initContent = mkIf cfg.enableZshIntegration ''
if [[ $TERM != "dumb" ]]; then
eval "$(${ewwCmd} shell-completions --shell zsh)"
fi
'';
programs.zsh.initContent = mkIf cfg.enableZshIntegration ''
if [[ $TERM != "dumb" ]]; then
eval "$(${ewwCmd} shell-completions --shell zsh)"
fi
'';
programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration ''
if test "$TERM" != "dumb"
eval "$(${ewwCmd} shell-completions --shell fish)"
end
'';
};
programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration ''
if test "$TERM" != "dumb"
eval "$(${ewwCmd} shell-completions --shell fish)"
end
'';
};
}

View file

@ -1,54 +1,76 @@
{ config, lib, pkgs, ... }:
let inherit (lib) mkOption optionalAttrs types;
in {
imports = let
msg = ''
'programs.eza.enableAliases' has been deprecated and replaced with integration
options per shell, for example, 'programs.eza.enableBashIntegration'.
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkOption optionalAttrs types;
in
{
imports =
let
msg = ''
'programs.eza.enableAliases' has been deprecated and replaced with integration
options per shell, for example, 'programs.eza.enableBashIntegration'.
Note, the default for these options is 'true' so if you want to enable the
aliases you can simply remove 'programs.eza.enableAliases' from your
configuration.'';
mkRenamed = opt:
lib.mkRenamedOptionModule [ "programs" "exa" opt ] [
"programs"
"eza"
opt
];
in (map mkRenamed [ "enable" "extraOptions" "icons" "git" ])
++ [ (lib.mkRemovedOptionModule [ "programs" "eza" "enableAliases" ] msg) ];
Note, the default for these options is 'true' so if you want to enable the
aliases you can simply remove 'programs.eza.enableAliases' from your
configuration.'';
mkRenamed =
opt:
lib.mkRenamedOptionModule
[ "programs" "exa" opt ]
[
"programs"
"eza"
opt
];
in
(map mkRenamed [
"enable"
"extraOptions"
"icons"
"git"
])
++ [ (lib.mkRemovedOptionModule [ "programs" "eza" "enableAliases" ] msg) ];
meta.maintainers = [ lib.maintainers.cafkafk ];
options.programs.eza = {
enable = lib.mkEnableOption "eza, a modern replacement for {command}`ls`";
enableBashIntegration =
lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableBashIntegration = lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableFishIntegration =
lib.hm.shell.mkFishIntegrationOption { inherit config; };
enableFishIntegration = lib.hm.shell.mkFishIntegrationOption { inherit config; };
enableIonIntegration =
lib.hm.shell.mkIonIntegrationOption { inherit config; };
enableIonIntegration = lib.hm.shell.mkIonIntegrationOption { inherit config; };
enableNushellIntegration =
lib.hm.shell.mkNushellIntegrationOption { inherit config; };
enableNushellIntegration = lib.hm.shell.mkNushellIntegrationOption { inherit config; };
enableZshIntegration =
lib.hm.shell.mkZshIntegrationOption { inherit config; };
enableZshIntegration = lib.hm.shell.mkZshIntegrationOption { inherit config; };
extraOptions = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "--group-directories-first" "--header" ];
example = [
"--group-directories-first"
"--header"
];
description = ''
Extra command line options passed to eza.
'';
};
icons = mkOption {
type = types.enum [ null true false "auto" "always" "never" ];
type = types.enum [
null
true
false
"auto"
"always"
"never"
];
default = null;
description = ''
Display icons next to file names ({option}`--icons` argument).
@ -59,7 +81,12 @@ in {
};
colors = mkOption {
type = types.enum [ null "auto" "always" "never" ];
type = types.enum [
null
"auto"
"always"
"never"
];
default = null;
description = ''
Use terminal colors in output ({option}`--color` argument).
@ -77,60 +104,65 @@ in {
package = lib.mkPackageOption pkgs "eza" { nullable = true; };
};
config = let
cfg = config.programs.eza;
config =
let
cfg = config.programs.eza;
iconsOption = let
v = if lib.isBool cfg.icons then
(if cfg.icons then "auto" else null)
else
cfg.icons;
in lib.optionals (v != null) [ "--icons" v ];
iconsOption =
let
v = if lib.isBool cfg.icons then (if cfg.icons then "auto" else null) else cfg.icons;
in
lib.optionals (v != null) [
"--icons"
v
];
args = lib.escapeShellArgs (iconsOption
++ lib.optionals (cfg.colors != null) [ "--color" cfg.colors ]
++ lib.optional cfg.git "--git" ++ cfg.extraOptions);
args = lib.escapeShellArgs (
iconsOption
++ lib.optionals (cfg.colors != null) [
"--color"
cfg.colors
]
++ lib.optional cfg.git "--git"
++ cfg.extraOptions
);
optionsAlias = optionalAttrs (args != "") { eza = "eza ${args}"; };
optionsAlias = optionalAttrs (args != "") { eza = "eza ${args}"; };
aliases = builtins.mapAttrs (_name: value: lib.mkDefault value) {
ls = "eza";
ll = "eza -l";
la = "eza -a";
lt = "eza --tree";
lla = "eza -la";
aliases = builtins.mapAttrs (_name: value: lib.mkDefault value) {
ls = "eza";
ll = "eza -l";
la = "eza -a";
lt = "eza --tree";
lla = "eza -la";
};
in
lib.mkIf cfg.enable {
warnings = lib.optional (lib.isBool cfg.icons) ''
Setting programs.eza.icons to a Boolean is deprecated.
Please update your configuration so that
programs.eza.icons = ${if cfg.icons then ''"auto"'' else "null"}'';
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
programs.bash.shellAliases = optionsAlias // optionalAttrs cfg.enableBashIntegration aliases;
programs.zsh.shellAliases = optionsAlias // optionalAttrs cfg.enableZshIntegration aliases;
programs.fish = lib.mkMerge [
(lib.mkIf (!config.programs.fish.preferAbbrs) {
shellAliases = optionsAlias // optionalAttrs cfg.enableFishIntegration aliases;
})
(lib.mkIf config.programs.fish.preferAbbrs {
shellAliases = optionsAlias;
shellAbbrs = optionalAttrs cfg.enableFishIntegration aliases;
})
];
programs.ion.shellAliases = optionsAlias // optionalAttrs cfg.enableIonIntegration aliases;
programs.nushell.shellAliases = optionsAlias // optionalAttrs cfg.enableNushellIntegration aliases;
};
in lib.mkIf cfg.enable {
warnings = lib.optional (lib.isBool cfg.icons) ''
Setting programs.eza.icons to a Boolean is deprecated.
Please update your configuration so that
programs.eza.icons = ${if cfg.icons then ''"auto"'' else "null"}'';
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
programs.bash.shellAliases = optionsAlias
// optionalAttrs cfg.enableBashIntegration aliases;
programs.zsh.shellAliases = optionsAlias
// optionalAttrs cfg.enableZshIntegration aliases;
programs.fish = lib.mkMerge [
(lib.mkIf (!config.programs.fish.preferAbbrs) {
shellAliases = optionsAlias
// optionalAttrs cfg.enableFishIntegration aliases;
})
(lib.mkIf config.programs.fish.preferAbbrs {
shellAliases = optionsAlias;
shellAbbrs = optionalAttrs cfg.enableFishIntegration aliases;
})
];
programs.ion.shellAliases = optionsAlias
// optionalAttrs cfg.enableIonIntegration aliases;
programs.nushell.shellAliases = optionsAlias
// optionalAttrs cfg.enableNushellIntegration aliases;
};
}

View file

@ -1,14 +1,28 @@
{ pkgs, lib, config, ... }:
{
pkgs,
lib,
config,
...
}:
let
inherit (lib) mkEnableOption mkPackageOption mkOption mkIf literalExpression;
inherit (lib)
mkEnableOption
mkPackageOption
mkOption
mkIf
literalExpression
;
cfg = config.programs.fastfetch;
jsonFormat = pkgs.formats.json { };
in {
meta.maintainers =
[ lib.hm.maintainers.afresquet lib.maintainers.khaneliman ];
in
{
meta.maintainers = [
lib.hm.maintainers.afresquet
lib.maintainers.khaneliman
];
options.programs.fastfetch = {
enable = mkEnableOption "Fastfetch";

View file

@ -1,16 +1,25 @@
{ config, lib, pkgs, ... }:
let inherit (lib) mkOption types;
in {
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkOption types;
in
{
meta.maintainers = [ lib.maintainers.uncenter ];
options.programs.fd = {
enable = lib.mkEnableOption
"fd, a simple, fast and user-friendly alternative to {command}`find`";
enable = lib.mkEnableOption "fd, a simple, fast and user-friendly alternative to {command}`find`";
ignores = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ ".git/" "*.bak" ];
example = [
".git/"
"*.bak"
];
description = "List of paths that should be globally ignored.";
};
@ -25,7 +34,10 @@ in {
extraOptions = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "--no-ignore" "--absolute-path" ];
example = [
"--no-ignore"
"--absolute-path"
];
description = ''
Extra command line options passed to fd.
'';
@ -34,28 +46,29 @@ in {
package = lib.mkPackageOption pkgs "fd" { nullable = true; };
};
config = let
cfg = config.programs.fd;
config =
let
cfg = config.programs.fd;
args = lib.escapeShellArgs
(lib.optional cfg.hidden "--hidden" ++ cfg.extraOptions);
args = lib.escapeShellArgs (lib.optional cfg.hidden "--hidden" ++ cfg.extraOptions);
optionsAlias = lib.optionalAttrs (args != "") { fd = "fd ${args}"; };
in lib.mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
optionsAlias = lib.optionalAttrs (args != "") { fd = "fd ${args}"; };
in
lib.mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
programs.bash.shellAliases = optionsAlias;
programs.bash.shellAliases = optionsAlias;
programs.zsh.shellAliases = optionsAlias;
programs.zsh.shellAliases = optionsAlias;
programs.fish.shellAliases = optionsAlias;
programs.fish.shellAliases = optionsAlias;
programs.ion.shellAliases = optionsAlias;
programs.ion.shellAliases = optionsAlias;
programs.nushell.shellAliases = optionsAlias;
programs.nushell.shellAliases = optionsAlias;
xdg.configFile."fd/ignore" = lib.mkIf (cfg.ignores != [ ]) {
text = lib.concatStringsSep "\n" cfg.ignores + "\n";
xdg.configFile."fd/ignore" = lib.mkIf (cfg.ignores != [ ]) {
text = lib.concatStringsSep "\n" cfg.ignores + "\n";
};
};
};
}

View file

@ -1,25 +1,39 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) filterAttrs mapAttrsToList mkOption types;
inherit (lib)
filterAttrs
mapAttrsToList
mkOption
types
;
cfg = config.programs.feh;
bindingsOf = t: with types; attrsOf (nullOr (either t (listOf t)));
renderThemes = options:
renderThemes =
options:
let
render = mapAttrsToList
(theme: options: "${theme} ${lib.escapeShellArgs options}");
in lib.concatStringsSep "\n" (render options);
render = mapAttrsToList (theme: options: "${theme} ${lib.escapeShellArgs options}");
in
lib.concatStringsSep "\n" (render options);
renderBindings = bindings:
renderBindings =
bindings:
let
enabled = filterAttrs (n: v: v != null) bindings;
disabled = filterAttrs (n: v: v == null) bindings;
render = mapAttrsToList renderBinding;
in lib.concatStringsSep "\n" (render disabled ++ render enabled);
in
lib.concatStringsSep "\n" (render disabled ++ render enabled);
renderBinding = func: key:
renderBinding =
func: key:
if key == null then
func
else if lib.isList key then
@ -27,7 +41,8 @@ let
else
"${func} ${toString key}";
in {
in
{
options.programs.feh = {
enable = lib.mkEnableOption "feh - a fast and light image viewer";
@ -39,7 +54,10 @@ in {
example = {
zoom_in = 4;
zoom_out = "C-4";
prev_img = [ 3 "C-3" ];
prev_img = [
3
"C-3"
];
};
description = ''
Override feh's default mouse button mapping. If you want to disable an
@ -56,7 +74,10 @@ in {
example = {
zoom_in = "plus";
zoom_out = "minus";
prev_img = [ "h" "Left" ];
prev_img = [
"h"
"Left"
];
};
description = ''
Override feh's default keybindings. If you want to disable a keybinding
@ -71,10 +92,27 @@ in {
default = { };
type = with types; attrsOf (listOf str);
example = {
feh = [ "--image-bg" "black" ];
webcam = [ "--multiwindow" "--reload" "20" ];
present = [ "--full-screen" "--sort" "name" "--hide-pointer" ];
booth = [ "--full-screen" "--hide-pointer" "--slideshow-delay" "20" ];
feh = [
"--image-bg"
"black"
];
webcam = [
"--multiwindow"
"--reload"
"20"
];
present = [
"--full-screen"
"--sort"
"name"
"--hide-pointer"
];
booth = [
"--full-screen"
"--hide-pointer"
"--slideshow-delay"
"20"
];
imagemap = [
"-rVq"
"--thumb-width"
@ -84,7 +122,10 @@ in {
"--index-info"
"%n\\n%wx%h"
];
example = [ "--info" "foo bar" ];
example = [
"--info"
"foo bar"
];
};
description = ''
Define themes for feh.
@ -96,11 +137,12 @@ in {
};
config = lib.mkIf cfg.enable {
assertions = [{
assertion = ((filterAttrs (n: v: v == "") cfg.keybindings) == { });
message =
"To disable a keybinding, use `null` instead of an empty string.";
}];
assertions = [
{
assertion = ((filterAttrs (n: v: v == "") cfg.keybindings) == { });
message = "To disable a keybinding, use `null` instead of an empty string.";
}
];
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
@ -112,7 +154,8 @@ in {
text = renderBindings cfg.keybindings + "\n";
};
xdg.configFile."feh/themes" =
lib.mkIf (cfg.themes != { }) { text = renderThemes cfg.themes + "\n"; };
xdg.configFile."feh/themes" = lib.mkIf (cfg.themes != { }) {
text = renderThemes cfg.themes + "\n";
};
};
}

View file

@ -2,12 +2,16 @@
let
inherit (lib) mkRemovedOptionModule;
modulePath = [ "programs" "firefox" ];
modulePath = [
"programs"
"firefox"
];
moduleName = lib.concatStringsSep "." modulePath;
mkFirefoxModule = import ./firefox/mkFirefoxModule.nix;
in {
in
{
meta.maintainers = [
lib.maintainers.rycee
lib.hm.maintainers.bricked
@ -22,7 +26,9 @@ in {
unwrappedPackageName = "firefox-unwrapped";
visible = true;
platforms.linux = { configPath = ".mozilla/firefox"; };
platforms.linux = {
configPath = ".mozilla/firefox";
};
platforms.darwin = {
configPath = "Library/Application Support/Firefox";
};
@ -36,11 +42,14 @@ in {
to
${moduleName}.profiles.myprofile.extensions.packages = [ foo bar ];'')
(mkRemovedOptionModule (modulePath ++ [ "enableAdobeFlash" ])
"Support for this option has been removed.")
(mkRemovedOptionModule (modulePath ++ [ "enableGoogleTalk" ])
"Support for this option has been removed.")
(mkRemovedOptionModule (modulePath ++ [ "enableIcedTea" ])
"Support for this option has been removed.")
(mkRemovedOptionModule (
modulePath ++ [ "enableAdobeFlash" ]
) "Support for this option has been removed.")
(mkRemovedOptionModule (
modulePath ++ [ "enableGoogleTalk" ]
) "Support for this option has been removed.")
(mkRemovedOptionModule (
modulePath ++ [ "enableIcedTea" ]
) "Support for this option has been removed.")
];
}

File diff suppressed because it is too large Load diff

View file

@ -5,71 +5,83 @@ let
inherit (builtins) attrValues;
inherit (lib) types mkOption;
in rec {
settingsType = with types;
in
rec {
settingsType =
with types;
coercedTo (addCheck (attrsOf nodeType)
# Check whether attribute set is of correct type
(attrs: !(attrs ? settings) || nodeType.check attrs.settings)) attrValues
(listOf nodeType);
# Check whether attribute set is of correct type
(attrs: !(attrs ? settings) || nodeType.check attrs.settings)
) attrValues (listOf nodeType);
bookmarkSubmodule = types.submodule ({ name, ... }: {
options = {
name = mkOption {
type = types.str;
default = name;
description = "Bookmark name.";
};
bookmarkSubmodule =
types.submodule (
{ name, ... }:
{
options = {
name = mkOption {
type = types.str;
default = name;
description = "Bookmark name.";
};
tags = mkOption {
type = types.listOf types.str;
default = [ ];
description = "Bookmark tags.";
};
tags = mkOption {
type = types.listOf types.str;
default = [ ];
description = "Bookmark tags.";
};
keyword = mkOption {
type = types.nullOr types.str;
default = null;
description = "Bookmark search keyword.";
};
keyword = mkOption {
type = types.nullOr types.str;
default = null;
description = "Bookmark search keyword.";
};
url = mkOption {
type = types.str;
description = "Bookmark url, use %s for search terms.";
};
url = mkOption {
type = types.str;
description = "Bookmark url, use %s for search terms.";
};
};
}
)
// {
description = "bookmark submodule";
};
}) // {
description = "bookmark submodule";
};
bookmarkType = types.addCheck bookmarkSubmodule (x: x ? "url");
directoryType = types.submodule ({ name, ... }: {
options = {
name = mkOption {
type = types.str;
default = name;
description = "Directory name.";
};
directoryType =
types.submodule (
{ name, ... }:
{
options = {
name = mkOption {
type = types.str;
default = name;
description = "Directory name.";
};
bookmarks = mkOption {
type = types.listOf nodeType;
default = [ ];
description = "Bookmarks within directory.";
};
bookmarks = mkOption {
type = types.listOf nodeType;
default = [ ];
description = "Bookmarks within directory.";
};
toolbar = mkOption {
type = types.bool;
default = false;
description = ''
Make this the toolbar directory. Note, this does _not_
mean that this directory will be added to the toolbar,
this directory _is_ the toolbar.
'';
};
toolbar = mkOption {
type = types.bool;
default = false;
description = ''
Make this the toolbar directory. Note, this does _not_
mean that this directory will be added to the toolbar,
this directory _is_ the toolbar.
'';
};
};
}
)
// {
description = "directory submodule";
};
}) // {
description = "directory submodule";
};
nodeType = types.either bookmarkType directoryType;
}

View file

@ -1,35 +1,43 @@
{ config, lib, pkgs, modulePath }:
{
config,
lib,
pkgs,
modulePath,
}:
let
inherit (lib)
escapeXML concatStringsSep mkOption maintainers types literalExpression;
escapeXML
concatStringsSep
mkOption
maintainers
types
literalExpression
;
inherit (bookmarkTypes) settingsType;
bookmarkTypes = import ./bookmark-types.nix { inherit lib; };
bookmarksFile = bookmarks:
bookmarksFile =
bookmarks:
let
indent = level:
lib.concatStringsSep "" (map (lib.const " ") (lib.range 1 level));
indent = level: lib.concatStringsSep "" (map (lib.const " ") (lib.range 1 level));
bookmarkToHTML = indentLevel: bookmark:
''
${indent indentLevel}<DT><A HREF="${
escapeXML bookmark.url
}" ADD_DATE="1" LAST_MODIFIED="1"${
lib.optionalString (bookmark.keyword != null)
" SHORTCUTURL=\"${escapeXML bookmark.keyword}\""
}${
lib.optionalString (bookmark.tags != [ ])
" TAGS=\"${escapeXML (concatStringsSep "," bookmark.tags)}\""
}>${escapeXML bookmark.name}</A>'';
bookmarkToHTML =
indentLevel: bookmark:
''${indent indentLevel}<DT><A HREF="${escapeXML bookmark.url}" ADD_DATE="1" LAST_MODIFIED="1"${
lib.optionalString (bookmark.keyword != null) " SHORTCUTURL=\"${escapeXML bookmark.keyword}\""
}${
lib.optionalString (
bookmark.tags != [ ]
) " TAGS=\"${escapeXML (concatStringsSep "," bookmark.tags)}\""
}>${escapeXML bookmark.name}</A>'';
directoryToHTML = indentLevel: directory: ''
${indent indentLevel}<DT>${
if directory.toolbar then
''
<H3 ADD_DATE="1" LAST_MODIFIED="1" PERSONAL_TOOLBAR_FOLDER="true">Bookmarks Toolbar''
''<H3 ADD_DATE="1" LAST_MODIFIED="1" PERSONAL_TOOLBAR_FOLDER="true">Bookmarks Toolbar''
else
''<H3 ADD_DATE="1" LAST_MODIFIED="1">${escapeXML directory.name}''
}</H3>
@ -37,18 +45,16 @@ let
${allItemsToHTML (indentLevel + 1) directory.bookmarks}
${indent indentLevel}</DL><p>'';
itemToHTMLOrRecurse = indentLevel: item:
if item ? "url" then
bookmarkToHTML indentLevel item
else
directoryToHTML indentLevel item;
itemToHTMLOrRecurse =
indentLevel: item:
if item ? "url" then bookmarkToHTML indentLevel item else directoryToHTML indentLevel item;
allItemsToHTML = indentLevel: bookmarks:
lib.concatStringsSep "\n"
(map (itemToHTMLOrRecurse indentLevel) bookmarks);
allItemsToHTML =
indentLevel: bookmarks: lib.concatStringsSep "\n" (map (itemToHTMLOrRecurse indentLevel) bookmarks);
bookmarkEntries = allItemsToHTML 1 bookmarks;
in pkgs.writeText "bookmarks.html" ''
in
pkgs.writeText "bookmarks.html" ''
<!DOCTYPE NETSCAPE-Bookmark-file-1>
<!-- This is an automatically generated file.
It will be read and overwritten.
@ -60,7 +66,8 @@ let
${bookmarkEntries}
</DL>
'';
in {
in
{
imports = [
(pkgs.path + "/nixos/modules/misc/assertions.nix")
(pkgs.path + "/nixos/modules/misc/meta.nix")
@ -131,16 +138,14 @@ in {
};
config = {
assertions = [{
assertion = config.enable -> config.force;
message = ''
Using '${
lib.showAttrPath (modulePath ++ [ "settings" ])
}' will override all previous bookmarks.
Enable ${
lib.showAttrPath (modulePath ++ [ "force" ])
}' to acknowledge this.
'';
}];
assertions = [
{
assertion = config.enable -> config.force;
message = ''
Using '${lib.showAttrPath (modulePath ++ [ "settings" ])}' will override all previous bookmarks.
Enable ${lib.showAttrPath (modulePath ++ [ "force" ])}' to acknowledge this.
'';
}
];
};
}

View file

@ -1,61 +1,87 @@
{ config, lib, pkgs, appName, package, modulePath, profilePath }:
{
config,
lib,
pkgs,
appName,
package,
modulePath,
profilePath,
}:
let
inherit (lib) mapAttrs mapAttrs' mkOption optionalAttrs types warn;
inherit (lib)
mapAttrs
mapAttrs'
mkOption
optionalAttrs
types
warn
;
jsonFormat = pkgs.formats.json { };
# Map of nice field names to internal field names.
# This is intended to be exhaustive and should be
# updated at every version bump.
internalFieldNames = (lib.genAttrs [
"name"
"isAppProvided"
"loadPath"
"updateInterval"
"updateURL"
"iconMapObj"
"metaData"
"orderHint"
"definedAliases"
"urls"
] (name: "_${name}")) // {
searchForm = "__searchForm";
};
internalFieldNames =
(lib.genAttrs [
"name"
"isAppProvided"
"loadPath"
"updateInterval"
"updateURL"
"iconMapObj"
"metaData"
"orderHint"
"definedAliases"
"urls"
] (name: "_${name}"))
// {
searchForm = "__searchForm";
};
# Convenience to specify absolute path to icon
iconUrl = icon:
if lib.isPath icon || lib.hasPrefix "/" icon then
"file://${icon}"
else
icon;
iconUrl = icon: if lib.isPath icon || lib.hasPrefix "/" icon then "file://${icon}" else icon;
processCustomEngineInput = input:
processCustomEngineInput =
input:
{
name = input.id;
} // (removeAttrs input [ "icon" ])
}
// (removeAttrs input [ "icon" ])
// optionalAttrs (input ? icon || input ? iconMapObj) {
iconMapObj = mapAttrs (name: iconUrl) ((optionalAttrs (input ? icon) {
# Convenience to specify single icon instead of map
"16" = input.icon;
}) // (input.iconMapObj or { }));
} // {
iconMapObj = mapAttrs (name: iconUrl) (
(optionalAttrs (input ? icon) {
# Convenience to specify single icon instead of map
"16" = input.icon;
})
// (input.iconMapObj or { })
);
}
// {
# Required for custom engine configurations, loadPaths
# are unique identifiers that are generally formatted
# like: [source]/path/to/engine.xml
loadPath = "[home-manager]/${
lib.showAttrPath (modulePath ++ [ "engines" input.id ])
}";
lib.showAttrPath (
modulePath
++ [
"engines"
input.id
]
)
}";
};
processEngineInput = id: input:
processEngineInput =
id: input:
let
requiredInput = {
inherit id;
isAppProvided =
input.isAppProvided or (removeAttrs input [ "metaData" ] == { });
isAppProvided = input.isAppProvided or (removeAttrs input [ "metaData" ] == { });
metaData = input.metaData or { };
};
in if requiredInput.isAppProvided then
in
if requiredInput.isAppProvided then
requiredInput
else
lib.pipe (input // requiredInput) [
@ -64,105 +90,123 @@ let
processCustomEngineInput
];
buildEngineConfig = name: input:
buildEngineConfig =
name: input:
mapAttrs' (name: value: {
name = internalFieldNames.${name} or name;
inherit value;
}) (processEngineInput name input);
sortEngineConfigs = configs:
sortEngineConfigs =
configs:
let
buildEngineConfigWithOrder = order: id:
buildEngineConfigWithOrder =
order: id:
let
config = configs.${id} or {
inherit id;
_isAppProvided = true;
_metaData = { };
config =
configs.${id} or {
inherit id;
_isAppProvided = true;
_metaData = { };
};
in
config
// {
_metaData = config._metaData // {
inherit order;
};
in config // { _metaData = config._metaData // { inherit order; }; };
};
engineConfigsWithoutOrder =
lib.attrValues (removeAttrs configs config.order);
engineConfigsWithoutOrder = lib.attrValues (removeAttrs configs config.order);
sortedEngineConfigs = (lib.imap buildEngineConfigWithOrder config.order)
++ engineConfigsWithoutOrder;
in sortedEngineConfigs;
sortedEngineConfigs =
(lib.imap buildEngineConfigWithOrder config.order) ++ engineConfigsWithoutOrder;
in
sortedEngineConfigs;
engineInput = config.engines // {
# Infer config.default as an app provided
# engine if it's not in config.engines
${config.default} = config.engines.${config.default} or { };
} // {
${config.privateDefault} = config.engines.${config.privateDefault} or { };
};
engineInput =
config.engines
// {
# Infer config.default as an app provided
# engine if it's not in config.engines
${config.default} = config.engines.${config.default} or { };
}
// {
${config.privateDefault} = config.engines.${config.privateDefault} or { };
};
settings = {
version = 12;
engines = sortEngineConfigs (mapAttrs buildEngineConfig engineInput);
metaData = optionalAttrs (config.default != null) {
defaultEngineId = config.default;
defaultEngineIdHash = "@hash@";
} // optionalAttrs (config.privateDefault != null) {
privateDefaultEngineId = config.privateDefault;
privateDefaultEngineIdHash = "@privateHash@";
} // {
useSavedOrder = config.order != [ ];
};
metaData =
optionalAttrs (config.default != null) {
defaultEngineId = config.default;
defaultEngineIdHash = "@hash@";
}
// optionalAttrs (config.privateDefault != null) {
privateDefaultEngineId = config.privateDefault;
privateDefaultEngineIdHash = "@privateHash@";
}
// {
useSavedOrder = config.order != [ ];
};
};
# Home Manager doesn't circumvent user consent and isn't acting
# maliciously. We're modifying the search outside of the browser, but
# a claim by Mozilla to remove this would be very anti-user, and
# is unlikely to be an issue for our use case.
disclaimer = "By modifying this file, I agree that I am doing so "
disclaimer =
"By modifying this file, I agree that I am doing so "
+ "only within @appName@ itself, using official, user-driven search "
+ "engine selection processes, and in a way which does not circumvent "
+ "user consent. I acknowledge that any attempt to change this file "
+ "from outside of @appName@ is a malicious act, and will be responded "
+ "to accordingly.";
salt = if config.default != null then
profilePath + config.default + disclaimer
else
null;
salt = if config.default != null then profilePath + config.default + disclaimer else null;
privateSalt = if config.privateDefault != null then
profilePath + config.privateDefault + disclaimer
else
null;
privateSalt =
if config.privateDefault != null then profilePath + config.privateDefault + disclaimer else null;
appNameVariable = if package == null then
"appName=${lib.escapeShellArg appName}"
else ''
applicationIni="$(find ${lib.escapeShellArg package} -maxdepth 3 -path ${
lib.escapeShellArg package
}'/lib/*/application.ini' -print -quit)"
if test -n "$applicationIni"; then
appName="$(sed -n 's/^Name=\(.*\)$/\1/p' "$applicationIni" | head -n1)"
appNameVariable =
if package == null then
"appName=${lib.escapeShellArg appName}"
else
appName=${lib.escapeShellArg appName}
fi
'';
''
applicationIni="$(find ${lib.escapeShellArg package} -maxdepth 3 -path ${lib.escapeShellArg package}'/lib/*/application.ini' -print -quit)"
if test -n "$applicationIni"; then
appName="$(sed -n 's/^Name=\(.*\)$/\1/p' "$applicationIni" | head -n1)"
else
appName=${lib.escapeShellArg appName}
fi
'';
file = pkgs.runCommand "search.json.mozlz4" {
nativeBuildInputs = with pkgs; [ mozlz4a openssl ];
json = builtins.toJSON settings;
inherit salt privateSalt;
} ''
${appNameVariable}
file =
pkgs.runCommand "search.json.mozlz4"
{
nativeBuildInputs = with pkgs; [
mozlz4a
openssl
];
json = builtins.toJSON settings;
inherit salt privateSalt;
}
''
${appNameVariable}
salt=''${salt//@appName@/"$appName"}
privateSalt=''${privateSalt//@appName@/"$appName"}
salt=''${salt//@appName@/"$appName"}
privateSalt=''${privateSalt//@appName@/"$appName"}
if [[ -n $salt ]]; then
export hash=$(echo -n "$salt" | openssl dgst -sha256 -binary | base64)
export privateHash=$(echo -n "$privateSalt" | openssl dgst -sha256 -binary | base64)
mozlz4a <(substituteStream json search.json.in --subst-var hash --subst-var privateHash) "$out"
else
mozlz4a <(echo "$json") "$out"
fi
'';
if [[ -n $salt ]]; then
export hash=$(echo -n "$salt" | openssl dgst -sha256 -binary | base64)
export privateHash=$(echo -n "$privateSalt" | openssl dgst -sha256 -binary | base64)
mozlz4a <(substituteStream json search.json.in --subst-var hash --subst-var privateHash) "$out"
else
mozlz4a <(echo "$json") "$out"
fi
'';
engineNameToId = {
# Derived from https://searchfox.org/mozilla-central/rev/e3f42ec9320748b2aab3d474d1e47075def9000c/services/settings/dumps/main/search-config-v2.json
@ -322,47 +366,62 @@ let
"Wikipedia (tr)" = "wikipedia-tr";
};
migrateEngineNameToIdV7 = engine:
migrateEngineNameToIdV7 =
engine:
if builtins.hasAttr engine engineNameToId then
warn "Search engines are now referenced by id instead of by name, use '${
warn
"Search engines are now referenced by id instead of by name, use '${engineNameToId.${engine}}' instead of '${engine}'"
engineNameToId.${engine}
}' instead of '${engine}'" engineNameToId.${engine}
else
engine;
migrateEngineToV11 = engine:
engine // lib.optionalAttrs (engine ? iconMapObj) {
iconMapObj = mapAttrs' (name: value:
let nameToIntResult = builtins.tryEval (lib.toInt name);
in {
name = if nameToIntResult.success then
name
else
let size = toString (builtins.fromJSON name).width;
in warn
"JSON object names for 'iconMapObj' are deprecated, use '${size}' instead of '${name}'"
size;
migrateEngineToV11 =
engine:
engine
// lib.optionalAttrs (engine ? iconMapObj) {
iconMapObj = mapAttrs' (
name: value:
let
nameToIntResult = builtins.tryEval (lib.toInt name);
in
{
name =
if nameToIntResult.success then
name
else
let
size = toString (builtins.fromJSON name).width;
in
warn "JSON object names for 'iconMapObj' are deprecated, use '${size}' instead of '${name}'" size;
inherit value;
}) engine.iconMapObj;
}
) engine.iconMapObj;
};
migrateEngineToV12 = engine:
migrateEngineToV12 =
engine:
let
iconMapObj = optionalAttrs (engine ? iconURL) {
"16" = warn "'iconURL' is deprecated, use 'icon = ${
lib.strings.escapeNixString engine.iconURL
}' instead" engine.iconURL;
} // optionalAttrs (engine ? iconUpdateURL) {
"16" = warn "'iconUpdateURL' is deprecated, use 'icon = ${
lib.strings.escapeNixString engine.iconUpdateURL
}' instead" engine.iconUpdateURL;
} // (engine.iconMapObj or { });
in lib.throwIf (engine ? hasPreferredIcon)
"hasPreferredIcon has been removed"
(removeAttrs engine [ "iconURL" "iconUpdateURL" ])
iconMapObj =
optionalAttrs (engine ? iconURL) {
"16" =
warn "'iconURL' is deprecated, use 'icon = ${lib.strings.escapeNixString engine.iconURL}' instead" engine.iconURL;
}
// optionalAttrs (engine ? iconUpdateURL) {
"16" =
warn "'iconUpdateURL' is deprecated, use 'icon = ${lib.strings.escapeNixString engine.iconUpdateURL}' instead" engine.iconUpdateURL;
}
// (engine.iconMapObj or { });
in
lib.throwIf (engine ? hasPreferredIcon) "hasPreferredIcon has been removed" (
removeAttrs engine [
"iconURL"
"iconUpdateURL"
]
)
// lib.optionalAttrs (iconMapObj != { }) { inherit iconMapObj; };
in {
in
{
imports = [ (pkgs.path + "/nixos/modules/misc/meta.nix") ];
meta.maintainers = with lib.maintainers; [ kira-bruneau ];
@ -370,8 +429,11 @@ in {
options = {
enable = mkOption {
type = with types; bool;
default = config.default != null || config.privateDefault != null
|| config.order != [ ] || config.engines != { };
default =
config.default != null
|| config.privateDefault != null
|| config.order != [ ]
|| config.engines != { };
internal = true;
};
@ -389,8 +451,7 @@ in {
default = mkOption {
type = with types; nullOr str;
apply = engine:
if engine != null then migrateEngineNameToIdV7 engine else null;
apply = engine: if engine != null then migrateEngineNameToIdV7 engine else null;
default = null;
example = "ddg";
description = ''
@ -401,8 +462,7 @@ in {
privateDefault = mkOption {
type = with types; nullOr str;
apply = engine:
if engine != null then migrateEngineNameToIdV7 engine else null;
apply = engine: if engine != null then migrateEngineNameToIdV7 engine else null;
default = null;
example = "ddg";
description = ''
@ -414,7 +474,10 @@ in {
type = with types; uniq (listOf str);
apply = builtins.map migrateEngineNameToIdV7;
default = [ ];
example = [ "ddg" "google" ];
example = [
"ddg"
"google"
];
description = ''
The order the search engines are listed in. Any engines that
aren't included in this list will be listed after these in an
@ -425,10 +488,12 @@ in {
engines = mkOption {
type = with types; attrsOf (attrsOf jsonFormat.type);
apply = mapAttrs' (name: value: {
name = migrateEngineNameToIdV7 name;
inherit value;
});
apply = mapAttrs' (
name: value: {
name = migrateEngineNameToIdV7 name;
inherit value;
}
);
default = { };
example = lib.literalExpression ''

View file

@ -1,31 +1,46 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) isAttrs literalExpression mkIf mkOption optional types;
inherit (lib)
isAttrs
literalExpression
mkIf
mkOption
optional
types
;
cfg = config.programs.fish;
pluginModule = types.submodule ({ config, ... }: {
options = {
src = mkOption {
type = types.path;
description = ''
Path to the plugin folder.
pluginModule = types.submodule (
{ config, ... }:
{
options = {
src = mkOption {
type = types.path;
description = ''
Path to the plugin folder.
Relevant pieces will be added to the fish function path and
the completion path. The {file}`init.fish` and
{file}`key_binding.fish` files are sourced if
they exist.
'';
};
Relevant pieces will be added to the fish function path and
the completion path. The {file}`init.fish` and
{file}`key_binding.fish` files are sourced if
they exist.
'';
};
name = mkOption {
type = types.str;
description = ''
The name of the plugin.
'';
name = mkOption {
type = types.str;
description = ''
The name of the plugin.
'';
};
};
};
});
}
);
functionModule = types.submodule {
options = {
@ -110,7 +125,11 @@ let
onSignal = mkOption {
type = with types; nullOr (either str int);
default = null;
example = [ "SIGHUP" "HUP" 1 ];
example = [
"SIGHUP"
"HUP"
1
];
description = ''
Tells fish to run this function when the specified signal is
delivered. The signal can be a signal number or signal name.
@ -195,49 +214,64 @@ let
};
};
abbrsStr = lib.concatStringsSep "\n" (lib.mapAttrsToList (name: def:
let
mods = lib.cli.toGNUCommandLineShell {
mkOption = k: v:
if v == null then
[ ]
else if k == "set-cursor" then
[ "--${k}=${lib.generators.mkValueStringDefault { } v}" ]
else [
"--${k}"
(lib.generators.mkValueStringDefault { } v)
];
} {
inherit (def) position regex command function;
set-cursor = def.setCursor;
};
modifiers = if isAttrs def then mods else "";
expansion = if isAttrs def then def.expansion else def;
in "abbr --add ${modifiers} -- ${name}"
+ lib.optionalString (expansion != null) " ${lib.escapeShellArg expansion}")
cfg.shellAbbrs);
abbrsStr = lib.concatStringsSep "\n" (
lib.mapAttrsToList (
name: def:
let
mods =
lib.cli.toGNUCommandLineShell
{
mkOption =
k: v:
if v == null then
[ ]
else if k == "set-cursor" then
[ "--${k}=${lib.generators.mkValueStringDefault { } v}" ]
else
[
"--${k}"
(lib.generators.mkValueStringDefault { } v)
];
}
{
inherit (def)
position
regex
command
function
;
set-cursor = def.setCursor;
};
modifiers = if isAttrs def then mods else "";
expansion = if isAttrs def then def.expansion else def;
in
"abbr --add ${modifiers} -- ${name}"
+ lib.optionalString (expansion != null) " ${lib.escapeShellArg expansion}"
) cfg.shellAbbrs
);
aliasesStr = lib.concatStringsSep "\n"
(lib.mapAttrsToList (k: v: "alias ${k} ${lib.escapeShellArg v}")
cfg.shellAliases);
aliasesStr = lib.concatStringsSep "\n" (
lib.mapAttrsToList (k: v: "alias ${k} ${lib.escapeShellArg v}") cfg.shellAliases
);
fishIndent = name: text:
fishIndent =
name: text:
pkgs.runCommand name {
nativeBuildInputs = [ cfg.package ];
inherit text;
passAsFile = [ "text" ];
} "env HOME=$(mktemp -d) fish_indent < $textPath > $out";
translatedSessionVariables =
pkgs.runCommandLocal "hm-session-vars.fish" { } ''
(echo "function setup_hm_session_vars;"
${pkgs.buildPackages.babelfish}/bin/babelfish \
<${config.home.sessionVariablesPackage}/etc/profile.d/hm-session-vars.sh
echo "end"
echo "setup_hm_session_vars") > $out
'';
translatedSessionVariables = pkgs.runCommandLocal "hm-session-vars.fish" { } ''
(echo "function setup_hm_session_vars;"
${pkgs.buildPackages.babelfish}/bin/babelfish \
<${config.home.sessionVariablesPackage}/etc/profile.d/hm-session-vars.sh
echo "end"
echo "setup_hm_session_vars") > $out
'';
in {
in
{
imports = [
(lib.mkRemovedOptionModule [ "programs" "fish" "promptInit" ] ''
Prompt is now configured through the
@ -254,8 +288,8 @@ in {
package = lib.mkPackageOption pkgs "fish" { };
generateCompletions = lib.mkEnableOption
"the automatic generation of completions based upon installed man pages"
generateCompletions =
lib.mkEnableOption "the automatic generation of completions based upon installed man pages"
// {
default = true;
};
@ -396,176 +430,204 @@ in {
};
};
config = mkIf cfg.enable (lib.mkMerge [
{ home.packages = [ cfg.package ]; }
config = mkIf cfg.enable (
lib.mkMerge [
{ home.packages = [ cfg.package ]; }
(mkIf cfg.generateCompletions {
# Support completion for `man` by building a cache for `apropos`.
programs.man.generateCaches = lib.mkDefault true;
(mkIf cfg.generateCompletions {
# Support completion for `man` by building a cache for `apropos`.
programs.man.generateCaches = lib.mkDefault true;
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 ? "", ... }:
xdg.dataFile."fish/home-manager_generated_completions".source =
let
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}
'';
# Paths later in the list will overwrite those already linked
destructiveSymlinkJoin =
args_@{
name,
paths,
preferLocalBuild ? true,
allowSubstitutes ? false,
postBuild ? "",
...
}:
let
args =
removeAttrs args_ [
"name"
"postBuild"
]
// {
# 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 = let
getName = attrs:
attrs.name or "${attrs.pname or "«pname-missing»"}-${
attrs.version or "«version-missing»"
}";
in package:
pkgs.runCommand "${getName package}-fish-completions" {
srcs = [ package ] ++ lib.filter (p: p != null)
(builtins.map (outName: package.${outName} or null)
config.home.extraOutputsToInstall);
nativeBuildInputs = [ pkgs.python3 ];
buildInputs = [ cfg.package ];
preferLocalBuild = true;
} ''
mkdir -p $out
for src in $srcs; do
if [ -d $src/share/man ]; then
find -L $src/share/man -type f \
-exec python ${cfg.package}/share/fish/tools/create_manpage_completions.py --directory $out {} + \
> /dev/null
fi
done
generateCompletions =
let
getName =
attrs: attrs.name or "${attrs.pname or "«pname-missing»"}-${attrs.version or "«version-missing»"}";
in
package:
pkgs.runCommand "${getName package}-fish-completions"
{
srcs =
[ package ]
++ lib.filter (p: p != null) (
builtins.map (outName: package.${outName} or null) config.home.extraOutputsToInstall
);
nativeBuildInputs = [ pkgs.python3 ];
buildInputs = [ cfg.package ];
preferLocalBuild = true;
}
''
mkdir -p $out
for src in $srcs; do
if [ -d $src/share/man ]; then
find -L $src/share/man -type f \
-exec python ${cfg.package}/share/fish/tools/create_manpage_completions.py --directory $out {} + \
> /dev/null
fi
done
'';
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 (lib.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
'';
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 (lib.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".source = fishIndent "config.fish" ''
# ~/.config/fish/config.fish: DO NOT EDIT -- this file has been generated
# automatically by home-manager.
{
xdg.configFile."fish/config.fish".source = fishIndent "config.fish" ''
# ~/.config/fish/config.fish: DO NOT EDIT -- this file has been generated
# automatically by home-manager.
# Only execute this file once per shell.
set -q __fish_home_manager_config_sourced; and exit
set -g __fish_home_manager_config_sourced 1
# Only execute this file once per shell.
set -q __fish_home_manager_config_sourced; and exit
set -g __fish_home_manager_config_sourced 1
source ${translatedSessionVariables}
source ${translatedSessionVariables}
${cfg.shellInit}
${cfg.shellInit}
status is-login; and begin
status is-login; and begin
# Login shell initialisation
${cfg.loginShellInit}
# Login shell initialisation
${cfg.loginShellInit}
end
end
status is-interactive; and begin
status is-interactive; and begin
# Abbreviations
${abbrsStr}
# Abbreviations
${abbrsStr}
# Aliases
${aliasesStr}
# Aliases
${aliasesStr}
# Interactive shell initialisation
${cfg.interactiveShellInit}
# Interactive shell initialisation
${cfg.interactiveShellInit}
end
end
${cfg.shellInitLast}
'';
}
{
xdg.configFile = lib.mapAttrs' (name: def: {
name = "fish/functions/${name}.fish";
value = {
source =
let
modifierStr = n: v: optional (v != null) ''--${n}="${toString v}"'';
modifierStrs = n: v: optional (v != null) "--${n}=${toString v}";
modifierBool = n: v: optional (v != null && v) "--${n}";
${cfg.shellInitLast}
'';
}
{
xdg.configFile = lib.mapAttrs' (name: def: {
name = "fish/functions/${name}.fish";
value = {
source = let
modifierStr = n: v: optional (v != null) ''--${n}="${toString v}"'';
modifierStrs = n: v: optional (v != null) "--${n}=${toString v}";
modifierBool = n: v: optional (v != null && v) "--${n}";
mods =
with def;
modifierStr "description" description
++ modifierStr "wraps" wraps
++ lib.concatMap (modifierStr "on-event") (lib.toList 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;
mods = with def;
modifierStr "description" description ++ modifierStr "wraps" wraps
++ lib.concatMap (modifierStr "on-event") (lib.toList 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
fishIndent "${name}.fish" ''
function ${name}${modifiers}
${lib.strings.removeSuffix "\n" body}
end
'';
};
}) cfg.functions;
}
modifiers = if isAttrs def then " ${toString mods}" else "";
body = if isAttrs def then def.body else def;
in fishIndent "${name}.fish" ''
function ${name}${modifiers}
${lib.strings.removeSuffix "\n" body}
end
'';
};
}) cfg.functions;
}
# Each plugin gets a corresponding conf.d/plugin-NAME.fish file to load
# in the paths and any initialization scripts.
(mkIf (lib.length cfg.plugins > 0) {
xdg.configFile = lib.mkMerge (
map (plugin: {
"fish/conf.d/plugin-${plugin.name}.fish".source = fishIndent "${plugin.name}.fish" ''
# Plugin ${plugin.name}
set -l plugin_dir ${plugin.src}
# Each plugin gets a corresponding conf.d/plugin-NAME.fish file to load
# in the paths and any initialization scripts.
(mkIf (lib.length cfg.plugins > 0) {
xdg.configFile = lib.mkMerge (map (plugin: {
"fish/conf.d/plugin-${plugin.name}.fish".source =
fishIndent "${plugin.name}.fish" ''
# Plugin ${plugin.name}
set -l plugin_dir ${plugin.src}
# Set paths to import plugin components
if test -d $plugin_dir/functions
set fish_function_path $fish_function_path[1] $plugin_dir/functions $fish_function_path[2..-1]
end
if test -d $plugin_dir/completions
set fish_complete_path $fish_complete_path[1] $plugin_dir/completions $fish_complete_path[2..-1]
end
# Source initialization code if it exists.
if test -d $plugin_dir/conf.d
for f in $plugin_dir/conf.d/*.fish
source $f
# Set paths to import plugin components
if test -d $plugin_dir/functions
set fish_function_path $fish_function_path[1] $plugin_dir/functions $fish_function_path[2..-1]
end
end
if test -f $plugin_dir/key_bindings.fish
source $plugin_dir/key_bindings.fish
end
if test -d $plugin_dir/completions
set fish_complete_path $fish_complete_path[1] $plugin_dir/completions $fish_complete_path[2..-1]
end
if test -f $plugin_dir/init.fish
source $plugin_dir/init.fish
end
'';
}) cfg.plugins);
})
]);
# 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
);
})
]
);
}

View file

@ -1,9 +1,13 @@
{ lib, ... }:
let
modulePath = [ "programs" "floorp" ];
modulePath = [
"programs"
"floorp"
];
mkFirefoxModule = import ./firefox/mkFirefoxModule.nix;
in {
in
{
meta.maintainers = [ lib.hm.maintainers.bricked ];
imports = [
@ -14,8 +18,12 @@ in {
unwrappedPackageName = "floorp-unwrapped";
visible = true;
platforms.linux = { configPath = ".floorp"; };
platforms.darwin = { configPath = "Library/Application Support/Floorp"; };
platforms.linux = {
configPath = ".floorp";
};
platforms.darwin = {
configPath = "Library/Application Support/Floorp";
};
})
];
}

View file

@ -1,8 +1,14 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.foot;
iniFormat = pkgs.formats.ini { };
in {
in
{
meta.maintainers = with lib.maintainers; [ plabadens ];
options.programs.foot = {
@ -39,8 +45,7 @@ in {
config = lib.mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "programs.foot" pkgs
lib.platforms.linux)
(lib.hm.assertions.assertPlatform "programs.foot" pkgs lib.platforms.linux)
];
home.packages = [ cfg.package ];
@ -52,8 +57,7 @@ in {
systemd.user.services = lib.mkIf cfg.server.enable {
foot = {
Unit = {
Description =
"Fast, lightweight and minimalistic Wayland terminal emulator.";
Description = "Fast, lightweight and minimalistic Wayland terminal emulator.";
Documentation = "man:foot(1)";
PartOf = [ "graphical-session.target" ];
After = [ "graphical-session.target" ];
@ -65,7 +69,9 @@ in {
OOMPolicy = "continue";
};
Install = { WantedBy = [ "graphical-session.target" ]; };
Install = {
WantedBy = [ "graphical-session.target" ];
};
};
};
};

View file

@ -1,21 +1,36 @@
{ lib, pkgs, config, ... }:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib)
concatStringsSep mapAttrsToList mkIf mkEnableOption mkPackageOption mkOption
literalExpression;
concatStringsSep
mapAttrsToList
mkIf
mkEnableOption
mkPackageOption
mkOption
literalExpression
;
cfg = config.programs.freetube;
settings = settings:
settings =
settings:
let
convertSetting = name: value:
convertSetting =
name: value:
builtins.toJSON {
"_id" = name;
"value" = value;
};
in concatStringsSep "\n" (mapAttrsToList convertSetting settings) + "\n";
in {
in
concatStringsSep "\n" (mapAttrsToList convertSetting settings) + "\n";
in
{
meta.maintainers = with lib.maintainers; [ vonixxx ];
options.programs.freetube = {
@ -49,12 +64,14 @@ in {
xdg.configFile."FreeTube/hm_settings.db" = {
source = pkgs.writeText "hm_settings.db" (settings cfg.settings);
onChange = let
hmSettingsDb = "${config.xdg.configHome}/FreeTube/hm_settings.db";
settingsDb = "${config.xdg.configHome}/FreeTube/settings.db";
in ''
run install -Dm644 $VERBOSE_ARG '${hmSettingsDb}' '${settingsDb}'
'';
onChange =
let
hmSettingsDb = "${config.xdg.configHome}/FreeTube/hm_settings.db";
settingsDb = "${config.xdg.configHome}/FreeTube/settings.db";
in
''
run install -Dm644 $VERBOSE_ARG '${hmSettingsDb}' '${settingsDb}'
'';
};
};
}

View file

@ -1,14 +1,26 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) literalExpression mkEnableOption mkPackageOption mkOption mkIf;
inherit (lib)
literalExpression
mkEnableOption
mkPackageOption
mkOption
mkIf
;
cfg = config.programs.fuzzel;
iniFormat = pkgs.formats.ini { };
in {
in
{
meta.maintainers = [ lib.maintainers.Scrumplex ];
options.programs.fuzzel = {
@ -38,8 +50,7 @@ in {
config = mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "programs.fuzzel" pkgs
lib.platforms.linux)
(lib.hm.assertions.assertPlatform "programs.fuzzel" pkgs lib.platforms.linux)
];
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];

View file

@ -1,46 +1,73 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) getExe literalExpression mkIf mkOption mkOrder types;
inherit (lib)
getExe
literalExpression
mkIf
mkOption
mkOrder
types
;
cfg = config.programs.fzf;
renderedColors = colors:
lib.concatStringsSep ","
(lib.mapAttrsToList (name: value: "${name}:${value}") colors);
renderedColors =
colors: lib.concatStringsSep "," (lib.mapAttrsToList (name: value: "${name}:${value}") colors);
hasShellIntegrationEmbedded = lib.versionAtLeast cfg.package.version "0.48.0";
bashIntegration = if hasShellIntegrationEmbedded then ''
if [[ :$SHELLOPTS: =~ :(vi|emacs): ]]; then
eval "$(${getExe cfg.package} --bash)"
fi
'' else ''
if [[ :$SHELLOPTS: =~ :(vi|emacs): ]]; then
. ${cfg.package}/share/fzf/completion.bash
. ${cfg.package}/share/fzf/key-bindings.bash
fi
'';
bashIntegration =
if hasShellIntegrationEmbedded then
''
if [[ :$SHELLOPTS: =~ :(vi|emacs): ]]; then
eval "$(${getExe cfg.package} --bash)"
fi
''
else
''
if [[ :$SHELLOPTS: =~ :(vi|emacs): ]]; then
. ${cfg.package}/share/fzf/completion.bash
. ${cfg.package}/share/fzf/key-bindings.bash
fi
'';
zshIntegration = if hasShellIntegrationEmbedded then ''
if [[ $options[zle] = on ]]; then
eval "$(${getExe cfg.package} --zsh)"
fi
'' else ''
if [[ $options[zle] = on ]]; then
. ${cfg.package}/share/fzf/completion.zsh
. ${cfg.package}/share/fzf/key-bindings.zsh
fi
'';
zshIntegration =
if hasShellIntegrationEmbedded then
''
if [[ $options[zle] = on ]]; then
eval "$(${getExe cfg.package} --zsh)"
fi
''
else
''
if [[ $options[zle] = on ]]; then
. ${cfg.package}/share/fzf/completion.zsh
. ${cfg.package}/share/fzf/key-bindings.zsh
fi
'';
fishIntegration = if hasShellIntegrationEmbedded then ''
${getExe cfg.package} --fish | source
'' else ''
source ${cfg.package}/share/fzf/key-bindings.fish && fzf_key_bindings
'';
in {
fishIntegration =
if hasShellIntegrationEmbedded then
''
${getExe cfg.package} --fish | source
''
else
''
source ${cfg.package}/share/fzf/key-bindings.fish && fzf_key_bindings
'';
in
{
imports = [
(lib.mkRemovedOptionModule [ "programs" "fzf" "historyWidgetCommand" ]
"This option is no longer supported by fzf.")
(lib.mkRemovedOptionModule [
"programs"
"fzf"
"historyWidgetCommand"
] "This option is no longer supported by fzf.")
];
meta.maintainers = with lib.maintainers; [ khaneliman ];
@ -63,7 +90,10 @@ in {
defaultOptions = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "--height 40%" "--border" ];
example = [
"--height 40%"
"--border"
];
description = ''
Extra command line options given to fzf by default.
'';
@ -110,7 +140,10 @@ in {
historyWidgetOptions = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "--sort" "--exact" ];
example = [
"--sort"
"--exact"
];
description = ''
Command line options for the CTRL-R keybinding.
'';
@ -151,49 +184,44 @@ in {
};
};
enableBashIntegration =
lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableBashIntegration = lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableFishIntegration =
lib.hm.shell.mkFishIntegrationOption { inherit config; };
enableFishIntegration = lib.hm.shell.mkFishIntegrationOption { inherit config; };
enableZshIntegration =
lib.hm.shell.mkZshIntegrationOption { inherit config; };
enableZshIntegration = lib.hm.shell.mkZshIntegrationOption { inherit config; };
};
config = mkIf cfg.enable {
home.packages = [ cfg.package ];
home.sessionVariables = lib.mapAttrs (n: v: toString v)
(lib.filterAttrs (n: v: v != [ ] && v != null) {
home.sessionVariables = lib.mapAttrs (n: v: toString v) (
lib.filterAttrs (n: v: v != [ ] && v != null) {
FZF_ALT_C_COMMAND = cfg.changeDirWidgetCommand;
FZF_ALT_C_OPTS = cfg.changeDirWidgetOptions;
FZF_CTRL_R_OPTS = cfg.historyWidgetOptions;
FZF_CTRL_T_COMMAND = cfg.fileWidgetCommand;
FZF_CTRL_T_OPTS = cfg.fileWidgetOptions;
FZF_DEFAULT_COMMAND = cfg.defaultCommand;
FZF_DEFAULT_OPTS = cfg.defaultOptions
++ lib.optionals (cfg.colors != { })
[ "--color ${renderedColors cfg.colors}" ];
FZF_DEFAULT_OPTS =
cfg.defaultOptions
++ lib.optionals (cfg.colors != { }) [ "--color ${renderedColors cfg.colors}" ];
FZF_TMUX = if cfg.tmux.enableShellIntegration then "1" else null;
FZF_TMUX_OPTS = cfg.tmux.shellIntegrationOptions;
});
}
);
# Note, since fzf unconditionally binds C-r we use `mkOrder` to make the
# initialization show up a bit earlier. This is to make initialization of
# other history managers, like mcfly or atuin, take precedence.
programs.bash.initExtra =
mkIf cfg.enableBashIntegration (mkOrder 200 bashIntegration);
programs.bash.initExtra = mkIf cfg.enableBashIntegration (mkOrder 200 bashIntegration);
# Note, since fzf unconditionally binds C-r we use `mkOrder` to make the
# initialization show up a bit earlier. This is to make initialization of
# other history managers, like mcfly or atuin, take precedence.
# Still needs to be initialized after oh-my-zsh (order 800), otherwise
# omz will take precedence.
programs.zsh.initContent =
mkIf cfg.enableZshIntegration (mkOrder 910 zshIntegration);
programs.zsh.initContent = mkIf cfg.enableZshIntegration (mkOrder 910 zshIntegration);
programs.fish.interactiveShellInit =
mkIf cfg.enableFishIntegration (mkOrder 200 fishIntegration);
programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration (mkOrder 200 fishIntegration);
};
}

View file

@ -1,9 +1,15 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.gallery-dl;
jsonFormat = pkgs.formats.json { };
in {
in
{
meta.maintainers = [ ];
options.programs.gallery-dl = {

View file

@ -1,6 +1,8 @@
{ lib, ... }:
let inherit (lib) mkOption types;
in {
let
inherit (lib) mkOption types;
in
{
options.getmail = {
enable = lib.mkEnableOption "the getmail mail retriever for this account";
@ -16,7 +18,10 @@ in {
mailboxes = mkOption {
type = types.nonEmptyListOf types.str;
default = [ ];
example = [ "INBOX" "INBOX.spam" ];
example = [
"INBOX"
"INBOX.spam"
];
description = ''
A non-empty list of mailboxes. To download all mail you can
use the `ALL` mailbox.

View file

@ -1,27 +1,33 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
accounts = lib.filter (a: a.getmail.enable)
(lib.attrValues config.accounts.email.accounts);
accounts = lib.filter (a: a.getmail.enable) (lib.attrValues config.accounts.email.accounts);
renderAccountConfig = account:
renderAccountConfig =
account:
let
inherit (account) getmail imap passwordCommand;
passCmd = lib.concatMapStringsSep ", " (x: "'${x}'") passwordCommand;
renderedMailboxes =
lib.concatMapStrings (x: "'${x}', ") getmail.mailboxes;
retrieverType = if imap.tls.enable then
"SimpleIMAPSSLRetriever"
else
"SimpleIMAPRetriever";
destination = if getmail.destinationCommand != null then {
destinationType = "MDA_external";
destinationPath = getmail.destinationCommand;
} else {
destinationType = "Maildir";
destinationPath = "${account.maildir.absPath}/";
};
renderedMailboxes = lib.concatMapStrings (x: "'${x}', ") getmail.mailboxes;
retrieverType = if imap.tls.enable then "SimpleIMAPSSLRetriever" else "SimpleIMAPRetriever";
destination =
if getmail.destinationCommand != null then
{
destinationType = "MDA_external";
destinationPath = getmail.destinationCommand;
}
else
{
destinationType = "Maildir";
destinationPath = "${account.maildir.absPath}/";
};
renderGetmailBoolean = v: if v then "true" else "false";
in ''
in
''
# Generated by Home-Manager.
[retriever]
type = ${retrieverType}
@ -41,25 +47,23 @@ let
'';
getmailEnabled = lib.length (lib.filter (a: a.getmail.enable) accounts) > 0;
# Watch out! This is used by the getmail.service too!
renderConfigFilepath = a:
".getmail/getmail${if a.primary then "rc" else a.name}";
renderConfigFilepath = a: ".getmail/getmail${if a.primary then "rc" else a.name}";
in {
in
{
options = {
accounts.email.accounts = lib.mkOption {
type = with lib.types;
attrsOf (submodule (import ./getmail-accounts.nix));
type = with lib.types; attrsOf (submodule (import ./getmail-accounts.nix));
};
};
config = lib.mkIf getmailEnabled {
assertions = [
(lib.hm.assertions.assertPlatform "programs.getmail" pkgs
lib.platforms.linux)
(lib.hm.assertions.assertPlatform "programs.getmail" pkgs lib.platforms.linux)
];
home.file = lib.foldl' (a: b: a // b) { }
(map (a: { "${renderConfigFilepath a}".text = renderAccountConfig a; })
accounts);
home.file = lib.foldl' (a: b: a // b) { } (
map (a: { "${renderConfigFilepath a}".text = renderAccountConfig a; }) accounts
);
};
}

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
@ -6,7 +11,8 @@ let
yamlFormat = pkgs.formats.yaml { };
in {
in
{
meta.maintainers = [ lib.hm.maintainers.janik ];
options.programs.gh-dash = {
@ -36,7 +42,6 @@ in {
programs.gh.extensions = lib.mkIf (cfg.package != null) [ cfg.package ];
xdg.configFile."gh-dash/config.yml".source =
yamlFormat.generate "gh-dash-config.yml" cfg.settings;
xdg.configFile."gh-dash/config.yml".source = yamlFormat.generate "gh-dash-config.yml" cfg.settings;
};
}

View file

@ -1,6 +1,16 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) literalExpression mkIf mkOption types;
inherit (lib)
literalExpression
mkIf
mkOption
types
;
cfg = config.programs.gh;
@ -42,27 +52,49 @@ let
};
};
in {
meta.maintainers = with lib.maintainers; [ gerschtli berbiche ];
in
{
meta.maintainers = with lib.maintainers; [
gerschtli
berbiche
];
imports = (map (x:
lib.mkRenamedOptionModule [ "programs" "gh" x ] [
"programs"
"gh"
"settings"
x
]) [ "aliases" "editor" ]) ++ [
(lib.mkRenamedOptionModule [ "programs" "gh" "gitProtocol" ] [
"programs"
"gh"
"settings"
"git_protocol"
])
(lib.mkRenamedOptionModule [
"programs"
"gh"
"enableGitCredentialHelper"
] [ "programs" "gh" "gitCredentialHelper" "enable" ])
imports =
(map
(
x:
lib.mkRenamedOptionModule
[ "programs" "gh" x ]
[
"programs"
"gh"
"settings"
x
]
)
[
"aliases"
"editor"
]
)
++ [
(lib.mkRenamedOptionModule
[ "programs" "gh" "gitProtocol" ]
[
"programs"
"gh"
"settings"
"git_protocol"
]
)
(lib.mkRenamedOptionModule
[
"programs"
"gh"
"enableGitCredentialHelper"
]
[ "programs" "gh" "gitCredentialHelper" "enable" ]
)
];
options.programs.gh = {
@ -73,8 +105,7 @@ in {
settings = mkOption {
type = settingsType;
default = { };
description =
"Configuration written to {file}`$XDG_CONFIG_HOME/gh/config.yml`.";
description = "Configuration written to {file}`$XDG_CONFIG_HOME/gh/config.yml`.";
example = literalExpression ''
{
git_protocol = "ssh";
@ -96,7 +127,10 @@ in {
hosts = mkOption {
type = types.listOf types.str;
default = [ "https://github.com" "https://gist.github.com" ];
default = [
"https://github.com"
"https://gist.github.com"
];
description = "GitHub hosts to enable the gh git credential helper for";
example = literalExpression ''
[ "https://github.com" "https://github.example.com" ]
@ -117,8 +151,9 @@ in {
config = mkIf cfg.enable {
home.packages = [ cfg.package ];
xdg.configFile."gh/config.yml".source =
yamlFormat.generate "gh-config.yml" ({ version = "1"; } // cfg.settings);
xdg.configFile."gh/config.yml".source = yamlFormat.generate "gh-config.yml" (
{ version = "1"; } // cfg.settings
);
# Version 2.40.0+ of `gh` needs to migrate account formats, this needs to
# happen before the version = 1 is placed in the configuration file. Running
@ -127,8 +162,10 @@ in {
#
# See https://github.com/nix-community/home-manager/issues/4744 for details.
home.activation.migrateGhAccounts =
let ghHosts = "${config.xdg.configHome}/gh/hosts.yml";
in lib.hm.dag.entryBetween [ "linkGeneration" ] [ "writeBoundary" ] ''
let
ghHosts = "${config.xdg.configHome}/gh/hosts.yml";
in
lib.hm.dag.entryBetween [ "linkGeneration" ] [ "writeBoundary" ] ''
if [[ ! -L "${ghHosts}" && -f "${ghHosts}" && $(grep --invert-match --quiet '^version:' ${ghHosts}) ]]; then
(
TMP_DIR=$(mktemp -d)
@ -141,17 +178,24 @@ in {
fi
'';
programs.git.extraConfig.credential = mkIf cfg.gitCredentialHelper.enable
(builtins.listToAttrs (map (host:
lib.nameValuePair host {
helper = "${cfg.package}/bin/gh auth git-credential";
}) cfg.gitCredentialHelper.hosts));
programs.git.extraConfig.credential = mkIf cfg.gitCredentialHelper.enable (
builtins.listToAttrs (
map (
host:
lib.nameValuePair host {
helper = "${cfg.package}/bin/gh auth git-credential";
}
) cfg.gitCredentialHelper.hosts
)
);
xdg.dataFile."gh/extensions" = mkIf (cfg.extensions != [ ]) {
source = pkgs.linkFarm "gh-extensions" (builtins.map (p: {
name = p.pname;
path = "${p}/bin";
}) cfg.extensions);
source = pkgs.linkFarm "gh-extensions" (
builtins.map (p: {
name = p.pname;
path = "${p}/bin";
}) cfg.extensions
);
};
};
}

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.ghostty;
@ -7,198 +12,210 @@ let
mkKeyValue = lib.generators.mkKeyValueDefault { } " = ";
};
keyValue = pkgs.formats.keyValue keyValueSettings;
in {
meta.maintainers = with lib.maintainers; [ HeitorAugustoLN khaneliman ];
in
{
meta.maintainers = with lib.maintainers; [
HeitorAugustoLN
khaneliman
];
options.programs.ghostty = let
mkShellIntegrationOption = option:
option // {
options.programs.ghostty =
let
mkShellIntegrationOption =
option:
option
// {
description = ''
${option.description}
This ensures that shell integration works in more scenarios, such as
switching shells within Ghostty. But it is not needed to have shell
integration.
See
<https://ghostty.org/docs/features/shell-integration#manual-shell-integration-setup>
for more information.
'';
};
in
{
enable = lib.mkEnableOption "Ghostty";
package = lib.mkPackageOption pkgs "ghostty" {
nullable = true;
extraDescription = "Set programs.ghostty.package to null on platforms where ghostty is not available or marked broken";
};
settings = lib.mkOption {
inherit (keyValue) type;
default = { };
example = lib.literalExpression ''
{
theme = "catppuccin-mocha";
font-size = 10;
keybind = [
"ctrl+h=goto_split:left"
"ctrl+l=goto_split:right"
];
}
'';
description = ''
${option.description}
Configuration written to {file}`$XDG_CONFIG_HOME/ghostty/config`.
This ensures that shell integration works in more scenarios, such as
switching shells within Ghostty. But it is not needed to have shell
integration.
See
<https://ghostty.org/docs/features/shell-integration#manual-shell-integration-setup>
for more information.
See <https://ghostty.org/docs/config/reference> for more information.
'';
};
in {
enable = lib.mkEnableOption "Ghostty";
package = lib.mkPackageOption pkgs "ghostty" {
nullable = true;
extraDescription =
"Set programs.ghostty.package to null on platforms where ghostty is not available or marked broken";
};
settings = lib.mkOption {
inherit (keyValue) type;
default = { };
example = lib.literalExpression ''
{
theme = "catppuccin-mocha";
font-size = 10;
keybind = [
"ctrl+h=goto_split:left"
"ctrl+l=goto_split:right"
];
}
'';
description = ''
Configuration written to {file}`$XDG_CONFIG_HOME/ghostty/config`.
See <https://ghostty.org/docs/config/reference> for more information.
'';
};
themes = lib.mkOption {
type = lib.types.attrsOf keyValue.type;
default = { };
example = {
catppuccin-mocha = {
palette = [
"0=#45475a"
"1=#f38ba8"
"2=#a6e3a1"
"3=#f9e2af"
"4=#89b4fa"
"5=#f5c2e7"
"6=#94e2d5"
"7=#bac2de"
"8=#585b70"
"9=#f38ba8"
"10=#a6e3a1"
"11=#f9e2af"
"12=#89b4fa"
"13=#f5c2e7"
"14=#94e2d5"
"15=#a6adc8"
];
background = "1e1e2e";
foreground = "cdd6f4";
cursor-color = "f5e0dc";
selection-background = "353749";
selection-foreground = "cdd6f4";
themes = lib.mkOption {
type = lib.types.attrsOf keyValue.type;
default = { };
example = {
catppuccin-mocha = {
palette = [
"0=#45475a"
"1=#f38ba8"
"2=#a6e3a1"
"3=#f9e2af"
"4=#89b4fa"
"5=#f5c2e7"
"6=#94e2d5"
"7=#bac2de"
"8=#585b70"
"9=#f38ba8"
"10=#a6e3a1"
"11=#f9e2af"
"12=#89b4fa"
"13=#f5c2e7"
"14=#94e2d5"
"15=#a6adc8"
];
background = "1e1e2e";
foreground = "cdd6f4";
cursor-color = "f5e0dc";
selection-background = "353749";
selection-foreground = "cdd6f4";
};
};
description = ''
Custom themes written to {file}`$XDG_CONFIG_HOME/ghostty/themes`.
See <https://ghostty.org/docs/features/theme#authoring-a-custom-theme> for more information.
'';
};
description = ''
Custom themes written to {file}`$XDG_CONFIG_HOME/ghostty/themes`.
See <https://ghostty.org/docs/features/theme#authoring-a-custom-theme> for more information.
'';
};
clearDefaultKeybinds = lib.mkEnableOption "" // {
description = "Whether to clear default keybinds.";
};
clearDefaultKeybinds = lib.mkEnableOption "" // {
description = "Whether to clear default keybinds.";
};
installVimSyntax = lib.mkEnableOption "installation of Ghostty configuration syntax for Vim";
installVimSyntax =
lib.mkEnableOption "installation of Ghostty configuration syntax for Vim";
installBatSyntax =
lib.mkEnableOption "installation of Ghostty configuration syntax for bat"
// {
installBatSyntax = lib.mkEnableOption "installation of Ghostty configuration syntax for bat" // {
default = cfg.package != null;
defaultText =
lib.literalMD "`true` if programs.ghostty.package is not null";
defaultText = lib.literalMD "`true` if programs.ghostty.package is not null";
};
enableBashIntegration = mkShellIntegrationOption
(lib.hm.shell.mkBashIntegrationOption { inherit config; });
enableBashIntegration = mkShellIntegrationOption (
lib.hm.shell.mkBashIntegrationOption { inherit config; }
);
enableFishIntegration = mkShellIntegrationOption
(lib.hm.shell.mkFishIntegrationOption { inherit config; });
enableFishIntegration = mkShellIntegrationOption (
lib.hm.shell.mkFishIntegrationOption { inherit config; }
);
enableZshIntegration = mkShellIntegrationOption
(lib.hm.shell.mkZshIntegrationOption { inherit config; });
};
enableZshIntegration = mkShellIntegrationOption (
lib.hm.shell.mkZshIntegrationOption { inherit config; }
);
};
config = lib.mkIf cfg.enable (lib.mkMerge [
{
home.packages = lib.optionals (cfg.package != null) [ cfg.package ];
config = lib.mkIf cfg.enable (
lib.mkMerge [
{
home.packages = lib.optionals (cfg.package != null) [ cfg.package ];
programs.ghostty.settings = lib.mkIf cfg.clearDefaultKeybinds {
keybind = lib.mkBefore [ "clear" ];
};
# MacOS also supports XDG configuration directory, so we use it for both
# Linux and macOS to reduce complexity
xdg.configFile = let
validate = file:
lib.mkIf (cfg.package != null) "${
lib.getExe cfg.package
} +validate-config --config-file=${config.xdg.configHome}/ghostty/${file}";
in lib.mkMerge [
{
"ghostty/config" = lib.mkIf (cfg.settings != { }) {
source = keyValue.generate "ghostty-config" cfg.settings;
onChange = validate "config";
};
}
(lib.mkIf (cfg.themes != { }) (lib.mapAttrs' (name: value: {
name = "ghostty/themes/${name}";
value = {
source = keyValue.generate "ghostty-${name}-theme" value;
onChange = validate "themes/${name}";
};
}) cfg.themes))
];
}
(lib.mkIf cfg.installVimSyntax {
assertions = [{
assertion = cfg.installVimSyntax -> cfg.package != null;
message =
"programs.ghostty.installVimSyntax cannot be enabled when programs.ghostty.package is null";
}];
programs.vim.plugins =
lib.optionals (cfg.package != null) [ cfg.package.vim ];
})
(lib.mkIf cfg.installBatSyntax {
assertions = [{
assertion = cfg.installBatSyntax -> cfg.package != null;
message =
"programs.ghostty.installBatSyntax cannot be enabled when programs.ghostty.package is null";
}];
programs.bat = lib.mkIf (cfg.package != null) {
syntaxes.ghostty = {
src = cfg.package;
file = "share/bat/syntaxes/ghostty.sublime-syntax";
programs.ghostty.settings = lib.mkIf cfg.clearDefaultKeybinds {
keybind = lib.mkBefore [ "clear" ];
};
config.map-syntax =
[ "${config.xdg.configHome}/ghostty/config:Ghostty Config" ];
};
})
(lib.mkIf cfg.enableBashIntegration {
# Make order 101 to be placed exactly after bash completions, as Ghostty
# documentation suggests sourcing the script as soon as possible
programs.bash.initExtra = lib.mkOrder 101 ''
if [[ -n "''${GHOSTTY_RESOURCES_DIR}" ]]; then
builtin source "''${GHOSTTY_RESOURCES_DIR}/shell-integration/bash/ghostty.bash"
fi
'';
})
# MacOS also supports XDG configuration directory, so we use it for both
# Linux and macOS to reduce complexity
xdg.configFile =
let
validate =
file:
lib.mkIf (cfg.package != null)
"${lib.getExe cfg.package} +validate-config --config-file=${config.xdg.configHome}/ghostty/${file}";
in
lib.mkMerge [
{
"ghostty/config" = lib.mkIf (cfg.settings != { }) {
source = keyValue.generate "ghostty-config" cfg.settings;
onChange = validate "config";
};
}
(lib.mkIf cfg.enableFishIntegration {
programs.fish.shellInit = ''
if set -q GHOSTTY_RESOURCES_DIR
source "$GHOSTTY_RESOURCES_DIR/shell-integration/fish/vendor_conf.d/ghostty-shell-integration.fish"
end
'';
})
(lib.mkIf (cfg.themes != { }) (
lib.mapAttrs' (name: value: {
name = "ghostty/themes/${name}";
value = {
source = keyValue.generate "ghostty-${name}-theme" value;
onChange = validate "themes/${name}";
};
}) cfg.themes
))
];
}
(lib.mkIf cfg.enableZshIntegration {
programs.zsh.initContent = ''
if [[ -n $GHOSTTY_RESOURCES_DIR ]]; then
source "$GHOSTTY_RESOURCES_DIR"/shell-integration/zsh/ghostty-integration
fi
'';
})
]);
(lib.mkIf cfg.installVimSyntax {
assertions = [
{
assertion = cfg.installVimSyntax -> cfg.package != null;
message = "programs.ghostty.installVimSyntax cannot be enabled when programs.ghostty.package is null";
}
];
programs.vim.plugins = lib.optionals (cfg.package != null) [ cfg.package.vim ];
})
(lib.mkIf cfg.installBatSyntax {
assertions = [
{
assertion = cfg.installBatSyntax -> cfg.package != null;
message = "programs.ghostty.installBatSyntax cannot be enabled when programs.ghostty.package is null";
}
];
programs.bat = lib.mkIf (cfg.package != null) {
syntaxes.ghostty = {
src = cfg.package;
file = "share/bat/syntaxes/ghostty.sublime-syntax";
};
config.map-syntax = [ "${config.xdg.configHome}/ghostty/config:Ghostty Config" ];
};
})
(lib.mkIf cfg.enableBashIntegration {
# Make order 101 to be placed exactly after bash completions, as Ghostty
# documentation suggests sourcing the script as soon as possible
programs.bash.initExtra = lib.mkOrder 101 ''
if [[ -n "''${GHOSTTY_RESOURCES_DIR}" ]]; then
builtin source "''${GHOSTTY_RESOURCES_DIR}/shell-integration/bash/ghostty.bash"
fi
'';
})
(lib.mkIf cfg.enableFishIntegration {
programs.fish.shellInit = ''
if set -q GHOSTTY_RESOURCES_DIR
source "$GHOSTTY_RESOURCES_DIR/shell-integration/fish/vendor_conf.d/ghostty-shell-integration.fish"
end
'';
})
(lib.mkIf cfg.enableZshIntegration {
programs.zsh.initContent = ''
if [[ -n $GHOSTTY_RESOURCES_DIR ]]; then
source "$GHOSTTY_RESOURCES_DIR"/shell-integration/zsh/ghostty-integration
fi
'';
})
]
);
}

View file

@ -1,8 +1,14 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.git-cliff;
tomlFormat = pkgs.formats.toml { };
in {
in
{
meta.maintainers = [ lib.hm.maintainers.NateCox ];
options.programs.git-cliff = {

View file

@ -1,10 +1,16 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.git-credential-oauth;
in {
in
{
meta.maintainers = [ lib.maintainers.tomodachi94 ];
options = {
@ -30,9 +36,10 @@ in {
home.packages = [ cfg.package ];
programs.git.extraConfig.credential.helper = lib.mkAfter [
("${cfg.package}/bin/git-credential-oauth"
+ lib.optionalString (cfg.extraFlags != [ ])
" ${lib.strings.concatStringsSep " " cfg.extraFlags}")
(
"${cfg.package}/bin/git-credential-oauth"
+ lib.optionalString (cfg.extraFlags != [ ]) " ${lib.strings.concatStringsSep " " cfg.extraFlags}"
)
];
};
}

View file

@ -1,39 +1,46 @@
{ pkgs, config, lib, ... }:
{
pkgs,
config,
lib,
...
}:
let
inherit (lib) mkEnableOption mkPackageOption optionalString;
cfg = config.programs.git-worktree-switcher;
initScript = shell:
if (shell == "fish") then ''
${lib.getExe pkgs.git-worktree-switcher} init ${shell} | source
'' else ''
eval "$(${lib.getExe pkgs.git-worktree-switcher} init ${shell})"
'';
in {
meta.maintainers = with lib.maintainers; [ jiriks74 mateusauler ];
initScript =
shell:
if (shell == "fish") then
''
${lib.getExe pkgs.git-worktree-switcher} init ${shell} | source
''
else
''
eval "$(${lib.getExe pkgs.git-worktree-switcher} init ${shell})"
'';
in
{
meta.maintainers = with lib.maintainers; [
jiriks74
mateusauler
];
options.programs.git-worktree-switcher = {
enable = mkEnableOption "git-worktree-switcher";
package = mkPackageOption pkgs "git-worktree-switcher" { };
enableBashIntegration =
lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableBashIntegration = lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableFishIntegration =
lib.hm.shell.mkFishIntegrationOption { inherit config; };
enableFishIntegration = lib.hm.shell.mkFishIntegrationOption { inherit config; };
enableZshIntegration =
lib.hm.shell.mkZshIntegrationOption { inherit config; };
enableZshIntegration = lib.hm.shell.mkZshIntegrationOption { inherit config; };
};
config = lib.mkIf cfg.enable {
home.packages = [ cfg.package ];
programs.bash.initExtra =
optionalString cfg.enableBashIntegration (initScript "bash");
programs.fish.interactiveShellInit =
optionalString cfg.enableFishIntegration (initScript "fish");
programs.zsh.initContent =
optionalString cfg.enableZshIntegration (initScript "zsh");
programs.bash.initExtra = optionalString cfg.enableBashIntegration (initScript "bash");
programs.fish.interactiveShellInit = optionalString cfg.enableFishIntegration (initScript "fish");
programs.zsh.initContent = optionalString cfg.enableZshIntegration (initScript "zsh");
};
}

View file

@ -1,76 +1,102 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib)
concatStringsSep literalExpression mkDefault mkEnableOption mkIf mkOption
mkOptionDefault mkPackageOption types;
concatStringsSep
literalExpression
mkDefault
mkEnableOption
mkIf
mkOption
mkOptionDefault
mkPackageOption
types
;
cfg = config.programs.git;
gitIniType = with types;
gitIniType =
with types;
let
primitiveType = either str (either bool int);
multipleType = either primitiveType (listOf primitiveType);
sectionType = attrsOf multipleType;
supersectionType = attrsOf (either multipleType sectionType);
in attrsOf supersectionType;
in
attrsOf supersectionType;
includeModule = types.submodule ({ config, ... }: {
options = {
condition = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Include this configuration only when {var}`condition`
matches. Allowed conditions are described in
{manpage}`git-config(1)`.
'';
};
includeModule = types.submodule (
{ config, ... }:
{
options = {
condition = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Include this configuration only when {var}`condition`
matches. Allowed conditions are described in
{manpage}`git-config(1)`.
'';
};
path = mkOption {
type = with types; either str path;
description = "Path of the configuration file to include.";
};
path = mkOption {
type = with types; either str path;
description = "Path of the configuration file to include.";
};
contents = mkOption {
type = types.attrsOf types.anything;
default = { };
example = literalExpression ''
{
user = {
email = "bob@work.example.com";
name = "Bob Work";
signingKey = "1A2B3C4D5E6F7G8H";
contents = mkOption {
type = types.attrsOf types.anything;
default = { };
example = literalExpression ''
{
user = {
email = "bob@work.example.com";
name = "Bob Work";
signingKey = "1A2B3C4D5E6F7G8H";
};
commit = {
gpgSign = true;
};
};
commit = {
gpgSign = true;
};
};
'';
description = ''
Configuration to include. If empty then a path must be given.
'';
description = ''
Configuration to include. If empty then a path must be given.
This follows the configuration structure as described in
{manpage}`git-config(1)`.
'';
This follows the configuration structure as described in
{manpage}`git-config(1)`.
'';
};
contentSuffix = mkOption {
type = types.str;
default = "gitconfig";
description = ''
Nix store name for the git configuration text file,
when generating the configuration text from nix options.
'';
};
};
config.path = mkIf (config.contents != { }) (
mkDefault (
pkgs.writeText (lib.hm.strings.storeFileName config.contentSuffix) (
lib.generators.toGitINI config.contents
)
)
);
}
);
contentSuffix = mkOption {
type = types.str;
default = "gitconfig";
description = ''
Nix store name for the git configuration text file,
when generating the configuration text from nix options.
'';
};
};
config.path = mkIf (config.contents != { }) (mkDefault
(pkgs.writeText (lib.hm.strings.storeFileName config.contentSuffix)
(lib.generators.toGitINI config.contents)));
});
in {
meta.maintainers = with lib.maintainers; [ khaneliman rycee ];
in
{
meta.maintainers = with lib.maintainers; [
khaneliman
rycee
];
options = {
programs.git = {
@ -99,7 +125,9 @@ in {
aliases = mkOption {
type = types.attrsOf types.str;
default = { };
example = { co = "checkout"; };
example = {
co = "checkout";
};
description = "Git aliases to define.";
};
@ -116,7 +144,13 @@ in {
};
format = mkOption {
type = types.nullOr (types.enum [ "openpgp" "ssh" "x509" ]);
type = types.nullOr (
types.enum [
"openpgp"
"ssh"
"x509"
]
);
defaultText = literalExpression ''
"openpgp" for state version < 25.05,
undefined for state version 25.05
@ -143,7 +177,9 @@ in {
type = types.either types.lines gitIniType;
default = { };
example = {
core = { whitespace = "trailing-space,space-before-tab"; };
core = {
whitespace = "trailing-space,space-before-tab";
};
url."ssh://git@host".insteadOf = "otherhost";
};
description = ''
@ -175,7 +211,10 @@ in {
ignores = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "*~" "*.swp" ];
example = [
"*~"
"*.swp"
];
description = "List of paths that should be globally ignored.";
};
@ -264,7 +303,10 @@ in {
pagerOpts = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "--tabs=4" "-RFX" ];
example = [
"--tabs=4"
"-RFX"
];
description = ''
Arguments to be passed to {command}`less`.
'';
@ -289,7 +331,10 @@ in {
};
background = mkOption {
type = types.enum [ "light" "dark" ];
type = types.enum [
"light"
"dark"
];
default = "light";
example = "dark";
description = ''
@ -299,7 +344,11 @@ in {
};
color = mkOption {
type = types.enum [ "always" "auto" "never" ];
type = types.enum [
"always"
"auto"
"never"
];
default = "auto";
example = "always";
description = ''
@ -308,8 +357,11 @@ in {
};
display = mkOption {
type =
types.enum [ "side-by-side" "side-by-side-show-both" "inline" ];
type = types.enum [
"side-by-side"
"side-by-side-show-both"
"inline"
];
default = "side-by-side";
example = "inline";
description = ''
@ -329,11 +381,13 @@ in {
package = mkPackageOption pkgs "delta" { };
options = mkOption {
type = with types;
type =
with types;
let
primitiveType = either str (either bool int);
sectionType = attrsOf primitiveType;
in attrsOf (either primitiveType sectionType);
in
attrsOf (either primitiveType sectionType);
default = { };
example = {
features = "decorations";
@ -360,7 +414,10 @@ in {
pagerOpts = mkOption {
type = types.listOf types.str;
default = [ "--tabs=4" "-RFX" ];
default = [
"--tabs=4"
"-RFX"
];
description = ''
Arguments to be passed to {command}`less`.
'';
@ -443,300 +500,363 @@ in {
};
imports = [
(lib.mkRenamedOptionModule [ "programs" "git" "signing" "gpgPath" ] [
"programs"
"git"
"signing"
"signer"
])
(lib.mkRenamedOptionModule
[ "programs" "git" "signing" "gpgPath" ]
[
"programs"
"git"
"signing"
"signer"
]
)
];
config = mkIf cfg.enable (lib.mkMerge [
{
home.packages = [ cfg.package ];
config = mkIf cfg.enable (
lib.mkMerge [
{
home.packages = [ cfg.package ];
assertions = [{
assertion = let
enabled = [
cfg.delta.enable
cfg.diff-so-fancy.enable
cfg.difftastic.enable
cfg.diff-highlight.enable
cfg.riff.enable
];
in lib.count lib.id enabled <= 1;
message =
"Only one of 'programs.git.delta.enable' or 'programs.git.difftastic.enable' or 'programs.git.diff-so-fancy.enable' or 'programs.git.diff-highlight' can be set to true at the same time.";
}];
programs.git.iniContent.user = {
name = mkIf (cfg.userName != null) cfg.userName;
email = mkIf (cfg.userEmail != null) cfg.userEmail;
};
xdg.configFile = {
"git/config".text = lib.generators.toGitINI cfg.iniContent;
"git/ignore" = mkIf (cfg.ignores != [ ]) {
text = concatStringsSep "\n" cfg.ignores + "\n";
};
"git/attributes" = mkIf (cfg.attributes != [ ]) {
text = concatStringsSep "\n" cfg.attributes + "\n";
};
};
}
{
programs.git.iniContent = let
hasSmtp = name: account: account.smtp != null;
genIdentity = name: account:
let inherit (account) address realName smtp userName;
in lib.nameValuePair "sendemail.${name}"
(if account.msmtp.enable then {
sendmailCmd = "${pkgs.msmtp}/bin/msmtp";
envelopeSender = "auto";
from = "${realName} <${address}>";
} else
{
smtpEncryption = if smtp.tls.enable then
(if smtp.tls.useStartTls
|| lib.versionOlder config.home.stateVersion "20.09" then
"tls"
else
"ssl")
else
"";
smtpSslCertPath =
mkIf smtp.tls.enable (toString smtp.tls.certificatesFile);
smtpServer = smtp.host;
smtpUser = userName;
from = "${realName} <${address}>";
} // lib.optionalAttrs (smtp.port != null) {
smtpServerPort = smtp.port;
});
in lib.mapAttrs' genIdentity
(lib.filterAttrs hasSmtp config.accounts.email.accounts);
}
(mkIf (cfg.signing != { }) {
programs.git = {
signing = {
format = if (lib.versionOlder config.home.stateVersion "25.05") then
(mkOptionDefault "openpgp")
else
(mkOptionDefault null);
signer = let
defaultSigners = {
openpgp = lib.getExe config.programs.gpg.package;
ssh = lib.getExe' pkgs.openssh "ssh-keygen";
x509 = lib.getExe' config.programs.gpg.package "gpgsm";
};
in mkIf (cfg.signing.format != null)
(mkOptionDefault defaultSigners.${cfg.signing.format});
};
iniContent = lib.mkMerge [
(mkIf (cfg.signing.key != null) {
user.signingKey = mkDefault cfg.signing.key;
})
(mkIf (cfg.signing.signByDefault != null) {
commit.gpgSign = mkDefault cfg.signing.signByDefault;
tag.gpgSign = mkDefault cfg.signing.signByDefault;
})
(mkIf (cfg.signing.format != null) {
gpg = {
format = mkDefault cfg.signing.format;
${cfg.signing.format}.program = mkDefault cfg.signing.signer;
};
})
assertions = [
{
assertion =
let
enabled = [
cfg.delta.enable
cfg.diff-so-fancy.enable
cfg.difftastic.enable
cfg.diff-highlight.enable
cfg.riff.enable
];
in
lib.count lib.id enabled <= 1;
message = "Only one of 'programs.git.delta.enable' or 'programs.git.difftastic.enable' or 'programs.git.diff-so-fancy.enable' or 'programs.git.diff-highlight' can be set to true at the same time.";
}
];
};
})
(mkIf (cfg.hooks != { }) {
programs.git.iniContent = {
core.hooksPath = let
entries =
lib.mapAttrsToList (name: path: { inherit name path; }) cfg.hooks;
in toString (pkgs.linkFarm "git-hooks" entries);
};
})
programs.git.iniContent.user = {
name = mkIf (cfg.userName != null) cfg.userName;
email = mkIf (cfg.userEmail != null) cfg.userEmail;
};
(mkIf (cfg.aliases != { }) { programs.git.iniContent.alias = cfg.aliases; })
xdg.configFile = {
"git/config".text = lib.generators.toGitINI cfg.iniContent;
(mkIf (lib.isAttrs cfg.extraConfig) {
programs.git.iniContent = cfg.extraConfig;
})
(mkIf (lib.isString cfg.extraConfig) {
warnings = [''
Using programs.git.extraConfig as a string option is
deprecated and will be removed in the future. Please
change to using it as an attribute set instead.
''];
xdg.configFile."git/config".text = cfg.extraConfig;
})
(mkIf (cfg.includes != [ ]) {
xdg.configFile."git/config".text = let
include = i:
with i;
if condition != null then {
includeIf.${condition}.path = "${path}";
} else {
include.path = "${path}";
"git/ignore" = mkIf (cfg.ignores != [ ]) {
text = concatStringsSep "\n" cfg.ignores + "\n";
};
in lib.mkAfter (concatStringsSep "\n"
(map lib.generators.toGitINI (map include cfg.includes)));
})
(mkIf cfg.lfs.enable {
home.packages = [ pkgs.git-lfs ];
programs.git.iniContent.filter.lfs =
let skipArg = lib.optional cfg.lfs.skipSmudge "--skip";
in {
clean = "git-lfs clean -- %f";
process =
concatStringsSep " " ([ "git-lfs" "filter-process" ] ++ skipArg);
required = true;
smudge = concatStringsSep " "
([ "git-lfs" "smudge" ] ++ skipArg ++ [ "--" "%f" ]);
"git/attributes" = mkIf (cfg.attributes != [ ]) {
text = concatStringsSep "\n" cfg.attributes + "\n";
};
};
})
}
(mkIf cfg.maintenance.enable {
programs.git.iniContent.maintenance.repo = cfg.maintenance.repositories;
{
programs.git.iniContent =
let
hasSmtp = name: account: account.smtp != null;
systemd.user.services."git-maintenance@" = {
Unit = {
Description = "Optimize Git repositories data";
Documentation = [ "man:git-maintenance(1)" ];
genIdentity =
name: account:
let
inherit (account)
address
realName
smtp
userName
;
in
lib.nameValuePair "sendemail.${name}" (
if account.msmtp.enable then
{
sendmailCmd = "${pkgs.msmtp}/bin/msmtp";
envelopeSender = "auto";
from = "${realName} <${address}>";
}
else
{
smtpEncryption =
if smtp.tls.enable then
(if smtp.tls.useStartTls || lib.versionOlder config.home.stateVersion "20.09" then "tls" else "ssl")
else
"";
smtpSslCertPath = mkIf smtp.tls.enable (toString smtp.tls.certificatesFile);
smtpServer = smtp.host;
smtpUser = userName;
from = "${realName} <${address}>";
}
// lib.optionalAttrs (smtp.port != null) {
smtpServerPort = smtp.port;
}
);
in
lib.mapAttrs' genIdentity (lib.filterAttrs hasSmtp config.accounts.email.accounts);
}
(mkIf (cfg.signing != { }) {
programs.git = {
signing = {
format =
if (lib.versionOlder config.home.stateVersion "25.05") then
(mkOptionDefault "openpgp")
else
(mkOptionDefault null);
signer =
let
defaultSigners = {
openpgp = lib.getExe config.programs.gpg.package;
ssh = lib.getExe' pkgs.openssh "ssh-keygen";
x509 = lib.getExe' config.programs.gpg.package "gpgsm";
};
in
mkIf (cfg.signing.format != null) (mkOptionDefault defaultSigners.${cfg.signing.format});
};
iniContent = lib.mkMerge [
(mkIf (cfg.signing.key != null) {
user.signingKey = mkDefault cfg.signing.key;
})
(mkIf (cfg.signing.signByDefault != null) {
commit.gpgSign = mkDefault cfg.signing.signByDefault;
tag.gpgSign = mkDefault cfg.signing.signByDefault;
})
(mkIf (cfg.signing.format != null) {
gpg = {
format = mkDefault cfg.signing.format;
${cfg.signing.format}.program = mkDefault cfg.signing.signer;
};
})
];
};
})
(mkIf (cfg.hooks != { }) {
programs.git.iniContent = {
core.hooksPath =
let
entries = lib.mapAttrsToList (name: path: { inherit name path; }) cfg.hooks;
in
toString (pkgs.linkFarm "git-hooks" entries);
};
})
(mkIf (cfg.aliases != { }) { programs.git.iniContent.alias = cfg.aliases; })
(mkIf (lib.isAttrs cfg.extraConfig) {
programs.git.iniContent = cfg.extraConfig;
})
(mkIf (lib.isString cfg.extraConfig) {
warnings = [
''
Using programs.git.extraConfig as a string option is
deprecated and will be removed in the future. Please
change to using it as an attribute set instead.
''
];
xdg.configFile."git/config".text = cfg.extraConfig;
})
(mkIf (cfg.includes != [ ]) {
xdg.configFile."git/config".text =
let
include =
i:
with i;
if condition != null then
{
includeIf.${condition}.path = "${path}";
}
else
{
include.path = "${path}";
};
in
lib.mkAfter (concatStringsSep "\n" (map lib.generators.toGitINI (map include cfg.includes)));
})
(mkIf cfg.lfs.enable {
home.packages = [ pkgs.git-lfs ];
programs.git.iniContent.filter.lfs =
let
skipArg = lib.optional cfg.lfs.skipSmudge "--skip";
in
{
clean = "git-lfs clean -- %f";
process = concatStringsSep " " (
[
"git-lfs"
"filter-process"
]
++ skipArg
);
required = true;
smudge = concatStringsSep " " (
[
"git-lfs"
"smudge"
]
++ skipArg
++ [
"--"
"%f"
]
);
};
})
(mkIf cfg.maintenance.enable {
programs.git.iniContent.maintenance.repo = cfg.maintenance.repositories;
systemd.user.services."git-maintenance@" = {
Unit = {
Description = "Optimize Git repositories data";
Documentation = [ "man:git-maintenance(1)" ];
};
Service = {
Type = "oneshot";
ExecStart =
let
exe = lib.getExe cfg.package;
in
''
"${exe}" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%i
'';
LockPersonality = "yes";
MemoryDenyWriteExecute = "yes";
NoNewPrivileges = "yes";
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_VSOCK";
RestrictNamespaces = "yes";
RestrictRealtime = "yes";
RestrictSUIDSGID = "yes";
SystemCallArchitectures = "native";
SystemCallFilter = "@system-service";
};
};
Service = {
Type = "oneshot";
ExecStart = let exe = lib.getExe cfg.package;
in ''
"${exe}" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%i
'';
LockPersonality = "yes";
MemoryDenyWriteExecute = "yes";
NoNewPrivileges = "yes";
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_VSOCK";
RestrictNamespaces = "yes";
RestrictRealtime = "yes";
RestrictSUIDSGID = "yes";
SystemCallArchitectures = "native";
SystemCallFilter = "@system-service";
};
};
systemd.user.timers =
let
toSystemdTimer =
name: time:
lib.attrsets.nameValuePair "git-maintenance@${name}" {
Unit.Description = "Optimize Git repositories data";
systemd.user.timers = let
toSystemdTimer = name: time:
lib.attrsets.nameValuePair "git-maintenance@${name}" {
Unit.Description = "Optimize Git repositories data";
Timer = {
OnCalendar = time;
Persistent = true;
};
Timer = {
OnCalendar = time;
Persistent = true;
Install.WantedBy = [ "timers.target" ];
};
in
lib.attrsets.mapAttrs' toSystemdTimer cfg.maintenance.timers;
})
(mkIf cfg.diff-highlight.enable {
programs.git.iniContent =
let
dhCommand = "${cfg.package}/share/git/contrib/diff-highlight/diff-highlight";
in
{
core.pager = "${dhCommand} | ${lib.getExe pkgs.less} ${lib.escapeShellArgs cfg.diff-highlight.pagerOpts}";
interactive.diffFilter = dhCommand;
};
})
(
let
difftCommand = concatStringsSep " " [
"${lib.getExe cfg.difftastic.package}"
"--color ${cfg.difftastic.color}"
"--background ${cfg.difftastic.background}"
"--display ${cfg.difftastic.display}"
];
in
(lib.mkMerge [
(mkIf cfg.difftastic.enable {
home.packages = [ cfg.difftastic.package ];
programs.git.iniContent = {
diff.external = difftCommand;
};
})
(mkIf cfg.difftastic.enableAsDifftool {
home.packages = [ cfg.difftastic.package ];
programs.git.iniContent = {
diff = {
tool = lib.mkDefault "difftastic";
};
difftool = {
difftastic = {
cmd = "${difftCommand} $LOCAL $REMOTE";
};
};
};
})
])
)
(
let
deltaPackage = cfg.delta.package;
deltaCommand = "${deltaPackage}/bin/delta";
in
mkIf cfg.delta.enable {
home.packages = [ deltaPackage ];
programs.git.iniContent = {
core.pager = deltaCommand;
interactive.diffFilter = "${deltaCommand} --color-only";
delta = cfg.delta.options;
};
}
)
(mkIf cfg.diff-so-fancy.enable {
home.packages = [ pkgs.diff-so-fancy ];
programs.git.iniContent =
let
dsfCommand = "${pkgs.diff-so-fancy}/bin/diff-so-fancy";
in
{
core.pager = "${dsfCommand} | ${pkgs.less}/bin/less ${lib.escapeShellArgs cfg.diff-so-fancy.pagerOpts}";
interactive.diffFilter = "${dsfCommand} --patch";
diff-so-fancy = {
markEmptyLines = cfg.diff-so-fancy.markEmptyLines;
changeHunkIndicators = cfg.diff-so-fancy.changeHunkIndicators;
stripLeadingSymbols = cfg.diff-so-fancy.stripLeadingSymbols;
useUnicodeRuler = cfg.diff-so-fancy.useUnicodeRuler;
rulerWidth = mkIf (cfg.diff-so-fancy.rulerWidth != null) (cfg.diff-so-fancy.rulerWidth);
};
};
})
(
let
riffExe = baseNameOf (lib.getExe cfg.riff.package);
in
mkIf cfg.riff.enable {
home.packages = [ cfg.riff.package ];
# https://github.com/walles/riff/blob/b17e6f17ce807c8652bc59cd46758661d23ce358/README.md#usage
programs.git.iniContent = {
pager = {
diff = riffExe;
log = riffExe;
show = riffExe;
};
Install.WantedBy = [ "timers.target" ];
interactive.diffFilter = "${riffExe} --color=on";
};
in lib.attrsets.mapAttrs' toSystemdTimer cfg.maintenance.timers;
})
}
)
(mkIf cfg.diff-highlight.enable {
programs.git.iniContent = let
dhCommand =
"${cfg.package}/share/git/contrib/diff-highlight/diff-highlight";
in {
core.pager = "${dhCommand} | ${lib.getExe pkgs.less} ${
lib.escapeShellArgs cfg.diff-highlight.pagerOpts
}";
interactive.diffFilter = dhCommand;
};
})
(let
difftCommand = concatStringsSep " " [
"${lib.getExe cfg.difftastic.package}"
"--color ${cfg.difftastic.color}"
"--background ${cfg.difftastic.background}"
"--display ${cfg.difftastic.display}"
];
in (lib.mkMerge [
(mkIf cfg.difftastic.enable {
home.packages = [ cfg.difftastic.package ];
programs.git.iniContent = { diff.external = difftCommand; };
(mkIf (cfg.riff.enable && cfg.riff.commandLineOptions != "") {
home.sessionVariables.RIFF = cfg.riff.commandLineOptions;
})
(mkIf cfg.difftastic.enableAsDifftool {
home.packages = [ cfg.difftastic.package ];
programs.git.iniContent = {
diff = { tool = lib.mkDefault "difftastic"; };
difftool = {
difftastic = { cmd = "${difftCommand} $LOCAL $REMOTE"; };
};
};
})
]))
(let
deltaPackage = cfg.delta.package;
deltaCommand = "${deltaPackage}/bin/delta";
in mkIf cfg.delta.enable {
home.packages = [ deltaPackage ];
programs.git.iniContent = {
core.pager = deltaCommand;
interactive.diffFilter = "${deltaCommand} --color-only";
delta = cfg.delta.options;
};
})
(mkIf cfg.diff-so-fancy.enable {
home.packages = [ pkgs.diff-so-fancy ];
programs.git.iniContent =
let dsfCommand = "${pkgs.diff-so-fancy}/bin/diff-so-fancy";
in {
core.pager = "${dsfCommand} | ${pkgs.less}/bin/less ${
lib.escapeShellArgs cfg.diff-so-fancy.pagerOpts
}";
interactive.diffFilter = "${dsfCommand} --patch";
diff-so-fancy = {
markEmptyLines = cfg.diff-so-fancy.markEmptyLines;
changeHunkIndicators = cfg.diff-so-fancy.changeHunkIndicators;
stripLeadingSymbols = cfg.diff-so-fancy.stripLeadingSymbols;
useUnicodeRuler = cfg.diff-so-fancy.useUnicodeRuler;
rulerWidth = mkIf (cfg.diff-so-fancy.rulerWidth != null)
(cfg.diff-so-fancy.rulerWidth);
};
};
})
(let riffExe = baseNameOf (lib.getExe cfg.riff.package);
in mkIf cfg.riff.enable {
home.packages = [ cfg.riff.package ];
# https://github.com/walles/riff/blob/b17e6f17ce807c8652bc59cd46758661d23ce358/README.md#usage
programs.git.iniContent = {
pager = {
diff = riffExe;
log = riffExe;
show = riffExe;
};
interactive.diffFilter = "${riffExe} --color=on";
};
})
(mkIf (cfg.riff.enable && cfg.riff.commandLineOptions != "") {
home.sessionVariables.RIFF = cfg.riff.commandLineOptions;
})
]);
]
);
}

View file

@ -1,15 +1,20 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkOption types;
cfg = config.programs.gitui;
in {
in
{
meta.maintainers = [ lib.hm.maintainers.mifom ];
options.programs.gitui = {
enable = lib.mkEnableOption
"gitui, blazing fast terminal-ui for git written in rust";
enable = lib.mkEnableOption "gitui, blazing fast terminal-ui for git written in rust";
package = lib.mkPackageOption pkgs "gitui" { };

View file

@ -1,35 +1,42 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkOption types;
cfg = config.programs.gnome-shell;
extensionOpts = { config, ... }: {
options = {
id = mkOption {
type = types.str;
example = "user-theme@gnome-shell-extensions.gcampax.github.com";
description = ''
ID of the GNOME Shell extension. If not provided, it
will be obtained from `package.extensionUuid`.
'';
extensionOpts =
{ config, ... }:
{
options = {
id = mkOption {
type = types.str;
example = "user-theme@gnome-shell-extensions.gcampax.github.com";
description = ''
ID of the GNOME Shell extension. If not provided, it
will be obtained from `package.extensionUuid`.
'';
};
package = mkOption {
type = types.package;
example = "pkgs.gnome-shell-extensions";
description = ''
Package providing a GNOME Shell extension in
`$out/share/gnome-shell/extensions/''${id}`.
'';
};
};
package = mkOption {
type = types.package;
example = "pkgs.gnome-shell-extensions";
description = ''
Package providing a GNOME Shell extension in
`$out/share/gnome-shell/extensions/''${id}`.
'';
config = lib.mkIf (lib.hasAttr "extensionUuid" config.package) {
id = lib.mkDefault config.package.extensionUuid;
};
};
config = lib.mkIf (lib.hasAttr "extensionUuid" config.package) {
id = lib.mkDefault config.package.extensionUuid;
};
};
themeOpts = {
options = {
name = mkOption {
@ -52,7 +59,8 @@ let
};
};
in {
in
{
meta.maintainers = [ lib.maintainers.terlar ];
options.programs.gnome-shell = {
@ -90,26 +98,29 @@ in {
};
};
config = lib.mkIf cfg.enable (lib.mkMerge [
(lib.mkIf (cfg.extensions != [ ]) {
dconf.settings."org/gnome/shell" = {
disable-user-extensions = false;
enabled-extensions = lib.catAttrs "id" cfg.extensions;
};
config = lib.mkIf cfg.enable (
lib.mkMerge [
(lib.mkIf (cfg.extensions != [ ]) {
dconf.settings."org/gnome/shell" = {
disable-user-extensions = false;
enabled-extensions = lib.catAttrs "id" cfg.extensions;
};
home.packages = lib.catAttrs "package" cfg.extensions;
})
home.packages = lib.catAttrs "package" cfg.extensions;
})
(lib.mkIf (cfg.theme != null) {
dconf.settings."org/gnome/shell/extensions/user-theme".name =
cfg.theme.name;
(lib.mkIf (cfg.theme != null) {
dconf.settings."org/gnome/shell/extensions/user-theme".name = cfg.theme.name;
programs.gnome-shell.extensions = [{
id = "user-theme@gnome-shell-extensions.gcampax.github.com";
package = pkgs.gnome-shell-extensions;
}];
programs.gnome-shell.extensions = [
{
id = "user-theme@gnome-shell-extensions.gcampax.github.com";
package = pkgs.gnome-shell-extensions;
}
];
home.packages = [ cfg.theme.package ];
})
]);
home.packages = [ cfg.theme.package ];
})
]
);
}

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkOption types;
@ -12,206 +17,224 @@ let
"tty"
];
backForeSubModule = types.submodule ({ ... }: {
options = {
foreground = mkOption {
type = types.str;
description = "The foreground color.";
backForeSubModule = types.submodule (
{ ... }:
{
options = {
foreground = mkOption {
type = types.str;
description = "The foreground color.";
};
background = mkOption {
type = types.str;
description = "The background color.";
};
};
}
);
background = mkOption {
type = types.str;
description = "The background color.";
profileColorsSubModule = types.submodule (
{ ... }:
{
options = {
foregroundColor = mkOption {
type = types.str;
description = "The foreground color.";
};
backgroundColor = mkOption {
type = types.str;
description = "The background color.";
};
boldColor = mkOption {
default = null;
type = types.nullOr types.str;
description = "The bold color, null to use same as foreground.";
};
palette = mkOption {
type = types.listOf types.str;
description = "The terminal palette.";
};
cursor = mkOption {
default = null;
type = types.nullOr backForeSubModule;
description = "The color for the terminal cursor.";
};
highlight = mkOption {
default = null;
type = types.nullOr backForeSubModule;
description = "The colors for the terminals highlighted area.";
};
};
};
});
}
);
profileColorsSubModule = types.submodule ({ ... }: {
options = {
foregroundColor = mkOption {
type = types.str;
description = "The foreground color.";
profileSubModule = types.submodule (
{ name, config, ... }:
{
options = {
default = mkOption {
default = false;
type = types.bool;
description = "Whether this should be the default profile.";
};
visibleName = mkOption {
type = types.str;
description = "The profile name.";
};
colors = mkOption {
default = null;
type = types.nullOr profileColorsSubModule;
description = "The terminal colors, null to use system default.";
};
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"
];
description = "The cursor shape.";
};
font = mkOption {
default = null;
type = types.nullOr types.str;
description = "The font name, null to use system default.";
};
allowBold = mkOption {
default = null;
type = types.nullOr types.bool;
description = ''
If `true`, allow applications in the
terminal to make text boldface.
'';
};
scrollOnOutput = mkOption {
default = true;
type = types.bool;
description = "Whether to scroll when output is written.";
};
showScrollbar = mkOption {
default = true;
type = types.bool;
description = "Whether the scroll bar should be visible.";
};
scrollbackLines = mkOption {
default = 10000;
type = types.nullOr types.int;
description = ''
The number of scrollback lines to keep, null for infinite.
'';
};
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.";
};
backspaceBinding = mkOption {
default = "ascii-delete";
type = eraseBinding;
description = ''
Which string the terminal should send to an application when the user
presses the *Backspace* key.
`auto`
: Attempt to determine the right value from the terminal's IO settings.
`ascii-backspace`
: Send an ASCII backspace character (`0x08`).
`ascii-delete`
: Send an ASCII delete character (`0x7F`).
`delete-sequence`
: Send the `@7` control sequence.
`tty`
: Send terminal's "erase" setting.
'';
};
boldIsBright = mkOption {
default = null;
type = types.nullOr types.bool;
description = "Whether bold text is shown in bright colors.";
};
deleteBinding = mkOption {
default = "delete-sequence";
type = eraseBinding;
description = ''
Which string the terminal should send to an application when the user
presses the *Delete* key.
`auto`
: Send the `@7` control sequence.
`ascii-backspace`
: Send an ASCII backspace character (`0x08`).
`ascii-delete`
: Send an ASCII delete character (`0x7F`).
`delete-sequence`
: Send the `@7` control sequence.
`tty`
: Send terminal's "erase" setting.
'';
};
audibleBell = mkOption {
default = true;
type = types.bool;
description = "Turn on/off the terminal's bell.";
};
transparencyPercent = mkOption {
default = null;
type = types.nullOr (types.ints.between 0 100);
description = "Background transparency in percent.";
};
};
}
);
backgroundColor = mkOption {
type = types.str;
description = "The background color.";
};
boldColor = mkOption {
default = null;
type = types.nullOr types.str;
description = "The bold color, null to use same as foreground.";
};
palette = mkOption {
type = types.listOf types.str;
description = "The terminal palette.";
};
cursor = mkOption {
default = null;
type = types.nullOr backForeSubModule;
description = "The color for the terminal cursor.";
};
highlight = mkOption {
default = null;
type = types.nullOr backForeSubModule;
description = "The colors for the terminals highlighted area.";
};
};
});
profileSubModule = types.submodule ({ name, config, ... }: {
options = {
default = mkOption {
default = false;
type = types.bool;
description = "Whether this should be the default profile.";
};
visibleName = mkOption {
type = types.str;
description = "The profile name.";
};
colors = mkOption {
default = null;
type = types.nullOr profileColorsSubModule;
description = "The terminal colors, null to use system default.";
};
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" ];
description = "The cursor shape.";
};
font = mkOption {
default = null;
type = types.nullOr types.str;
description = "The font name, null to use system default.";
};
allowBold = mkOption {
default = null;
type = types.nullOr types.bool;
description = ''
If `true`, allow applications in the
terminal to make text boldface.
'';
};
scrollOnOutput = mkOption {
default = true;
type = types.bool;
description = "Whether to scroll when output is written.";
};
showScrollbar = mkOption {
default = true;
type = types.bool;
description = "Whether the scroll bar should be visible.";
};
scrollbackLines = mkOption {
default = 10000;
type = types.nullOr types.int;
description = ''
The number of scrollback lines to keep, null for infinite.
'';
};
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.";
};
backspaceBinding = mkOption {
default = "ascii-delete";
type = eraseBinding;
description = ''
Which string the terminal should send to an application when the user
presses the *Backspace* key.
`auto`
: Attempt to determine the right value from the terminal's IO settings.
`ascii-backspace`
: Send an ASCII backspace character (`0x08`).
`ascii-delete`
: Send an ASCII delete character (`0x7F`).
`delete-sequence`
: Send the `@7` control sequence.
`tty`
: Send terminal's "erase" setting.
'';
};
boldIsBright = mkOption {
default = null;
type = types.nullOr types.bool;
description = "Whether bold text is shown in bright colors.";
};
deleteBinding = mkOption {
default = "delete-sequence";
type = eraseBinding;
description = ''
Which string the terminal should send to an application when the user
presses the *Delete* key.
`auto`
: Send the `@7` control sequence.
`ascii-backspace`
: Send an ASCII backspace character (`0x08`).
`ascii-delete`
: Send an ASCII delete character (`0x7F`).
`delete-sequence`
: Send the `@7` control sequence.
`tty`
: Send terminal's "erase" setting.
'';
};
audibleBell = mkOption {
default = true;
type = types.bool;
description = "Turn on/off the terminal's bell.";
};
transparencyPercent = mkOption {
default = null;
type = types.nullOr (types.ints.between 0 100);
description = "Background transparency in percent.";
};
};
});
buildProfileSet = pcfg:
buildProfileSet =
pcfg:
{
audible-bell = pcfg.audibleBell;
visible-name = pcfg.visibleName;
@ -223,53 +246,97 @@ let
login-shell = pcfg.loginShell;
backspace-binding = pcfg.backspaceBinding;
delete-binding = pcfg.deleteBinding;
} // (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;
font = pcfg.font;
}) // (if (pcfg.colors == null) then {
use-theme-colors = true;
} else
({
use-theme-colors = false;
foreground-color = pcfg.colors.foregroundColor;
background-color = pcfg.colors.backgroundColor;
palette = pcfg.colors.palette;
} // lib.optionalAttrs (pcfg.allowBold != null) {
allow-bold = pcfg.allowBold;
} // (if (pcfg.colors.boldColor == null) then {
bold-color-same-as-fg = true;
} else {
bold-color-same-as-fg = false;
bold-color = pcfg.colors.boldColor;
}) // lib.optionalAttrs (pcfg.boldIsBright != null) {
bold-is-bright = pcfg.boldIsBright;
} // (if (pcfg.colors.cursor != null) then {
cursor-colors-set = true;
cursor-foreground-color = pcfg.colors.cursor.foreground;
cursor-background-color = pcfg.colors.cursor.background;
} else {
cursor-colors-set = false;
}) // (if (pcfg.colors.highlight != null) then {
highlight-colors-set = true;
highlight-foreground-color = pcfg.colors.highlight.foreground;
highlight-background-color = pcfg.colors.highlight.background;
} else {
highlight-colors-set = false;
}) // lib.optionalAttrs (pcfg.transparencyPercent != null) {
background-transparency-percent = pcfg.transparencyPercent;
use-theme-transparency = false;
use-transparent-background = true;
}));
}
// (
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;
font = pcfg.font;
}
)
// (
if (pcfg.colors == null) then
{
use-theme-colors = true;
}
else
(
{
use-theme-colors = false;
foreground-color = pcfg.colors.foregroundColor;
background-color = pcfg.colors.backgroundColor;
palette = pcfg.colors.palette;
}
// lib.optionalAttrs (pcfg.allowBold != null) {
allow-bold = pcfg.allowBold;
}
// (
if (pcfg.colors.boldColor == null) then
{
bold-color-same-as-fg = true;
}
else
{
bold-color-same-as-fg = false;
bold-color = pcfg.colors.boldColor;
}
)
// lib.optionalAttrs (pcfg.boldIsBright != null) {
bold-is-bright = pcfg.boldIsBright;
}
// (
if (pcfg.colors.cursor != null) then
{
cursor-colors-set = true;
cursor-foreground-color = pcfg.colors.cursor.foreground;
cursor-background-color = pcfg.colors.cursor.background;
}
else
{
cursor-colors-set = false;
}
)
// (
if (pcfg.colors.highlight != null) then
{
highlight-colors-set = true;
highlight-foreground-color = pcfg.colors.highlight.foreground;
highlight-background-color = pcfg.colors.highlight.background;
}
else
{
highlight-colors-set = false;
}
)
// lib.optionalAttrs (pcfg.transparencyPercent != null) {
background-transparency-percent = pcfg.transparencyPercent;
use-theme-transparency = false;
use-transparent-background = true;
}
)
);
in {
meta.maintainers = with lib.maintainers; [ kamadorueda rycee ];
in
{
meta.maintainers = with lib.maintainers; [
kamadorueda
rycee
];
options = {
programs.gnome-terminal = {
@ -283,7 +350,12 @@ in {
themeVariant = mkOption {
default = "default";
type = types.enum [ "default" "light" "dark" "system" ];
type = types.enum [
"default"
"light"
"dark"
"system"
];
description = "The theme variation to request";
};
@ -301,37 +373,41 @@ in {
config = lib.mkIf cfg.enable {
assertions = [
(let
uuidre =
"[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}";
erroneous = lib.filter (n: builtins.match uuidre n == null)
(lib.attrNames cfg.profile);
in {
assertion = erroneous == [ ];
message = ''
The attribute name of a Gnome Terminal profile must be a UUID.
Incorrect profile names: ${lib.concatStringsSep ", " erroneous}'';
})
(
let
uuidre = "[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}";
erroneous = lib.filter (n: builtins.match uuidre n == null) (lib.attrNames cfg.profile);
in
{
assertion = erroneous == [ ];
message = ''
The attribute name of a Gnome Terminal profile must be a UUID.
Incorrect profile names: ${lib.concatStringsSep ", " erroneous}'';
}
)
];
home.packages = [ pkgs.gnome-terminal ];
dconf.settings = let dconfPath = "org/gnome/terminal/legacy";
in {
"${dconfPath}" = {
default-show-menubar = cfg.showMenubar;
theme-variant = cfg.themeVariant;
schema-version = 3;
};
dconf.settings =
let
dconfPath = "org/gnome/terminal/legacy";
in
{
"${dconfPath}" = {
default-show-menubar = cfg.showMenubar;
theme-variant = cfg.themeVariant;
schema-version = 3;
};
"${dconfPath}/profiles:" = {
default = lib.head
(lib.attrNames (lib.filterAttrs (n: v: v.default) cfg.profile));
list = lib.attrNames cfg.profile;
};
} // lib.mapAttrs'
(n: v: lib.nameValuePair "${dconfPath}/profiles:/:${n}" (buildProfileSet v))
cfg.profile;
"${dconfPath}/profiles:" = {
default = lib.head (lib.attrNames (lib.filterAttrs (n: v: v.default) cfg.profile));
list = lib.attrNames cfg.profile;
};
}
// lib.mapAttrs' (
n: v: lib.nameValuePair "${dconfPath}/profiles:/:${n}" (buildProfileSet v)
) cfg.profile;
programs.bash.enableVteIntegration = true;
programs.zsh.enableVteIntegration = true;

View file

@ -1,12 +1,23 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) literalExpression mkIf mkOption types;
inherit (lib)
literalExpression
mkIf
mkOption
types
;
cfg = config.programs.go;
modeFileContent = "${cfg.telemetry.mode} ${cfg.telemetry.date}";
in {
in
{
meta.maintainers = [ lib.maintainers.rvolosatovs ];
options = {
@ -41,7 +52,10 @@ in {
extraGoPaths = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "extraGoPath1" "extraGoPath2" ];
example = [
"extraGoPath1"
"extraGoPath2"
];
description = ''
Extra {env}`GOPATH`s relative to {env}`HOME` appended
after [](#opt-programs.go.goPath), if that option is set.
@ -58,7 +72,10 @@ in {
goPrivate = mkOption {
type = with types; listOf str;
default = [ ];
example = [ "*.corp.example.com" "rsc.io/private" ];
example = [
"*.corp.example.com"
"rsc.io/private"
];
description = ''
The {env}`GOPRIVATE` environment variable controls
which modules the go command considers to be private (not
@ -71,7 +88,13 @@ in {
type = types.submodule {
options = {
mode = mkOption {
type = with types; nullOr (enum [ "off" "local" "on" ]);
type =
with types;
nullOr (enum [
"off"
"local"
"on"
]);
default = null;
description = "Go telemetry mode to be set.";
};
@ -94,41 +117,46 @@ in {
};
};
config = mkIf cfg.enable (lib.mkMerge [
{
home.packages = [ cfg.package ];
config = mkIf cfg.enable (
lib.mkMerge [
{
home.packages = [ cfg.package ];
home.file = let
goPath = if cfg.goPath != null then cfg.goPath else "go";
mkSrc = n: v: { "${goPath}/src/${n}".source = v; };
in lib.foldl' (a: b: a // b) { } (lib.mapAttrsToList mkSrc cfg.packages);
}
home.file =
let
goPath = if cfg.goPath != null then cfg.goPath else "go";
mkSrc = n: v: { "${goPath}/src/${n}".source = v; };
in
lib.foldl' (a: b: a // b) { } (lib.mapAttrsToList mkSrc cfg.packages);
}
(mkIf (cfg.goPath != null) {
home.sessionVariables.GOPATH = lib.concatStringsSep ":"
(map builtins.toPath (map (path: "${config.home.homeDirectory}/${path}")
([ cfg.goPath ] ++ cfg.extraGoPaths)));
})
(mkIf (cfg.goPath != null) {
home.sessionVariables.GOPATH = lib.concatStringsSep ":" (
map builtins.toPath (
map (path: "${config.home.homeDirectory}/${path}") ([ cfg.goPath ] ++ cfg.extraGoPaths)
)
);
})
(mkIf (cfg.goBin != null) {
home.sessionVariables.GOBIN =
builtins.toPath "${config.home.homeDirectory}/${cfg.goBin}";
})
(mkIf (cfg.goBin != null) {
home.sessionVariables.GOBIN = builtins.toPath "${config.home.homeDirectory}/${cfg.goBin}";
})
(mkIf (cfg.goPrivate != [ ]) {
home.sessionVariables.GOPRIVATE = lib.concatStringsSep "," cfg.goPrivate;
})
(mkIf (cfg.goPrivate != [ ]) {
home.sessionVariables.GOPRIVATE = lib.concatStringsSep "," cfg.goPrivate;
})
(mkIf (cfg.telemetry.mode != null) {
home.file."Library/Application Support/go/telemetry/mode" = {
enable = pkgs.stdenv.hostPlatform.isDarwin;
text = modeFileContent;
};
(mkIf (cfg.telemetry.mode != null) {
home.file."Library/Application Support/go/telemetry/mode" = {
enable = pkgs.stdenv.hostPlatform.isDarwin;
text = modeFileContent;
};
xdg.configFile."go/telemetry/mode" = {
enable = !pkgs.stdenv.hostPlatform.isDarwin;
text = modeFileContent;
};
})
]);
xdg.configFile."go/telemetry/mode" = {
enable = !pkgs.stdenv.hostPlatform.isDarwin;
text = modeFileContent;
};
})
]
);
}

View file

@ -1,14 +1,23 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) literalExpression mkDefault mkIf mkOption optional types;
inherit (lib)
literalExpression
mkDefault
mkIf
mkOption
optional
types
;
cfg = config.programs.gpg;
mkKeyValue = key: value:
if lib.isString value then
"${key} ${value}"
else
lib.optionalString value key;
mkKeyValue =
key: value: if lib.isString value then "${key} ${value}" else lib.optionalString value key;
cfgText = lib.generators.toKeyValue {
inherit mkKeyValue;
@ -20,126 +29,141 @@ let
listsAsDuplicateKeys = true;
} cfg.scdaemonSettings;
primitiveType = types.oneOf [ types.str types.bool ];
primitiveType = types.oneOf [
types.str
types.bool
];
publicKeyOpts = { config, ... }: {
options = {
text = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Text of an OpenPGP public key.
'';
publicKeyOpts =
{ config, ... }:
{
options = {
text = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Text of an OpenPGP public key.
'';
};
source = mkOption {
type = types.path;
description = ''
Path of an OpenPGP public key file.
'';
};
trust = mkOption {
type = types.nullOr (
types.enum [
"unknown"
1
"never"
2
"marginal"
3
"full"
4
"ultimate"
5
]
);
default = null;
apply =
v:
if lib.isString v then
{
unknown = 1;
never = 2;
marginal = 3;
full = 4;
ultimate = 5;
}
.${v}
else
v;
description = ''
The amount of trust you have in the key ownership and the care the
owner puts into signing other keys. The available levels are
`unknown` or `1`
: I don't know or won't say.
`never` or `2`
: I do **not** trust.
`marginal` or `3`
: I trust marginally.
`full` or `4`
: I trust fully.
`ultimate` or `5`
: I trust ultimately.
See the [Key Management chapter](https://www.gnupg.org/gph/en/manual/x334.html)
of the GNU Privacy Handbook for more.
'';
};
};
source = mkOption {
type = types.path;
description = ''
Path of an OpenPGP public key file.
'';
};
trust = mkOption {
type = types.nullOr (types.enum [
"unknown"
1
"never"
2
"marginal"
3
"full"
4
"ultimate"
5
]);
default = null;
apply = v:
if lib.isString v then
{
unknown = 1;
never = 2;
marginal = 3;
full = 4;
ultimate = 5;
}.${v}
else
v;
description = ''
The amount of trust you have in the key ownership and the care the
owner puts into signing other keys. The available levels are
`unknown` or `1`
: I don't know or won't say.
`never` or `2`
: I do **not** trust.
`marginal` or `3`
: I trust marginally.
`full` or `4`
: I trust fully.
`ultimate` or `5`
: I trust ultimately.
See the [Key Management chapter](https://www.gnupg.org/gph/en/manual/x334.html)
of the GNU Privacy Handbook for more.
'';
config = {
source = mkIf (config.text != null) (pkgs.writeText "gpg-pubkey" config.text);
};
};
config = {
source =
mkIf (config.text != null) (pkgs.writeText "gpg-pubkey" config.text);
};
};
importTrustBashFunctions =
let
gpg = "${cfg.package}/bin/gpg";
in
''
function gpgKeyId() {
${gpg} --show-key --with-colons "$1" \
| grep ^pub: \
| cut -d: -f5
}
importTrustBashFunctions = let gpg = "${cfg.package}/bin/gpg";
in ''
function gpgKeyId() {
${gpg} --show-key --with-colons "$1" \
| grep ^pub: \
| cut -d: -f5
}
function importTrust() {
local keyIds trust
IFS='\n' read -ra keyIds <<< "$(gpgKeyId "$1")"
trust="$2"
for id in "''${keyIds[@]}" ; do
{ echo trust; echo "$trust"; (( trust == 5 )) && echo y; echo quit; } \
| ${gpg} --no-tty --command-fd 0 --edit-key "$id"
done
}
function importTrust() {
local keyIds trust
IFS='\n' read -ra keyIds <<< "$(gpgKeyId "$1")"
trust="$2"
for id in "''${keyIds[@]}" ; do
{ echo trust; echo "$trust"; (( trust == 5 )) && echo y; echo quit; } \
| ${gpg} --no-tty --command-fd 0 --edit-key "$id"
done
}
'';
keyringFiles = let
gpg = "${cfg.package}/bin/gpg";
importKey = { source, trust, ... }: ''
${gpg} --import ${source}
${lib.optionalString (trust != null)
''importTrust "${source}" ${toString trust}''}
'';
importKeys = lib.concatMapStringsSep "\n" importKey cfg.publicKeys;
in pkgs.runCommand "gpg-pubring" { buildInputs = [ cfg.package ]; } ''
export GNUPGHOME
GNUPGHOME=$(mktemp -d)
keyringFiles =
let
gpg = "${cfg.package}/bin/gpg";
${importTrustBashFunctions}
${importKeys}
importKey =
{ source, trust, ... }:
''
${gpg} --import ${source}
${lib.optionalString (trust != null) ''importTrust "${source}" ${toString trust}''}
'';
mkdir $out
cp $GNUPGHOME/pubring.kbx $out/pubring.kbx
if [[ -e $GNUPGHOME/trustdb.gpg ]] ; then
cp $GNUPGHOME/trustdb.gpg $out/trustdb.gpg
fi
'';
importKeys = lib.concatMapStringsSep "\n" importKey cfg.publicKeys;
in
pkgs.runCommand "gpg-pubring" { buildInputs = [ cfg.package ]; } ''
export GNUPGHOME
GNUPGHOME=$(mktemp -d)
in {
${importTrustBashFunctions}
${importKeys}
mkdir $out
cp $GNUPGHOME/pubring.kbx $out/pubring.kbx
if [[ -e $GNUPGHOME/trustdb.gpg ]] ; then
cp $GNUPGHOME/trustdb.gpg $out/trustdb.gpg
fi
'';
in
{
options.programs.gpg = {
enable = lib.mkEnableOption "GnuPG";
@ -149,8 +173,7 @@ in {
};
settings = mkOption {
type =
types.attrsOf (types.either primitiveType (types.listOf types.str));
type = types.attrsOf (types.either primitiveType (types.listOf types.str));
example = literalExpression ''
{
no-comments = false;
@ -169,8 +192,7 @@ in {
};
scdaemonSettings = mkOption {
type =
types.attrsOf (types.either primitiveType (types.listOf types.str));
type = types.attrsOf (types.either primitiveType (types.listOf types.str));
example = literalExpression ''
{
disable-ccid = true;
@ -189,8 +211,7 @@ in {
type = types.path;
example = literalExpression ''"''${config.xdg.dataHome}/gnupg"'';
default = "${config.home.homeDirectory}/.gnupg";
defaultText =
literalExpression ''"''${config.home.homeDirectory}/.gnupg"'';
defaultText = literalExpression ''"''${config.home.homeDirectory}/.gnupg"'';
description = "Directory to store keychains and configuration.";
};
@ -242,8 +263,7 @@ in {
personal-cipher-preferences = mkDefault "AES256 AES192 AES";
personal-digest-preferences = mkDefault "SHA512 SHA384 SHA256";
personal-compress-preferences = mkDefault "ZLIB BZIP2 ZIP Uncompressed";
default-preference-list = mkDefault
"SHA512 SHA384 SHA256 AES256 AES192 AES ZLIB BZIP2 ZIP Uncompressed";
default-preference-list = mkDefault "SHA512 SHA384 SHA256 AES256 AES192 AES ZLIB BZIP2 ZIP Uncompressed";
cert-digest-algo = mkDefault "SHA512";
s2k-digest-algo = mkDefault "SHA512";
s2k-cipher-algo = mkDefault "AES256";
@ -265,56 +285,60 @@ in {
};
home.packages = [ cfg.package ];
home.sessionVariables = { GNUPGHOME = cfg.homedir; };
home.sessionVariables = {
GNUPGHOME = cfg.homedir;
};
home.file."${cfg.homedir}/gpg.conf".text = cfgText;
home.file."${cfg.homedir}/scdaemon.conf".text = scdaemonCfgText;
# Link keyring if keys are not mutable
home.file."${cfg.homedir}/pubring.kbx" =
mkIf (!cfg.mutableKeys && cfg.publicKeys != [ ]) {
source = "${keyringFiles}/pubring.kbx";
};
home.file."${cfg.homedir}/pubring.kbx" = mkIf (!cfg.mutableKeys && cfg.publicKeys != [ ]) {
source = "${keyringFiles}/pubring.kbx";
};
home.activation = {
createGpgHomedir =
lib.hm.dag.entryBetween [ "linkGeneration" ] [ "writeBoundary" ] ''
run mkdir -m700 -p $VERBOSE_ARG ${lib.escapeShellArg cfg.homedir}
'';
createGpgHomedir = lib.hm.dag.entryBetween [ "linkGeneration" ] [ "writeBoundary" ] ''
run mkdir -m700 -p $VERBOSE_ARG ${lib.escapeShellArg cfg.homedir}
'';
importGpgKeys = let
gpg = "${cfg.package}/bin/gpg";
importGpgKeys =
let
gpg = "${cfg.package}/bin/gpg";
importKey = { source, trust, ... }:
# Import mutable keys
optional cfg.mutableKeys "run ${gpg} $QUIET_ARG --import ${source}"
importKey =
{ source, trust, ... }:
# Import mutable keys
optional cfg.mutableKeys "run ${gpg} $QUIET_ARG --import ${source}"
# Import mutable trust
++ optional (trust != null && cfg.mutableTrust)
''run importTrust "${source}" ${toString trust}'';
# Import mutable trust
++ optional (trust != null && cfg.mutableTrust) ''run importTrust "${source}" ${toString trust}'';
anyTrust = lib.any (k: k.trust != null) cfg.publicKeys;
anyTrust = lib.any (k: k.trust != null) cfg.publicKeys;
importKeys =
lib.concatStringsSep "\n" (lib.concatMap importKey cfg.publicKeys);
importKeys = lib.concatStringsSep "\n" (lib.concatMap importKey cfg.publicKeys);
# If any key/trust should be imported then create the block. Otherwise
# leave it empty.
block = lib.concatStringsSep "\n" (optional (importKeys != "") ''
export GNUPGHOME=${lib.escapeShellArg cfg.homedir}
if [[ ! -v VERBOSE ]]; then
QUIET_ARG="--quiet"
else
QUIET_ARG=""
fi
${importTrustBashFunctions}
${importKeys}
unset GNUPGHOME QUIET_ARG keyId importTrust
'' ++ optional (!cfg.mutableTrust && anyTrust) ''
install -m 0700 ${keyringFiles}/trustdb.gpg "${cfg.homedir}/trustdb.gpg"'');
in mkIf (cfg.publicKeys != [ ])
(lib.hm.dag.entryAfter [ "linkGeneration" ] block);
# If any key/trust should be imported then create the block. Otherwise
# leave it empty.
block = lib.concatStringsSep "\n" (
optional (importKeys != "") ''
export GNUPGHOME=${lib.escapeShellArg cfg.homedir}
if [[ ! -v VERBOSE ]]; then
QUIET_ARG="--quiet"
else
QUIET_ARG=""
fi
${importTrustBashFunctions}
${importKeys}
unset GNUPGHOME QUIET_ARG keyId importTrust
''
++ optional (
!cfg.mutableTrust && anyTrust
) ''install -m 0700 ${keyringFiles}/trustdb.gpg "${cfg.homedir}/trustdb.gpg"''
);
in
mkIf (cfg.publicKeys != [ ]) (lib.hm.dag.entryAfter [ "linkGeneration" ] block);
};
};
}

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkIf mkOption types;
@ -6,34 +11,41 @@ let
defaultHomeDirectory = ".gradle";
settingsFormat = pkgs.formats.javaProperties { };
initScript = types.submodule ({ name, config, ... }: {
options = {
text = mkOption {
type = types.nullOr types.lines;
default = null;
description = ''
Text of the init script file. if this option is null
then `source` must be set.
'';
initScript = types.submodule (
{ name, config, ... }:
{
options = {
text = mkOption {
type = types.nullOr types.lines;
default = null;
description = ''
Text of the init script file. if this option is null
then `source` must be set.
'';
};
source = mkOption {
type = types.path;
description = ''
Path of the init script file. If
`text` is non-null then this option will automatically point
to a file containing that text.
'';
};
};
source = mkOption {
type = types.path;
description = ''
Path of the init script file. If
`text` is non-null then this option will automatically point
to a file containing that text.
'';
};
};
config.source = mkIf (config.text != null) (lib.mkDefault
(pkgs.writeTextFile {
inherit (config) text;
name = lib.hm.strings.storeFileName name;
}));
});
in {
config.source = mkIf (config.text != null) (
lib.mkDefault (
pkgs.writeTextFile {
inherit (config) text;
name = lib.hm.strings.storeFileName name;
}
)
);
}
);
in
{
meta.maintainers = [ lib.hm.maintainers.britter ];
options.programs.gradle = {
@ -96,19 +108,26 @@ in {
};
};
config = let gradleHome = "${config.home.homeDirectory}/${cfg.home}";
in mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
config =
let
gradleHome = "${config.home.homeDirectory}/${cfg.home}";
in
mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
home.file = lib.mkMerge ([{
"${cfg.home}/gradle.properties" = mkIf (cfg.settings != { }) {
source = settingsFormat.generate "gradle.properties" cfg.settings;
home.file = lib.mkMerge (
[
{
"${cfg.home}/gradle.properties" = mkIf (cfg.settings != { }) {
source = settingsFormat.generate "gradle.properties" cfg.settings;
};
}
]
++ lib.mapAttrsToList (k: v: { "${cfg.home}/init.d/${k}".source = v.source; }) cfg.initScripts
);
home.sessionVariables = mkIf (cfg.home != defaultHomeDirectory) {
GRADLE_USER_HOME = gradleHome;
};
}] ++ lib.mapAttrsToList
(k: v: { "${cfg.home}/init.d/${k}".source = v.source; }) cfg.initScripts);
home.sessionVariables = mkIf (cfg.home != defaultHomeDirectory) {
GRADLE_USER_HOME = gradleHome;
};
};
}

View file

@ -1,6 +1,13 @@
{ config, lib, pkgs, ... }:
let cfg = config.programs.granted;
in {
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.granted;
in
{
meta.maintainers = [ lib.hm.maintainers.wcarlsen ];
options.programs.granted = {
@ -8,11 +15,9 @@ in {
package = lib.mkPackageOption pkgs "granted" { };
enableZshIntegration =
lib.hm.shell.mkZshIntegrationOption { inherit config; };
enableZshIntegration = lib.hm.shell.mkZshIntegrationOption { inherit config; };
enableFishIntegration =
lib.hm.shell.mkFishIntegrationOption { inherit config; };
enableFishIntegration = lib.hm.shell.mkFishIntegrationOption { inherit config; };
};
config = lib.mkIf cfg.enable {

View file

@ -1,8 +1,14 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.havoc;
iniFormat = pkgs.formats.ini { };
in {
in
{
meta.maintainers = with lib.maintainers; [ AndersonTorres ];
options.programs.havoc = {
@ -47,8 +53,7 @@ in {
config = lib.mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "programs.havoc" pkgs
lib.platforms.linux)
(lib.hm.assertions.assertPlatform "programs.havoc" pkgs lib.platforms.linux)
];
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];

View file

@ -1,10 +1,21 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) literalExpression mkIf mkOption types;
inherit (lib)
literalExpression
mkIf
mkOption
types
;
cfg = config.programs.helix;
tomlFormat = pkgs.formats.toml { };
in {
in
{
meta.maintainers = [ lib.hm.maintainers.Philipp-M ];
options.programs.helix = {
@ -70,8 +81,10 @@ in {
};
languages = mkOption {
type = with types;
coercedTo (listOf tomlFormat.type) (language:
type =
with types;
coercedTo (listOf tomlFormat.type) (
language:
lib.warn ''
The syntax of programs.helix.languages has changed.
It now generates the whole languages.toml file instead of just the language array in that file.
@ -79,7 +92,8 @@ in {
Use
programs.helix.languages = { language = <languages list>; }
instead.
'' { inherit language; }) (addCheck tomlFormat.type builtins.isAttrs);
'' { inherit language; }
) (addCheck tomlFormat.type builtins.isAttrs);
default = { };
example = literalExpression ''
{
@ -106,7 +120,10 @@ in {
ignores = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ ".build/" "!.gitignore" ];
example = [
".build/"
"!.gitignore"
];
description = ''
List of paths that should be globally ignored for file picker.
Supports the usual ignore and negative ignore (unignore) rules used in `.gitignore` files.
@ -185,48 +202,53 @@ in {
};
config = mkIf cfg.enable {
home.packages = if cfg.extraPackages != [ ] then
[
(pkgs.symlinkJoin {
name =
"${lib.getName cfg.package}-wrapped-${lib.getVersion cfg.package}";
paths = [ cfg.package ];
preferLocalBuild = true;
nativeBuildInputs = [ pkgs.makeWrapper ];
postBuild = ''
wrapProgram $out/bin/hx \
--suffix PATH : ${lib.makeBinPath cfg.extraPackages}
'';
})
]
else
[ cfg.package ];
home.packages =
if cfg.extraPackages != [ ] then
[
(pkgs.symlinkJoin {
name = "${lib.getName cfg.package}-wrapped-${lib.getVersion cfg.package}";
paths = [ cfg.package ];
preferLocalBuild = true;
nativeBuildInputs = [ pkgs.makeWrapper ];
postBuild = ''
wrapProgram $out/bin/hx \
--suffix PATH : ${lib.makeBinPath cfg.extraPackages}
'';
})
]
else
[ cfg.package ];
home.sessionVariables = mkIf cfg.defaultEditor { EDITOR = "hx"; };
xdg.configFile = let
settings = {
"helix/config.toml" = mkIf (cfg.settings != { }) {
source = let
configFile = tomlFormat.generate "config.toml" cfg.settings;
extraConfigFile =
pkgs.writeText "extra-config.toml" ("\n" + cfg.extraConfig);
in pkgs.runCommand "helix-config.toml" { } ''
cat ${configFile} ${extraConfigFile} >> $out
'';
xdg.configFile =
let
settings = {
"helix/config.toml" = mkIf (cfg.settings != { }) {
source =
let
configFile = tomlFormat.generate "config.toml" cfg.settings;
extraConfigFile = pkgs.writeText "extra-config.toml" ("\n" + cfg.extraConfig);
in
pkgs.runCommand "helix-config.toml" { } ''
cat ${configFile} ${extraConfigFile} >> $out
'';
};
"helix/languages.toml" = mkIf (cfg.languages != { }) {
source = tomlFormat.generate "helix-languages-config" cfg.languages;
};
"helix/ignore" = mkIf (cfg.ignores != [ ]) {
text = lib.concatStringsSep "\n" cfg.ignores + "\n";
};
};
"helix/languages.toml" = mkIf (cfg.languages != { }) {
source = tomlFormat.generate "helix-languages-config" cfg.languages;
};
"helix/ignore" = mkIf (cfg.ignores != [ ]) {
text = lib.concatStringsSep "\n" cfg.ignores + "\n";
};
};
themes = lib.mapAttrs' (n: v:
lib.nameValuePair "helix/themes/${n}.toml" {
source = tomlFormat.generate "helix-theme-${n}" v;
}) cfg.themes;
in settings // themes;
themes = lib.mapAttrs' (
n: v:
lib.nameValuePair "helix/themes/${n}.toml" {
source = tomlFormat.generate "helix-theme-${n}" v;
}
) cfg.themes;
in
settings // themes;
};
}

View file

@ -1,6 +1,16 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
let
inherit (lib) literalExpression mkIf mkOption types;
inherit (lib)
literalExpression
mkIf
mkOption
types
;
cfg = config.programs.hexchat;
@ -44,13 +54,18 @@ let
};
};
modChannelOption = with types;
modChannelOption =
with types;
submodule {
options = {
autojoin = mkOption {
type = listOf str;
default = [ ];
example = [ "#home-manager" "#linux" "#nix" ];
example = [
"#home-manager"
"#linux"
"#nix"
];
description = "Channels list to autojoin on connecting to server.";
};
@ -163,16 +178,14 @@ let
transformField = k: v: if (v != null) then "${k}=${v}" else null;
listChar = c: l:
if l != [ ] then
lib.concatMapStringsSep "\n" (transformField c) l
else
null;
listChar = c: l: if l != [ ] then lib.concatMapStringsSep "\n" (transformField c) l else null;
computeFieldsValue = channel:
computeFieldsValue =
channel:
let
ifTrue = p: n: if p then n else 0;
result = with channel.options;
result =
with channel.options;
lib.foldl' (a: b: a + b) 0 [
(ifTrue (!connectToSelectedServerOnly) 1)
(ifTrue useGlobalUserInformation 2)
@ -181,7 +194,8 @@ let
(ifTrue (!bypassProxy) 16)
(ifTrue acceptInvalidSSLCertificates 32)
];
in toString (if channel.options == null then 0 else result);
in
toString (if channel.options == null then 0 else result);
loginMethodMap = {
nickServMsg = 1;
@ -193,30 +207,38 @@ let
saslExternal = 10;
};
loginMethod = channel:
transformField "L" (lib.optionalString (channel.loginMethod != null)
(toString loginMethodMap.${channel.loginMethod}));
loginMethod =
channel:
transformField "L" (
lib.optionalString (channel.loginMethod != null) (toString loginMethodMap.${channel.loginMethod})
);
# Note: Missing option `D=`.
transformChannel = channelName:
let channel = cfg.channels.${channelName};
in lib.concatStringsSep "\n" (lib.remove null [
"" # Leave a space between one server and another
(transformField "N" channelName)
(loginMethod channel)
(transformField "E" channel.charset)
(transformField "F" (computeFieldsValue channel))
(transformField "I" channel.nickname)
(transformField "i" channel.nickname2)
(transformField "R" channel.realName)
(transformField "U" channel.userName)
(transformField "P" channel.password)
(listChar "S" channel.servers)
(listChar "J" channel.autojoin)
(listChar "C" channel.commands)
]);
transformChannel =
channelName:
let
channel = cfg.channels.${channelName};
in
lib.concatStringsSep "\n" (
lib.remove null [
"" # Leave a space between one server and another
(transformField "N" channelName)
(loginMethod channel)
(transformField "E" channel.charset)
(transformField "F" (computeFieldsValue channel))
(transformField "I" channel.nickname)
(transformField "i" channel.nickname2)
(transformField "R" channel.realName)
(transformField "U" channel.userName)
(transformField "P" channel.password)
(listChar "S" channel.servers)
(listChar "J" channel.autojoin)
(listChar "C" channel.commands)
]
);
in {
in
{
meta.maintainers = with lib.maintainers; [ thiagokokada ];
options.programs.hexchat = {
@ -320,8 +342,7 @@ in {
config = mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "programs.hexchat" pkgs
lib.platforms.linux)
(lib.hm.assertions.assertPlatform "programs.hexchat" pkgs lib.platforms.linux)
];
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
@ -333,15 +354,13 @@ in {
xdg.configFile."hexchat/hexchat.conf" = mkIf (cfg.settings != null) {
force = cfg.overwriteConfigFiles;
text = lib.concatMapStringsSep "\n" (x: x + " = " + cfg.settings.${x})
(lib.attrNames cfg.settings);
text = lib.concatMapStringsSep "\n" (x: x + " = " + cfg.settings.${x}) (lib.attrNames cfg.settings);
};
xdg.configFile."hexchat/servlist.conf" = mkIf (cfg.channels != { }) {
force = cfg.overwriteConfigFiles;
# Final line breaks is required to avoid cropping last field value.
text = lib.concatMapStringsSep "\n" transformChannel
(lib.attrNames cfg.channels) + "\n\n";
text = lib.concatMapStringsSep "\n" transformChannel (lib.attrNames cfg.channels) + "\n\n";
};
};
}

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkOption optionalAttrs types;
@ -15,7 +20,8 @@ let
# make encryption config based on the given home-manager email
# account TLS config
mkEncryptionConfig = tls:
mkEncryptionConfig =
tls:
if tls.useStartTls then
"start-tls"
else if tls.enable then
@ -25,12 +31,12 @@ let
# make a himalaya account config based on the given home-manager
# email account config
mkAccountConfig = _: account:
mkAccountConfig =
_: account:
let
notmuchEnabled = account.notmuch.enable;
imapEnabled = !isNull account.imap && !notmuchEnabled;
maildirEnabled = !isNull account.maildir && !imapEnabled
&& !notmuchEnabled;
maildirEnabled = !isNull account.maildir && !imapEnabled && !notmuchEnabled;
globalConfig = {
email = account.address;
@ -44,13 +50,12 @@ let
};
};
signatureConfig =
optionalAttrs (account.signature.showSignature == "append") {
# TODO: signature cannot be attached yet
# https://github.com/pimalaya/himalaya/issues/534
signature = account.signature.text;
signature-delim = account.signature.delimiter;
};
signatureConfig = optionalAttrs (account.signature.showSignature == "append") {
# TODO: signature cannot be attached yet
# https://github.com/pimalaya/himalaya/issues/534
signature = account.signature.text;
signature-delim = account.signature.delimiter;
};
imapConfig = optionalAttrs imapEnabled (compactAttrs {
backend.type = "imap";
@ -59,8 +64,7 @@ let
backend.encryption.type = mkEncryptionConfig account.imap.tls;
backend.login = account.userName;
backend.auth.type = "password";
backend.auth.cmd =
builtins.concatStringsSep " " account.passwordCommand;
backend.auth.cmd = builtins.concatStringsSep " " account.passwordCommand;
});
maildirConfig = optionalAttrs maildirEnabled (compactAttrs {
@ -77,19 +81,16 @@ let
message.send.backend.type = "smtp";
message.send.backend.host = account.smtp.host;
message.send.backend.port = account.smtp.port;
message.send.backend.encryption.type =
mkEncryptionConfig account.smtp.tls;
message.send.backend.encryption.type = mkEncryptionConfig account.smtp.tls;
message.send.backend.login = account.userName;
message.send.backend.auth.type = "password";
message.send.backend.auth.cmd =
builtins.concatStringsSep " " account.passwordCommand;
message.send.backend.auth.cmd = builtins.concatStringsSep " " account.passwordCommand;
});
sendmailConfig =
optionalAttrs (isNull account.smtp && !isNull account.msmtp) {
message.send.backend.type = "sendmail";
message.send.backend.cmd = lib.getExe pkgs.msmtp;
};
sendmailConfig = optionalAttrs (isNull account.smtp && !isNull account.msmtp) {
message.send.backend.type = "sendmail";
message.send.backend.cmd = lib.getExe pkgs.msmtp;
};
config = lib.attrsets.mergeAttrsList [
globalConfig
@ -101,10 +102,15 @@ let
sendmailConfig
];
in lib.recursiveUpdate config account.himalaya.settings;
in
lib.recursiveUpdate config account.himalaya.settings;
in {
meta.maintainers = with lib.hm.maintainers; [ soywod toastal ];
in
{
meta.maintainers = with lib.hm.maintainers; [
soywod
toastal
];
imports = [
(lib.mkRemovedOptionModule [ "services" "himalaya-watch" "enable" ] ''
@ -133,21 +139,22 @@ in {
};
accounts.email.accounts = mkOption {
type = types.attrsOf (types.submodule {
options.himalaya = {
enable = lib.mkEnableOption
"the email client Himalaya CLI for this email account";
type = types.attrsOf (
types.submodule {
options.himalaya = {
enable = lib.mkEnableOption "the email client Himalaya CLI for this email account";
settings = mkOption {
type = types.submodule { freeformType = tomlFormat.type; };
default = { };
description = ''
Himalaya CLI configuration for this email account.
See <https://github.com/pimalaya/himalaya/blob/master/config.sample.toml> for supported values.
'';
settings = mkOption {
type = types.submodule { freeformType = tomlFormat.type; };
default = { };
description = ''
Himalaya CLI configuration for this email account.
See <https://github.com/pimalaya/himalaya/blob/master/config.sample.toml> for supported values.
'';
};
};
};
});
}
);
};
};
@ -155,26 +162,37 @@ in {
home.packages = lib.mkIf (himalaya.package != null) [ himalaya.package ];
xdg = {
configFile."himalaya/config.toml".source = let
enabledAccounts = lib.filterAttrs (_: account: account.himalaya.enable)
config.accounts.email.accounts;
accountsConfig = lib.mapAttrs mkAccountConfig enabledAccounts;
globalConfig = compactAttrs himalaya.settings;
allConfig = globalConfig // { accounts = accountsConfig; };
in tomlFormat.generate "himalaya.config.toml" allConfig;
configFile."himalaya/config.toml".source =
let
enabledAccounts = lib.filterAttrs (
_: account: account.himalaya.enable
) config.accounts.email.accounts;
accountsConfig = lib.mapAttrs mkAccountConfig enabledAccounts;
globalConfig = compactAttrs himalaya.settings;
allConfig = globalConfig // {
accounts = accountsConfig;
};
in
tomlFormat.generate "himalaya.config.toml" allConfig;
desktopEntries.himalaya = lib.mkIf
(pkgs.stdenv.hostPlatform.isLinux && (himalaya.package != null)) {
type = "Application";
name = "himalaya";
genericName = "Email Client";
comment = "CLI to manage emails";
terminal = true;
exec = "himalaya %u";
categories = [ "Network" ];
mimeType = [ "x-scheme-handler/mailto" "message/rfc822" ];
settings = { Keywords = "email"; };
};
desktopEntries.himalaya =
lib.mkIf (pkgs.stdenv.hostPlatform.isLinux && (himalaya.package != null))
{
type = "Application";
name = "himalaya";
genericName = "Email Client";
comment = "CLI to manage emails";
terminal = true;
exec = "himalaya %u";
categories = [ "Network" ];
mimeType = [
"x-scheme-handler/mailto"
"message/rfc822"
];
settings = {
Keywords = "email";
};
};
};
};
}

View file

@ -1,6 +1,13 @@
{ config, lib, pkgs, ... }:
let cfg = config.programs.home-manager;
in {
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.home-manager;
in
{
meta.maintainers = [ lib.maintainers.rycee ];
options = {
@ -22,7 +29,6 @@ in {
};
config = lib.mkIf (cfg.enable && !config.submoduleSupport.enable) {
home.packages =
[ (pkgs.callPackage ../../home-manager { inherit (cfg) path; }) ];
home.packages = [ (pkgs.callPackage ../../home-manager { inherit (cfg) path; }) ];
};
}

View file

@ -1,6 +1,13 @@
{ config, lib, pkgs, ... }:
let cfg = config.programs.hstr;
in {
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.hstr;
in
{
meta.maintainers = [ lib.hm.maintainers.Dines97 ];
options.programs.hstr = {
@ -10,11 +17,9 @@ in {
package = lib.mkPackageOption pkgs "hstr" { };
enableBashIntegration =
lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableBashIntegration = lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableZshIntegration =
lib.hm.shell.mkZshIntegrationOption { inherit config; };
enableZshIntegration = lib.hm.shell.mkZshIntegrationOption { inherit config; };
};
config = lib.mkIf cfg.enable {

View file

@ -1,12 +1,20 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (pkgs.stdenv.hostPlatform) isDarwin;
cfg = config.programs.htop;
formatOption = n: v:
let v' = if lib.isBool v then (if v then "1" else "0") else toString v;
in "${n}=${v'}";
formatOption =
n: v:
let
v' = if lib.isBool v then (if v then "1" else "0") else toString v;
in
"${n}=${v'}";
formatMeters = side: meters: {
"${side}_meters" = lib.concatMap (lib.mapAttrsToList (x: _: x)) meters;
@ -103,15 +111,25 @@ let
led = meter modes.LED;
blank = text "Blank";
in {
in
{
meta.maintainers = [ lib.hm.maintainers.bjpbakker ];
options.programs.htop = {
enable = lib.mkEnableOption "htop";
settings = lib.mkOption {
type = with lib.types;
attrsOf (oneOf [ bool int str (listOf (oneOf [ int str ])) ]);
type =
with lib.types;
attrsOf (oneOf [
bool
int
str
(listOf (oneOf [
int
str
]))
]);
default = { };
example = lib.literalExpression ''
{
@ -158,31 +176,41 @@ in {
config = lib.mkIf cfg.enable {
lib.htop = {
inherit fields defaultFields modes leftMeters rightMeters bar text graph
led blank;
inherit
fields
defaultFields
modes
leftMeters
rightMeters
bar
text
graph
led
blank
;
};
home.packages = [ cfg.package ];
xdg.configFile."htop" = let
defaults = {
fields = if isDarwin then
lib.remove fields.M_SHARE defaultFields
else
defaultFields;
xdg.configFile."htop" =
let
defaults = {
fields = if isDarwin then lib.remove fields.M_SHARE defaultFields else defaultFields;
};
before = lib.optionalAttrs (cfg.settings ? header_layout) {
inherit (cfg.settings) header_layout;
};
settings = defaults // (removeAttrs cfg.settings (lib.attrNames before));
formatOptions = lib.mapAttrsToList formatOption;
in
lib.mkIf (cfg.settings != { }) {
source = pkgs.writeTextDir "htoprc" (
lib.concatStringsSep "\n" (formatOptions before ++ formatOptions settings) + "\n"
);
};
before = lib.optionalAttrs (cfg.settings ? header_layout) {
inherit (cfg.settings) header_layout;
};
settings = defaults // (removeAttrs cfg.settings (lib.attrNames before));
formatOptions = lib.mapAttrsToList formatOption;
in lib.mkIf (cfg.settings != { }) {
source = pkgs.writeTextDir "htoprc" (lib.concatStringsSep "\n"
(formatOptions before ++ formatOptions settings) + "\n");
};
};
}

View file

@ -1,9 +1,15 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.hyfetch;
jsonFormat = pkgs.formats.json { };
in {
in
{
meta.maintainers = [ lib.hm.maintainers.lilyinstarlight ];
options.programs.hyfetch = {

View file

@ -1,11 +1,20 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
let
cfg = config.programs.hyprlock;
in {
meta.maintainers = with lib.maintainers; [ khaneliman fufexan ];
in
{
meta.maintainers = with lib.maintainers; [
khaneliman
fufexan
];
options.programs.hyprlock = {
enable = lib.mkEnableOption "" // {
@ -28,20 +37,24 @@ in {
package = lib.mkPackageOption pkgs "hyprlock" { nullable = true; };
settings = lib.mkOption {
type = with lib.types;
type =
with lib.types;
let
valueType = nullOr (oneOf [
bool
int
float
str
path
(attrsOf valueType)
(listOf valueType)
]) // {
description = "Hyprlock configuration value";
};
in valueType;
valueType =
nullOr (oneOf [
bool
int
float
str
path
(attrsOf valueType)
(listOf valueType)
])
// {
description = "Hyprlock configuration value";
};
in
valueType;
default = { };
example = lib.literalExpression ''
{
@ -92,17 +105,28 @@ in {
'';
};
sourceFirst = lib.mkEnableOption ''
putting source entries at the top of the configuration
'' // {
default = true;
};
sourceFirst =
lib.mkEnableOption ''
putting source entries at the top of the configuration
''
// {
default = true;
};
importantPrefixes = lib.mkOption {
type = with lib.types; listOf str;
default = [ "$" "bezier" "monitor" "size" ]
++ lib.optionals cfg.sourceFirst [ "source" ];
example = [ "$" "bezier" "monitor" "size" ];
default = [
"$"
"bezier"
"monitor"
"size"
] ++ lib.optionals cfg.sourceFirst [ "source" ];
example = [
"$"
"bezier"
"monitor"
"size"
];
description = ''
List of prefix of attributes to source at the top of the config.
'';
@ -113,13 +137,18 @@ in {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
xdg.configFile."hypr/hyprlock.conf" =
let shouldGenerate = cfg.extraConfig != "" || cfg.settings != { };
in lib.mkIf shouldGenerate {
text = lib.optionalString (cfg.settings != { })
(lib.hm.generators.toHyprconf {
attrs = cfg.settings;
inherit (cfg) importantPrefixes;
}) + lib.optionalString (cfg.extraConfig != null) cfg.extraConfig;
let
shouldGenerate = cfg.extraConfig != "" || cfg.settings != { };
in
lib.mkIf shouldGenerate {
text =
lib.optionalString (cfg.settings != { }) (
lib.hm.generators.toHyprconf {
attrs = cfg.settings;
inherit (cfg) importantPrefixes;
}
)
+ lib.optionalString (cfg.extraConfig != null) cfg.extraConfig;
};
};
}

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) types;
@ -7,15 +12,24 @@ let
# Re-make the atom type for the INI files.
# For some reason, the normal INI type seems to be incompatible with
# DAG
configAtomType = let
# Keep the INI atom type here
optType = with types; (nullOr (oneOf [ int bool str float ]));
in types.mkOptionType {
name = "INI config atom";
description = "INI atom (null, int, bool, string, or float)";
check = x: optType.check x;
merge = (loc: defs: (optType.merge loc defs));
};
configAtomType =
let
# Keep the INI atom type here
optType =
with types;
(nullOr (oneOf [
int
bool
str
float
]));
in
types.mkOptionType {
name = "INI config atom";
description = "INI atom (null, int, bool, string, or float)";
check = x: optType.check x;
merge = (loc: defs: (optType.merge loc defs));
};
# Create the type of the actual config type
configType = types.attrsOf configAtomType;
@ -23,7 +37,8 @@ let
# The INI generator
mkIni = lib.generators.toINI { };
in {
in
{
meta.maintainers = [ lib.maintainers.noodlez1232 ];
options.programs.i3blocks = {
@ -63,46 +78,46 @@ in {
};
};
config = let
# A function to create the file that will be put into the XDG config home.
makeFile = config:
let
# Takes a singular name value pair and turns it into an attrset
nameValuePairToAttr = value: (builtins.listToAttrs [ value ]);
# Converts a dag entry to a name-value pair
dagEntryToNameValue = entry: (lib.nameValuePair entry.name entry.data);
config =
let
# A function to create the file that will be put into the XDG config home.
makeFile =
config:
let
# Takes a singular name value pair and turns it into an attrset
nameValuePairToAttr = value: (builtins.listToAttrs [ value ]);
# Converts a dag entry to a name-value pair
dagEntryToNameValue = entry: (lib.nameValuePair entry.name entry.data);
# Try to sort the blocks
trySortedBlocks = lib.hm.dag.topoSort config;
# Try to sort the blocks
trySortedBlocks = lib.hm.dag.topoSort config;
# Get the blocks if successful, abort if not
blocks = if trySortedBlocks ? result then
trySortedBlocks.result
else
abort
"Dependency cycle in i3blocks: ${builtins.toJSON trySortedBlocks}";
# Get the blocks if successful, abort if not
blocks =
if trySortedBlocks ? result then
trySortedBlocks.result
else
abort "Dependency cycle in i3blocks: ${builtins.toJSON trySortedBlocks}";
# Turn the blocks back into their name value pairs
orderedBlocks =
(map (value: (nameValuePairToAttr (dagEntryToNameValue value)))
blocks);
in {
# We create an "INI" file for each bar, then append them all in order
text =
lib.concatStringsSep "\n" (map (value: (mkIni value)) orderedBlocks);
};
# Turn the blocks back into their name value pairs
orderedBlocks = (map (value: (nameValuePairToAttr (dagEntryToNameValue value))) blocks);
in
{
# We create an "INI" file for each bar, then append them all in order
text = lib.concatStringsSep "\n" (map (value: (mkIni value)) orderedBlocks);
};
# Make our config (if enabled
in lib.mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "programs.i3blocks" pkgs
lib.platforms.linux)
];
# Make our config (if enabled
in
lib.mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "programs.i3blocks" pkgs lib.platforms.linux)
];
home.packages = [ cfg.package ];
home.packages = [ cfg.package ];
xdg.configFile = (lib.mapAttrs'
(name: value: lib.nameValuePair "i3blocks/${name}" (makeFile value))
cfg.bars);
};
xdg.configFile = (
lib.mapAttrs' (name: value: lib.nameValuePair "i3blocks/${name}" (makeFile value)) cfg.bars
);
};
}

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) literalExpression mkOption types;
@ -6,124 +11,132 @@ let
settingsFormat = pkgs.formats.toml { };
in {
meta.maintainers = with lib.maintainers; [ farlion thiagokokada ];
in
{
meta.maintainers = with lib.maintainers; [
farlion
thiagokokada
];
options.programs.i3status-rust = {
enable = lib.mkEnableOption "a replacement for i3-status written in Rust";
bars = mkOption {
type = types.attrsOf (types.submodule {
options = {
type = types.attrsOf (
types.submodule {
options = {
blocks = mkOption {
type = settingsFormat.type;
default = [
{ block = "cpu"; }
{
block = "disk_space";
path = "/";
info_type = "available";
interval = 20;
warning = 20.0;
alert = 10.0;
format = " $icon root: $available.eng(w:2) ";
}
{
block = "memory";
format = " $icon $mem_total_used_percents.eng(w:2) ";
format_alt = " $icon_swap $swap_used_percents.eng(w:2) ";
}
{
block = "sound";
click = [{
button = "left";
cmd = "pavucontrol";
}];
}
{
block = "time";
interval = 5;
format = " $timestamp.datetime(f:'%a %d/%m %R') ";
}
];
description = ''
Configuration blocks to add to i3status-rust
{file}`config`. See
<https://github.com/greshake/i3status-rust/blob/master/blocks.md>
for block options.
'';
example = literalExpression ''
[
blocks = mkOption {
type = settingsFormat.type;
default = [
{ block = "cpu"; }
{
block = "disk_space";
path = "/";
info_type = "available";
interval = 60;
interval = 20;
warning = 20.0;
alert = 10.0;
format = " $icon root: $available.eng(w:2) ";
}
{
block = "memory";
format = " $icon $mem_total_used_percents.eng(w:2) ";
format_alt = " $icon_swap $swap_used_percents.eng(w:2) ";
}
{
block = "sound";
format = " $icon $output_name {$volume.eng(w:2) |}";
click = [
{
button = "left";
cmd = "pavucontrol --tab=3";
cmd = "pavucontrol";
}
];
mappings = {
"alsa_output.pci-0000_00_1f.3.analog-stereo" = "";
"bluez_sink.70_26_05_DA_27_A4.a2dp_sink" = "";
};
}
{
block = "time";
interval = 5;
format = " $timestamp.datetime(f:'%a %d/%m %R') ";
}
];
'';
};
description = ''
Configuration blocks to add to i3status-rust
{file}`config`. See
<https://github.com/greshake/i3status-rust/blob/master/blocks.md>
for block options.
'';
example = literalExpression ''
[
{
block = "disk_space";
path = "/";
info_type = "available";
interval = 60;
warning = 20.0;
alert = 10.0;
}
{
block = "sound";
format = " $icon $output_name {$volume.eng(w:2) |}";
click = [
{
button = "left";
cmd = "pavucontrol --tab=3";
}
];
mappings = {
"alsa_output.pci-0000_00_1f.3.analog-stereo" = "";
"bluez_sink.70_26_05_DA_27_A4.a2dp_sink" = "";
};
}
];
'';
};
settings = mkOption {
type = settingsFormat.type;
default = { };
description = ''
Any extra options to add to i3status-rust
{file}`config`.
'';
example = literalExpression ''
{
theme = {
theme = "solarized-dark";
overrides = {
idle_bg = "#123456";
idle_fg = "#abcdef";
settings = mkOption {
type = settingsFormat.type;
default = { };
description = ''
Any extra options to add to i3status-rust
{file}`config`.
'';
example = literalExpression ''
{
theme = {
theme = "solarized-dark";
overrides = {
idle_bg = "#123456";
idle_fg = "#abcdef";
};
};
};
}
'';
};
}
'';
};
icons = mkOption {
type = types.str;
default = "none";
description = ''
The icons set to use. See
<https://github.com/greshake/i3status-rust/blob/master/doc/themes.md>
for a list of available icon sets.
'';
example = "awesome6";
};
icons = mkOption {
type = types.str;
default = "none";
description = ''
The icons set to use. See
<https://github.com/greshake/i3status-rust/blob/master/doc/themes.md>
for a list of available icon sets.
'';
example = "awesome6";
};
theme = mkOption {
type = types.str;
default = "plain";
description = ''
The theme to use. See
<https://github.com/greshake/i3status-rust/blob/master/doc/themes.md>
for a list of available themes.
'';
example = "gruvbox-dark";
theme = mkOption {
type = types.str;
default = "plain";
description = ''
The theme to use. See
<https://github.com/greshake/i3status-rust/blob/master/doc/themes.md>
for a list of available themes.
'';
example = "gruvbox-dark";
};
};
};
});
}
);
default = {
default = {
@ -225,35 +238,44 @@ in {
config = lib.mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "programs.i3status-rust" pkgs
lib.platforms.linux)
(lib.hm.assertions.assertPlatform "programs.i3status-rust" pkgs lib.platforms.linux)
{
assertion = lib.versionOlder cfg.package.version "0.31.0"
|| lib.versionAtLeast cfg.package.version "0.31.2";
message =
"Only i3status-rust <0.31.0 or 0.31.2 is supported due to a config format incompatibility.";
assertion =
lib.versionOlder cfg.package.version "0.31.0" || lib.versionAtLeast cfg.package.version "0.31.2";
message = "Only i3status-rust <0.31.0 or 0.31.2 is supported due to a config format incompatibility.";
}
];
home.packages = [ cfg.package ];
xdg.configFile = lib.mapAttrs' (cfgFileSuffix: cfgBar:
xdg.configFile = lib.mapAttrs' (
cfgFileSuffix: cfgBar:
lib.nameValuePair "i3status-rust/config-${cfgFileSuffix}.toml" {
onChange = ''
${pkgs.procps}/bin/pkill -u $USER -USR2 i3status-rs || true
'';
source = settingsFormat.generate "config-${cfgFileSuffix}.toml" ({
theme = if lib.versionAtLeast cfg.package.version "0.30.0" then {
theme = cfgBar.theme;
} else
cfgBar.theme;
icons = if lib.versionAtLeast cfg.package.version "0.30.0" then {
icons = cfgBar.icons;
} else
cfgBar.icons;
block = cfgBar.blocks;
} // cfgBar.settings);
}) cfg.bars;
source = settingsFormat.generate "config-${cfgFileSuffix}.toml" (
{
theme =
if lib.versionAtLeast cfg.package.version "0.30.0" then
{
theme = cfgBar.theme;
}
else
cfgBar.theme;
icons =
if lib.versionAtLeast cfg.package.version "0.30.0" then
{
icons = cfgBar.icons;
}
else
cfgBar.icons;
block = cfgBar.blocks;
}
// cfgBar.settings
);
}
) cfg.bars;
};
}

View file

@ -1,6 +1,16 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) literalExpression mkDefault mkOption types;
inherit (lib)
literalExpression
mkDefault
mkOption
types
;
cfg = config.programs.i3status;
@ -8,30 +18,45 @@ let
formatOrder = n: ''order += "${n}"'';
formatModule = n: v:
formatModule =
n: v:
let
formatLine = n: v:
formatLine =
n: v:
let
formatValue = v:
formatValue =
v:
if lib.isBool v then
(if v then "true" else "false")
else if lib.isString v then
''"${v}"''
else
toString v;
in "${n} = ${formatValue v}";
in ''
in
"${n} = ${formatValue v}";
in
''
${n} {
${lib.concatStringsSep "\n " (lib.mapAttrsToList formatLine v)}
}
'';
settingsType = with types; attrsOf (oneOf [ bool int str ]);
settingsType =
with types;
attrsOf (oneOf [
bool
int
str
]);
sortAttrNamesByPosition = comparator: set:
let pos = n: set."${n}".position;
in lib.sort (a: b: comparator (pos a) (pos b)) (lib.attrNames set);
in {
sortAttrNamesByPosition =
comparator: set:
let
pos = n: set."${n}".position;
in
lib.sort (a: b: comparator (pos a) (pos b)) (lib.attrNames set);
in
{
meta.maintainers = [ lib.hm.maintainers.justinlovinger ];
options.programs.i3status = {
@ -68,40 +93,42 @@ in {
};
modules = mkOption {
type = types.attrsOf (types.submodule {
options = {
enable = mkOption {
type = types.bool;
default = true;
description = ''
Whether or not to enable this module.
'';
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 `order`.
'';
};
settings = mkOption {
type = settingsType;
default = { };
description = ''
Configuration to add to this i3status module.
See
{manpage}`i3status(1)`
for options.
'';
example = literalExpression ''
{
format = " %volume";
format_muted = " muted (%volume)";
device = "pulse:1";
}
'';
};
};
position = mkOption {
type = with types; either int float;
description = ''
Position of this module in i3status `order`.
'';
};
settings = mkOption {
type = settingsType;
default = { };
description = ''
Configuration to add to this i3status module.
See
{manpage}`i3status(1)`
for options.
'';
example = literalExpression ''
{
format = " %volume";
format_muted = " muted (%volume)";
device = "pulse:1";
}
'';
};
};
});
}
);
default = { };
description = ''
Modules to add to i3status {file}`config` file.
@ -140,7 +167,9 @@ in {
};
modules = {
ipv6 = { position = mkDefault 1; };
ipv6 = {
position = mkDefault 1;
};
"wireless _first_" = {
position = mkDefault 2;
@ -160,17 +189,23 @@ in {
"battery all" = {
position = mkDefault 4;
settings = { format = mkDefault "%status %percentage %remaining"; };
settings = {
format = mkDefault "%status %percentage %remaining";
};
};
"disk /" = {
position = mkDefault 5;
settings = { format = mkDefault "%avail"; };
settings = {
format = mkDefault "%avail";
};
};
load = {
position = mkDefault 6;
settings = { format = mkDefault "%1min"; };
settings = {
format = mkDefault "%1min";
};
};
memory = {
@ -184,17 +219,20 @@ in {
"tztime local" = {
position = mkDefault 8;
settings = { format = mkDefault "%Y-%m-%d %H:%M:%S"; };
settings = {
format = mkDefault "%Y-%m-%d %H:%M:%S";
};
};
};
};
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
xdg.configFile."i3status/config".text = lib.concatStringsSep "\n" ([ ]
xdg.configFile."i3status/config".text = lib.concatStringsSep "\n" (
[ ]
++ lib.optional (cfg.general != { }) (formatModule "general" cfg.general)
++ map formatOrder (sortAttrNamesByPosition lib.lessThan enabledModules)
++ lib.mapAttrsToList formatModule
(lib.mapAttrs (n: v: v.settings) enabledModules));
++ lib.mapAttrsToList formatModule (lib.mapAttrs (n: v: v.settings) enabledModules)
);
};
}

View file

@ -1,8 +1,14 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.iamb;
tomlFormat = pkgs.formats.toml { };
in {
in
{
options.programs.iamb = {
enable = lib.mkEnableOption "iamb";

View file

@ -1,23 +1,38 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.imv;
toConfig = attrs:
toConfig =
attrs:
''
# Generated by Home Manager.
'' + lib.generators.toINI { } attrs;
in {
''
+ lib.generators.toINI { } attrs;
in
{
meta.maintainers = [ lib.maintainers.christoph-heiss ];
options.programs.imv = {
enable = lib.mkEnableOption
"imv: a command line image viewer intended for use with tiling window managers";
enable = lib.mkEnableOption "imv: a command line image viewer intended for use with tiling window managers";
package = lib.mkPackageOption pkgs "imv" { nullable = true; };
settings = lib.mkOption {
default = { };
type = with lib.types; attrsOf (attrsOf (oneOf [ bool int str ]));
type =
with lib.types;
attrsOf (
attrsOf (oneOf [
bool
int
str
])
);
description = ''
Configuration options for imv. See
{manpage}`imv(5)`.

View file

@ -17,7 +17,12 @@
# two files, showing you a unified table of contents for all packages.
# This is really nice.
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.info;
@ -27,7 +32,8 @@ let
# from this package in the activation script.
infoPkg = pkgs.texinfoInteractive;
in {
in
{
imports = [
(lib.mkRemovedOptionModule [ "programs" "info" "homeInfoDirLocation" ] ''
The `dir` file is now generated as part of the Home Manager profile and
@ -48,13 +54,21 @@ in {
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
'';
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
'';
};
}

View file

@ -1,18 +1,23 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkOption types;
cfg = config.programs.ion;
aliasesStr = lib.concatStringsSep "\n"
(lib.mapAttrsToList (k: v: "alias ${k} = ${lib.escapeShellArg v}")
cfg.shellAliases);
in {
aliasesStr = lib.concatStringsSep "\n" (
lib.mapAttrsToList (k: v: "alias ${k} = ${lib.escapeShellArg v}") cfg.shellAliases
);
in
{
meta.maintainers = [ lib.maintainers.jo1gi ];
options.programs.ion = {
enable =
lib.mkEnableOption "the Ion Shell. Compatible with Redox and Linux";
enable = lib.mkEnableOption "the Ion Shell. Compatible with Redox and Linux";
package = lib.mkPackageOption pkgs "ion" { };

View file

@ -1,6 +1,17 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) concatStringsSep flip mapAttrsToList mkOption types;
inherit (lib)
concatStringsSep
flip
mapAttrsToList
mkOption
types
;
cfg = config.programs.irssi;
@ -11,50 +22,58 @@ let
,
'';
assignFormat = set:
concatStringsSep "\n"
(mapAttrsToList (k: v: " ${k} = \"${quoteStr v}\";") set);
assignFormat =
set: concatStringsSep "\n" (mapAttrsToList (k: v: " ${k} = \"${quoteStr v}\";") set);
chatnetString = concatStringsSep "\n" (flip mapAttrsToList cfg.networks
(k: v: ''
${k} = {
type = "${v.type}";
nick = "${quoteStr v.nick}";
autosendcmd = "${lib.concatMapStringsSep ";" quoteStr v.autoCommands}";
${
lib.optionalString (v.saslExternal) ''
chatnetString = concatStringsSep "\n" (
flip mapAttrsToList cfg.networks (
k: v: ''
${k} = {
type = "${v.type}";
nick = "${quoteStr v.nick}";
autosendcmd = "${lib.concatMapStringsSep ";" quoteStr v.autoCommands}";
${lib.optionalString (v.saslExternal) ''
sasl_username = "${quoteStr v.nick}";
sasl_mechanism = "EXTERNAL";''
}
};
''));
sasl_mechanism = "EXTERNAL";''}
};
''
)
);
serversString = concatStringsSep cnl (flip mapAttrsToList cfg.networks
(k: v: ''
{
chatnet = "${k}";
address = "${v.server.address}";
port = "${toString v.server.port}";
use_ssl = "${lib.hm.booleans.yesNo v.server.ssl.enable}";
ssl_verify = "${lib.hm.booleans.yesNo v.server.ssl.verify}";
autoconnect = "${lib.hm.booleans.yesNo v.server.autoConnect}";
${
lib.optionalString (v.server.ssl.certificateFile != null) ''
ssl_cert = "${v.server.ssl.certificateFile}";
''
}
}
''));
channelString = concatStringsSep cnl (lib.concatLists
(flip mapAttrsToList cfg.networks (k: v:
(flip mapAttrsToList v.channels (c: cv: ''
serversString = concatStringsSep cnl (
flip mapAttrsToList cfg.networks (
k: v: ''
{
chatnet = "${k}";
name = "${c}";
autojoin = "${lib.hm.booleans.yesNo cv.autoJoin}";
address = "${v.server.address}";
port = "${toString v.server.port}";
use_ssl = "${lib.hm.booleans.yesNo v.server.ssl.enable}";
ssl_verify = "${lib.hm.booleans.yesNo v.server.ssl.verify}";
autoconnect = "${lib.hm.booleans.yesNo v.server.autoConnect}";
${lib.optionalString (v.server.ssl.certificateFile != null) ''
ssl_cert = "${v.server.ssl.certificateFile}";
''}
}
'')))));
''
)
);
channelString = concatStringsSep cnl (
lib.concatLists (
flip mapAttrsToList cfg.networks (
k: v:
(flip mapAttrsToList v.channels (
c: cv: ''
{
chatnet = "${k}";
name = "${c}";
autojoin = "${lib.hm.booleans.yesNo cv.autoJoin}";
}
''
))
)
)
);
channelType = types.submodule {
options = {
@ -73,91 +92,95 @@ let
};
};
networkType = types.submodule ({ name, ... }: {
options = {
name = mkOption {
visible = false;
default = name;
type = types.str;
};
nick = mkOption {
type = types.str;
description = "Nickname in that network.";
};
type = mkOption {
type = types.str;
description = "Type of the network.";
default = "IRC";
};
autoCommands = mkOption {
type = types.listOf types.str;
default = [ ];
description = "List of commands to execute on connect.";
};
server = {
address = mkOption {
networkType = types.submodule (
{ name, ... }:
{
options = {
name = mkOption {
visible = false;
default = name;
type = types.str;
description = "Address of the chat server.";
};
port = mkOption {
type = types.port;
default = 6667;
description = "Port of the chat server.";
nick = mkOption {
type = types.str;
description = "Nickname in that network.";
};
ssl = {
enable = mkOption {
type = mkOption {
type = types.str;
description = "Type of the network.";
default = "IRC";
};
autoCommands = mkOption {
type = types.listOf types.str;
default = [ ];
description = "List of commands to execute on connect.";
};
server = {
address = mkOption {
type = types.str;
description = "Address of the chat server.";
};
port = mkOption {
type = types.port;
default = 6667;
description = "Port of the chat server.";
};
ssl = {
enable = mkOption {
type = types.bool;
default = true;
description = "Whether SSL should be used.";
};
verify = mkOption {
type = types.bool;
default = true;
description = "Whether the SSL certificate should be verified.";
};
certificateFile = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
Path to a file containing the certificate used for
client authentication to the server.
'';
};
};
autoConnect = mkOption {
type = types.bool;
default = true;
description = "Whether SSL should be used.";
};
verify = mkOption {
type = types.bool;
default = true;
description = "Whether the SSL certificate should be verified.";
};
certificateFile = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
Path to a file containing the certificate used for
client authentication to the server.
'';
default = false;
description = "Whether Irssi connects to the server on launch.";
};
};
autoConnect = mkOption {
channels = mkOption {
description = "Channels for the given network.";
type = types.attrsOf channelType;
default = { };
};
saslExternal = mkOption {
type = types.bool;
default = false;
description = "Whether Irssi connects to the server on launch.";
description = ''
Enable SASL external authentication. This requires setting a path in
[](#opt-programs.irssi.networks._name_.server.ssl.certificateFile).
'';
};
};
}
);
channels = mkOption {
description = "Channels for the given network.";
type = types.attrsOf channelType;
default = { };
};
saslExternal = mkOption {
type = types.bool;
default = false;
description = ''
Enable SASL external authentication. This requires setting a path in
[](#opt-programs.irssi.networks._name_.server.ssl.certificateFile).
'';
};
};
});
in {
in
{
options = {
programs.irssi = {

View file

@ -1,11 +1,17 @@
# This module provides JAVA_HOME, with a different way to install java locally.
# This module is modified from the NixOS module `programs.java`
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.java;
in {
in
{
meta.maintainers = with lib.maintainers; [ ShamrockLee ];
options = {

View file

@ -1,6 +1,8 @@
{ config, lib, ... }:
let cfg = config.programs.jetbrains-remote;
in {
let
cfg = config.programs.jetbrains-remote;
in
{
meta.maintainers = with lib.maintainers; [ genericnerdyusername ];
options.programs.jetbrains-remote = {
@ -19,14 +21,19 @@ in {
};
config = lib.mkIf (cfg.enable && cfg.ides != [ ]) {
home.activation.jetBrainsRemote = let
mkLine = ide:
# Errors out if the symlink already exists
"${ide}/bin/${ide.meta.mainProgram}-remote-dev-server registerBackendLocationForGateway || true";
lines = map mkLine cfg.ides;
linesStr = ''
rm $HOME/.cache/JetBrains/RemoteDev/userProvidedDist/_nix_store* || true
'' + lib.concatStringsSep "\n" lines;
in lib.hm.dag.entryAfter [ "writeBoundary" ] linesStr;
home.activation.jetBrainsRemote =
let
mkLine =
ide:
# Errors out if the symlink already exists
"${ide}/bin/${ide.meta.mainProgram}-remote-dev-server registerBackendLocationForGateway || true";
lines = map mkLine cfg.ides;
linesStr =
''
rm $HOME/.cache/JetBrains/RemoteDev/userProvidedDist/_nix_store* || true
''
+ lib.concatStringsSep "\n" lines;
in
lib.hm.dag.entryAfter [ "writeBoundary" ] linesStr;
};
}

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
@ -9,7 +14,8 @@ let
# config path is the same for linux and mac
configPath = "${config.xdg.configHome}/joplin-desktop/settings.json";
in {
in
{
meta.maintainers = [ lib.hm.maintainers.zorrobert ];
options.programs.joplin-desktop = {
@ -89,47 +95,57 @@ in {
home.packages = [ cfg.package ];
home.activation = {
activateJoplinDesktopConfig = let
newConfig = jsonFormat.generate "joplin-settings.json"
(lib.attrsets.filterAttrs (n: v: (v != null) && (v != "")) ({
# TODO: find a better way to convert nix attribute names to strings:
# sync.interval = ... -> "sync.interval" = ...
activateJoplinDesktopConfig =
let
newConfig = jsonFormat.generate "joplin-settings.json" (
lib.attrsets.filterAttrs (n: v: (v != null) && (v != "")) (
{
# TODO: find a better way to convert nix attribute names to strings:
# sync.interval = ... -> "sync.interval" = ...
"editor" = cfg.general.editor;
"editor" = cfg.general.editor;
"sync.target" = {
"undefined" = null;
"none" = 0;
"file-system" = 2;
"onedrive" = 3;
"nextcloud" = 5;
"webdav" = 6;
"dropbox" = 7;
"s3" = 8;
"joplin-server" = 9;
"joplin-cloud" = 10;
}.${cfg.sync.target};
"sync.target" =
{
"undefined" = null;
"none" = 0;
"file-system" = 2;
"onedrive" = 3;
"nextcloud" = 5;
"webdav" = 6;
"dropbox" = 7;
"s3" = 8;
"joplin-server" = 9;
"joplin-cloud" = 10;
}
.${cfg.sync.target};
"sync.interval" = {
"undefined" = null;
"disabled" = 0;
"5m" = 300;
"10m" = 600;
"30m" = 1800;
"1h" = 3600;
"12h" = 43200;
"1d" = 86400;
}.${cfg.sync.interval};
} // cfg.extraConfig));
in lib.hm.dag.entryAfter [ "linkGeneration" ] ''
# Ensure that settings.json exists.
mkdir -p ${builtins.dirOf configPath}
touch ${configPath}
# Config has to be written to temporary variable because jq cannot edit files in place.
config="$(jq -s '.[0] + .[1]' ${configPath} ${newConfig})"
printf '%s\n' "$config" > ${configPath}
unset config
'';
"sync.interval" =
{
"undefined" = null;
"disabled" = 0;
"5m" = 300;
"10m" = 600;
"30m" = 1800;
"1h" = 3600;
"12h" = 43200;
"1d" = 86400;
}
.${cfg.sync.interval};
}
// cfg.extraConfig
)
);
in
lib.hm.dag.entryAfter [ "linkGeneration" ] ''
# Ensure that settings.json exists.
mkdir -p ${builtins.dirOf configPath}
touch ${configPath}
# Config has to be written to temporary variable because jq cannot edit files in place.
config="$(jq -s '.[0] + .[1]' ${configPath} ${newConfig})"
printf '%s\n' "$config" > ${configPath}
unset config
'';
};
};
}

View file

@ -1,10 +1,16 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkIf mkOption types;
cfg = config.programs.joshuto;
tomlFormat = pkgs.formats.toml { };
in {
in
{
meta.maintainers = [ lib.hm.maintainers.rasmus-kirk ];
options.programs.joshuto = {

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkIf mkOption types;
@ -24,7 +29,8 @@ let
};
};
in {
in
{
options = {
programs.jq = {
enable = lib.mkEnableOption "the jq command-line JSON processor";
@ -71,10 +77,12 @@ in {
config = mkIf cfg.enable {
home.packages = [ cfg.package ];
home.sessionVariables = let c = cfg.colors;
in {
JQ_COLORS =
"${c.null}:${c.false}:${c.true}:${c.numbers}:${c.strings}:${c.arrays}:${c.objects}:${c.objectKeys}";
};
home.sessionVariables =
let
c = cfg.colors;
in
{
JQ_COLORS = "${c.null}:${c.false}:${c.true}:${c.numbers}:${c.strings}:${c.arrays}:${c.objects}:${c.objectKeys}";
};
};
}

View file

@ -1,9 +1,15 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.jqp;
yamlFormat = pkgs.formats.yaml { };
in {
in
{
options.programs.jqp = {
enable = lib.mkEnableOption "jqp, jq playground";
@ -15,7 +21,9 @@ in {
example = {
theme = {
name = "monokai";
chromaStyleOverrides = { kc = "#009900 underline"; };
chromaStyleOverrides = {
kc = "#009900 underline";
};
};
};
description = "Jqp configuration";

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