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

6
flake.lock generated
View file

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

View file

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

View file

@ -268,10 +268,26 @@ let
};
aliases = mkOption {
type = types.listOf (types.strMatching ".*@.*");
description = "Alternative identities of this account.";
default = [ ];
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 {

View file

@ -56,6 +56,11 @@ let
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;
};
})
(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 = {
Description = "Fcitx5 input method editor";
PartOf = [ "graphical-session.target" ];
After = [ "graphical-session.target" ];
};
Service.ExecStart = "${fcitx5Package}/bin/fcitx5";
Install.WantedBy = [ "graphical-session.target" ];

View file

@ -25,9 +25,11 @@
{ 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
options = {
@ -118,7 +120,7 @@ with lib;
};
LimitLoadToSessionType = mkOption {
type = types.nullOr types.str;
type = types.nullOr (types.oneOf [ types.str (types.listOf types.str) ]);
default = null;
description = ''
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 {
default = null;
example = {
example = [{
Hour = 2;
Minute = 30;
};
}];
description = ''
This optional key causes the job to be started every calendar interval as specified. Missing arguments
are considered to be wildcard. The semantics are much like `crontab(5)`. Unlike cron which skips job
invocations when the computer is asleep, launchd will start the job the next time the computer wakes
This optional key causes the job to be started every calendar interval as specified. The semantics are
much like {manpage}`crontab(5)`: Missing attributes are considered to be wildcard. Unlike cron which skips
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
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 {
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.
'';
};
};
}));
type = types.nullOr launchdTypes.StartCalendarInterval;
};
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 to the job, throttling its CPU usage and I/O bandwidth. The following are valid values:
Background
: 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
user experience.
Background
: 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
user experience.
Standard
: Standard jobs are equivalent to no ProcessType being set.
Standard
: Standard jobs are equivalent to no ProcessType being set.
Adaptive
: Adaptive jobs move between the Background and Interactive classifications based on activity over
XPC connections. See {manpage}`xpc_transaction_begin(3)` for details.
Adaptive
: Adaptive jobs move between the Background and Interactive classifications based on activity over
XPC connections. See `xpc_transaction_begin(3)` for details.
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
used if an app's ability to be responsive depends on it, and cannot be made Adaptive.
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
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 {
type = types.nullOr types.bool;
default = null;
@ -717,7 +694,7 @@ with lib;
MachServices = mkOption {
default = null;
example = { ResetAtClose = true; };
example = { "org.nixos.service" = { ResetAtClose = true; }; };
description = ''
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
@ -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
launchd.
'';
type = types.nullOr (types.submodule {
options = {
ResetAtClose = mkOption {
type = types.nullOr types.bool;
default = null;
description = ''
If this boolean is false, the port is recycled, thus leaving clients to remain oblivious to the
demand nature of job. If the value is set to true, clients receive port death notifications when
the job lets go of the receive right. The port will be recreated atomically with respect to bootstrap_look_up()
calls, so that clients can trust that after receiving a port death notification,
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.
'';
};
type = types.nullOr (types.attrsOf (types.either types.bool
(types.submodule {
options = {
ResetAtClose = mkOption {
type = types.nullOr types.bool;
default = null;
description = ''
If this boolean is false, the port is recycled, thus leaving clients to remain oblivious to the
demand nature of job. If the value is set to true, clients receive port death notifications when
the job lets go of the receive right. The port will be recreated atomically with respect to bootstrap_look_up()
calls, so that clients can trust that after receiving a port death notification,
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 {
type = types.nullOr types.bool;
default = null;
description = ''
Reserve the name in the namespace, but cause bootstrap_look_up() to fail until the job has
checked in with launchd.
'';
HideUntilCheckIn = mkOption {
type = types.nullOr types.bool;
default = null;
description = ''
Reserve the name in the namespace, but cause bootstrap_look_up() to fail until the job has
checked in with launchd.
'';
};
};
};
});
})));
};
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 {
default = null;
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].
#
# [1] https://github.com/NixOS/nixpkgs/blob/fca0d6e093c82b31103dc0dacc48da2a9b06e24b/maintainers/maintainer-list.nix#LC1
{
aabccd021 = {
name = "Muhamad Abdurahman";
@ -113,6 +112,12 @@
github = "diniamo";
githubId = 55629891;
};
dsoverlord = {
name = "Kirill Zakharov";
email = "dsoverlord@vk.com";
github = "dsoverlord";
githubId = 78819443;
};
dwagenk = {
email = "dwagenk@mailbox.org";
github = "dwagenk";
@ -664,4 +669,26 @@
github = "ckgxrg-salt";
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.
'';
}
{
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)
cfg.stateFile)
{ "${cfg.cacheHome}/.keep".text = ""; }
{ "${cfg.stateHome}/.keep".text = ""; }
];
}
];

