1
0
Fork 0
mirror of https://github.com/nix-community/home-manager.git synced 2025-03-31 04:04:32 +00:00

Merge branch 'nix-community:master' into master

This commit is contained in:
Kyure_A 2025-02-28 10:22:34 +09:00 committed by GitHub
commit b21bdddbc9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
209 changed files with 2608 additions and 1139 deletions

View file

@ -4,7 +4,7 @@ in {
options = { options = {
flake = flake-parts-lib.mkSubmoduleOptions { flake = flake-parts-lib.mkSubmoduleOptions {
homeConfigurations = mkOption { homeConfigurations = mkOption {
type = types.lazyAttrsOf types.deferredModule; type = types.lazyAttrsOf types.raw;
default = { }; default = { };
description = '' description = ''
Instantiated Home Manager configurations. Instantiated Home Manager configurations.
@ -15,7 +15,7 @@ in {
''; '';
}; };
homeManagerModules = mkOption { homeManagerModules = mkOption {
type = types.lazyAttrsOf types.unspecified; type = types.lazyAttrsOf types.deferredModule;
default = { }; default = { };
apply = mapAttrs (k: v: { apply = mapAttrs (k: v: {
_class = "homeManager"; _class = "homeManager";

6
flake.lock generated
View file

@ -2,11 +2,11 @@
"nodes": { "nodes": {
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1739020877, "lastModified": 1739736696,
"narHash": "sha256-mIvECo/NNdJJ/bXjNqIh8yeoSjVLAuDuTUzAo7dzs8Y=", "narHash": "sha256-zON2GNBkzsIyALlOCFiEBcIjI4w38GYOb+P+R4S8Jsw=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "a79cfe0ebd24952b580b1cf08cd906354996d547", "rev": "d74a2335ac9c133d6bbec9fc98d91a77f1604c1f",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -6,29 +6,22 @@
outputs = { self, nixpkgs, ... }: outputs = { self, nixpkgs, ... }:
{ {
nixosModules = rec { nixosModules = rec {
home-manager = import ./nixos; home-manager = ./nixos;
default = home-manager; default = home-manager;
}; };
# deprecated in Nix 2.8
nixosModule = self.nixosModules.default;
darwinModules = rec { darwinModules = rec {
home-manager = import ./nix-darwin; home-manager = ./nix-darwin;
default = home-manager; default = home-manager;
}; };
# unofficial; deprecated in Nix 2.8
darwinModule = self.darwinModules.default;
flakeModules = rec { flakeModules = rec {
home-manager = import ./flake-module.nix; home-manager = ./flake-module.nix;
default = home-manager; default = home-manager;
}; };
templates = { templates = {
standalone = { default = self.templates.standalone;
path = ./templates/standalone;
description = "Standalone setup";
};
nixos = { nixos = {
path = ./templates/nixos; path = ./templates/nixos;
description = "Home Manager as a NixOS module,"; description = "Home Manager as a NixOS module,";
@ -37,10 +30,12 @@
path = ./templates/nix-darwin; path = ./templates/nix-darwin;
description = "Home Manager as a nix-darwin module,"; description = "Home Manager as a nix-darwin module,";
}; };
standalone = {
path = ./templates/standalone;
description = "Standalone setup";
};
}; };
defaultTemplate = self.templates.standalone;
lib = import ./lib { inherit (nixpkgs) lib; }; lib = import ./lib { inherit (nixpkgs) lib; };
} // (let } // (let
forAllSystems = nixpkgs.lib.genAttrs nixpkgs.lib.systems.flakeExposed; forAllSystems = nixpkgs.lib.genAttrs nixpkgs.lib.systems.flakeExposed;
@ -69,7 +64,5 @@
docs-json = docs.options.json; docs-json = docs.options.json;
docs-manpages = docs.manPages; docs-manpages = docs.manPages;
}); });
defaultPackage = forAllSystems (system: self.packages.${system}.default);
}); });
} }

View file

@ -268,10 +268,26 @@ let
}; };
aliases = mkOption { aliases = mkOption {
type = types.listOf (types.strMatching ".*@.*"); description = "Alternative identities of this account.";
default = [ ]; default = [ ];
example = [ "webmaster@example.org" "admin@example.org" ]; example = [ "webmaster@example.org" "admin@example.org" ];
description = "Alternative email addresses of this account."; type = types.listOf (types.oneOf [
(types.strMatching ".*@.*")
(types.submodule {
options = {
realName = mkOption {
type = types.str;
example = "Jane Doe";
description = "Name displayed when sending mails.";
};
address = mkOption {
type = types.strMatching ".*@.*";
example = "jane.doe@example.org";
description = "The email address of this identity.";
};
};
})
]);
}; };
realName = mkOption { realName = mkOption {

View file

@ -56,6 +56,11 @@ let
description = "The cursor size for hyprcursor."; description = "The cursor size for hyprcursor.";
}; };
}; };
sway = {
enable = mkEnableOption
"sway config generation for {option}`home.pointerCursor`";
};
}; };
}; };
@ -197,5 +202,18 @@ in {
if cfg.hyprcursor.size != null then cfg.hyprcursor.size else cfg.size; if cfg.hyprcursor.size != null then cfg.hyprcursor.size else cfg.size;
}; };
}) })
(mkIf cfg.sway.enable {
wayland.windowManager.sway = {
config = {
seat = {
"*" = {
xcursor_theme =
"${cfg.name} ${toString config.gtk.cursorTheme.size}";
};
};
};
};
})
]); ]);
} }

View file