View file

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

View file

@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: Home Manager Modules\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2025-01-03 09:09+0100\n"
"PO-Revision-Date: 2023-12-10 15:58+0000\n"
"Last-Translator: Nara Díaz Viñolas <rdvdev2@gmail.com>\n"
"PO-Revision-Date: 2025-02-19 21:00+0000\n"
"Last-Translator: Alejandro Masó Bonilla <alejandrobonilla2001@gmail.com>\n"
"Language-Team: Catalan <https://hosted.weblate.org/projects/home-manager/"
"modules/ca/>\n"
"Language: ca\n"
@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\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
msgid "Creating home file links in %s"
@ -29,11 +29,11 @@ msgstr "Netejant enllaços orfes de %s"
#: modules/home-environment.nix:591
msgid "Creating new profile generation"
msgstr ""
msgstr "Creant una nova generació per al nou perfil"
#: modules/home-environment.nix:594
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
msgid ""
@ -55,13 +55,13 @@ msgstr ""
"Potser hi ha un conflicte amb un paquet instal·lat mitjançant\n"
"\"%s\"? Prova d'executar\n"
"\n"
" %s\n"
". . . . %s\n"
"\n"
"i si hi ha un paquet conflictiu el pots eliminar amb\n"
"\n"
" %s\n"
". . . . %s\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
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
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
msgid "Sanity checking Nix"
@ -102,7 +102,7 @@ msgstr "Execució en viu"
#: modules/lib-bash/activation-init.sh:159
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
msgid "Activation variables:"

View file

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

View file

@ -137,6 +137,18 @@ let
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:
@ -178,6 +190,11 @@ let
value.source = pkg;
};
nativeMessagingHostsJoined = pkgs.symlinkJoin {
name = "${drvName}-native-messaging-hosts";
paths = cfg.nativeMessagingHosts;
};
package = if cfg.commandLineArgs != [ ] then
cfg.package.override {
commandLineArgs = concatStringsSep " " cfg.commandLineArgs;
@ -189,7 +206,14 @@ let
home.packages = [ package ];
home.file = optionalAttrs (!isProprietaryChrome) (listToAttrs
((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 {

View file

@ -54,155 +54,168 @@ in {
};
};
config = mkIf cfg.enable {
# Add default settings from `dircolors --print-database`.
programs.dircolors.settings = {
RESET = mkDefault "0";
DIR = mkDefault "01;34";
LINK = mkDefault "01;36";
MULTIHARDLINK = mkDefault "00";
FIFO = mkDefault "40;33";
SOCK = mkDefault "01;35";
DOOR = mkDefault "01;35";
BLK = mkDefault "40;33;01";
CHR = mkDefault "40;33;01";
ORPHAN = mkDefault "40;31;01";
MISSING = mkDefault "00";
SETUID = mkDefault "37;41";
SETGID = mkDefault "30;43";
CAPABILITY = mkDefault "30;41";
STICKY_OTHER_WRITABLE = mkDefault "30;42";
OTHER_WRITABLE = mkDefault "34;42";
STICKY = mkDefault "37;44";
EXEC = mkDefault "01;32";
".tar" = mkDefault "01;31";
".tgz" = mkDefault "01;31";
".arc" = mkDefault "01;31";
".arj" = mkDefault "01;31";
".taz" = mkDefault "01;31";
".lha" = mkDefault "01;31";
".lz4" = mkDefault "01;31";
".lzh" = mkDefault "01;31";
".lzma" = mkDefault "01;31";
".tlz" = mkDefault "01;31";
".txz" = mkDefault "01;31";
".tzo" = mkDefault "01;31";
".t7z" = mkDefault "01;31";
".zip" = mkDefault "01;31";
".z" = mkDefault "01;31";
".dz" = mkDefault "01;31";
".gz" = mkDefault "01;31";
".lrz" = mkDefault "01;31";
".lz" = mkDefault "01;31";
".lzo" = mkDefault "01;31";
".xz" = mkDefault "01;31";
".zst" = mkDefault "01;31";
".tzst" = mkDefault "01;31";
".bz2" = mkDefault "01;31";
".bz" = mkDefault "01;31";
".tbz" = mkDefault "01;31";
".tbz2" = mkDefault "01;31";
".tz" = mkDefault "01;31";
".deb" = mkDefault "01;31";
".rpm" = mkDefault "01;31";
".jar" = mkDefault "01;31";
".war" = mkDefault "01;31";
".ear" = mkDefault "01;31";
".sar" = mkDefault "01;31";
".rar" = mkDefault "01;31";
".alz" = mkDefault "01;31";
".ace" = mkDefault "01;31";
".zoo" = mkDefault "01;31";
".cpio" = mkDefault "01;31";
".7z" = mkDefault "01;31";
".rz" = mkDefault "01;31";
".cab" = mkDefault "01;31";
".wim" = mkDefault "01;31";
".swm" = mkDefault "01;31";
".dwm" = mkDefault "01;31";
".esd" = mkDefault "01;31";
".jpg" = mkDefault "01;35";
".jpeg" = mkDefault "01;35";
".mjpg" = mkDefault "01;35";
".mjpeg" = mkDefault "01;35";
".gif" = mkDefault "01;35";
".bmp" = mkDefault "01;35";
".pbm" = mkDefault "01;35";
".pgm" = mkDefault "01;35";
".ppm" = mkDefault "01;35";
".tga" = mkDefault "01;35";
".xbm" = mkDefault "01;35";
".xpm" = mkDefault "01;35";
".tif" = mkDefault "01;35";
".tiff" = mkDefault "01;35";
".png" = mkDefault "01;35";
".svg" = mkDefault "01;35";
".svgz" = mkDefault "01;35";
".mng" = mkDefault "01;35";
".pcx" = mkDefault "01;35";
".mov" = mkDefault "01;35";
".mpg" = mkDefault "01;35";
".mpeg" = mkDefault "01;35";
".m2v" = mkDefault "01;35";
".mkv" = mkDefault "01;35";
".webm" = mkDefault "01;35";
".ogm" = mkDefault "01;35";
".mp4" = mkDefault "01;35";
".m4v" = mkDefault "01;35";
".mp4v" = mkDefault "01;35";
".vob" = mkDefault "01;35";
".qt" = mkDefault "01;35";
".nuv" = mkDefault "01;35";
".wmv" = mkDefault "01;35";
".asf" = mkDefault "01;35";
".rm" = mkDefault "01;35";
".rmvb" = mkDefault "01;35";
".flc" = mkDefault "01;35";
".avi" = mkDefault "01;35";
".fli" = mkDefault "01;35";
".flv" = mkDefault "01;35";
".gl" = mkDefault "01;35";
".dl" = mkDefault "01;35";
".xcf" = mkDefault "01;35";
".xwd" = mkDefault "01;35";
".yuv" = mkDefault "01;35";
".cgm" = mkDefault "01;35";
".emf" = mkDefault "01;35";
".ogv" = mkDefault "01;35";
".ogx" = mkDefault "01;35";
".aac" = mkDefault "00;36";
".au" = mkDefault "00;36";
".flac" = mkDefault "00;36";
".m4a" = mkDefault "00;36";
".mid" = mkDefault "00;36";
".midi" = mkDefault "00;36";
".mka" = mkDefault "00;36";
".mp3" = mkDefault "00;36";
".mpc" = mkDefault "00;36";
".ogg" = mkDefault "00;36";
".ra" = mkDefault "00;36";
".wav" = mkDefault "00;36";
".oga" = mkDefault "00;36";
".opus" = mkDefault "00;36";
".spx" = mkDefault "00;36";
".xspf" = mkDefault "00;36";
};
config = let
dircolorsPath = if config.home.preferXdgDirectories then
"${config.xdg.configHome}/dir_colors"
else
"~/.dir_colors";
home.file.".dir_colors".text = concatStringsSep "\n" ([ ]
dircolorsConfig = concatStringsSep "\n" ([ ]
++ mapAttrsToList formatLine cfg.settings ++ [ "" ]
++ 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 ''
eval $(${pkgs.coreutils}/bin/dircolors -b ~/.dir_colors)
'';
programs.bash.initExtra = mkIf cfg.enableBashIntegration ''
eval $(${pkgs.coreutils}/bin/dircolors -b ${dircolorsPath})
'';
programs.fish.shellInit = mkIf cfg.enableFishIntegration ''
eval (${pkgs.coreutils}/bin/dircolors -c ~/.dir_colors)
'';
programs.fish.shellInit = mkIf cfg.enableFishIntegration ''
eval (${pkgs.coreutils}/bin/dircolors -c ${dircolorsPath})
'';
# Set `LS_COLORS` before Oh My Zsh and `initExtra`.
programs.zsh.initExtraBeforeCompInit = mkIf cfg.enableZshIntegration ''
eval $(${pkgs.coreutils}/bin/dircolors -b ~/.dir_colors)
'';
};
# Set `LS_COLORS` before Oh My Zsh and `initExtra`.
programs.zsh.initExtraBeforeCompInit = mkIf cfg.enableZshIntegration ''
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, ... }:
with lib;
let
modulePath = [ "programs" "firefox" ];
moduleName = concatStringsSep "." modulePath;
mkFirefoxModule = import ./firefox/mkFirefoxModule.nix;
in {
meta.maintainers = [ maintainers.rycee hm.maintainers.bricked ];
meta.maintainers =
[ maintainers.rycee hm.maintainers.bricked hm.maintainers.HPsaucii ];
imports = [
(mkFirefoxModule {
@ -21,25 +18,20 @@ in {
unwrappedPackageName = "firefox-unwrapped";
visible = true;
platforms.linux = rec {
vendorPath = ".mozilla";
configPath = "${vendorPath}/firefox";
};
platforms.linux = rec { configPath = ".mozilla/firefox"; };
platforms.darwin = {
vendorPath = "Library/Application Support/Mozilla";
configPath = "Library/Application Support/Firefox";
};
})
(mkRemovedOptionModule (modulePath ++ [ "extensions" ]) ''
Extensions are now managed per-profile. That is, change from
${moduleName}.extensions = [ foo bar ];
to
${moduleName}.profiles.myprofile.extensions = [ foo bar ];'')
${moduleName}.profiles.myprofile.extensions.packages = [ foo bar ];'')
(mkRemovedOptionModule (modulePath ++ [ "enableAdobeFlash" ])
"Support for this option has been removed.")
(mkRemovedOptionModule (modulePath ++ [ "enableGoogleTalk" ])

View file

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

View file

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

View file

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

View file

@ -31,7 +31,7 @@ in {
package = lib.mkPackageOption pkgs "ghostty" {
nullable = true;
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 {

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.difftastic.enable
cfg.diff-highlight.enable
cfg.riff.enable
];
in count id enabled <= 1;
message =
@ -496,7 +520,7 @@ in {
format = if (versionOlder config.home.stateVersion "25.05") then
(mkOptionDefault "openpgp")
else
null;
(mkOptionDefault null);
signer = let
defaultSigners = {
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 {
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 ];
xdg.configFile."htop/htoprc" = let
xdg.configFile."htop" = let
defaults = {
fields = if isDarwin then
remove fields.M_SHARE defaultFields
@ -188,9 +189,9 @@ in {
formatOptions = mapAttrsToList formatOption;
in mkIf (cfg.settings != { }) {
text =
concatStringsSep "\n" (formatOptions before ++ formatOptions settings)
+ "\n";
source = pkgs.writeTextDir "htoprc"
(concatStringsSep "\n" (formatOptions before ++ formatOptions settings)
+ "\n");
};
};
}

View file

@ -31,7 +31,7 @@ in {
"${ide}/bin/${ide.meta.mainProgram}-remote-dev-server registerBackendLocationForGateway || true";
lines = map mkLine cfg.ides;
linesStr = ''
rm $HOME/.cache/JetBrains/RemoteDev/userProvidedDist/_nix_store*
rm $HOME/.cache/JetBrains/RemoteDev/userProvidedDist/_nix_store* || true
'' + concatStringsSep "\n" lines;
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}";
};
toKittyActionAliases = lib.generators.toKeyValue {
mkKeyValue = alias_name: action: "action_alias ${alias_name} ${action}";
};
toKittyEnv = lib.generators.toKeyValue {
mkKeyValue = name: value: "env ${name}=${value}";
};
@ -143,6 +147,18 @@ in {
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 {
type = types.attrsOf types.str;
default = { };
@ -234,6 +250,7 @@ in {
shell_integration ${cfg.shellIntegration.mode}
'')
(toKittyConfig cfg.settings)
(toKittyActionAliases cfg.actionAliases)
(toKittyKeybindings cfg.keybindings)
(toKittyEnv cfg.environment)
cfg.extraConfig

View file

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

View file

@ -21,6 +21,7 @@ in {
"enableBashIntegration"
"enableZshIntegration"
"enableFishIntegration"
"enableNushellIntegration"
"settings"
];
@ -39,6 +40,9 @@ in {
enableZshIntegration =
lib.hm.shell.mkZshIntegrationOption { inherit config; };
enableNushellIntegration =
lib.hm.shell.mkNushellIntegrationOption { inherit config; };
globalConfig = mkOption {
type = tomlFormat.type;
default = { };
@ -103,6 +107,16 @@ in {
fish.interactiveShellInit = mkIf cfg.enableFishIntegration ''
${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);
addrs = map (a: a.address) muAccounts;
# 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
in sort lessThan (addrs ++ aliases);

View file

@ -52,15 +52,11 @@ in {
};
config = {
warnings = lib.optionals
(osConfig != null && !(cfg.clean.enable -> !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."
];
assertions = [{
assertion = (cfg.flake != null) -> !(lib.hasSuffix ".nix" cfg.flake);
message = "nh.flake must be a directory, not a nix file";
}];
warnings = (lib.optional
(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.")
++ (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.");
home = lib.mkIf cfg.enable {
packages = [ cfg.package ];

View file

@ -37,8 +37,9 @@ let
in {
name = catAttrs "realName" primary;
primary_email = catAttrs "address" primary;
other_email = catAttrs "aliases" primary ++ catAttrs "address" secondaries
++ catAttrs "aliases" secondaries;
other_email = map (email: email.address or email) (flatten
(catAttrs "aliases" primary ++ catAttrs "address" secondaries
++ catAttrs "aliases" secondaries));
};
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:
# For backwards compatibility, the primary address reuses the account ID.
let
id = if address == account.address then
account.id
else
builtins.hashString "sha256" address;
id = getId account address;
addressIsString = builtins.isString address;
in {
"mail.identity.id_${id}.fullName" = account.realName;
"mail.identity.id_${id}.useremail" = address;
"mail.identity.id_${id}.fullName" =
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}.htmlSigText" =
if account.signature.showSignature == "none" then
@ -87,9 +96,7 @@ let
addresses = [ account.address ] ++ account.aliases;
in {
"mail.account.account_${id}.identities" = concatStringsSep ","
([ "id_${id}" ]
++ map (address: "id_${builtins.hashString "sha256" address}")
account.aliases);
(map (address: "id_${getId account address}") addresses);
"mail.account.account_${id}.server" = "server_${id}";
} // optionalAttrs account.primary {
"mail.accountmanager.defaultaccount" = "account_${id}";
@ -128,6 +135,18 @@ let
(builtins.map (address: toThunderbirdIdentity account address) addresses)
// 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: ''
// Generated by Home Manager.
@ -158,6 +177,16 @@ in {
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 {
type = with types;
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 {
type = thunderbirdJson;
default = { };
@ -400,6 +448,10 @@ in {
++ optional (any (p: p.withExternalGnupg) (attrValues cfg.profiles))
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 ([{
"${thunderbirdConfigPath}/profiles.ini" =
mkIf (cfg.profiles != { }) { text = generators.toINI { } profilesIni; };
@ -411,11 +463,17 @@ in {
mkIf (profile.userContent != "") { text = profile.userContent; };
"${thunderbirdProfilesPath}/${name}/user.js" = let
accounts = filter (a:
emailAccounts = filter (a:
a.thunderbird.profiles == [ ]
|| 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 {
text = mkUserJs (builtins.foldl' (a: b: a // b) { } ([
cfg.settings
@ -433,7 +491,8 @@ in {
{ "mail.openpgp.allow_external_gnupg" = profile.withExternalGnupg; }
profile.settings
] ++ (map (a: toThunderbirdAccount a profile) accounts)))
] ++ (map (a: toThunderbirdAccount a profile) emailAccounts)
++ (map (f: toThunderbirdFeed f profile) feedAccounts)))
profile.extraConfig;
};

View file

@ -284,7 +284,7 @@ in {
shell = mkOption {
default = defaultShell;
example = "\${pkgs.zsh}/bin/zsh";
example = literalExpression "${pkgs.zsh}/bin/zsh";
type = with types; nullOr str;
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
"${config.xdg.configHome}/${configDir}/User";
configFilePath = "${userDir}/settings.json";
tasksFilePath = "${userDir}/tasks.json";
keybindingsFilePath = "${userDir}/keybindings.json";
configFilePath = name:
"${userDir}/${
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?
extensionPath = ".${extensionDir}/extensions";
extensionJson = pkgs.vscode-utils.toExtensionJson cfg.extensions;
extensionJsonFile = pkgs.writeTextFile {
name = "extensions-json";
destination = "/share/vscode/extensions/extensions.json";
text = extensionJson;
};
extensionJson = ext: pkgs.vscode-utils.toExtensionJson ext;
extensionJsonFile = name: text:
pkgs.writeTextFile {
inherit text;
name = "extensions-json-${name}";
destination = "/share/vscode/extensions/extensions.json";
};
mergedUserSettings = cfg.userSettings
// optionalAttrs (!cfg.enableUpdateCheck) { "update.mode" = "none"; }
// optionalAttrs (!cfg.enableExtensionUpdateCheck) {
mergedUserSettings =
userSettings: enableUpdateCheck: enableExtensionUpdateCheck:
userSettings
// optionalAttrs (enableUpdateCheck == false) { "update.mode" = "none"; }
// optionalAttrs (enableExtensionUpdateCheck == 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 {
type = jsonFormat.type;
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 {
type = jsonFormat.type;
default = { };
@ -221,45 +190,207 @@ in {
};
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 {
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.file = mkMerge [
(mkIf (mergedUserSettings != { }) {
"${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";
# The file `${userDir}/globalStorage/storage.json` needs to be writable by VSCode,
# since it contains other data, such as theme backgrounds, recently opened folders, etc.
# 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
subDir = "share/vscode/extensions";
toPaths = ext:
map (k: { "${extensionPath}/${k}".source = "${ext}/${subDir}/${k}"; })
(if ext ? vscodeExtUniqueId then
[ ext.vscodeExtUniqueId ]
else
builtins.attrNames (builtins.readDir (ext + "/${subDir}")));
in if cfg.mutableExtensionsDir then
mkMerge (concatMap toPaths cfg.extensions
++ lib.optional (lib.versionAtLeast vscodeVersion "1.74.0") {
in if (cfg.mutableExtensionsDir && allProfilesExceptDefault == { }) then
# Mutable extensions dir can only occur when only default profile is set.
# 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
# extensions.json with both mutable and immutable extensions.
"${extensionPath}/.extensions-immutable.json" = {
text = extensionJson;
text = extensionJson defaultProfile.extensions;
onChange = ''
run rm $VERBOSE_ARG -f ${extensionPath}/{extensions.json,.init-default-profile-extensions}
verboseEcho "Regenerating VSCode extensions.json"
@ -271,25 +402,14 @@ in {
"${extensionPath}".source = let
combinedExtensionsDrv = pkgs.buildEnv {
name = "vscode-extensions";
paths = cfg.extensions
++ lib.optional (lib.versionAtLeast vscodeVersion "1.74.0")
extensionJsonFile;
paths = (flatten (mapAttrsToList (n: v: v.extensions) cfg.profiles))
++ optional
(versionAtLeast vscodeVersion "1.74.0" && defaultProfile != { })
(extensionJsonFile "default"
(extensionJson defaultProfile.extensions));
};
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 {
programs.vscode.userSettings = mkIf cfg.hie.enable {
programs.vscode.profiles.default.userSettings = mkIf cfg.hie.enable {
"languageServerHaskell.enableHIE" = true;
"languageServerHaskell.hieExecutablePath" = cfg.hie.executablePath;
};
programs.vscode.extensions =
programs.vscode.profiles.default.extensions =
[ pkgs.vscode-extensions.justusadam.language-haskell ]
++ lib.optional cfg.hie.enable
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 {
type = nullOr (either path lines);
default = null;
@ -324,6 +335,8 @@ in {
ExecReload = "${pkgs.coreutils}/bin/kill -SIGUSR2 $MAINPID";
Restart = "on-failure";
KillMode = "mixed";
} // optionalAttrs cfg.systemd.enableInspect {
Environment = [ "GTK_DEBUG=interactive" ];
};
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, ... }:
with lib;
{
let inherit (lib) mkOption types;
in {
options.imapnotify = {
enable = mkEnableOption "imapnotify";
enable = lib.mkEnableOption "imapnotify";
onNotify = mkOption {
type = with types; either str (attrsOf str);
@ -30,10 +28,16 @@ with lib;
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 {
type = let jsonFormat = pkgs.formats.json { }; in jsonFormat.type;
default = { };
example = { wait = 10; };
description = "Additional configuration to add for this account.";
};
};

View file

@ -23,7 +23,10 @@ let
Service = {
# Use the nix store path for config to ensure service restarts when it changes
ExecStart =
"${getExe cfg.package} -conf '${genAccountConfig account}'";
"${getExe cfg.package} -conf '${genAccountConfig account}'" + " ${
lib.optionalString (account.imapnotify.extraArgs != [ ])
(toString account.imapnotify.extraArgs)
}";
Restart = "always";
RestartSec = 30;
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 {
default = "-time";
type =
@ -315,6 +324,7 @@ in {
'';
text = ''
${optionalInteger "max-visible" cfg.maxVisible}
${optionalInteger "max-history" cfg.maxHistory}
${optionalString "sort" cfg.sort}
${optionalString "output" cfg.output}
${optionalString "layer" cfg.layer}

View file

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

View file

@ -4,6 +4,14 @@ let
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 {
meta.maintainers = [ lib.hm.maintainers.danjujan ];
@ -22,6 +30,34 @@ in {
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 {
@ -38,6 +74,10 @@ in {
rsync
kmod
gawk
gnugrep
gnused
coreutils
findutils
nettools
util-linux
profile-sync-daemon
@ -84,5 +124,7 @@ in {
Timer = { OnUnitActiveSec = cfg.resyncTimer; };
};
};
xdg.configFile."psd/psd.conf".text = configFile;
};
}

View file

@ -127,6 +127,7 @@ in {
ExecStart = concatStringsSep " "
([ "${cfg.xss-lock.package}/bin/xss-lock" "-s \${XDG_SESSION_ID}" ]
++ cfg.xss-lock.extraOptions ++ [ "-- ${cfg.lockCmd}" ]);
Restart = "always";
};
};
}
@ -153,6 +154,7 @@ in {
"-locker '${pkgs.systemd}/bin/loginctl lock-session \${XDG_SESSION_ID}'"
] ++ optional cfg.xautolock.detectSleep "-detectsleep"
++ 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 = {
Type = if cfg.once then "oneshot" else "simple";
ExecStart = "${script}";
};
} // lib.optionalAttrs (!cfg.once) { Restart = "always"; };
Install.WantedBy = [ "graphical-session.target" ];
};
};

View file

@ -1,9 +1,24 @@
{ config, lib, pkgs, ... }:
{
config = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin {
let cfg = config.targets.darwin;
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.
home.file."Applications/Home Manager Apps".source = let
home.file.${cfg.linkApps.directory}.source = let
apps = pkgs.buildEnv {
name = "home-manager-applications";
paths = config.home.packages;

View file

@ -1,8 +1,6 @@
{ config, lib, pkgs, ... }:
with lib;
{
{ config, lib, ... }:
let inherit (lib) concatStringsSep mkOption types;
in {
options.test.asserts = {
warnings = {
enable = mkOption {
@ -37,8 +35,8 @@ with lib;
};
};
config = mkMerge [
(mkIf config.test.asserts.warnings.enable {
config = lib.mkMerge [
(lib.mkIf config.test.asserts.warnings.enable {
home.file = {
"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 = {
"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 ''
--

View file

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

View file

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

View file

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

View file

@ -1,5 +1,3 @@
{ ... }:
{
accounts.email = {
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" = {
enable = false;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,3 @@
{ config, lib, pkgs, ... }:
with lib;
{
config = {
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, ... }:
with lib;
{
{ config, pkgs, ... }: {
config = {
nmt.script = let
dir = if (pkgs.stdenv.isDarwin && !config.xdg.enable) then

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,3 @@
{ config, lib, pkgs, ... }:
with lib;
{
config = {
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, ... }:
with lib;
{
{ pkgs, ... }: {
config = {
programs.zsh.enable = true;
programs.dircolors = {
enable = true;
@ -22,6 +20,11 @@ with lib;
assertFileContent \
home-files/.dir_colors \
${./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 = {
programs.eww = {
enable = true;

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