@ -54,6 +54,7 @@ in {
Unit = { Unit = {
Description = "Fcitx5 input method editor"; Description = "Fcitx5 input method editor";
PartOf = [ "graphical-session.target" ]; PartOf = [ "graphical-session.target" ];
After = [ "graphical-session.target" ];
}; };
Service.ExecStart = "${fcitx5Package}/bin/fcitx5"; Service.ExecStart = "${fcitx5Package}/bin/fcitx5";
Install.WantedBy = [ "graphical-session.target" ]; Install.WantedBy = [ "graphical-session.target" ];

View file

@ -25,9 +25,11 @@
{ config, lib, ... }: { config, lib, ... }:
with lib; let
inherit (lib) types mkOption; # added by Home Manager
{ launchdTypes = import ./types.nix { inherit config lib; };
in {
freeformType = with types; attrsOf anything; # added by Home Manager freeformType = with types; attrsOf anything; # added by Home Manager
options = { options = {
@ -118,7 +120,7 @@ with lib;
}; };
LimitLoadToSessionType = mkOption { LimitLoadToSessionType = mkOption {
type = types.nullOr types.str; type = types.nullOr (types.oneOf [ types.str (types.listOf types.str) ]);
default = null; default = null;
description = '' description = ''
This configuration file only applies to sessions of the type specified. This key is used in concert This configuration file only applies to sessions of the type specified. This key is used in concert
@ -369,60 +371,26 @@ with lib;
StartCalendarInterval = mkOption { StartCalendarInterval = mkOption {
default = null; default = null;
example = { example = [{
Hour = 2; Hour = 2;
Minute = 30; Minute = 30;
}; }];
description = '' description = ''
This optional key causes the job to be started every calendar interval as specified. Missing arguments This optional key causes the job to be started every calendar interval as specified. The semantics are
are considered to be wildcard. The semantics are much like `crontab(5)`. Unlike cron which skips job much like {manpage}`crontab(5)`: Missing attributes are considered to be wildcard. Unlike cron which skips
invocations when the computer is asleep, launchd will start the job the next time the computer wakes job invocations when the computer is asleep, launchd will start the job the next time the computer wakes
up. If multiple intervals transpire before the computer is woken, those events will be coalesced into up. If multiple intervals transpire before the computer is woken, those events will be coalesced into
one event upon wake from sleep. one event upon waking from sleep.
::: {.important}
The list must not be empty and must not contain duplicate entries (attrsets which compare equally).
:::
::: {.caution}
Since missing attrs become wildcards, an empty attrset effectively means "every minute".
:::
''; '';
type = types.nullOr (types.listOf (types.submodule { type = types.nullOr launchdTypes.StartCalendarInterval;
options = {
Minute = mkOption {
type = types.nullOr types.int;
default = null;
description = ''
The minute on which this job will be run.
'';
};
Hour = mkOption {
type = types.nullOr types.int;
default = null;
description = ''
The hour on which this job will be run.
'';
};
Day = mkOption {
type = types.nullOr types.int;
default = null;
description = ''
The day on which this job will be run.
'';
};
Weekday = mkOption {
type = types.nullOr types.int;
default = null;
description = ''
The weekday on which this job will be run (0 and 7 are Sunday).
'';
};
Month = mkOption {
type = types.nullOr types.int;
default = null;
description = ''
The month on which this job will be run.
'';
};
};
}));
}; };
StandardInPath = mkOption { StandardInPath = mkOption {
@ -669,22 +637,22 @@ with lib;
resource limits based on what kind of job it is. If left unspecified, the system will apply light resource limits based on what kind of job it is. If left unspecified, the system will apply light
resource limits to the job, throttling its CPU usage and I/O bandwidth. The following are valid values: resource limits to the job, throttling its CPU usage and I/O bandwidth. The following are valid values:
Background Background
: Background jobs are generally processes that do work that was not directly requested by the user. : Background jobs are generally processes that do work that was not directly requested by the user.
The resource limits applied to Background jobs are intended to prevent them from disrupting the The resource limits applied to Background jobs are intended to prevent them from disrupting the
user experience. user experience.
Standard Standard
: Standard jobs are equivalent to no ProcessType being set. : Standard jobs are equivalent to no ProcessType being set.
Adaptive Adaptive
: Adaptive jobs move between the Background and Interactive classifications based on activity over : Adaptive jobs move between the Background and Interactive classifications based on activity over
XPC connections. See {manpage}`xpc_transaction_begin(3)` for details. XPC connections. See `xpc_transaction_begin(3)` for details.
Interactive Interactive
: Interactive jobs run with the same resource limitations as apps, that is to say, none. Interactive : Interactive jobs run with the same resource limitations as apps, that is to say, none. Interactive
jobs are critical to maintaining a responsive user experience, and this key should only be jobs are critical to maintaining a responsive user experience, and this key should only be
used if an app's ability to be responsive depends on it, and cannot be made Adaptive. used if an app's ability to be responsive depends on it, and cannot be made Adaptive.
''; '';
}; };
@ -706,6 +674,15 @@ with lib;
''; '';
}; };
LowPriorityBackgroundIO = mkOption {
type = types.nullOr types.bool;
default = null;
description = ''
This optional key specifies whether the kernel should consider this daemon to be low priority when
doing file system I/O when the process is throttled with the Darwin-background classification.
'';
};
LaunchOnlyOnce = mkOption { LaunchOnlyOnce = mkOption {
type = types.nullOr types.bool; type = types.nullOr types.bool;
default = null; default = null;
@ -717,7 +694,7 @@ with lib;
MachServices = mkOption { MachServices = mkOption {
default = null; default = null;
example = { ResetAtClose = true; }; example = { "org.nixos.service" = { ResetAtClose = true; }; };
description = '' description = ''
This optional key is used to specify Mach services to be registered with the Mach bootstrap sub-system. This optional key is used to specify Mach services to be registered with the Mach bootstrap sub-system.
Each key in this dictionary should be the name of service to be advertised. The value of the key must Each key in this dictionary should be the name of service to be advertised. The value of the key must
@ -726,31 +703,32 @@ with lib;
Finally, for the job itself, the values will be replaced with Mach ports at the time of check-in with Finally, for the job itself, the values will be replaced with Mach ports at the time of check-in with
launchd. launchd.
''; '';
type = types.nullOr (types.submodule { type = types.nullOr (types.attrsOf (types.either types.bool
options = { (types.submodule {
ResetAtClose = mkOption { options = {
type = types.nullOr types.bool; ResetAtClose = mkOption {
default = null; type = types.nullOr types.bool;
description = '' default = null;
If this boolean is false, the port is recycled, thus leaving clients to remain oblivious to the description = ''
demand nature of job. If the value is set to true, clients receive port death notifications when If this boolean is false, the port is recycled, thus leaving clients to remain oblivious to the
the job lets go of the receive right. The port will be recreated atomically with respect to bootstrap_look_up() demand nature of job. If the value is set to true, clients receive port death notifications when
calls, so that clients can trust that after receiving a port death notification, the job lets go of the receive right. The port will be recreated atomically with respect to bootstrap_look_up()
the new port will have already been recreated. Setting the value to true should be done with calls, so that clients can trust that after receiving a port death notification,
care. Not all clients may be able to handle this behavior. The default value is false. the new port will have already been recreated. Setting the value to true should be done with
''; care. Not all clients may be able to handle this behavior. The default value is false.
}; '';
};
HideUntilCheckIn = mkOption { HideUntilCheckIn = mkOption {
type = types.nullOr types.bool; type = types.nullOr types.bool;
default = null; default = null;
description = '' description = ''
Reserve the name in the namespace, but cause bootstrap_look_up() to fail until the job has Reserve the name in the namespace, but cause bootstrap_look_up() to fail until the job has
checked in with launchd. checked in with launchd.
''; '';
};
}; };
}; })));
});
}; };
LaunchEvents = mkOption { LaunchEvents = mkOption {
@ -778,6 +756,26 @@ with lib;
}; };
}; };
ServiceIPC = mkOption {
type = types.nullOr types.bool;
default = null;
description = ''
This optional key specifies whether the job participates in advanced
communication with launchd. The default is false. This flag is
incompatible with the inetdCompatibility key.
'';
};
SessionCreate = mkOption {
type = types.nullOr types.bool;
default = null;
description = ''
This key specifies that the job should be spawned into a new security
audit session rather than the default session for the context is belongs
to. See auditon(2) for details.
'';
};
Sockets = mkOption { Sockets = mkOption {
default = null; default = null;
description = '' description = ''

121
modules/launchd/types.nix Normal file
View file

@ -0,0 +1,121 @@
# launchd option type from nix-darwin
#
# Original code from https://github.com/LnL7/nix-darwin/commit/861af0fc94df9454f4e92d6892f75588763164bb
{ lib, ... }:
let
inherit (lib) imap1 types mkOption showOption mergeDefinitions;
inherit (builtins) map filter length deepSeq throw toString concatLists;
inherit (lib.options) showDefs;
wildcardText = lib.literalMD "`*`";
/* *
A type of list which does not allow duplicate elements. The base/inner
list type to use (e.g. `types.listOf` or `types.nonEmptyListOf`) is passed
via argument `listType`, which must be the final type and not a function.
NOTE: The extra check for duplicates is quadratic and strict, so use this
type sparingly and only:
* when needed, and
* when the list is expected to be recursively short (e.g. < 10 elements)
and shallow (i.e. strict evaluation of the list won't take too long)
The implementation of this function is similar to that of
`types.nonEmptyListOf`.
*/
types'.uniqueList = listType:
listType // {
description = "unique ${
types.optionDescriptionPhrase (class: class == "noun") listType
}";
substSubModules = m: types'.uniqueList (listType.substSubModules m);
# This has been taken from the implementation of `types.listOf`, but has
# been modified to throw on duplicates. This check cannot be done in the
# `check` fn as this check is deep/strict, and because `check` runs
# prior to merging.
merge = loc: defs:
let
# Each element of `dupes` is a list. When there are duplicates,
# later lists will be duplicates of earlier lists, so just throw on
# the first set of duplicates found so that we don't have duplicate
# error msgs.
checked = filter (li:
if length li > 1 then
throw ''
The option `${
showOption loc
}' contains duplicate entries after merging:
${showDefs li}''
else
false) dupes;
dupes =
map (def: filter (def': def'.value == def.value) merged) merged;
merged = filter (x: x ? value) (concatLists (imap1 (n: def:
imap1 (m: el:
let
inherit (def) file;
loc' = loc
++ [ "[definition ${toString n}-entry ${toString m}]" ];
in (mergeDefinitions loc' listType.nestedTypes.elemType [{
inherit file;
value = el;
}]).optionalValue // {
inherit loc' file;
}) def.value) defs));
in deepSeq checked (map (x: x.value) merged);
};
in {
StartCalendarInterval = let
CalendarIntervalEntry = types.submodule {
options = {
Minute = mkOption {
type = types.nullOr (types.ints.between 0 59);
default = null;
defaultText = wildcardText;
description = ''
The minute on which this job will be run.
'';
};
Hour = mkOption {
type = types.nullOr (types.ints.between 0 23);
default = null;
defaultText = wildcardText;
description = ''
The hour on which this job will be run.
'';
};
Day = mkOption {
type = types.nullOr (types.ints.between 1 31);
default = null;
defaultText = wildcardText;
description = ''
The day on which this job will be run.
'';
};
Weekday = mkOption {
type = types.nullOr (types.ints.between 0 7);
default = null;
defaultText = wildcardText;
description = ''
The weekday on which this job will be run (0 and 7 are Sunday).
'';
};
Month = mkOption {
type = types.nullOr (types.ints.between 1 12);
default = null;
defaultText = wildcardText;
description = ''
The month on which this job will be run.
'';
};
};
};
in types.either CalendarIntervalEntry
(types'.uniqueList (types.nonEmptyListOf CalendarIntervalEntry));
}

View file

@ -5,7 +5,6 @@
# are expected to be follow the same format as described in [1]. # are expected to be follow the same format as described in [1].
# #
# [1] https://github.com/NixOS/nixpkgs/blob/fca0d6e093c82b31103dc0dacc48da2a9b06e24b/maintainers/maintainer-list.nix#LC1 # [1] https://github.com/NixOS/nixpkgs/blob/fca0d6e093c82b31103dc0dacc48da2a9b06e24b/maintainers/maintainer-list.nix#LC1
{ {
aabccd021 = { aabccd021 = {
name = "Muhamad Abdurahman"; name = "Muhamad Abdurahman";
@ -113,6 +112,12 @@
github = "diniamo"; github = "diniamo";
githubId = 55629891; githubId = 55629891;
}; };
dsoverlord = {
name = "Kirill Zakharov";
email = "dsoverlord@vk.com";
github = "dsoverlord";
githubId = 78819443;
};
dwagenk = { dwagenk = {
email = "dwagenk@mailbox.org"; email = "dwagenk@mailbox.org";
github = "dwagenk"; github = "dwagenk";
@ -664,4 +669,26 @@
github = "ckgxrg-salt"; github = "ckgxrg-salt";
githubId = 165614491; githubId = 165614491;
}; };
HPsaucii = {
name = "Holly Powell";
email = "me@hpsaucii.dev";
github = "HPsaucii";
githubId = 126502193;
keys = [{
longkeyid = "rsa4096/0xEDB2C634166AE6AD";
fingerprint = "AD32 73D4 5E0E 9478 E826 543F EDB2 C634 166A E6AD";
}];
};
folliehiyuki = {
name = "Hoang Nguyen";
email = "folliekazetani@protonmail.com";
github = "folliehiyuki";
githubId = 67634026;
};
"3ulalia" = {
name = "Eulalia del Sol";
email = "3ulalia@proton.me";
github = "3ulalia";
githubId = "179992797";
};
} }

View file

@ -0,0 +1,92 @@
{ config, lib, pkgs, ... }:
let
inherit (pkgs.stdenv) isDarwin;
cfg = config.mozilla;
defaultPaths = [
# Link a .keep file to keep the directory around
(pkgs.writeTextDir "lib/mozilla/native-messaging-hosts/.keep" "")
];
thunderbirdNativeMessagingHostsPath = if isDarwin then
"Library/Mozilla/NativeMessagingHosts"
else
".mozilla/native-messaging-hosts";
firefoxNativeMessagingHostsPath = if isDarwin then
"Library/Application Support/Mozilla/NativeMessagingHosts"
else
".mozilla/native-messaging-hosts";
in {
meta.maintainers = with lib.maintainers; [
booxter
rycee
lib.hm.maintainers.bricked
];
options.mozilla = {
firefoxNativeMessagingHosts = lib.mkOption {
internal = true;
type = with lib.types; listOf package;
default = [ ];
description = ''
List of Firefox native messaging hosts to configure.
'';
};
thunderbirdNativeMessagingHosts = lib.mkOption {
internal = true;
type = with lib.types; listOf package;
default = [ ];
description = ''
List of Thunderbird native messaging hosts to configure.
'';
};
};
config = lib.mkIf (cfg.firefoxNativeMessagingHosts != [ ]
|| cfg.thunderbirdNativeMessagingHosts != [ ]) {
home.file = if isDarwin then
let
firefoxNativeMessagingHostsJoined = pkgs.symlinkJoin {
name = "ff-native-messaging-hosts";
paths = defaultPaths ++ cfg.firefoxNativeMessagingHosts;
};
thunderbirdNativeMessagingHostsJoined = pkgs.symlinkJoin {
name = "th-native-messaging-hosts";
paths = defaultPaths ++ cfg.thunderbirdNativeMessagingHosts;
};
in {
"${thunderbirdNativeMessagingHostsPath}" =
lib.mkIf (cfg.thunderbirdNativeMessagingHosts != [ ]) {
source =
"${thunderbirdNativeMessagingHostsJoined}/lib/mozilla/native-messaging-hosts";
recursive = true;
};
"${firefoxNativeMessagingHostsPath}" =
lib.mkIf (cfg.firefoxNativeMessagingHosts != [ ]) {
source =
"${firefoxNativeMessagingHostsJoined}/lib/mozilla/native-messaging-hosts";
recursive = true;
};
}
else
let
nativeMessagingHostsJoined = pkgs.symlinkJoin {
name = "mozilla-native-messaging-hosts";
# on Linux, the directory is shared between Firefox and Thunderbird; merge both into one
paths = defaultPaths ++ cfg.firefoxNativeMessagingHosts
++ cfg.thunderbirdNativeMessagingHosts;
};
in {
"${firefoxNativeMessagingHostsPath}" = {
source =
"${nativeMessagingHostsJoined}/lib/mozilla/native-messaging-hosts";
recursive = true;
};
};
};
}

View file

@ -2062,6 +2062,58 @@ in {
See https://github.com/mateusauler/git-worktree-switcher for more. See https://github.com/mateusauler/git-worktree-switcher for more.
''; '';
} }
{
time = "2025-02-20T18:39:31+00:00";
condition = hostPlatform.isLinux;
message = ''
A new module is available: 'programs.swayimg'.
swayimg is a fully customizable and lightweight image viewer for
Wayland based display servers.
See https://github.com/artemsen/swayimg for more.
'';
}
{
time = "2025-02-16T17:00:00+00:00";
message = ''
A new module is available: 'services.wluma'.
Wluma is a tool for Wayland compositors to automatically adjust
screen brightness based on the screen contents and amount of ambient light around you.
'';
}
{
time = "2025-02-21T16:53:20+00:00";
message = ''
A new module is available: 'programs.earthly'.
Earthly is a build configuration framework utilizing buildkit and
Dockerfile-like syntax for fast builds and simplicity.
'';
}
{
time = "2025-02-22T16:53:20+00:00";
message = ''
A new module is available: 'programs.jqp'.
A TUI playground for experimenting with `jq`.
'';
}
{
time = "2025-02-22T16:46:56+00:00";
condition = hostPlatform.isLinux;
message = ''
A new module is available: 'services.wpaperd'.
This replaces the existing module, 'programs.wpaperd', and adds a
systemd service to ensure its execution.
'';
}
]; ];
}; };
} }

View file

@ -143,6 +143,7 @@ in {
(mapAttrs' (name: file: nameValuePair "${cfg.stateHome}/${name}" file) (mapAttrs' (name: file: nameValuePair "${cfg.stateHome}/${name}" file)
cfg.stateFile) cfg.stateFile)
{ "${cfg.cacheHome}/.keep".text = ""; } { "${cfg.cacheHome}/.keep".text = ""; }
{ "${cfg.stateHome}/.keep".text = ""; }
]; ];
} }
]; ];

View file

@ -30,6 +30,7 @@ let
./misc/fontconfig.nix ./misc/fontconfig.nix
./misc/gtk.nix ./misc/gtk.nix
./misc/lib.nix ./misc/lib.nix
./misc/mozilla-messaging-hosts.nix
./misc/news.nix ./misc/news.nix
./misc/nixgl.nix ./misc/nixgl.nix
./misc/numlock.nix ./misc/numlock.nix
@ -89,6 +90,7 @@ let
./programs/dircolors.nix ./programs/dircolors.nix
./programs/direnv.nix ./programs/direnv.nix
./programs/discocss.nix ./programs/discocss.nix
./programs/earthly.nix
./programs/eclipse.nix ./programs/eclipse.nix
./programs/emacs.nix ./programs/emacs.nix
./programs/eww.nix ./programs/eww.nix
@ -138,6 +140,7 @@ let
./programs/java.nix ./programs/java.nix
./programs/jetbrains-remote.nix ./programs/jetbrains-remote.nix
./programs/jq.nix ./programs/jq.nix
./programs/jqp.nix
./programs/jujutsu.nix ./programs/jujutsu.nix
./programs/joshuto.nix ./programs/joshuto.nix
./programs/joplin-desktop.nix ./programs/joplin-desktop.nix
@ -237,6 +240,7 @@ let
./programs/sqls.nix ./programs/sqls.nix
./programs/ssh.nix ./programs/ssh.nix
./programs/starship.nix ./programs/starship.nix
./programs/swayimg.nix
./programs/swaylock.nix ./programs/swaylock.nix
./programs/swayr.nix ./programs/swayr.nix
./programs/taskwarrior.nix ./programs/taskwarrior.nix
@ -260,6 +264,7 @@ let
./programs/vifm.nix ./programs/vifm.nix
./programs/vim-vint.nix ./programs/vim-vint.nix
./programs/vim.nix ./programs/vim.nix
./programs/vinegar.nix
./programs/vscode.nix ./programs/vscode.nix
./programs/vscode/haskell.nix ./programs/vscode/haskell.nix
./programs/pywal.nix ./programs/pywal.nix
@ -269,7 +274,6 @@ let
./programs/wezterm.nix ./programs/wezterm.nix
./programs/wlogout.nix ./programs/wlogout.nix
./programs/wofi.nix ./programs/wofi.nix
./programs/wpaperd.nix
./programs/xmobar.nix ./programs/xmobar.nix
./programs/xplr.nix ./programs/xplr.nix
./programs/yambar.nix ./programs/yambar.nix
@ -302,6 +306,7 @@ let
./services/cliphist.nix ./services/cliphist.nix
./services/clipman.nix ./services/clipman.nix
./services/clipmenu.nix ./services/clipmenu.nix
./services/clipse.nix
./services/comodoro.nix ./services/comodoro.nix
./services/conky.nix ./services/conky.nix
./services/copyq.nix ./services/copyq.nix
@ -418,7 +423,9 @@ let
./services/window-managers/wayfire.nix ./services/window-managers/wayfire.nix
./services/window-managers/xmonad.nix ./services/window-managers/xmonad.nix
./services/wlsunset.nix ./services/wlsunset.nix
./services/wluma.nix
./services/wob.nix ./services/wob.nix
./services/wpaperd.nix
./services/xcape.nix ./services/xcape.nix
./services/xembed-sni-proxy.nix ./services/xembed-sni-proxy.nix
./services/xidlehook.nix ./services/xidlehook.nix

View file

@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: Home Manager Modules\n" "Project-Id-Version: Home Manager Modules\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" "Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2025-01-03 09:09+0100\n" "POT-Creation-Date: 2025-01-03 09:09+0100\n"
"PO-Revision-Date: 2023-12-10 15:58+0000\n" "PO-Revision-Date: 2025-02-19 21:00+0000\n"
"Last-Translator: Nara Díaz Viñolas <rdvdev2@gmail.com>\n" "Last-Translator: Alejandro Masó Bonilla <alejandrobonilla2001@gmail.com>\n"
"Language-Team: Catalan <https://hosted.weblate.org/projects/home-manager/" "Language-Team: Catalan <https://hosted.weblate.org/projects/home-manager/"
"modules/ca/>\n" "modules/ca/>\n"
"Language: ca\n" "Language: ca\n"
@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.3-dev\n" "X-Generator: Weblate 5.10.1-dev\n"
#: modules/files.nix:188 #: modules/files.nix:188
msgid "Creating home file links in %s" msgid "Creating home file links in %s"
@ -29,11 +29,11 @@ msgstr "Netejant enllaços orfes de %s"
#: modules/home-environment.nix:591 #: modules/home-environment.nix:591
msgid "Creating new profile generation" msgid "Creating new profile generation"
msgstr "" msgstr "Creant una nova generació per al nou perfil"
#: modules/home-environment.nix:594 #: modules/home-environment.nix:594
msgid "No change so reusing latest profile generation" msgid "No change so reusing latest profile generation"
msgstr "" msgstr "No hi ha canvis llavors s'utilitzarà la generació anterior"
#: modules/home-environment.nix:643 #: modules/home-environment.nix:643
msgid "" msgid ""
@ -55,13 +55,13 @@ msgstr ""
"Potser hi ha un conflicte amb un paquet instal·lat mitjançant\n" "Potser hi ha un conflicte amb un paquet instal·lat mitjançant\n"
"\"%s\"? Prova d'executar\n" "\"%s\"? Prova d'executar\n"
"\n" "\n"
" %s\n" ". . . . %s\n"
"\n" "\n"
"i si hi ha un paquet conflictiu el pots eliminar amb\n" "i si hi ha un paquet conflictiu el pots eliminar amb\n"
"\n" "\n"
" %s\n" ". . . . %s\n"
"\n" "\n"
"i després provar d'activar la teva configuració de Home Manager de nou." "Després provar d'activar la teva configuració de Home Manager de nou."
#: modules/home-environment.nix:676 #: modules/home-environment.nix:676
msgid "Activating %s" msgid "Activating %s"
@ -86,7 +86,7 @@ msgstr "Error: HOME està configurat a \"%s\", però s'esperava \"%s\""
#: modules/lib-bash/activation-init.sh:132 #: modules/lib-bash/activation-init.sh:132
msgid "Starting Home Manager activation" msgid "Starting Home Manager activation"
msgstr "Començant activació de Home Manager" msgstr "Començant l'activació de Home Manager"
#: modules/lib-bash/activation-init.sh:136 #: modules/lib-bash/activation-init.sh:136
msgid "Sanity checking Nix" msgid "Sanity checking Nix"
@ -102,7 +102,7 @@ msgstr "Execució en viu"
#: modules/lib-bash/activation-init.sh:159 #: modules/lib-bash/activation-init.sh:159
msgid "Using Nix version: %s" msgid "Using Nix version: %s"
msgstr "Utilitzant versió de Nix: %s" msgstr "Utilitzant la versió de Nix: %s"
#: modules/lib-bash/activation-init.sh:162 #: modules/lib-bash/activation-init.sh:162
msgid "Activation variables:" msgid "Activation variables:"

View file

@ -134,8 +134,9 @@ in {
oauthParams = { auth, params }: oauthParams = { auth, params }:
if useOauth auth && params != null && params != { } then if useOauth auth && params != null && params != { } then
"?" + builtins.concatStringsSep "&" lib.attrsets.mapAttrsToList "?" + builtins.concatStringsSep "&"
(k: v: k + "=" + lib.strings.escapeURL v) params (lib.attrsets.mapAttrsToList (k: v: k + "=" + lib.strings.escapeURL v)
(lib.attrsets.filterAttrs (k: v: v != null) params))
else else
""; "";

View file

@ -137,6 +137,18 @@ let
List of ${name} dictionaries to install. List of ${name} dictionaries to install.
''; '';
}; };
nativeMessagingHosts = mkOption {
type = types.listOf types.package;
default = [ ];
example = literalExpression ''
[
pkgs.kdePackages.plasma-browser-integration
]
'';
description = ''
List of ${name} native messaging hosts to install.
'';
};
}; };
browserConfig = cfg: browserConfig = cfg:
@ -178,6 +190,11 @@ let
value.source = pkg; value.source = pkg;
}; };
nativeMessagingHostsJoined = pkgs.symlinkJoin {
name = "${drvName}-native-messaging-hosts";
paths = cfg.nativeMessagingHosts;
};
package = if cfg.commandLineArgs != [ ] then package = if cfg.commandLineArgs != [ ] then
cfg.package.override { cfg.package.override {
commandLineArgs = concatStringsSep " " cfg.commandLineArgs; commandLineArgs = concatStringsSep " " cfg.commandLineArgs;
@ -189,7 +206,14 @@ let
home.packages = [ package ]; home.packages = [ package ];
home.file = optionalAttrs (!isProprietaryChrome) (listToAttrs home.file = optionalAttrs (!isProprietaryChrome) (listToAttrs
((map extensionJson cfg.extensions) ((map extensionJson cfg.extensions)
++ (map dictionary cfg.dictionaries))); ++ (map dictionary cfg.dictionaries)) // {
"${configDir}/NativeMessagingHosts" =
lib.mkIf (cfg.nativeMessagingHosts != [ ]) {
source =
"${nativeMessagingHostsJoined}/etc/chromium/native-messaging-hosts";
recursive = true;
};
});
}; };
in { in {

View file

@ -54,155 +54,168 @@ in {
}; };
}; };
config = mkIf cfg.enable { config = let
# Add default settings from `dircolors --print-database`. dircolorsPath = if config.home.preferXdgDirectories then
programs.dircolors.settings = { "${config.xdg.configHome}/dir_colors"
RESET = mkDefault "0"; else
DIR = mkDefault "01;34"; "~/.dir_colors";
LINK = mkDefault "01;36";
MULTIHARDLINK = mkDefault "00";
FIFO = mkDefault "40;33";
SOCK = mkDefault "01;35";
DOOR = mkDefault "01;35";
BLK = mkDefault "40;33;01";
CHR = mkDefault "40;33;01";
ORPHAN = mkDefault "40;31;01";
MISSING = mkDefault "00";
SETUID = mkDefault "37;41";
SETGID = mkDefault "30;43";
CAPABILITY = mkDefault "30;41";
STICKY_OTHER_WRITABLE = mkDefault "30;42";
OTHER_WRITABLE = mkDefault "34;42";
STICKY = mkDefault "37;44";
EXEC = mkDefault "01;32";
".tar" = mkDefault "01;31";
".tgz" = mkDefault "01;31";
".arc" = mkDefault "01;31";
".arj" = mkDefault "01;31";
".taz" = mkDefault "01;31";
".lha" = mkDefault "01;31";
".lz4" = mkDefault "01;31";
".lzh" = mkDefault "01;31";
".lzma" = mkDefault "01;31";
".tlz" = mkDefault "01;31";
".txz" = mkDefault "01;31";
".tzo" = mkDefault "01;31";
".t7z" = mkDefault "01;31";
".zip" = mkDefault "01;31";
".z" = mkDefault "01;31";
".dz" = mkDefault "01;31";
".gz" = mkDefault "01;31";
".lrz" = mkDefault "01;31";
".lz" = mkDefault "01;31";
".lzo" = mkDefault "01;31";
".xz" = mkDefault "01;31";
".zst" = mkDefault "01;31";
".tzst" = mkDefault "01;31";
".bz2" = mkDefault "01;31";
".bz" = mkDefault "01;31";
".tbz" = mkDefault "01;31";
".tbz2" = mkDefault "01;31";
".tz" = mkDefault "01;31";
".deb" = mkDefault "01;31";
".rpm" = mkDefault "01;31";
".jar" = mkDefault "01;31";
".war" = mkDefault "01;31";
".ear" = mkDefault "01;31";
".sar" = mkDefault "01;31";
".rar" = mkDefault "01;31";
".alz" = mkDefault "01;31";
".ace" = mkDefault "01;31";
".zoo" = mkDefault "01;31";
".cpio" = mkDefault "01;31";
".7z" = mkDefault "01;31";
".rz" = mkDefault "01;31";
".cab" = mkDefault "01;31";
".wim" = mkDefault "01;31";
".swm" = mkDefault "01;31";
".dwm" = mkDefault "01;31";
".esd" = mkDefault "01;31";
".jpg" = mkDefault "01;35";
".jpeg" = mkDefault "01;35";
".mjpg" = mkDefault "01;35";
".mjpeg" = mkDefault "01;35";
".gif" = mkDefault "01;35";
".bmp" = mkDefault "01;35";
".pbm" = mkDefault "01;35";
".pgm" = mkDefault "01;35";
".ppm" = mkDefault "01;35";
".tga" = mkDefault "01;35";
".xbm" = mkDefault "01;35";
".xpm" = mkDefault "01;35";
".tif" = mkDefault "01;35";
".tiff" = mkDefault "01;35";
".png" = mkDefault "01;35";
".svg" = mkDefault "01;35";
".svgz" = mkDefault "01;35";
".mng" = mkDefault "01;35";
".pcx" = mkDefault "01;35";
".mov" = mkDefault "01;35";
".mpg" = mkDefault "01;35";
".mpeg" = mkDefault "01;35";
".m2v" = mkDefault "01;35";
".mkv" = mkDefault "01;35";
".webm" = mkDefault "01;35";
".ogm" = mkDefault "01;35";
".mp4" = mkDefault "01;35";
".m4v" = mkDefault "01;35";
".mp4v" = mkDefault "01;35";
".vob" = mkDefault "01;35";
".qt" = mkDefault "01;35";
".nuv" = mkDefault "01;35";
".wmv" = mkDefault "01;35";
".asf" = mkDefault "01;35";
".rm" = mkDefault "01;35";
".rmvb" = mkDefault "01;35";
".flc" = mkDefault "01;35";
".avi" = mkDefault "01;35";
".fli" = mkDefault "01;35";
".flv" = mkDefault "01;35";
".gl" = mkDefault "01;35";
".dl" = mkDefault "01;35";
".xcf" = mkDefault "01;35";
".xwd" = mkDefault "01;35";
".yuv" = mkDefault "01;35";
".cgm" = mkDefault "01;35";
".emf" = mkDefault "01;35";
".ogv" = mkDefault "01;35";
".ogx" = mkDefault "01;35";
".aac" = mkDefault "00;36";
".au" = mkDefault "00;36";
".flac" = mkDefault "00;36";
".m4a" = mkDefault "00;36";
".mid" = mkDefault "00;36";
".midi" = mkDefault "00;36";
".mka" = mkDefault "00;36";
".mp3" = mkDefault "00;36";
".mpc" = mkDefault "00;36";
".ogg" = mkDefault "00;36";
".ra" = mkDefault "00;36";
".wav" = mkDefault "00;36";
".oga" = mkDefault "00;36";
".opus" = mkDefault "00;36";
".spx" = mkDefault "00;36";
".xspf" = mkDefault "00;36";
};
home.file.".dir_colors".text = concatStringsSep "\n" ([ ] dircolorsConfig = concatStringsSep "\n" ([ ]
++ mapAttrsToList formatLine cfg.settings ++ [ "" ] ++ mapAttrsToList formatLine cfg.settings ++ [ "" ]
++ optional (cfg.extraConfig != "") cfg.extraConfig); ++ optional (cfg.extraConfig != "") cfg.extraConfig);
in mkIf cfg.enable (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 '' programs.bash.initExtra = mkIf cfg.enableBashIntegration ''
eval $(${pkgs.coreutils}/bin/dircolors -b ~/.dir_colors) eval $(${pkgs.coreutils}/bin/dircolors -b ${dircolorsPath})
''; '';
programs.fish.shellInit = mkIf cfg.enableFishIntegration '' programs.fish.shellInit = mkIf cfg.enableFishIntegration ''
eval (${pkgs.coreutils}/bin/dircolors -c ~/.dir_colors) eval (${pkgs.coreutils}/bin/dircolors -c ${dircolorsPath})
''; '';
# Set `LS_COLORS` before Oh My Zsh and `initExtra`. # Set `LS_COLORS` before Oh My Zsh and `initExtra`.
programs.zsh.initExtraBeforeCompInit = mkIf cfg.enableZshIntegration '' programs.zsh.initExtraBeforeCompInit = mkIf cfg.enableZshIntegration ''
eval $(${pkgs.coreutils}/bin/dircolors -b ~/.dir_colors) eval $(${pkgs.coreutils}/bin/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

@ -0,0 +1,40 @@
{ config, lib, pkgs, ... }:
let
cfg = config.programs.earthly;
yamlFormat = pkgs.formats.yaml { };
in {
meta.maintainers = [ lib.hm.maintainers.folliehiyuki ];
options.programs.earthly = {
enable = lib.mkEnableOption "earthly";
package = lib.mkPackageOption pkgs "earthly" { };
settings = lib.mkOption {
type = yamlFormat.type;
default = { };
description = ''
Configuration written to ~/.earthly/config.yml file.
See https://docs.earthly.dev/docs/earthly-config for supported values.
'';
example = lib.literalExpression ''
global = {
disable_analytics = true;
disable_log_sharing = true;
};
'';
};
};
config = lib.mkIf cfg.enable {
home.packages = [ cfg.package ];
home.file.".earthly/config.yml" = lib.mkIf (cfg.settings != { }) {
source = yamlFormat.generate "earthly-config" cfg.settings;
};
};
}

View file

@ -1,17 +1,14 @@
{ lib, ... }: { lib, ... }:
with lib; with lib;
let let
modulePath = [ "programs" "firefox" ]; modulePath = [ "programs" "firefox" ];
moduleName = concatStringsSep "." modulePath; moduleName = concatStringsSep "." modulePath;
mkFirefoxModule = import ./firefox/mkFirefoxModule.nix; mkFirefoxModule = import ./firefox/mkFirefoxModule.nix;
in { in {
meta.maintainers = [ maintainers.rycee hm.maintainers.bricked ]; meta.maintainers =
[ maintainers.rycee hm.maintainers.bricked hm.maintainers.HPsaucii ];
imports = [ imports = [
(mkFirefoxModule { (mkFirefoxModule {
@ -21,25 +18,20 @@ in {
unwrappedPackageName = "firefox-unwrapped"; unwrappedPackageName = "firefox-unwrapped";
visible = true; visible = true;
platforms.linux = rec { platforms.linux = rec { configPath = ".mozilla/firefox"; };
vendorPath = ".mozilla";
configPath = "${vendorPath}/firefox";
};
platforms.darwin = { platforms.darwin = {
vendorPath = "Library/Application Support/Mozilla";
configPath = "Library/Application Support/Firefox"; configPath = "Library/Application Support/Firefox";
}; };
}) })
(mkRemovedOptionModule (modulePath ++ [ "extensions" ]) '' (mkRemovedOptionModule (modulePath ++ [ "extensions" ]) ''
Extensions are now managed per-profile. That is, change from Extensions are now managed per-profile. That is, change from
${moduleName}.extensions = [ foo bar ]; ${moduleName}.extensions = [ foo bar ];
to to
${moduleName}.profiles.myprofile.extensions = [ foo bar ];'') ${moduleName}.profiles.myprofile.extensions.packages = [ foo bar ];'')
(mkRemovedOptionModule (modulePath ++ [ "enableAdobeFlash" ]) (mkRemovedOptionModule (modulePath ++ [ "enableAdobeFlash" ])
"Support for this option has been removed.") "Support for this option has been removed.")
(mkRemovedOptionModule (modulePath ++ [ "enableGoogleTalk" ]) (mkRemovedOptionModule (modulePath ++ [ "enableGoogleTalk" ])

View file

@ -1,13 +1,9 @@
{ modulePath, name, description ? null, wrappedPackageName ? null { modulePath, name, description ? null, wrappedPackageName ? null
, unwrappedPackageName ? null, platforms, visible ? false , unwrappedPackageName ? null, platforms, visible ? false
, enableBookmarks ? true }: , enableBookmarks ? true, }:
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib; with lib;
let let
inherit (pkgs.stdenv.hostPlatform) isDarwin; inherit (pkgs.stdenv.hostPlatform) isDarwin;
appName = name; appName = name;
@ -34,23 +30,6 @@ let
profilesPath = profilesPath =
if isDarwin then "${cfg.configPath}/Profiles" else cfg.configPath; if isDarwin then "${cfg.configPath}/Profiles" else cfg.configPath;
nativeMessagingHostsPath = if isDarwin then
"${cfg.vendorPath}/NativeMessagingHosts"
else
"${cfg.vendorPath}/native-messaging-hosts";
nativeMessagingHostsJoined = pkgs.symlinkJoin {
name = "ff_native-messaging-hosts";
paths = [
# Link a .keep file to keep the directory around
(pkgs.writeTextDir "lib/mozilla/native-messaging-hosts/.keep" "")
# Link package configured native messaging hosts (entire browser actually)
cfg.finalPackage
]
# Link user configured native messaging hosts
++ cfg.nativeMessagingHosts;
};
# The extensions path shared by all profiles; will not be supported # The extensions path shared by all profiles; will not be supported
# by future browser versions. # by future browser versions.
extensionPath = "extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"; extensionPath = "extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
@ -77,11 +56,13 @@ let
else else
builtins.toJSON pref); builtins.toJSON pref);
mkUserJs = prePrefs: prefs: extraPrefs: bookmarks: mkUserJs = prePrefs: prefs: extraPrefs: bookmarks: extensions:
let let
prefs' = lib.optionalAttrs ([ ] != bookmarks) { prefs' = lib.optionalAttrs ([ ] != bookmarks) {
"browser.bookmarks.file" = toString (browserBookmarksFile bookmarks); "browser.bookmarks.file" = toString (browserBookmarksFile bookmarks);
"browser.places.importBookmarksHTML" = true; "browser.places.importBookmarksHTML" = true;
} // lib.optionalAttrs (extensions != { }) {
"extensions.webextensions.ExtensionStorageIDB.enabled" = false;
} // prefs; } // prefs;
in '' in ''
// Generated by Home Manager. // Generated by Home Manager.
@ -218,7 +199,6 @@ let
# The configuration expected by the Firefox wrapper builder. # The configuration expected by the Firefox wrapper builder.
bcfg = setAttrByPath [ browserName ] fcfg; bcfg = setAttrByPath [ browserName ] fcfg;
in if package == null then in if package == null then
null null
else if isDarwin then else if isDarwin then
@ -227,10 +207,10 @@ let
package.override (old: { package.override (old: {
cfg = old.cfg or { } // fcfg; cfg = old.cfg or { } // fcfg;
extraPolicies = (old.extraPolicies or { }) // cfg.policies; extraPolicies = (old.extraPolicies or { }) // cfg.policies;
pkcs11Modules = (old.pkcs11Modules or [ ]) ++ cfg.pkcs11Modules;
}) })
else else
(pkgs.wrapFirefox.override { config = bcfg; }) package { }; (pkgs.wrapFirefox.override { config = bcfg; }) package { };
in { in {
options = setAttrByPath modulePath { options = setAttrByPath modulePath {
enable = mkOption { enable = mkOption {
@ -242,7 +222,7 @@ in {
optionalString (description != null) " ${description}" optionalString (description != null) " ${description}"
} }
${optionalString (!visible) ${optionalString (!visible)
"See `programs.firefox` for more configuration options."} "See `${moduleName}` for more configuration options."}
''; '';
}; };
@ -300,11 +280,7 @@ in {
vendorPath = mkOption { vendorPath = mkOption {
internal = true; internal = true;
type = with types; nullOr str; type = with types; nullOr str;
default = with platforms; default = null;
if isDarwin then
darwin.vendorPath or null
else
linux.vendorPath or null;
example = ".mozilla"; example = ".mozilla";
description = description =
"Directory containing the native messaging hosts directory."; "Directory containing the native messaging hosts directory.";
@ -319,7 +295,7 @@ in {
description = "Directory containing the ${appName} configuration files."; description = "Directory containing the ${appName} configuration files.";
}; };
nativeMessagingHosts = optionalAttrs (cfg.vendorPath != null) (mkOption { nativeMessagingHosts = mkOption {
inherit visible; inherit visible;
type = types.listOf types.package; type = types.listOf types.package;
default = [ ]; default = [ ];
@ -327,7 +303,7 @@ in {
Additional packages containing native messaging hosts that should be Additional packages containing native messaging hosts that should be
made available to ${appName} extensions. made available to ${appName} extensions.
''; '';
}); };
finalPackage = mkOption { finalPackage = mkOption {
inherit visible; inherit visible;
@ -667,37 +643,125 @@ in {
for more information. for more information.
''; '';
}; };
extensions = mkOption { extensions = mkOption {
type = types.listOf types.package; type = types.coercedTo (types.listOf types.package) (packages: {
default = [ ]; packages = mkIf (builtins.length packages > 0) (warn ''
example = literalExpression '' In order to support declarative extension configuration,
with pkgs.nur.repos.rycee.firefox-addons; [ extension installation has been moved from
privacy-badger ${moduleName}.profiles.<profile>.extensions
] to
''; ${moduleName}.profiles.<profile>.extensions.packages
'' packages);
}) (types.submodule {
options = {
packages = mkOption {
type = types.listOf types.package;
default = [ ];
example = literalExpression ''
with pkgs.nur.repos.rycee.firefox-addons; [
privacy-badger
]
'';
description = ''
List of ${name} add-on packages to install for this profile.
Some pre-packaged add-ons are accessible from the Nix User Repository.
Once you have NUR installed run
```console
$ nix-env -f '<nixpkgs>' -qaP -A nur.repos.rycee.firefox-addons
```
to list the available ${name} add-ons.
Note that it is necessary to manually enable these extensions
inside ${name} after the first installation.
To automatically enable extensions add
`"extensions.autoDisableScopes" = 0;`
to
[{option}`${moduleName}.profiles.<profile>.settings`](#opt-${moduleName}.profiles._name_.settings)
'';
};
force = mkOption {
description = ''
Whether to override all previous firefox settings.
This is required when using `settings`.
'';
default = false;
example = true;
type = types.bool;
};
settings = mkOption {
default = { };
example = literalExpression ''
{
# Example with uBlock origin's extensionID
"uBlock0@raymondhill.net".settings = {
selectedFilterLists = [
"ublock-filters"
"ublock-badware"
"ublock-privacy"
"ublock-unbreak"
"ublock-quick-fixes"
];
};
# Example with Stylus' UUID-form extensionID
"{7a7a4a92-a2a0-41d1-9fd7-1e92480d612d}".settings = {
dbInChromeStorage = true; # required for Stylus
}
}
'';
description = ''
Attribute set of options for each extension.
The keys of the attribute set consist of the ID of the extension
or its UUID wrapped in curly braces.
'';
type = types.attrsOf (types.submodule {
options = {
settings = mkOption {
type = types.attrsOf jsonFormat.type;
description =
"Json formatted options for the specified extensionID";
};
force = mkOption {
type = types.bool;
default = false;
example = true;
description = ''
Forcibly override any existing configuration for
this extension.
'';
};
};
});
};
};
});
default = { };
description = '' description = ''
List of ${appName} add-on packages to install for this profile. Submodule for installing and configuring extensions.
Some pre-packaged add-ons are accessible from the '';
[Nix User Repository](https://github.com/nix-community/NUR). example = literalExpression ''
Once you have NUR installed run {
packages = with pkgs.nur.repos.rycee.firefox-addons; [
```console ublock-origin
$ nix-env -f '<nixpkgs>' -qaP -A nur.repos.rycee.firefox-addons ];
``` settings."uBlock0@raymondhill.net".settings = {
selectedFilterLists = [
to list the available ${appName} add-ons. "ublock-filters"
"ublock-badware"
Note that it is necessary to manually enable these extensions "ublock-privacy"
inside ${appName} after the first installation. "ublock-unbreak"
"ublock-quick-fixes"
To automatically enable extensions add ];
`"extensions.autoDisableScopes" = 0;` };
to }
[{option}`${moduleName}.profiles.<profile>.settings`](#opt-${moduleName}.profiles._name_.settings)
''; '';
}; };
}; };
})); }));
default = { }; default = { };
@ -715,6 +779,14 @@ in {
`true`. `true`.
''; '';
}; };
pkcs11Modules = mkOption {
type = types.listOf types.package;
default = [ ];
description = ''
Additional packages to be loaded as PKCS #11 modules in Firefox.
'';
};
}; };
config = mkIf cfg.enable ({ config = mkIf cfg.enable ({
@ -748,7 +820,7 @@ in {
{ {
assertion = cfg.languagePacks == [ ] || cfg.package != null; assertion = cfg.languagePacks == [ ] || cfg.package != null;
message = '' message = ''
'programs.firefox.languagePacks' requires 'programs.firefox.package' '${moduleName}.languagePacks' requires '${moduleName}.package'
to be set to a non-null value. to be set to a non-null value.
''; '';
} }
@ -756,67 +828,93 @@ in {
(mkNoDuplicateAssertion cfg.profiles "profile") (mkNoDuplicateAssertion cfg.profiles "profile")
] ++ (mapAttrsToList ] ++ (mapAttrsToList
(_: profile: mkNoDuplicateAssertion profile.containers "container") (_: profile: mkNoDuplicateAssertion profile.containers "container")
cfg.profiles); cfg.profiles) ++ (mapAttrsToList (profileName: profile: {
assertion = profile.extensions.settings == { }
|| profile.extensions.force;
message = ''
Using '${
lib.showAttrPath
(modulePath ++ [ "profiles" profileName "extensions" "settings" ])
}' will override all previous extensions settings.
Enable '${
lib.showAttrPath
(modulePath ++ [ "profiles" profileName "extensions" "force" ])
}' to acknowledge this.
'';
}) cfg.profiles);
warnings = optional (cfg.enableGnomeExtensions or false) '' warnings = optional (cfg.enableGnomeExtensions or false) ''
Using '${moduleName}.enableGnomeExtensions' has been deprecated and Using '${moduleName}.enableGnomeExtensions' has been deprecated and
will be removed in the future. Please change to overriding the package will be removed in the future. Please change to overriding the package
configuration using '${moduleName}.package' instead. You can refer to configuration using '${moduleName}.package' instead. You can refer to
its example for how to do this. its example for how to do this.
'' ++ optional (cfg.vendorPath != null) ''
Using '${moduleName}.vendorPath' has been deprecated and
will be removed in the future. Native messaging hosts will function normally without specifying this path.
''; '';
home.packages = lib.optional (cfg.finalPackage != null) cfg.finalPackage; home.packages = lib.optional (cfg.finalPackage != null) cfg.finalPackage;
mozilla.firefoxNativeMessagingHosts = cfg.nativeMessagingHosts
# package configured native messaging hosts (entire browser actually)
++ (lib.optional (cfg.finalPackage != null) cfg.finalPackage);
home.file = mkMerge ([{ home.file = mkMerge ([{
"${cfg.configPath}/profiles.ini" = "${cfg.configPath}/profiles.ini" =
mkIf (cfg.profiles != { }) { text = profilesIni; }; mkIf (cfg.profiles != { }) { text = profilesIni; };
}] ++ optional (cfg.vendorPath != null) { }] ++ flip mapAttrsToList cfg.profiles (_: profile:
"${nativeMessagingHostsPath}" = { # Merge the regular profile settings with extension settings
source = mkMerge ([{
"${nativeMessagingHostsJoined}/lib/mozilla/native-messaging-hosts"; "${profilesPath}/${profile.path}/.keep".text = "";
recursive = true;
};
} ++ flip mapAttrsToList cfg.profiles (_: profile: {
"${profilesPath}/${profile.path}/.keep".text = "";
"${profilesPath}/${profile.path}/chrome/userChrome.css" = "${profilesPath}/${profile.path}/chrome/userChrome.css" =
mkIf (profile.userChrome != "") { text = profile.userChrome; }; mkIf (profile.userChrome != "") { text = profile.userChrome; };
"${profilesPath}/${profile.path}/chrome/userContent.css" = "${profilesPath}/${profile.path}/chrome/userContent.css" =
mkIf (profile.userContent != "") { text = profile.userContent; }; mkIf (profile.userContent != "") { text = profile.userContent; };
"${profilesPath}/${profile.path}/user.js" = mkIf (profile.preConfig != "" "${profilesPath}/${profile.path}/user.js" = mkIf (profile.preConfig
|| profile.settings != { } || profile.extraConfig != "" != "" || profile.settings != { } || profile.extraConfig != ""
|| profile.bookmarks != [ ]) { || profile.bookmarks != [ ]) {
text = mkUserJs profile.preConfig profile.settings profile.extraConfig text =
profile.bookmarks; mkUserJs profile.preConfig profile.settings profile.extraConfig
}; profile.bookmarks profile.extensions.settings;
};
"${profilesPath}/${profile.path}/containers.json" = "${profilesPath}/${profile.path}/containers.json" =
mkIf (profile.containers != { }) { mkIf (profile.containers != { }) {
text = mkContainersJson profile.containers; text = mkContainersJson profile.containers;
force = profile.containersForce; force = profile.containersForce;
}; };
"${profilesPath}/${profile.path}/search.json.mozlz4" = "${profilesPath}/${profile.path}/search.json.mozlz4" =
mkIf (profile.search.enable) { mkIf (profile.search.enable) {
enable = profile.search.enable; enable = profile.search.enable;
force = profile.search.force; force = profile.search.force;
source = profile.search.file; source = profile.search.file;
}; };
"${profilesPath}/${profile.path}/extensions" = "${profilesPath}/${profile.path}/extensions" =
mkIf (profile.extensions != [ ]) { mkIf (profile.extensions.packages != [ ]) {
source = let source = let
extensionsEnvPkg = pkgs.buildEnv { extensionsEnvPkg = pkgs.buildEnv {
name = "hm-firefox-extensions"; name = "hm-firefox-extensions";
paths = profile.extensions; paths = profile.extensions.packages;
}; };
in "${extensionsEnvPkg}/share/mozilla/${extensionPath}"; in "${extensionsEnvPkg}/share/mozilla/${extensionPath}";
recursive = true; recursive = true;
force = true; force = true;
}; };
})); }] ++
# Add extension settings as separate attributes
optional (profile.extensions.settings != { }) (mkMerge (mapAttrsToList
(name: settingConfig: {
"${profilesPath}/${profile.path}/browser-extension-data/${name}/storage.js" =
{
force = settingConfig.force;
text = generators.toJSON { } settingConfig.settings;
};
}) profile.extensions.settings)))));
} // setAttrByPath modulePath { } // setAttrByPath modulePath {
finalPackage = wrapPackage cfg.package; finalPackage = wrapPackage cfg.package;

View file

@ -66,7 +66,7 @@ let
}; };
onEvent = mkOption { onEvent = mkOption {
type = with types; nullOr str; type = with types; nullOr (either str (listOf str));
default = null; default = null;
description = '' description = ''
Tells fish to run this function when the specified named event is Tells fish to run this function when the specified named event is
@ -511,7 +511,7 @@ in {
mods = with def; mods = with def;
modifierStr "description" description ++ modifierStr "wraps" wraps modifierStr "description" description ++ modifierStr "wraps" wraps
++ modifierStr "on-event" onEvent ++ lib.concatMap (modifierStr "on-event") (lib.toList onEvent)
++ modifierStr "on-variable" onVariable ++ modifierStr "on-variable" onVariable
++ modifierStr "on-job-exit" onJobExit ++ modifierStr "on-job-exit" onJobExit
++ modifierStr "on-process-exit" onProcessExit ++ modifierStr "on-process-exit" onProcessExit

View file

@ -19,14 +19,8 @@ in {
unwrappedPackageName = "floorp-unwrapped"; unwrappedPackageName = "floorp-unwrapped";
visible = true; visible = true;
platforms.linux = { platforms.linux = { configPath = ".floorp"; };
configPath = ".floorp"; platforms.darwin = { configPath = "Library/Application Support/Floorp"; };
vendorPath = ".mozilla";
};
platforms.darwin = {
configPath = "Library/Application Support/Floorp";
vendorPath = "Library/Application Support/Mozilla";
};
}) })
]; ];
} }

View file

@ -31,7 +31,7 @@ in {
package = lib.mkPackageOption pkgs "ghostty" { package = lib.mkPackageOption pkgs "ghostty" {
nullable = true; nullable = true;
extraDescription = extraDescription =
"Set programs.ghostty.package to null on platfroms where ghostty is not available or marked broken"; "Set programs.ghostty.package to null on platforms where ghostty is not available or marked broken";
}; };
settings = lib.mkOption { settings = lib.mkOption {

View file

@ -411,6 +411,29 @@ in {
''; '';
}; };
}; };
riff = {
enable = mkEnableOption "" // {
description = ''
Enable the <command>riff</command> diff highlighter.
See <link xlink:href="https://github.com/walles/riff" />.
'';
};
package = mkPackageOption pkgs "riffdiff" { };
commandLineOptions = mkOption {
type = types.listOf types.str;
default = [ ];
example = literalExpression ''[ "--no-adds-only-special" ]'';
apply = concatStringsSep " ";
description = ''
Command line arguments to include in the <command>RIFF</command> environment variable.
Run <command>riff --help</command> for a full list of options
'';
};
};
}; };
}; };
@ -434,6 +457,7 @@ in {
cfg.diff-so-fancy.enable cfg.diff-so-fancy.enable
cfg.difftastic.enable cfg.difftastic.enable
cfg.diff-highlight.enable cfg.diff-highlight.enable
cfg.riff.enable
]; ];
in count id enabled <= 1; in count id enabled <= 1;
message = message =
@ -496,7 +520,7 @@ in {
format = if (versionOlder config.home.stateVersion "25.05") then format = if (versionOlder config.home.stateVersion "25.05") then
(mkOptionDefault "openpgp") (mkOptionDefault "openpgp")
else else
null; (mkOptionDefault null);
signer = let signer = let
defaultSigners = { defaultSigners = {
openpgp = getExe config.programs.gpg.package; openpgp = getExe config.programs.gpg.package;
@ -678,5 +702,25 @@ in {
}; };
}; };
}) })
(let riffExe = baseNameOf (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

@ -166,12 +166,13 @@ in {
config = mkIf cfg.enable { config = mkIf cfg.enable {
lib.htop = { lib.htop = {
inherit fields modes leftMeters rightMeters bar text graph led blank; inherit fields defaultFields modes leftMeters rightMeters bar text graph
led blank;
}; };
home.packages = [ cfg.package ]; home.packages = [ cfg.package ];
xdg.configFile."htop/htoprc" = let xdg.configFile."htop" = let
defaults = { defaults = {
fields = if isDarwin then fields = if isDarwin then
remove fields.M_SHARE defaultFields remove fields.M_SHARE defaultFields
@ -188,9 +189,9 @@ in {
formatOptions = mapAttrsToList formatOption; formatOptions = mapAttrsToList formatOption;
in mkIf (cfg.settings != { }) { in mkIf (cfg.settings != { }) {
text = source = pkgs.writeTextDir "htoprc"
concatStringsSep "\n" (formatOptions before ++ formatOptions settings) (concatStringsSep "\n" (formatOptions before ++ formatOptions settings)
+ "\n"; + "\n");
}; };
}; };
} }

View file

@ -31,7 +31,7 @@ in {
"${ide}/bin/${ide.meta.mainProgram}-remote-dev-server registerBackendLocationForGateway || true"; "${ide}/bin/${ide.meta.mainProgram}-remote-dev-server registerBackendLocationForGateway || true";
lines = map mkLine cfg.ides; lines = map mkLine cfg.ides;
linesStr = '' linesStr = ''
rm $HOME/.cache/JetBrains/RemoteDev/userProvidedDist/_nix_store* rm $HOME/.cache/JetBrains/RemoteDev/userProvidedDist/_nix_store* || true
'' + concatStringsSep "\n" lines; '' + concatStringsSep "\n" lines;
in hm.dag.entryAfter [ "writeBoundary" ] linesStr; in hm.dag.entryAfter [ "writeBoundary" ] linesStr;
}; };

33
modules/programs/jqp.nix Normal file
View file

@ -0,0 +1,33 @@
{ config, lib, pkgs, ... }:
let
cfg = config.programs.jqp;
yamlFormat = pkgs.formats.yaml { };
in {
options.programs.jqp = {
enable = lib.mkEnableOption "jqp, jq playground";
package = lib.mkPackageOption pkgs "jqp" { };
settings = lib.mkOption {
type = yamlFormat.type;
default = { };
example = {
theme = {
name = "monokai";
chromaStyleOverrides = { kc = "#009900 underline"; };
};
};
description = "Jqp configuration";
};
};
config = lib.mkIf cfg.enable {
home = {
packages = [ cfg.package ];
file.".jqp.yaml" = lib.mkIf (cfg.settings != { }) {
source = yamlFormat.generate "jqp-config" cfg.settings;
};
};
};
}

View file

@ -22,6 +22,10 @@ let
mkKeyValue = key: command: "map ${key} ${command}"; mkKeyValue = key: command: "map ${key} ${command}";
}; };
toKittyActionAliases = lib.generators.toKeyValue {
mkKeyValue = alias_name: action: "action_alias ${alias_name} ${action}";
};
toKittyEnv = lib.generators.toKeyValue { toKittyEnv = lib.generators.toKeyValue {
mkKeyValue = name: value: "env ${name}=${value}"; mkKeyValue = name: value: "env ${name}=${value}";
}; };
@ -143,6 +147,18 @@ in {
description = "The font to use."; description = "The font to use.";
}; };
actionAliases = mkOption {
type = types.attrsOf types.str;
default = { };
description = "Define action aliases.";
example = literalExpression ''
{
"launch_tab" = "launch --cwd=current --type=tab";
"launch_window" = "launch --cwd=current --type=os-window";
}
'';
};
keybindings = mkOption { keybindings = mkOption {
type = types.attrsOf types.str; type = types.attrsOf types.str;
default = { }; default = { };
@ -234,6 +250,7 @@ in {
shell_integration ${cfg.shellIntegration.mode} shell_integration ${cfg.shellIntegration.mode}
'') '')
(toKittyConfig cfg.settings) (toKittyConfig cfg.settings)
(toKittyActionAliases cfg.actionAliases)
(toKittyKeybindings cfg.keybindings) (toKittyKeybindings cfg.keybindings)
(toKittyEnv cfg.environment) (toKittyEnv cfg.environment)
cfg.extraConfig cfg.extraConfig

View file

@ -29,13 +29,9 @@ in {
wrappedPackageName = "librewolf"; wrappedPackageName = "librewolf";
unwrappedPackageName = "librewolf-unwrapped"; unwrappedPackageName = "librewolf-unwrapped";
platforms.linux = { platforms.linux = { configPath = ".librewolf"; };
configPath = ".librewolf";
vendorPath = ".mozilla";
};
platforms.darwin = { platforms.darwin = {
configPath = "Library/Application Support/LibreWolf"; configPath = "Library/Application Support/LibreWolf";
vendorPath = "Library/Application Support/Mozilla";
}; };
enableBookmarks = false; enableBookmarks = false;

View file

@ -21,6 +21,7 @@ in {
"enableBashIntegration" "enableBashIntegration"
"enableZshIntegration" "enableZshIntegration"
"enableFishIntegration" "enableFishIntegration"
"enableNushellIntegration"
"settings" "settings"
]; ];
@ -39,6 +40,9 @@ in {
enableZshIntegration = enableZshIntegration =
lib.hm.shell.mkZshIntegrationOption { inherit config; }; lib.hm.shell.mkZshIntegrationOption { inherit config; };
enableNushellIntegration =
lib.hm.shell.mkNushellIntegrationOption { inherit config; };
globalConfig = mkOption { globalConfig = mkOption {
type = tomlFormat.type; type = tomlFormat.type;
default = { }; default = { };
@ -103,6 +107,16 @@ in {
fish.interactiveShellInit = mkIf cfg.enableFishIntegration '' fish.interactiveShellInit = mkIf cfg.enableFishIntegration ''
${getExe cfg.package} activate fish | source ${getExe cfg.package} activate fish | source
''; '';
nushell = mkIf cfg.enableNushellIntegration {
extraEnv = ''
let mise_path = $nu.default-config-dir | path join mise.nu
^mise activate nu | save $mise_path --force
'';
extraConfig = ''
use ($nu.default-config-dir | path join mise.nu)
'';
};
}; };
}; };
} }

View file

@ -16,7 +16,8 @@ let
filter (a: a.mu.enable) (attrValues config.accounts.email.accounts); filter (a: a.mu.enable) (attrValues config.accounts.email.accounts);
addrs = map (a: a.address) muAccounts; addrs = map (a: a.address) muAccounts;
# Construct list of lists containing email aliases, and flatten # Construct list of lists containing email aliases, and flatten
aliases = flatten (map (a: a.aliases) muAccounts); aliases = map (alias: alias.address or alias)
(flatten (map (a: a.aliases) muAccounts));
# Sort the list # Sort the list
in sort lessThan (addrs ++ aliases); in sort lessThan (addrs ++ aliases);

View file

@ -52,15 +52,11 @@ in {
}; };
config = { config = {
warnings = lib.optionals warnings = (lib.optional
(osConfig != null && !(cfg.clean.enable -> !osConfig.nix.gc.automatic)) [ (cfg.clean.enable && osConfig != null && osConfig.nix.gc.automatic)
"programs.nh.clean.enable and nix.gc.automatic (system-wide in configuration.nix) are both enabled. Please use one or the other to avoid conflict." "programs.nh.clean.enable and nix.gc.automatic (system-wide in configuration.nix) are both enabled. Please use one or the other to avoid conflict.")
]; ++ (lib.optional (cfg.clean.enable && config.nix.gc.automatic)
"programs.nh.clean.enable and nix.gc.automatic (Home-Manager) are both enabled. Please use one or the other to avoid conflict.");
assertions = [{
assertion = (cfg.flake != null) -> !(lib.hasSuffix ".nix" cfg.flake);
message = "nh.flake must be a directory, not a nix file";
}];
home = lib.mkIf cfg.enable { home = lib.mkIf cfg.enable {
packages = [ cfg.package ]; packages = [ cfg.package ];

View file

@ -37,8 +37,9 @@ let
in { in {
name = catAttrs "realName" primary; name = catAttrs "realName" primary;
primary_email = catAttrs "address" primary; primary_email = catAttrs "address" primary;
other_email = catAttrs "aliases" primary ++ catAttrs "address" secondaries other_email = map (email: email.address or email) (flatten
++ catAttrs "aliases" secondaries; (catAttrs "aliases" primary ++ catAttrs "address" secondaries
++ catAttrs "aliases" secondaries));
}; };
search = { exclude_tags = cfg.search.excludeTags; }; search = { exclude_tags = cfg.search.excludeTags; };

View file

@ -0,0 +1,53 @@
{ config, lib, pkgs, ... }:
let
cfg = config.programs.swayimg;
iniFormat = pkgs.formats.ini { };
in {
meta.maintainers = with lib.maintainers; [ dod-101 ];
options.programs.swayimg = {
enable = lib.mkEnableOption "swayimg";
package = lib.mkOption {
type = lib.types.package;
default = pkgs.swayimg;
defaultText = lib.literalExpression "pkgs.swayimg";
description = "The swayimg package to install";
};
settings = lib.mkOption {
type = iniFormat.type;
default = { };
description = ''
Configuration written to
{file}`$XDG_CONFIG_HOME/swayimg/config`. See <https://github.com/artemsen/swayimg/blob/master/extra/swayimgrc> for a list of available options.
'';
example = lib.literalExpression ''
{
viewer = {
window = "#10000010";
scale = "fill";
};
"info.viewer" = {
top_left = "+name,+format";
};
"keys.viewer" = {
"Shift+r" = "rand_file";
};
}
'';
};
};
config = lib.mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "programs.swayimg" pkgs
lib.platforms.linux)
];
home.packages = [ cfg.package ];
xdg.configFile."swayimg/config" = lib.mkIf (cfg.settings != { }) {
source = iniFormat.generate "config" cfg.settings;
};
};
}

View file

@ -49,16 +49,25 @@ let
}; };
})); }));
getId = account: address:
if address == account.address then
account.id
else
(builtins.hashString "sha256" (if (builtins.isString address) then
address
else
(address.address + address.realName)));
toThunderbirdIdentity = account: address: toThunderbirdIdentity = account: address:
# For backwards compatibility, the primary address reuses the account ID. # For backwards compatibility, the primary address reuses the account ID.
let let
id = if address == account.address then id = getId account address;
account.id addressIsString = builtins.isString address;
else
builtins.hashString "sha256" address;
in { in {
"mail.identity.id_${id}.fullName" = account.realName; "mail.identity.id_${id}.fullName" =
"mail.identity.id_${id}.useremail" = address; if addressIsString then account.realName else address.realName;
"mail.identity.id_${id}.useremail" =
if addressIsString then address else address.address;
"mail.identity.id_${id}.valid" = true; "mail.identity.id_${id}.valid" = true;
"mail.identity.id_${id}.htmlSigText" = "mail.identity.id_${id}.htmlSigText" =
if account.signature.showSignature == "none" then if account.signature.showSignature == "none" then
@ -87,9 +96,7 @@ let
addresses = [ account.address ] ++ account.aliases; addresses = [ account.address ] ++ account.aliases;
in { in {
"mail.account.account_${id}.identities" = concatStringsSep "," "mail.account.account_${id}.identities" = concatStringsSep ","
([ "id_${id}" ] (map (address: "id_${getId account address}") addresses);
++ map (address: "id_${builtins.hashString "sha256" address}")
account.aliases);
"mail.account.account_${id}.server" = "server_${id}"; "mail.account.account_${id}.server" = "server_${id}";
} // optionalAttrs account.primary { } // optionalAttrs account.primary {
"mail.accountmanager.defaultaccount" = "account_${id}"; "mail.accountmanager.defaultaccount" = "account_${id}";
@ -128,6 +135,18 @@ let
(builtins.map (address: toThunderbirdIdentity account address) addresses) (builtins.map (address: toThunderbirdIdentity account address) addresses)
// account.thunderbird.settings id; // account.thunderbird.settings id;
toThunderbirdFeed = feed: profile:
let id = feed.id;
in {
"mail.account.account_${id}.server" = "server_${id}";
"mail.server.server_${id}.name" = feed.name;
"mail.server.server_${id}.type" = "rss";
"mail.server.server_${id}.directory" =
"${thunderbirdProfilesPath}/${profile.name}/Mail/Feeds-${id}";
"mail.server.server_${id}.directory-rel" = "[ProfD]Mail/Feeds-${id}";
"mail.server.server_${id}.hostname" = "Feeds-${id}";
};
mkUserJs = prefs: extraPrefs: '' mkUserJs = prefs: extraPrefs: ''
// Generated by Home Manager. // Generated by Home Manager.
@ -158,6 +177,16 @@ in {
description = "profile version, set null for nix-darwin"; description = "profile version, set null for nix-darwin";
}; };
nativeMessagingHosts = mkOption {
visible = true;
type = types.listOf types.package;
default = [ ];
description = ''
Additional packages containing native messaging hosts that should be
made available to Thunderbird extensions.
'';
};
profiles = mkOption { profiles = mkOption {
type = with types; type = with types;
attrsOf (submodule ({ config, name, ... }: { attrsOf (submodule ({ config, name, ... }: {
@ -179,6 +208,25 @@ in {
''; '';
}; };
feedAccounts = mkOption {
type = types.attrsOf (submodule ({ config, name, ... }: {
options = {
name = mkOption {
type = types.str;
default = name;
readOnly = true;
description = "This feed account's name.";
};
};
}));
default = { };
description = ''
Attribute set of feed accounts. Feeds themselves have to be
managed through Thunderbird's settings. This option allows
feeds to coexist with declaratively managed email accounts.
'';
};
settings = mkOption { settings = mkOption {
type = thunderbirdJson; type = thunderbirdJson;
default = { }; default = { };
@ -400,6 +448,10 @@ in {
++ optional (any (p: p.withExternalGnupg) (attrValues cfg.profiles)) ++ optional (any (p: p.withExternalGnupg) (attrValues cfg.profiles))
pkgs.gpgme; pkgs.gpgme;
mozilla.thunderbirdNativeMessagingHosts = [
cfg.package # package configured native messaging hosts (entire mail app actually)
] ++ cfg.nativeMessagingHosts; # user configured native messaging hosts
home.file = mkMerge ([{ home.file = mkMerge ([{
"${thunderbirdConfigPath}/profiles.ini" = "${thunderbirdConfigPath}/profiles.ini" =
mkIf (cfg.profiles != { }) { text = generators.toINI { } profilesIni; }; mkIf (cfg.profiles != { }) { text = generators.toINI { } profilesIni; };
@ -411,11 +463,17 @@ in {
mkIf (profile.userContent != "") { text = profile.userContent; }; mkIf (profile.userContent != "") { text = profile.userContent; };
"${thunderbirdProfilesPath}/${name}/user.js" = let "${thunderbirdProfilesPath}/${name}/user.js" = let
accounts = filter (a: emailAccounts = filter (a:
a.thunderbird.profiles == [ ] a.thunderbird.profiles == [ ]
|| any (p: p == name) a.thunderbird.profiles) enabledAccountsWithId; || any (p: p == name) a.thunderbird.profiles) enabledAccountsWithId;
smtp = filter (a: a.smtp != null) accounts; smtp = filter (a: a.smtp != null) emailAccounts;
feedAccounts =
map (f: f // { id = builtins.hashString "sha256" f.name; })
(attrValues profile.feedAccounts);
accounts = emailAccounts ++ feedAccounts;
in { in {
text = mkUserJs (builtins.foldl' (a: b: a // b) { } ([ text = mkUserJs (builtins.foldl' (a: b: a // b) { } ([
cfg.settings cfg.settings
@ -433,7 +491,8 @@ in {
{ "mail.openpgp.allow_external_gnupg" = profile.withExternalGnupg; } { "mail.openpgp.allow_external_gnupg" = profile.withExternalGnupg; }
profile.settings profile.settings
] ++ (map (a: toThunderbirdAccount a profile) accounts))) ] ++ (map (a: toThunderbirdAccount a profile) emailAccounts)
++ (map (f: toThunderbirdFeed f profile) feedAccounts)))
profile.extraConfig; profile.extraConfig;
}; };

View file

@ -284,7 +284,7 @@ in {
shell = mkOption { shell = mkOption {
default = defaultShell; default = defaultShell;
example = "\${pkgs.zsh}/bin/zsh"; example = literalExpression "${pkgs.zsh}/bin/zsh";
type = with types; nullOr str; type = with types; nullOr str;
description = "Set the default-shell tmux variable."; description = "Set the default-shell tmux variable.";
}; };

View file

@ -0,0 +1,50 @@
{ config, lib, pkgs, ... }:
let toml = pkgs.formats.toml { };
in {
meta.maintainers = with lib.maintainers; [ HeitorAugustoLN ];
options.programs.vinegar = {
enable = lib.mkEnableOption "Vinegar";
package = lib.mkPackageOption pkgs "vinegar" { };
settings = lib.mkOption {
type = lib.types.attrsOf toml.type;
default = { };
example = {
env.WINEFSYNC = "1";
studio = {
dxvk = false;
renderer = "Vulkan";
fflags.DFIntTaskSchedulerTargetFps = 144;
env = {
DXVK_HUD = "0";
MANGOHUD = "1";
};
};
};
description = ''
Configuration written to {file}`$XDG_CONFIG_HOME/vinegar/config.toml`.
See <https://vinegarhq.org/Configuration/> for more information.
'';
};
};
config = let cfg = config.programs.vinegar;
in lib.mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "programs.vinegar" pkgs
lib.platforms.linux)
];
home.packages = [ cfg.package ];
xdg.configFile."vinegar/config.toml" = lib.mkIf (cfg.settings != { }) {
source = toml.generate "vinegar-config.toml" cfg.settings;
};
};
}

View file

@ -32,66 +32,45 @@ let
else else
"${config.xdg.configHome}/${configDir}/User"; "${config.xdg.configHome}/${configDir}/User";
configFilePath = "${userDir}/settings.json"; configFilePath = name:
tasksFilePath = "${userDir}/tasks.json"; "${userDir}/${
keybindingsFilePath = "${userDir}/keybindings.json"; optionalString (name != "default") "profiles/${name}/"
}settings.json";
tasksFilePath = name:
"${userDir}/${
optionalString (name != "default") "profiles/${name}/"
}tasks.json";
keybindingsFilePath = name:
"${userDir}/${
optionalString (name != "default") "profiles/${name}/"
}keybindings.json";
snippetDir = "${userDir}/snippets"; snippetDir = name:
"${userDir}/${
optionalString (name != "default") "profiles/${name}/"
}snippets";
# TODO: On Darwin where are the extensions? # TODO: On Darwin where are the extensions?
extensionPath = ".${extensionDir}/extensions"; extensionPath = ".${extensionDir}/extensions";
extensionJson = pkgs.vscode-utils.toExtensionJson cfg.extensions; extensionJson = ext: pkgs.vscode-utils.toExtensionJson ext;
extensionJsonFile = pkgs.writeTextFile { extensionJsonFile = name: text:
name = "extensions-json"; pkgs.writeTextFile {
destination = "/share/vscode/extensions/extensions.json"; inherit text;
text = extensionJson; name = "extensions-json-${name}";
}; destination = "/share/vscode/extensions/extensions.json";
};
mergedUserSettings = cfg.userSettings mergedUserSettings =
// optionalAttrs (!cfg.enableUpdateCheck) { "update.mode" = "none"; } userSettings: enableUpdateCheck: enableExtensionUpdateCheck:
// optionalAttrs (!cfg.enableExtensionUpdateCheck) { userSettings
// optionalAttrs (enableUpdateCheck == false) { "update.mode" = "none"; }
// optionalAttrs (enableExtensionUpdateCheck == false) {
"extensions.autoCheckUpdates" = false; "extensions.autoCheckUpdates" = false;
}; };
in {
imports = [
(mkChangedOptionModule [ "programs" "vscode" "immutableExtensionsDir" ] [
"programs"
"vscode"
"mutableExtensionsDir"
] (config: !config.programs.vscode.immutableExtensionsDir))
];
options = {
programs.vscode = {
enable = mkEnableOption "Visual Studio Code";
package = mkOption {
type = types.package;
default = pkgs.vscode;
defaultText = literalExpression "pkgs.vscode";
example = literalExpression "pkgs.vscodium";
description = ''
Version of Visual Studio Code to install.
'';
};
enableUpdateCheck = mkOption {
type = types.bool;
default = true;
description = ''
Whether to enable update checks/notifications.
'';
};
enableExtensionUpdateCheck = mkOption {
type = types.bool;
default = true;
description = ''
Whether to enable update notifications for extensions.
'';
};
profileType = types.submodule {
options = {
userSettings = mkOption { userSettings = mkOption {
type = jsonFormat.type; type = jsonFormat.type;
default = { }; default = { };
@ -184,16 +163,6 @@ in {
''; '';
}; };
mutableExtensionsDir = mkOption {
type = types.bool;
default = true;
example = false;
description = ''
Whether extensions can be installed or updated manually
or by Visual Studio Code.
'';
};
languageSnippets = mkOption { languageSnippets = mkOption {
type = jsonFormat.type; type = jsonFormat.type;
default = { }; default = { };
@ -221,45 +190,207 @@ in {
}; };
description = "Defines global user snippets."; description = "Defines global user snippets.";
}; };
enableUpdateCheck = mkOption {
type = types.nullOr types.bool;
default = null;
description = ''
Whether to enable update checks/notifications.
Can only be set for the default profile, but
it applies to all profiles.
'';
};
enableExtensionUpdateCheck = mkOption {
type = types.nullOr types.bool;
default = null;
description = ''
Whether to enable update notifications for extensions.
Can only be set for the default profile, but
it applies to all profiles.
'';
};
};
};
defaultProfile = if cfg.profiles ? default then cfg.profiles.default else { };
allProfilesExceptDefault = removeAttrs cfg.profiles [ "default" ];
in {
imports = [
(mkChangedOptionModule [ "programs" "vscode" "immutableExtensionsDir" ] [
"programs"
"vscode"
"mutableExtensionsDir"
] (config: !config.programs.vscode.immutableExtensionsDir))
] ++ map (v:
mkRenamedOptionModule [ "programs" "vscode" v ] [
"programs"
"vscode"
"profiles"
"default"
v
]) [
"enableUpdateCheck"
"enableExtensionUpdateCheck"
"userSettings"
"userTasks"
"keybindings"
"extensions"
"languageSnippets"
"globalSnippets"
];
options.programs.vscode = {
enable = mkEnableOption "Visual Studio Code";
package = mkOption {
type = types.package;
default = pkgs.vscode;
defaultText = literalExpression "pkgs.vscode";
example = literalExpression "pkgs.vscodium";
description = ''
Version of Visual Studio Code to install.
'';
};
mutableExtensionsDir = mkOption {
type = types.bool;
default = allProfilesExceptDefault == { };
example = false;
description = ''
Whether extensions can be installed or updated manually
or by Visual Studio Code. Mutually exclusive to
programs.vscode.profiles.
'';
};
profiles = mkOption {
type = types.attrsOf profileType;
default = { };
description = ''
A list of all VSCode profiles. Mutually exclusive
to programs.vscode.mutableExtensionsDir
'';
}; };
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
warnings = [
(mkIf (allProfilesExceptDefault != { } && cfg.mutableExtensionsDir)
"programs.vscode.mutableExtensionsDir can be used only if no profiles apart from default are set.")
(mkIf ((filterAttrs (n: v:
(v ? enableExtensionUpdateCheck || v ? enableUpdateCheck)
&& (v.enableExtensionUpdateCheck != null || v.enableUpdateCheck
!= null)) allProfilesExceptDefault) != { })
"The option programs.vscode.profiles.*.enableExtensionUpdateCheck and option programs.vscode.profiles.*.enableUpdateCheck is invalid for all profiles except default.")
];
home.packages = [ cfg.package ]; home.packages = [ cfg.package ];
home.file = mkMerge [ # The file `${userDir}/globalStorage/storage.json` needs to be writable by VSCode,
(mkIf (mergedUserSettings != { }) { # since it contains other data, such as theme backgrounds, recently opened folders, etc.
"${configFilePath}".source =
jsonFormat.generate "vscode-user-settings" mergedUserSettings;
})
(mkIf (cfg.userTasks != { }) {
"${tasksFilePath}".source =
jsonFormat.generate "vscode-user-tasks" cfg.userTasks;
})
(mkIf (cfg.keybindings != [ ])
(let dropNullFields = filterAttrs (_: v: v != null);
in {
"${keybindingsFilePath}".source =
jsonFormat.generate "vscode-keybindings"
(map dropNullFields cfg.keybindings);
}))
(mkIf (cfg.extensions != [ ]) (let
subDir = "share/vscode/extensions";
# A caveat of adding profiles this way is, VSCode has to be closed
# when this file is being written, since the file is loaded into RAM
# and overwritten on closing VSCode.
home.activation.vscodeProfiles = hm.dag.entryAfter [ "writeBoundary" ] (let
modifyGlobalStorage =
pkgs.writeShellScript "vscode-global-storage-modify" ''
PATH=${makeBinPath [ pkgs.jq ]}''${PATH:+:}$PATH
file="${userDir}/globalStorage/storage.json"
if [ -f "$file" ]; then
existing_profiles=$(jq '.userDataProfiles // [] | map({ (.name): .location }) | add // {}' "$file")
file_write=""
profiles=(${
escapeShellArgs
(flatten (mapAttrsToList (n: v: n) allProfilesExceptDefault))
})
for profile in "''${profiles[@]}"; do
if [[ "$(echo $existing_profiles | jq --arg profile $profile 'has ($profile)')" != "true" ]] || [[ "$(echo $existing_profiles | jq --arg profile $profile 'has ($profile)')" == "true" && "$(echo $existing_profiles | jq --arg profile $profile '.[$profile]')" != "\"$profile\"" ]]; then
file_write="$file_write$([ "$file_write" != "" ] && echo "...")$profile"
fi
done
else
for profile in "''${profiles[@]}"; do
file_write="$file_write$([ "$file_write" != "" ] && echo "...")$profile"
done
echo "{}" > "$file"
fi
if [ "$file_write" != "" ]; then
userDataProfiles=$(jq ".userDataProfiles += $(echo $file_write | jq -R 'split("...") | map({ name: ., location: . })')" "$file")
echo $userDataProfiles > "$file"
fi
'';
in modifyGlobalStorage.outPath);
home.file = mkMerge (flatten [
(mapAttrsToList (n: v: [
(mkIf ((mergedUserSettings v.userSettings v.enableUpdateCheck
v.enableExtensionUpdateCheck) != { }) {
"${configFilePath n}".source =
jsonFormat.generate "vscode-user-settings"
(mergedUserSettings v.userSettings v.enableUpdateCheck
v.enableExtensionUpdateCheck);
})
(mkIf (v.userTasks != { }) {
"${tasksFilePath n}".source =
jsonFormat.generate "vscode-user-tasks" v.userTasks;
})
(mkIf (v.keybindings != [ ]) {
"${keybindingsFilePath n}".source =
jsonFormat.generate "vscode-keybindings"
(map (filterAttrs (_: v: v != null)) v.keybindings);
})
(mkIf (v.languageSnippets != { }) (mapAttrs' (language: snippet:
nameValuePair "${snippetDir n}/${language}.json" {
source =
jsonFormat.generate "user-snippet-${language}.json" snippet;
}) v.languageSnippets))
(mkIf (v.globalSnippets != { }) {
"${snippetDir n}/global.code-snippets".source =
jsonFormat.generate "user-snippet-global.code-snippets"
v.globalSnippets;
})
]) cfg.profiles)
# We write extensions.json for all profiles, except the default profile,
# since that is handled by code below.
(mkIf (allProfilesExceptDefault != { }) (mapAttrs' (n: v:
nameValuePair "${userDir}/profiles/${n}/extensions.json" {
source = "${
extensionJsonFile n (extensionJson v.extensions)
}/share/vscode/extensions/extensions.json";
}) allProfilesExceptDefault))
(mkIf (cfg.profiles != { }) (let
# Adapted from https://discourse.nixos.org/t/vscode-extensions-setup/1801/2 # Adapted from https://discourse.nixos.org/t/vscode-extensions-setup/1801/2
subDir = "share/vscode/extensions";
toPaths = ext: toPaths = ext:
map (k: { "${extensionPath}/${k}".source = "${ext}/${subDir}/${k}"; }) map (k: { "${extensionPath}/${k}".source = "${ext}/${subDir}/${k}"; })
(if ext ? vscodeExtUniqueId then (if ext ? vscodeExtUniqueId then
[ ext.vscodeExtUniqueId ] [ ext.vscodeExtUniqueId ]
else else
builtins.attrNames (builtins.readDir (ext + "/${subDir}"))); builtins.attrNames (builtins.readDir (ext + "/${subDir}")));
in if cfg.mutableExtensionsDir then in if (cfg.mutableExtensionsDir && allProfilesExceptDefault == { }) then
mkMerge (concatMap toPaths cfg.extensions # Mutable extensions dir can only occur when only default profile is set.
++ lib.optional (lib.versionAtLeast vscodeVersion "1.74.0") { # Force regenerating extensions.json using the below method,
# causes VSCode to create the extensions.json with all the extensions
# in the extension directory, which includes extensions from other profiles.
mkMerge (concatMap toPaths
(flatten (mapAttrsToList (n: v: v.extensions) cfg.profiles))
++ optional
(versionAtLeast vscodeVersion "1.74.0" && defaultProfile != { }) {
# Whenever our immutable extensions.json changes, force VSCode to regenerate # Whenever our immutable extensions.json changes, force VSCode to regenerate
# extensions.json with both mutable and immutable extensions. # extensions.json with both mutable and immutable extensions.
"${extensionPath}/.extensions-immutable.json" = { "${extensionPath}/.extensions-immutable.json" = {
text = extensionJson; text = extensionJson defaultProfile.extensions;
onChange = '' onChange = ''
run rm $VERBOSE_ARG -f ${extensionPath}/{extensions.json,.init-default-profile-extensions} run rm $VERBOSE_ARG -f ${extensionPath}/{extensions.json,.init-default-profile-extensions}
verboseEcho "Regenerating VSCode extensions.json" verboseEcho "Regenerating VSCode extensions.json"
@ -271,25 +402,14 @@ in {
"${extensionPath}".source = let "${extensionPath}".source = let
combinedExtensionsDrv = pkgs.buildEnv { combinedExtensionsDrv = pkgs.buildEnv {
name = "vscode-extensions"; name = "vscode-extensions";
paths = cfg.extensions paths = (flatten (mapAttrsToList (n: v: v.extensions) cfg.profiles))
++ lib.optional (lib.versionAtLeast vscodeVersion "1.74.0") ++ optional
extensionJsonFile; (versionAtLeast vscodeVersion "1.74.0" && defaultProfile != { })
(extensionJsonFile "default"
(extensionJson defaultProfile.extensions));
}; };
in "${combinedExtensionsDrv}/${subDir}"; in "${combinedExtensionsDrv}/${subDir}";
})) }))
]);
(mkIf (cfg.globalSnippets != { })
(let globalSnippets = "${snippetDir}/global.code-snippets";
in {
"${globalSnippets}".source =
jsonFormat.generate "user-snippet-global.code-snippets"
cfg.globalSnippets;
}))
(lib.mapAttrs' (language: snippet:
lib.nameValuePair "${snippetDir}/${language}.json" {
source = jsonFormat.generate "user-snippet-${language}.json" snippet;
}) cfg.languageSnippets)
];
}; };
} }

View file

@ -52,12 +52,12 @@ in {
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
programs.vscode.userSettings = mkIf cfg.hie.enable { programs.vscode.profiles.default.userSettings = mkIf cfg.hie.enable {
"languageServerHaskell.enableHIE" = true; "languageServerHaskell.enableHIE" = true;
"languageServerHaskell.hieExecutablePath" = cfg.hie.executablePath; "languageServerHaskell.hieExecutablePath" = cfg.hie.executablePath;
}; };
programs.vscode.extensions = programs.vscode.profiles.default.extensions =
[ pkgs.vscode-extensions.justusadam.language-haskell ] [ pkgs.vscode-extensions.justusadam.language-haskell ]
++ lib.optional cfg.hie.enable ++ lib.optional cfg.hie.enable
pkgs.vscode-extensions.alanz.vscode-hie-server; pkgs.vscode-extensions.alanz.vscode-hie-server;

View file

@ -211,6 +211,17 @@ in {
''; '';
}; };
systemd.enableInspect = mkOption {
type = bool;
default = false;
example = true;
description = ''
Inspect objects and find their CSS classes, experiment with live CSS styles, and lookup the current value of CSS properties.
See <https://developer.gnome.org/documentation/tools/inspector.html>
'';
};
style = mkOption { style = mkOption {
type = nullOr (either path lines); type = nullOr (either path lines);
default = null; default = null;
@ -324,6 +335,8 @@ in {
ExecReload = "${pkgs.coreutils}/bin/kill -SIGUSR2 $MAINPID"; ExecReload = "${pkgs.coreutils}/bin/kill -SIGUSR2 $MAINPID";
Restart = "on-failure"; Restart = "on-failure";
KillMode = "mixed"; KillMode = "mixed";
} // optionalAttrs cfg.systemd.enableInspect {
Environment = [ "GTK_DEBUG=interactive" ];
}; };
Install.WantedBy = Install.WantedBy =

View file

@ -1,49 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.wpaperd;
tomlFormat = pkgs.formats.toml { };
in {
meta.maintainers = [ hm.maintainers.Avimitin ];
options.programs.wpaperd = {
enable = mkEnableOption "wpaperd";
package = mkPackageOption pkgs "wpaperd" { };
settings = mkOption {
type = tomlFormat.type;
default = { };
example = literalExpression ''
{
eDP-1 = {
path = "/home/foo/Pictures/Wallpaper";
apply-shadow = true;
};
DP-2 = {
path = "/home/foo/Pictures/Anime";
sorting = "descending";
};
}
'';
description = ''
Configuration written to
{file}`$XDG_CONFIG_HOME/wpaperd/wallpaper.toml`.
See <https://github.com/danyspin97/wpaperd#wallpaper-configuration>
for the full list of options.
'';
};
};
config = mkIf cfg.enable {
home.packages = [ cfg.package ];
xdg.configFile = {
"wpaperd/wallpaper.toml" = mkIf (cfg.settings != { }) {
source = tomlFormat.generate "wpaperd-wallpaper" cfg.settings;
};
};
};
}

166
modules/services/clipse.nix Normal file
View file

@ -0,0 +1,166 @@
{ pkgs, config, lib, ... }:
let
cfg = config.services.clipse;
jsonFormat = pkgs.formats.json { };
in {
meta.maintainers = [ lib.hm.maintainers.dsoverlord ];
options.services.clipse = {
enable = lib.mkEnableOption "Enable clipse clipboard manager";
package = lib.mkPackageOption pkgs "clipse" { };
systemdTarget = lib.mkOption {
type = lib.types.str;
default = "graphical-session.target";
example = "sway-session.target";
description = ''
The systemd target that will automatically start the clipse service.
When setting this value to `"sway-session.target"`,
make sure to also enable {option}`wayland.windowManager.sway.systemd.enable`,
otherwise the service may never be started.
'';
};
allowDuplicates = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Allow duplicates";
};
historySize = lib.mkOption {
type = lib.types.int;
default = 100;
description = "Number of history lines to keep.";
};
imageDisplay = {
type = lib.mkOption {
type = lib.types.enum [ "basic" "kitty" "sixel" ];
default = "basic";
description = "Preview image method";
};
scaleX = lib.mkOption {
type = lib.types.int;
default = 9;
description = "Image scaling factor X";
};
scaleY = lib.mkOption {
type = lib.types.int;
default = 9;
description = "Image scaling factor Y";
};
heightCut = lib.mkOption {
type = lib.types.int;
default = 2;
description = "Height cut";
};
};
keyBindings = lib.mkOption {
type = jsonFormat.type;
default = { };
example = lib.literalExpression ''
{
"choose": "enter",
"clearSelected": "S",
"down": "down",
"end": "end",
"filter": "/",
"home": "home",
"more": "?",
"nextPage": "right",
"prevPage": "left",
"preview": "t",
"quit": "q",
"remove": "x",
"selectDown": "ctrl+down",
"selectSingle": "s",
"selectUp": "ctrl+up",
"togglePin": "p",
"togglePinned": "tab",
"up": "up",
"yankFilter": "ctrl+s"
}
'';
description = "Custom key bindings";
};
theme = lib.mkOption {
type = jsonFormat.type;
default = { useCustomTheme = false; };
example = lib.literalExpression ''
{
useCustomTheme = true;
DimmedDesc = "#ffffff";
DimmedTitle = "#ffffff";
FilteredMatch = "#ffffff";
NormalDesc = "#ffffff";
NormalTitle = "#ffffff";
SelectedDesc = "#ffffff";
SelectedTitle = "#ffffff";
SelectedBorder = "#ffffff";
SelectedDescBorder = "#ffffff";
TitleFore = "#ffffff";
Titleback = "#434C5E";
StatusMsg = "#ffffff";
PinIndicatorColor = "#ff0000";
};
'';
description = ''
Configuration written to
{file}`$XDG_CONFIG_HOME/clipse/custom_theme.json`.
'';
};
};
config = lib.mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "services.clipse" pkgs
lib.platforms.linux)
];
home.packages = [ cfg.package ];
xdg.configFile."clipse/config.json".source =
jsonFormat.generate "settings" {
allowDuplicates = cfg.allowDuplicates;
historyFile = "clipboard_history.json";
maxHistory = cfg.historySize;
logFile = "clipse.log";
themeFile = "custom_theme.json";
tempDir = "tmp_files";
keyBindings = cfg.keyBindings;
imageDisplay = cfg.imageDisplay;
};
xdg.configFile."clipse/custom_theme.json".source =
jsonFormat.generate "theme" cfg.theme;
systemd.user.services.clipse = lib.mkIf pkgs.stdenv.isLinux {
Unit = {
Description = "Clipse listener";
PartOf = [ "graphical-session.target" ];
After = [ "graphical-session.target" ];
};
Service = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = "${cfg.package}/bin/clipse -listen";
};
Install = { WantedBy = [ cfg.systemdTarget ]; };
};
};
}

View file

@ -1,10 +1,8 @@
{ pkgs, lib, ... }: { pkgs, lib, ... }:
let inherit (lib) mkOption types;
with lib; in {
{
options.imapnotify = { options.imapnotify = {
enable = mkEnableOption "imapnotify"; enable = lib.mkEnableOption "imapnotify";
onNotify = mkOption { onNotify = mkOption {
type = with types; either str (attrsOf str); type = with types; either str (attrsOf str);
@ -30,10 +28,16 @@ with lib;
description = "IMAP folders to watch."; description = "IMAP folders to watch.";
}; };
extraArgs = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "-wait 1" ];
description = "Extra arguments to pass to goimapnotify.";
};
extraConfig = mkOption { extraConfig = mkOption {
type = let jsonFormat = pkgs.formats.json { }; in jsonFormat.type; type = let jsonFormat = pkgs.formats.json { }; in jsonFormat.type;
default = { }; default = { };
example = { wait = 10; };
description = "Additional configuration to add for this account."; description = "Additional configuration to add for this account.";
}; };
}; };

View file

@ -23,7 +23,10 @@ let
Service = { Service = {
# Use the nix store path for config to ensure service restarts when it changes # Use the nix store path for config to ensure service restarts when it changes
ExecStart = ExecStart =
"${getExe cfg.package} -conf '${genAccountConfig account}'"; "${getExe cfg.package} -conf '${genAccountConfig account}'" + " ${
lib.optionalString (account.imapnotify.extraArgs != [ ])
(toString account.imapnotify.extraArgs)
}";
Restart = "always"; Restart = "always";
RestartSec = 30; RestartSec = 30;
Type = "simple"; Type = "simple";

View file

@ -33,6 +33,15 @@ in {
''; '';
}; };
maxHistory = mkOption {
default = 5;
type = types.nullOr types.int;
description = ''
Set maximum number of expired notifications to keep in the history
buffer. Set 0 to disable history.
'';
};
sort = mkOption { sort = mkOption {
default = "-time"; default = "-time";
type = type =
@ -315,6 +324,7 @@ in {
''; '';
text = '' text = ''
${optionalInteger "max-visible" cfg.maxVisible} ${optionalInteger "max-visible" cfg.maxVisible}
${optionalInteger "max-history" cfg.maxHistory}
${optionalString "sort" cfg.sort} ${optionalString "sort" cfg.sort}
${optionalString "output" cfg.output} ${optionalString "output" cfg.output}
${optionalString "layer" cfg.layer} ${optionalString "layer" cfg.layer}

View file

@ -1,38 +1,11 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
inherit (lib) mkIf mkOption types;
name = "mpd";
cfg = config.services.mpd; cfg = config.services.mpd;
mpdConf = pkgs.writeText "mpd.conf" ''
music_directory "${cfg.musicDirectory}"
playlist_directory "${cfg.playlistDirectory}"
${lib.optionalString (cfg.dbFile != null) ''
db_file "${cfg.dbFile}"
''}
state_file "${cfg.dataDir}/state"
sticker_file "${cfg.dataDir}/sticker.sql"
${optionalString (cfg.network.listenAddress != "any")
''bind_to_address "${cfg.network.listenAddress}"''}
${optionalString (cfg.network.port != 6600)
''port "${toString cfg.network.port}"''}
${cfg.extraConfig}
'';
in { in {
###### interface
options = { options = {
services.mpd = { services.mpd = {
enable = mkOption { enable = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
@ -52,7 +25,7 @@ in {
musicDirectory = mkOption { musicDirectory = mkOption {
type = with types; either path str; type = with types; either path str;
defaultText = literalExpression '' defaultText = lib.literalExpression ''
''${home.homeDirectory}/music if state version < 22.11 ''${home.homeDirectory}/music if state version < 22.11
''${xdg.userDirs.music} if xdg.userDirs.enable == true ''${xdg.userDirs.music} if xdg.userDirs.enable == true
undefined otherwise undefined otherwise
@ -100,7 +73,7 @@ in {
dataDir = mkOption { dataDir = mkOption {
type = types.path; type = types.path;
default = "${config.xdg.dataHome}/${name}"; default = "${config.xdg.dataHome}/mpd";
defaultText = "$XDG_DATA_HOME/mpd"; defaultText = "$XDG_DATA_HOME/mpd";
apply = toString; # Prevent copies to Nix store. apply = toString; # Prevent copies to Nix store.
description = '' description = ''
@ -113,8 +86,10 @@ in {
startWhenNeeded = mkOption { startWhenNeeded = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
visible = pkgs.stdenv.hostPlatform.isLinux;
readOnly = pkgs.stdenv.hostPlatform.isDarwin;
description = '' description = ''
Enable systemd socket activation. Enable systemd socket activation. This is only supported on Linux.
''; '';
}; };
@ -149,72 +124,97 @@ in {
''; '';
}; };
}; };
}; };
###### implementation config = let
mpdConf = pkgs.writeText "mpd.conf" (''
music_directory "${cfg.musicDirectory}"
playlist_directory "${cfg.playlistDirectory}"
'' + lib.optionalString (cfg.dbFile != null) ''
db_file "${cfg.dbFile}"
'' + lib.optionalString (pkgs.stdenv.hostPlatform.isDarwin) ''
log_file "${config.home.homeDirectory}/Library/Logs/mpd/log.txt"
'' + ''
state_file "${cfg.dataDir}/state"
sticker_file "${cfg.dataDir}/sticker.sql"
config = mkIf cfg.enable { '' + lib.optionalString (cfg.network.listenAddress != "any") ''
assertions = [ bind_to_address "${cfg.network.listenAddress}"
(lib.hm.assertions.assertPlatform "services.mpd" pkgs lib.platforms.linux) '' + lib.optionalString (cfg.network.port != 6600) ''
]; port "${toString cfg.network.port}"
'' + lib.optionalString (cfg.extraConfig != "") ''
${cfg.extraConfig}
'');
in mkIf cfg.enable {
home.packages = [ cfg.package ];
services.mpd = mkMerge [ services.mpd = lib.mkMerge [
(mkIf (versionAtLeast config.home.stateVersion "22.11" (mkIf (lib.versionAtLeast config.home.stateVersion "22.11"
&& config.xdg.userDirs.enable) { && config.xdg.userDirs.enable) {
musicDirectory = mkOptionDefault config.xdg.userDirs.music; musicDirectory = lib.mkOptionDefault config.xdg.userDirs.music;
}) })
(mkIf (versionOlder config.home.stateVersion "22.11") { (mkIf (lib.versionOlder config.home.stateVersion "22.11") {
musicDirectory = mkOptionDefault "${config.home.homeDirectory}/music"; musicDirectory =
lib.mkOptionDefault "${config.home.homeDirectory}/music";
}) })
]; ];
systemd.user.services.mpd = { systemd.user = lib.mkIf pkgs.stdenv.hostPlatform.isLinux {
Unit = mkMerge [ services.mpd = {
{ Unit = lib.mkMerge [
Description = "Music Player Daemon"; {
After = [ "network.target" "sound.target" ]; Description = "Music Player Daemon";
} After = [ "network.target" "sound.target" ];
}
(mkIf cfg.network.startWhenNeeded { (mkIf cfg.network.startWhenNeeded {
Requires = [ "mpd.socket" ]; Requires = [ "mpd.socket" ];
After = [ "mpd.socket" ]; After = [ "mpd.socket" ];
}) })
]; ];
Install = mkIf (!cfg.network.startWhenNeeded) { Install = mkIf (!cfg.network.startWhenNeeded) {
WantedBy = [ "default.target" ]; WantedBy = [ "default.target" ];
};
Service = {
Environment = [ "PATH=${config.home.profileDirectory}/bin" ];
ExecStart = "${cfg.package}/bin/mpd --no-daemon ${mpdConf} ${
lib.escapeShellArgs cfg.extraArgs
}";
Type = "notify";
ExecStartPre = ''
${pkgs.bash}/bin/bash -c "${pkgs.coreutils}/bin/mkdir -p '${cfg.dataDir}' '${cfg.playlistDirectory}'"'';
};
}; };
Service = { sockets.mpd = mkIf cfg.network.startWhenNeeded {
Environment = [ "PATH=${config.home.profileDirectory}/bin" ]; Socket = {
ExecStart = "${cfg.package}/bin/mpd --no-daemon ${mpdConf} ${ ListenStream = let
escapeShellArgs cfg.extraArgs listen = if cfg.network.listenAddress == "any" then
}"; toString cfg.network.port
Type = "notify"; else
ExecStartPre = '' "${cfg.network.listenAddress}:${toString cfg.network.port}";
${pkgs.bash}/bin/bash -c "${pkgs.coreutils}/bin/mkdir -p '${cfg.dataDir}' '${cfg.playlistDirectory}'"''; in [ listen "%t/mpd/socket" ];
Backlog = 5;
KeepAlive = true;
};
Install = { WantedBy = [ "sockets.target" ]; };
}; };
}; };
systemd.user.sockets.mpd = mkIf cfg.network.startWhenNeeded { launchd.agents.mpd = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin {
Socket = { enable = true;
ListenStream = let config = {
listen = if cfg.network.listenAddress == "any" then ProgramArguments =
toString cfg.network.port [ (lib.getExe cfg.package) "--no-daemon" "${mpdConf}" ]
else ++ cfg.extraArgs;
"${cfg.network.listenAddress}:${toString cfg.network.port}";
in [ listen "%t/mpd/socket" ];
Backlog = 5;
KeepAlive = true; KeepAlive = true;
ProcessType = "Interactive";
}; };
Install = { WantedBy = [ "sockets.target" ]; };
}; };
home.packages = [ cfg.package ];
}; };
} }

View file

@ -4,6 +4,14 @@ let
cfg = config.services.psd; cfg = config.services.psd;
configFile = ''
${lib.optionalString (cfg.browsers != [ ]) ''
BROWSERS=(${lib.concatStringsSep " " cfg.browsers})
''}
USE_BACKUP="${if cfg.useBackup then "yes" else "no"}"
BACKUP_LIMIT=${builtins.toString cfg.backupLimit}
'';
in { in {
meta.maintainers = [ lib.hm.maintainers.danjujan ]; meta.maintainers = [ lib.hm.maintainers.danjujan ];
@ -22,6 +30,34 @@ in {
defaults to seconds if omitted. defaults to seconds if omitted.
''; '';
}; };
browsers = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "chromium" "google-chrome" "firefox" ];
description = ''
A list of browsers to sync. An empty list will enable all browsers to be managed by profile-sync-daemon.
Available choices are:
chromium chromium-dev conkeror.mozdev.org epiphany falkon firefox firefox-trunk google-chrome google-chrome-beta google-chrome-unstable heftig-aurora icecat inox luakit midori opera opera-beta opera-developer opera-legacy otter-browser qupzilla qutebrowser palemoon rekonq seamonkey surf vivaldi vivaldi-snapshot
'';
};
useBackup = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Whether to completly enable or disable the crash recovery feature.
'';
};
backupLimit = lib.mkOption {
type = lib.types.ints.unsigned;
default = 5;
description = ''
Maximum number of crash recovery snapshots to keep (the oldest ones are deleted first).
'';
};
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
@ -38,6 +74,10 @@ in {
rsync rsync
kmod kmod
gawk gawk
gnugrep
gnused
coreutils
findutils
nettools nettools
util-linux util-linux
profile-sync-daemon profile-sync-daemon
@ -84,5 +124,7 @@ in {
Timer = { OnUnitActiveSec = cfg.resyncTimer; }; Timer = { OnUnitActiveSec = cfg.resyncTimer; };
}; };
}; };
xdg.configFile."psd/psd.conf".text = configFile;
}; };
} }

View file

@ -127,6 +127,7 @@ in {
ExecStart = concatStringsSep " " ExecStart = concatStringsSep " "
([ "${cfg.xss-lock.package}/bin/xss-lock" "-s \${XDG_SESSION_ID}" ] ([ "${cfg.xss-lock.package}/bin/xss-lock" "-s \${XDG_SESSION_ID}" ]
++ cfg.xss-lock.extraOptions ++ [ "-- ${cfg.lockCmd}" ]); ++ cfg.xss-lock.extraOptions ++ [ "-- ${cfg.lockCmd}" ]);
Restart = "always";
}; };
}; };
} }
@ -153,6 +154,7 @@ in {
"-locker '${pkgs.systemd}/bin/loginctl lock-session \${XDG_SESSION_ID}'" "-locker '${pkgs.systemd}/bin/loginctl lock-session \${XDG_SESSION_ID}'"
] ++ optional cfg.xautolock.detectSleep "-detectsleep" ] ++ optional cfg.xautolock.detectSleep "-detectsleep"
++ cfg.xautolock.extraOptions); ++ cfg.xautolock.extraOptions);
Restart = "always";
}; };
}; };
}) })

103
modules/services/wluma.nix Normal file
View file

@ -0,0 +1,103 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.wluma;
format = pkgs.formats.toml { };
configFile = format.generate "config.toml" cfg.settings;
in {
meta.maintainers = with lib.maintainers; [ _0x5a4 ];
options.services.wluma = {
enable = lib.mkEnableOption
"Enable wluma, a service for automatic brightness adjustment";
package = lib.mkOption {
type = lib.types.package;
default = pkgs.wluma;
defaultText = lib.literalExpression "pkgs.wluma";
description = "Package providing {command}`wluma`.";
};
settings = lib.mkOption {
type = format.type;
default = { };
example = {
als.iio = {
path = "";
thresholds = {
"0" = "night";
"20" = "dark";
"80" = "dim";
"250" = "normal";
"500" = "bright";
"800" = "outdoors";
};
};
};
description = ''
Configuration to use for wluma. See
<https://github.com/maximbaz/wluma/blob/main/config.toml>
for available options.
'';
};
systemd.enable = lib.mkOption {
description = "Wluma systemd integration";
type = lib.types.bool;
default = true;
};
systemd.target = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = config.wayland.systemd.target;
defaultText = lib.literalExpression "config.wayland.systemd.target";
example = "sway-session.target";
description = ''
The systemd target that will automatically start the Wluma service.
When setting this value to `"sway-session.target"`,
make sure to also enable {option}`wayland.windowManager.sway.systemd.enable`,
otherwise the service may never be started.
'';
};
};
config = lib.mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "services.wluma" pkgs
lib.platforms.linux)
];
home.packages = [ cfg.package ];
xdg.configFile = lib.mkIf (cfg.settings != { }) {
"wluma/config.toml".source = configFile;
};
systemd.user.services.wluma = lib.mkIf cfg.systemd.enable {
Unit = {
Description =
"Automatic brightness adjustment based on screen contents and ALS ";
After = [ cfg.systemd.target ];
PartOf = [ cfg.systemd.target ];
ConditionEnvironment = "WAYLAND_DISPLAY";
X-Restart-Triggers = lib.mkIf (cfg.settings != { }) [ "${configFile}" ];
};
Install.WantedBy = [ cfg.systemd.target ];
Service = {
ExecStart = lib.getExe cfg.package;
Restart = "always";
# Sandboxing.
LockPersonality = true;
MemoryDenyWriteExecute = true;
NoNewPrivileges = true;
PrivateUsers = true;
RestrictNamespaces = true;
SystemCallArchitectures = "native";
SystemCallFilter = "@system-service";
};
};
};
}

View file

@ -0,0 +1,84 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.wpaperd;
tomlFormat = pkgs.formats.toml { };
inherit (lib) mkRenamedOptionModule mkIf;
in {
meta.maintainers = [ lib.hm.maintainers."3ulalia" ];
imports = [
(mkRenamedOptionModule # \
[ "programs" "wpaperd" "enable" ] # \
[ "services" "wpaperd" "enable" ])
(mkRenamedOptionModule # \
[ "programs" "wpaperd" "package" ] # \
[ "services" "wpaperd" "package" ])
(mkRenamedOptionModule # \
[ "programs" "wpaperd" "settings" ] # \
[ "services" "wpaperd" "settings" ])
];
options.services.wpaperd = {
enable = lib.mkEnableOption "wpaperd";
package = lib.mkPackageOption pkgs "wpaperd" { };
settings = lib.mkOption {
type = tomlFormat.type;
default = { };
example = lib.literalExpression ''
{
eDP-1 = {
path = "/home/foo/Pictures/Wallpaper";
apply-shadow = true;
};
DP-2 = {
path = "/home/foo/Pictures/Anime";
sorting = "descending";
};
}
'';
description = ''
Configuration written to
{file}`$XDG_CONFIG_HOME/wpaperd/wallpaper.toml`.
See <https://github.com/danyspin97/wpaperd#wallpaper-configuration>
for the full list of options.
'';
};
};
config = mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "services.wpaperd" pkgs
lib.platforms.linux)
];
home.packages = [ cfg.package ];
xdg.configFile = {
"wpaperd/wallpaper.toml" = mkIf (cfg.settings != { }) {
source = tomlFormat.generate "wpaperd-wallpaper" cfg.settings;
};
};
systemd.user.services.wpaperd = {
Install = { WantedBy = [ config.wayland.systemd.target ]; };
Unit = {
ConditionEnvironment = "WAYLAND_DISPLAY";
Description = "wpaperd";
PartOf = [ config.wayland.systemd.target ];
After = [ config.wayland.systemd.target ];
X-Restart-Triggers =
[ "${config.xdg.configFile."wpaperd/wallpaper.toml".source}" ];
};
Service = {
ExecStart = "${lib.getExe cfg.package}";
Restart = "always";
RestartSec = "10";
};
};
};
}

View file

@ -151,7 +151,7 @@ in {
Service = { Service = {
Type = if cfg.once then "oneshot" else "simple"; Type = if cfg.once then "oneshot" else "simple";
ExecStart = "${script}"; ExecStart = "${script}";
}; } // lib.optionalAttrs (!cfg.once) { Restart = "always"; };
Install.WantedBy = [ "graphical-session.target" ]; Install.WantedBy = [ "graphical-session.target" ];
}; };
}; };

View file

@ -1,9 +1,24 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
{ let cfg = config.targets.darwin;
config = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin { in {
options.targets.darwin.linkApps = {
enable =
lib.mkEnableOption "linking macOS applications to the user environment"
// {
default = true;
};
directory = lib.mkOption {
type = lib.types.str;
default = "Applications/Home Manager Apps";
description = "Path to link apps relative to the home directory.";
};
};
config = lib.mkIf (pkgs.stdenv.hostPlatform.isDarwin && cfg.linkApps.enable) {
# Install MacOS applications to the user environment. # Install MacOS applications to the user environment.
home.file."Applications/Home Manager Apps".source = let home.file.${cfg.linkApps.directory}.source = let
apps = pkgs.buildEnv { apps = pkgs.buildEnv {
name = "home-manager-applications"; name = "home-manager-applications";
paths = config.home.packages; paths = config.home.packages;

View file

@ -1,8 +1,6 @@
{ config, lib, pkgs, ... }: { config, lib, ... }:
let inherit (lib) concatStringsSep mkOption types;
with lib; in {
{
options.test.asserts = { options.test.asserts = {
warnings = { warnings = {
enable = mkOption { enable = mkOption {
@ -37,8 +35,8 @@ with lib;
}; };
}; };
config = mkMerge [ config = lib.mkMerge [
(mkIf config.test.asserts.warnings.enable { (lib.mkIf config.test.asserts.warnings.enable {
home.file = { home.file = {
"asserts/warnings.actual".text = concatStringsSep '' "asserts/warnings.actual".text = concatStringsSep ''
@ -57,12 +55,13 @@ with lib;
''; '';
}) })
(mkIf config.test.asserts.assertions.enable { (lib.mkIf config.test.asserts.assertions.enable {
home.file = { home.file = {
"asserts/assertions.actual".text = concatStringsSep '' "asserts/assertions.actual".text = concatStringsSep ''
-- --
'' (map (x: x.message) (filter (x: !x.assertion) config.assertions)); ''
(map (x: x.message) (lib.filter (x: !x.assertion) config.assertions));
"asserts/assertions.expected".text = concatStringsSep '' "asserts/assertions.expected".text = concatStringsSep ''
-- --

View file

@ -146,6 +146,7 @@ in import nmtSrc {
./modules/programs/darcs ./modules/programs/darcs
./modules/programs/dircolors ./modules/programs/dircolors
./modules/programs/direnv ./modules/programs/direnv
./modules/programs/earthly
./modules/programs/emacs ./modules/programs/emacs
./modules/programs/fastfetch ./modules/programs/fastfetch
./modules/programs/feh ./modules/programs/feh
@ -170,6 +171,7 @@ in import nmtSrc {
./modules/programs/irssi ./modules/programs/irssi
./modules/programs/jujutsu ./modules/programs/jujutsu
./modules/programs/joplin-desktop ./modules/programs/joplin-desktop
./modules/programs/jqp
./modules/programs/k9s ./modules/programs/k9s
./modules/programs/kakoune ./modules/programs/kakoune
./modules/programs/khal ./modules/programs/khal
@ -243,6 +245,7 @@ in import nmtSrc {
./modules/programs/translate-shell ./modules/programs/translate-shell
./modules/programs/vifm ./modules/programs/vifm
./modules/programs/vim-vint ./modules/programs/vim-vint
./modules/programs/vinegar
./modules/programs/vscode ./modules/programs/vscode
./modules/programs/watson ./modules/programs/watson
./modules/programs/wezterm ./modules/programs/wezterm
@ -267,6 +270,7 @@ in import nmtSrc {
./modules/services/yubikey-agent-darwin ./modules/services/yubikey-agent-darwin
./modules/targets-darwin ./modules/targets-darwin
] ++ lib.optionals isLinux [ ] ++ lib.optionals isLinux [
./modules/config/home-cursor
./modules/config/i18n ./modules/config/i18n
./modules/i18n/input-method ./modules/i18n/input-method
./modules/misc/debug ./modules/misc/debug
@ -285,8 +289,10 @@ in import nmtSrc {
./modules/programs/boxxy ./modules/programs/boxxy
./modules/programs/cavalier ./modules/programs/cavalier
./modules/programs/eww ./modules/programs/eww
./modules/programs/firefox
./modules/programs/firefox/firefox.nix ./modules/programs/firefox/firefox.nix
./modules/programs/firefox/floorp.nix ./modules/programs/firefox/floorp.nix
./modules/programs/firefox/librewolf.nix
./modules/programs/foot ./modules/programs/foot
./modules/programs/freetube ./modules/programs/freetube
./modules/programs/fuzzel ./modules/programs/fuzzel
@ -306,6 +312,7 @@ in import nmtSrc {
./modules/programs/rbw ./modules/programs/rbw
./modules/programs/rofi ./modules/programs/rofi
./modules/programs/rofi-pass ./modules/programs/rofi-pass
./modules/programs/swayimg
./modules/programs/swaylock ./modules/programs/swaylock
./modules/programs/swayr ./modules/programs/swayr
./modules/programs/terminator ./modules/programs/terminator
@ -313,7 +320,6 @@ in import nmtSrc {
./modules/programs/waybar ./modules/programs/waybar
./modules/programs/wlogout ./modules/programs/wlogout
./modules/programs/wofi ./modules/programs/wofi
./modules/programs/wpaperd
./modules/programs/xmobar ./modules/programs/xmobar
./modules/programs/yambar ./modules/programs/yambar
./modules/programs/yt-dlp ./modules/programs/yt-dlp
@ -325,6 +331,7 @@ in import nmtSrc {
./modules/services/cachix-agent ./modules/services/cachix-agent
./modules/services/cliphist ./modules/services/cliphist
./modules/services/clipman ./modules/services/clipman
./modules/services/clipse
./modules/services/comodoro ./modules/services/comodoro
./modules/services/copyq ./modules/services/copyq
./modules/services/conky ./modules/services/conky
@ -390,6 +397,7 @@ in import nmtSrc {
./modules/services/window-managers/wayfire ./modules/services/window-managers/wayfire
./modules/services/wlsunset ./modules/services/wlsunset
./modules/services/wob ./modules/services/wob
./modules/services/wpaperd
./modules/services/xsettingsd ./modules/services/xsettingsd
./modules/services/yubikey-agent ./modules/services/yubikey-agent
./modules/systemd ./modules/systemd

View file

@ -1,4 +1,4 @@
{ ... }: { {
home.username = "alice"; home.username = "alice";
home.homeDirectory = "/home/alice"; home.homeDirectory = "/home/alice";
home.stateVersion = "24.11"; home.stateVersion = "24.11";

View file

@ -1,4 +1,4 @@
{ ... }: { {
home.username = "alice"; home.username = "alice";
home.homeDirectory = "/home/alice"; home.homeDirectory = "/home/alice";

View file

@ -1,5 +1,3 @@
{ ... }:
{ {
accounts.email = { accounts.email = {
maildirBasePath = "Mail"; maildirBasePath = "Mail";

View file

@ -0,0 +1,49 @@
{
# Ensure backwards compatibility with existing configs
home-cursor-legacy = { realPkgs, ... }: {
config = {
home.pointerCursor = {
package = realPkgs.catppuccin-cursors.macchiatoBlue;
name = "catppuccin-macchiato-blue-standard";
size = 64;
gtk.enable = true;
hyprcursor.enable = true;
x11.enable = true;
};
home.stateVersion = "24.11";
nmt.script = ''
assertFileContent \
home-path/share/icons/catppuccin-macchiato-blue-cursors/index.theme \
${./expected-index.theme}
hmEnvFile=home-path/etc/profile.d/hm-session-vars.sh
assertFileExists $hmEnvFile
assertFileRegex $hmEnvFile 'XCURSOR_THEME="catppuccin-macchiato-blue-standard"'
assertFileRegex $hmEnvFile 'XCURSOR_SIZE="64"'
assertFileRegex $hmEnvFile 'HYPRCURSOR_THEME="catppuccin-macchiato-blue-standard"'
assertFileRegex $hmEnvFile 'HYPRCURSOR_SIZE="64"'
'';
};
};
home-cursor-legacy-disabled = { ... }: {
config = {
home.pointerCursor = null;
home.stateVersion = "24.11";
nmt.script = ''
assertPathNotExists home-path/share/icons/catppuccin-macchiato-blue-cursors/index.theme
hmEnvFile=home-path/etc/profile.d/hm-session-vars.sh
assertFileExists $hmEnvFile
assertFileNotRegex $hmEnvFile 'XCURSOR_THEME="catppuccin-macchiato-blue-standard"'
assertFileNotRegex $hmEnvFile 'XCURSOR_SIZE="32"'
assertFileNotRegex $hmEnvFile 'HYPRCURSOR_THEME="catppuccin-macchiato-blue-standard"'
assertFileNotRegex $hmEnvFile 'HYPRCURSOR_SIZE="32"'
'';
};
};
}

View file

@ -0,0 +1,3 @@
[Icon Theme]
Name=Catppuccin Macchiato Blue
Comment=based on Volantes Cursors

View file

@ -1,5 +1,3 @@
{ ... }:
{ {
home.file."disabled" = { home.file."disabled" = {
enable = false; enable = false;

View file

@ -1,5 +1,3 @@
{ ... }:
{ {
home.file."executable" = { home.file."executable" = {
text = ""; text = "";

View file

@ -1,5 +1,3 @@
{ ... }:
{ {
home.file.".hidden".source = ./.hidden; home.file.".hidden".source = ./.hidden;

View file

@ -1,5 +1,3 @@
{ ... }:
{ {
home.file."source with spaces!".source = ./. + "/source with spaces!"; home.file."source with spaces!".source = ./. + "/source with spaces!";

View file

@ -1,5 +1,3 @@
{ ... }:
{ {
home.file = { home.file = {
conflict1 = { conflict1 = {

View file

@ -1,5 +1,3 @@
{ ... }:
{ {
home.file."$HOME/$FOO/bar baz".text = "blah"; home.file."$HOME/$FOO/bar baz".text = "blah";

View file

@ -1,5 +1,3 @@
{ ... }:
{ {
home.file."using-text".text = '' home.file."using-text".text = ''
This is the This is the

View file

@ -1,7 +1,3 @@
{ config, lib, pkgs, ... }:
with lib;
{ {
config = { config = {
launchd.agents."test-service" = { launchd.agents."test-service" = {

View file

@ -1,5 +1,3 @@
{ ... }:
{ {
editorconfig = { editorconfig = {
enable = true; enable = true;

View file

@ -1,8 +1,4 @@
{ config, lib, pkgs, ... }: { pkgs, ... }: {
with lib;
{
config = { config = {
home.packages = [ pkgs.comic-relief pkgs.unifont ]; home.packages = [ pkgs.comic-relief pkgs.unifont ];

View file

@ -1,5 +1,3 @@
{ ... }:
{ {
nix = { nix = {
registry = { registry = {

View file

@ -1,8 +1,4 @@
{ config, lib, ... }: { config, ... }: {
with lib;
{
config = { config = {
pam.sessionVariables = { pam.sessionVariables = {
V1 = "v1"; V1 = "v1";

View file

@ -1,7 +1,3 @@
{ config, lib, pkgs, ... }:
with lib;
{ {
home.file.testfile.text = "not special"; home.file.testfile.text = "not special";
specialisation.test.configuration = { specialisation.test.configuration = {

View file

@ -1,8 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, ... }: {
with lib;
{
config = { config = {
# Test fallback behavior for stateVersion >= 20.09, which is pure. # Test fallback behavior for stateVersion >= 20.09, which is pure.
xdg.enable = lib.mkForce false; xdg.enable = lib.mkForce false;

View file

@ -1,8 +1,4 @@
{ config, lib, pkgs, ... }: { pkgs, ... }: {
with lib;
{
config = { config = {
xdg.desktopEntries = { xdg.desktopEntries = {
full = { # full definition full = { # full definition

View file

@ -1,8 +1,4 @@
{ config, lib, pkgs, ... }: { config, ... }: {
with lib;
{
config = { config = {
xdg.configHome = /. + "${config.home.homeDirectory}/.dummy-config"; xdg.configHome = /. + "${config.home.homeDirectory}/.dummy-config";
xdg.dataHome = /. + "${config.home.homeDirectory}/.dummy-data"; xdg.dataHome = /. + "${config.home.homeDirectory}/.dummy-data";

View file

@ -1,7 +1,3 @@
{ config, lib, pkgs, ... }:
with lib;
{ {
config = { config = {
xdg.mimeApps = { xdg.mimeApps = {

View file

@ -1,4 +1,4 @@
{ ... }: { {
config = { config = {
xdg.mime.enable = false; xdg.mime.enable = false;
nmt.script = '' nmt.script = ''

View file

@ -1,7 +1,3 @@
{ config, lib, pkgs, ... }:
with lib;
{ {
config = { config = {
xsession = { xsession = {

View file

@ -1,7 +1,3 @@
{ config, lib, pkgs, ... }:
with lib;
{ {
config = { config = {
home.stateVersion = "19.09"; home.stateVersion = "19.09";

View file

@ -1,7 +1,3 @@
{ config, lib, pkgs, ... }:
with lib;
{ {
config = { config = {
programs.abook.enable = true; programs.abook.enable = true;

View file

@ -1,7 +1,3 @@
{ config, lib, pkgs, ... }:
with lib;
{ {
config = { config = {
programs.abook = { programs.abook = {

View file

@ -1,7 +1,3 @@
{ config, lib, pkgs, ... }:
with lib;
{ {
config = { config = {
test.asserts.assertions.expected = ['' test.asserts.assertions.expected = [''

View file

@ -2,4 +2,5 @@
aerc-noSettings = ./noSettings.nix; aerc-noSettings = ./noSettings.nix;
aerc-settings = ./settings.nix; aerc-settings = ./settings.nix;
aerc-assertion = ./assertion.nix; aerc-assertion = ./assertion.nix;
aerc-oauth = ./oauth.nix;
} }

View file

@ -1,7 +1,3 @@
{ config, lib, pkgs, ... }:
with lib;
{ {
config = { config = {
nmt.script = let dir = "home-files/.config/aerc"; nmt.script = let dir = "home-files/.config/aerc";

View file

@ -0,0 +1,9 @@
# Generated by Home Manager.
[basic]
copy-to = Sent
default = Inbox
from = Annie X. Hacker <anniex@mail.invalid>
outgoing = smtp+xoauth2://anniex@smtp.office365.com:587?client_id=9e5f94bc-e8a4-4e73-b8be-63364c29d753&token_endpoint=https%3A%2F%2Flogin.microsoftonline.com%2Fcommon%2Foauth2%2Fv2.0%2Ftoken
postpone = Drafts
source = imaps+xoauth2://anniex@outlook.office365.com:993?client_id=9e5f94bc-e8a4-4e73-b8be-63364c29d753&token_endpoint=https%3A%2F%2Flogin.microsoftonline.com%2Fcommon%2Foauth2%2Fv2.0%2Ftoken

View file

@ -0,0 +1,39 @@
{ config, pkgs, ... }: {
config = {
nmt.script = let
dir = if (pkgs.stdenv.isDarwin && !config.xdg.enable) then
"home-files/Library/Preferences/aerc"
else
"home-files/.config/aerc";
in ''
assertFileContent ${dir}/accounts.conf ${./oauth.expected}
'';
programs.aerc = {
enable = true;
extraConfig.general.unsafe-accounts-conf = true;
};
accounts.email.accounts = {
basic = {
realName = "Annie X. Hacker";
userName = "anniex";
address = "anniex@mail.invalid";
primary = true;
flavor = "outlook.office365.com";
aerc = rec {
enable = true;
imapAuth = "xoauth2";
smtpAuth = imapAuth;
imapOauth2Params = {
client_id = "9e5f94bc-e8a4-4e73-b8be-63364c29d753";
token_endpoint =
"https://login.microsoftonline.com/common/oauth2/v2.0/token";
};
smtpOauth2Params = imapOauth2Params;
};
};
};
};
}

View file

@ -1,8 +1,4 @@
{ config, lib, pkgs, ... }: { config, pkgs, ... }: {
with lib;
{
config = { config = {
nmt.script = let nmt.script = let
dir = if (pkgs.stdenv.isDarwin && !config.xdg.enable) then dir = if (pkgs.stdenv.isDarwin && !config.xdg.enable) then

View file

@ -1,5 +1,3 @@
{ ... }:
{ {
programs.atuin = { programs.atuin = {
enable = true; enable = true;

View file

@ -1,7 +1,3 @@
{ config, lib, pkgs, ... }:
with lib;
{ {
config = { config = {
programs.bash = { programs.bash = {

View file

@ -1,8 +1,4 @@
{ config, lib, pkgs, ... }: { config, ... }: {
with lib;
{
config = { config = {
programs.bottom = { programs.bottom = {
enable = true; enable = true;

View file

@ -1,8 +1,4 @@
{ config, lib, pkgs, ... }: { config, ... }: {
with lib;
{
config = { config = {
programs.bottom = { programs.bottom = {
enable = true; enable = true;

View file

@ -1,7 +1,3 @@
{ config, lib, pkgs, ... }:
with lib;
{ {
config = { config = {
programs.boxxy.enable = true; programs.boxxy.enable = true;

View file

@ -1,7 +1,3 @@
{ config, lib, pkgs, ... }:
with lib;
{ {
config = { config = {
programs.boxxy.enable = true; programs.boxxy.enable = true;

View file

@ -1 +1,4 @@
{ dircolors-settings = ./settings.nix; } {
dircolors-settings = ./settings.nix;
dircolors-xdg-config-settings = ./xdg-config-settings.nix;
}

View file

@ -1,9 +1,7 @@
{ config, lib, pkgs, ... }: { pkgs, ... }: {
with lib;
{
config = { config = {
programs.zsh.enable = true;
programs.dircolors = { programs.dircolors = {
enable = true; enable = true;
@ -22,6 +20,11 @@ with lib;
assertFileContent \ assertFileContent \
home-files/.dir_colors \ home-files/.dir_colors \
${./settings-expected.conf} ${./settings-expected.conf}
assertFileRegex \
home-files/.zshrc \
"eval \$(${pkgs.coreutils}/bin/dircolors -b ~/.dir_colors)"
''; '';
}; };
} }

View file

@ -0,0 +1,31 @@
{ config, pkgs, ... }: {
config = {
home.preferXdgDirectories = true;
programs.zsh.enable = true;
programs.dircolors = {
enable = true;
settings = {
OTHER_WRITABLE = "30;46";
".sh" = "01;32";
".csh" = "01;32";
};
extraConfig = ''
# Extra dircolors configuration.
'';
};
nmt.script = ''
assertFileContent \
home-files/.config/dir_colors \
${./settings-expected.conf}
assertFileRegex \
home-files/.zshrc \
"eval \$(${pkgs.coreutils}/bin/dircolors -b ${config.xdg.configHome}/dir_colors)"
'';
};
}

View file

@ -0,0 +1 @@
{ earthly-settings = ./earthly-settings.nix; }

View file

@ -0,0 +1,21 @@
{
programs.earthly = {
enable = true;
settings = {
global.disable_analytics = true;
git."github.com" = {
auth = "ssh";
user = "username";
};
};
};
test.stubs.earthly = { };
nmt.script = ''
assertFileExists home-files/.earthly/config.yml
assertFileContent home-files/.earthly/config.yml ${./earthly-settings.yml}
'';
}

View file

@ -0,0 +1,6 @@
git:
github.com:
auth: ssh
user: username
global:
disable_analytics: true

View file

@ -1,4 +1,4 @@
{ ... }: { {
config = { config = {
programs.eww = { programs.eww = {
enable = true; enable = true;

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