Compare commits

...

52 Commits

Author SHA1 Message Date
Robert Helgesson
a65c04965c gpg: update key hash in test
Fixes #8478
2026-01-05 14:29:03 +01:00
Noah765
c4eabb884b hyprpaper: update settings example
The configuration format changed in v0.8.0, which is available on nixpkgs.
2026-01-05 10:52:37 +01:00
June Stepp
156b698b75 anki: fix answerKeys of length one 2026-01-05 10:51:38 +01:00
Hoang Nguyen
9d1c71f390 gpg: add dirmngrSettings and gpgsmSettings options 2026-01-05 10:34:11 +01:00
Hoang Nguyen
47e195783e gpg: remove obsolete default values in the settings
- charset option doesn't exist. The correct option name is display-charset.
- fixed-list-mode option is always used and thus obsolete since GNUPG 2.0.10.
- use-agent is a dummy option. gpg will always requires the agent.
2026-01-05 10:34:11 +01:00
Benedikt Rips
f894bc4ffd ssh-agent: improve handling of SSH_AUTH_SOCK variable
Specifically, only preserve `$SSH_AUTH_SOCK` when it points to a
forwarded agent.
2026-01-04 20:52:35 +01:00
Benedikt Rips
73f5a5ecc9 ssh-agent: fix Nushell's check for emptiness
Previously, it would not succeed if `$env.SSH_AUTH_SOCK` is set to an
empty string.
2026-01-04 20:52:35 +01:00
Naïm Camille Favier
7d5927b63c xfconf: fix package 2026-01-04 12:26:39 +01:00
Ivan Isakov
8f7d6bacb6 launchd: Restore errexit after setting up launchd agents
At the beginning of the setup script `errexit` is disabled, but never
properly enabled again at the end. This causes potential issues/errors
in activation scripts following `setupLaunchAgents` to go unnoticed,
since the build doesn't actually fail.
2026-01-04 11:30:04 +01:00
Alex Martens
12cc14271b hyprshell: fix broken links 2026-01-04 09:32:19 +01:00
Benedikt Rips
c211298f7e tree-wide: use lib.hm.assertions.assertPlatform 2026-01-04 09:31:10 +01:00
Tim Kleinschmidt
1cfa305fba opencode: add agent skills support
Adds support for OpenCode Agent Skills by managing skill definitions
under "/opencode/skill/<name>/SKILL.md" via `programs.opencode.skills`.

Documentation: https://opencode.ai/docs/skills/
2026-01-03 11:47:20 +01:00
Tim Kleinschmidt
3e87b442b5 opencode: update docs
.config is already part of $XDG_CONFIG_HOME
2026-01-03 11:47:20 +01:00
leiserfg
99a037de18 vicinae: fix settings example 2026-01-03 11:31:39 +01:00
Robert Helgesson
3b3164dfe3 zsh: avoid escaping showing up in dotDir docs 2026-01-03 11:29:29 +01:00
Robert Helgesson
bc43546503 docs: turn option references into links 2026-01-03 11:29:29 +01:00
Aguirre Matteo
78a8fae57f yt-dlp: remove redundant extraConfig test 2026-01-03 11:23:26 +01:00
Aguirre Matteo
b558d54215 yt-dlp: allow multiple declarations of the same option 2026-01-03 11:23:26 +01:00
Robert Helgesson
9ef24320f1 emacs: remove unnecessary rec 2026-01-03 11:10:00 +01:00
Vladislav
18f9d668aa anki: fix UI scale configuration
Use `numbers.between 1.0 2.0` for the UI scale type to match Anki's
actual behavior where ProfileManager.uiScale clamps values below 1.0
to 1.0.
2026-01-03 10:49:37 +01:00
bandithedoge
2f06b72606 mpd: set network settings as environment variables
https://mpd.readthedocs.io/en/stable/client.html#connecting-to-mpd

These environment variables are picked up by, amongst others, clients
based on libmpdclient:

- 2a42a10067/src/settings.c (L108)
- 2a42a10067/src/settings.c (L135)
2026-01-02 23:05:42 +01:00
PerchunPak
d4e4d5cfa3 lib: make toHyprconf support strings and attrs in sections
Adds support for

    section = [
      "abc"
      { a = 123; }
    ];

Which gets generated to

    section=abc

    section {
      a=123
    }

This is very useful with the new windowrule syntax, where you can
create anonymous window rules as strings and named rules as attribute
sets. See <https://wiki.hypr.land/Configuring/Window-Rules/>.
2026-01-02 15:56:43 +01:00
Austin Horstman
e4e78a2cbe tests/linux-wallpaperengine: add execstart test
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-30 08:22:50 -06:00
Austin Horstman
ae1ea768ef linux-wallpaperengine: misc cleanup
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-30 08:22:50 -06:00
Austin Horstman
365cbc13c4 linux-wallpaperengine: fix ExecStart command
Make sure to properly separate command args.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-30 08:22:50 -06:00
teto
d99b4ca5de meli: support jmap
Enabled when flavor == fastmail.com
2025-12-29 23:55:10 +01:00
teto
64f4dadb80 neovim: fix extraLuaConfig example
reported by bruno
2025-12-29 16:00:00 -06:00
Austin Horstman
7a7b43c723 treewide: drop foo-dogsquared
Removed in https://github.com/NixOS/nixpkgs/pull/472804

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-28 22:03:17 -06:00
home-manager-ci[bot]
a84cccefd4 flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/3e2499d5539c16d0d173ba53552a4ff8547f4539?narHash=sha256-QEhk0eXgyIqTpJ/ehZKg9IKS7EtlWxF3N7DXy42zPfU%3D' (2025-12-25)
  → 'github:NixOS/nixpkgs/c0b0e0fddf73fd517c3471e546c0df87a42d53f4?narHash=sha256-coBu0ONtFzlwwVBzmjacUQwj3G%2BlybcZ1oeNSQkgC0M%3D' (2025-12-28)
2025-12-28 22:03:17 -06:00
teto
9d32c214db neovim: let user insert snippets in init.lua
It is a common complaint for users that they can't insert their own code
where they want in the init.lua.
2025-12-29 01:51:32 +01:00
leiserfg
87785ddbc7 vicinae: Add tests for old vicinae version 2025-12-28 17:17:29 -06:00
leiserfg
113b155fe8 vicinae: Update to post 0.17 settings 2025-12-28 17:17:29 -06:00
teto
398bc87bc8 neovim: refactor to get rid of makeNeovimConfig 2025-12-28 20:13:09 +01:00
home-manager-ci[bot]
3613abcbd7 flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/a6531044f6d0bef691ea18d4d4ce44d0daa6e816?narHash=sha256-3xY8CZ4rSnQ0NqGhMKAy5vgC%2B2IVK0NoVEzDoOh4DA4%3D' (2025-12-21)
  → 'github:NixOS/nixpkgs/3e2499d5539c16d0d173ba53552a4ff8547f4539?narHash=sha256-QEhk0eXgyIqTpJ/ehZKg9IKS7EtlWxF3N7DXy42zPfU%3D' (2025-12-25)
2025-12-28 10:30:53 -06:00
Austin Horstman
d7e794fe12 tests/anyrun: add empty css test
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-28 10:29:55 -06:00
Austin Horstman
8969535f1c anyrun: default extraCss to null
Prevent creating a file when not configured.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-28 10:29:55 -06:00
teto
80cca72314 meli: support account specific settings
also assert when overriding accounts. I had overriden settings when
testing this module, forgot about it and then wondered why my email
accounts were ignored.
2025-12-28 16:49:26 +01:00
Austin Horstman
d2e0458d65 zsh: don't suggest stateVersion update
Generally best to avoid telling normal users to adjust their
stateVersion to avoid other home-manager module logic changes based on
stateVersion.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-27 18:30:08 -06:00
Austin Horstman
b3ae822959 tests/zsh: add xdg dotDir tests
Verify we respect xdg.enable behavior when placing files.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-27 17:58:46 -06:00
Austin Horstman
d761c0ce89 news: add zsh dotDir default change
Default has changed to respect `xdg.enable`. Let user's know in case it
affects them surprisingly.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-27 17:58:46 -06:00
Austin Horstman
f84f474c1b zsh: respect xdg.enable for dotDir
Make sure we actually respect a user's `xdg.enable` preference.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-27 17:58:46 -06:00
Austin Horstman
ea6dfabe3c tests/zsh: add more test cases for dotdir
Adds tests for various dotDir configurations including trailing slashes
and spaces.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-27 17:58:46 -06:00
Austin Horstman
5432dc5bc4 zsh: fix dotDir path normalization and quoting
Fixes issue where dotDir with trailing slash caused failures.
Refactors lib.nix to use raw paths internally, fixing issues with spaces
in paths.
Updates history.path logic to correctly handle raw absolute paths.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-27 17:58:46 -06:00
Bruno BELANYI
bec08ef6e3 programs/ssh: DRY address/port options
The end goal is to hoist the forwarded path assertion directly into this
module rather than the top-level.
2025-12-27 15:12:05 -06:00
Sandro Marques
4067ca1ffb easyeffects: Fix race condition on Wayland session startup
Add systemd service ordering dependencies to prevent EasyEffects from
starting before the Wayland compositor is ready.

**Problem:** EasyEffects would crash during login with "Failed to create
wl_display (No such file or directory)" if started before the Wayland
display server was fully initialized.

**Solution:** Declaring the "After" property ensures EasyEffects waits
for the graphical session to be fully ready. The "PartOf" properly stops
EasyEffects when logging out. Got the tip from
https://github.com/wwmm/easyeffects/issues/1310.

Tested on NixOS 25.11 (Xantusia, 20251223.76701a1) and Home Manager 25.11
(0999ed8) with GNOME 49 on Wayland.
2025-12-27 12:56:02 -06:00
Oliver Geneser
2d36a6de2f ssh: add kexAlgorithms to matchBlocks
This commit adds the option to add kexAlgorithms as an matchBlock
option with updated test case.
2025-12-27 16:54:14 +01:00
Heitor Augusto
91cdb0e2d5 nixGL: patch systemd and d-bus services references 2025-12-25 11:16:13 -06:00
home-manager-ci[bot]
7eca7f7081 flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/c6245e83d836d0433170a16eb185cefe0572f8b8?narHash=sha256-G/WVghka6c4bAzMhTwT2vjLccg/awmHkdKSd2JrycLc%3D' (2025-12-18)
  → 'github:NixOS/nixpkgs/a6531044f6d0bef691ea18d4d4ce44d0daa6e816?narHash=sha256-3xY8CZ4rSnQ0NqGhMKAy5vgC%2B2IVK0NoVEzDoOh4DA4%3D' (2025-12-21)
2025-12-23 23:24:11 -06:00
Austin Horstman
20728df08f release/25.11: add darwin copy apps change
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-23 16:36:16 -06:00
Austin Horstman
af3c24de76 release/25.05: add git signing format change
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-23 16:36:16 -06:00
Austin Horstman
624c7e80fb release/23.05: add swaylock stateVersion change
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-23 16:36:16 -06:00
home-manager-ci[bot]
9c790e687e maintainers: update all-maintainers.nix
Automated update of the master maintainers list combining:
- Home Manager specific maintainers from modules/lib/maintainers.nix
- Nixpkgs maintainers referenced in Home Manager modules

**Added:** 0 maintainers
**Removed:** 0 maintainers
**Total:** 282 → 282 maintainers

Generated by: lib/python/generate-all-maintainers.py
2025-12-23 13:45:25 -06:00
87 changed files with 1148 additions and 332 deletions

View File

@@ -1097,19 +1097,6 @@
name = "Hoang Nguyen";
source = "home-manager";
};
foo-dogsquared = {
email = "foodogsquared@foodogsquared.one";
github = "foo-dogsquared";
githubId = 34962634;
keys = [
{
fingerprint = "DDD7 D0BD 602E 564B AA04 FC35 1431 0D91 4115 2B92";
}
];
matrix = "@foodogsquared:matrix.org";
name = "Gabriel Arazas";
source = "nixpkgs";
};
fpob = {
email = "fpob@proton.me";
github = "fpob";
@@ -2078,7 +2065,7 @@
source = "nixpkgs";
};
shikanime = {
email = "deva.shikanime@protonmail.com";
email = "william.phetsinorath@shikanime.studio";
github = "shikanime";
githubId = 22115108;
name = "William Phetsinorath";

View File

@@ -57,3 +57,9 @@ changes are only active if the `home.stateVersion` option is set to
now default to `true` which is consistent with the default values
for those options used by `i3` and `sway`.
- The [](#opt-programs.swaylock.enable) option now defaults to `false`
and must be explicitly enabled. Previously, it would be implicitly
enabled when `programs.swaylock.settings` was non-empty. Users with
`home.stateVersion` set to earlier versions will continue to get the
old implicit behavior.

View File

@@ -27,4 +27,8 @@ The state version in this release includes the changes below. These
changes are only active if the `home.stateVersion` option is set to
\"25.05\" or later.
- No changes.
- The [](#opt-programs.git.signing.format) option no longer defaults to
`"openpgp"`. Users who use Git signing with GPG should explicitly set
this option to `"openpgp"` to maintain the previous behavior. Users
with `home.stateVersion` set to earlier versions will continue to get
the `"openpgp"` default for backwards compatibility.

View File

@@ -80,3 +80,10 @@ changes are only active if the `home.stateVersion` option is set to
`{ PASSWORD_STORE_DIR = $XDG_DATA_HOME/password-store; }` anymore by its
default value. This will revert to the default behaviour of the program,
namely `$HOME/.password-store` to be used as the store path.
- On macOS, [](#opt-targets.darwin.copyApps.enable) is now enabled by
default instead of [](#opt-targets.darwin.linkApps.enable). This means
applications from `home.packages` will be copied to
`~/Applications/Home Manager Apps` rather than symlinked, making them
work properly with Spotlight. Users with `home.stateVersion` set to
earlier versions will continue to use `linkApps` by default.

View File

@@ -7,11 +7,19 @@ section is therefore not final.
This release has the following notable changes:
- The [](#opt-programs.anki.uiScale) option now expects a value in the
range 1.02.0, previously it erroneously expected values in the
range `0.01.0`.
## State Version Changes {#sec-release-26.05-state-version-changes}
The state version in this release includes the changes below. These
changes are only active if the `home.stateVersion` option is set to
\"26.05\" or later.
- The `gtk.gtk4.theme` option does not mirror `gtk.theme` by default
anymore.
- The [](#opt-gtk.gtk4.theme) option does not mirror
[](#opt-gtk.theme) by default anymore.
- The [](#opt-programs.zsh.dotDir) option now defaults to the XDG
configuration directory (usually `~/.config/zsh`) when
[](#opt-xdg.enable) is true.

6
flake.lock generated
View File

@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1766070988,
"narHash": "sha256-G/WVghka6c4bAzMhTwT2vjLccg/awmHkdKSd2JrycLc=",
"lastModified": 1766902085,
"narHash": "sha256-coBu0ONtFzlwwVBzmjacUQwj3G+lybcZ1oeNSQkgC0M=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "c6245e83d836d0433170a16eb185cefe0572f8b8",
"rev": "c0b0e0fddf73fd517c3471e546c0df87a42d53f4",
"type": "github"
},
"original": {

View File

@@ -270,9 +270,7 @@ in
setupLaunchAgents
# Restore errexit
if [[ -o errexit ]]; then
set -e
fi
set -e
'';
})
];

View File

@@ -21,6 +21,7 @@
isList
mapAttrsToList
replicate
attrNames
;
initialIndent = concatStrings (replicate indentLevel " ");
@@ -28,31 +29,36 @@
toHyprconf' =
indent: attrs:
let
sections = filterAttrs (n: v: isAttrs v || (isList v && all isAttrs v)) attrs;
isImportantField =
n: _: foldl (acc: prev: if hasPrefix prev n then true else acc) false importantPrefixes;
importantFields = filterAttrs isImportantField attrs;
withoutImportantFields = fields: removeAttrs fields (attrNames importantFields);
allSections = filterAttrs (n: v: isAttrs v || isList v) attrs;
sections = withoutImportantFields allSections;
mkSection =
n: attrs:
if lib.isList attrs then
(concatMapStringsSep "\n" (a: mkSection n a) attrs)
else
if isList attrs then
let
separator = if all isAttrs attrs then "\n" else "";
in
(concatMapStringsSep separator (a: mkSection n a) attrs)
else if isAttrs attrs then
''
${indent}${n} {
${toHyprconf' " ${indent}" attrs}${indent}}
'';
''
else
toHyprconf' indent { ${n} = attrs; };
mkFields = generators.toKeyValue {
listsAsDuplicateKeys = true;
inherit indent;
};
allFields = filterAttrs (n: v: !(isAttrs v || (isList v && all isAttrs v))) attrs;
isImportantField =
n: _: foldl (acc: prev: if hasPrefix prev n then true else acc) false importantPrefixes;
importantFields = filterAttrs isImportantField allFields;
fields = builtins.removeAttrs allFields (mapAttrsToList (n: _: n) importantFields);
allFields = filterAttrs (n: v: !(isAttrs v || isList v)) attrs;
fields = withoutImportantFields allFields;
in
mkFields importantFields
+ concatStringsSep "\n" (mapAttrsToList mkSection sections)

View File

@@ -0,0 +1,20 @@
{ config, ... }:
{
time = "2025-12-27T19:00:00+00:00";
condition = config.programs.zsh.enable;
message = ''
The default value of `programs.zsh.dotDir` has changed.
When `home.stateVersion` is set to "26.05" or later, and `xdg.enable` is
`true` (the default), `programs.zsh.dotDir` now defaults to
`''${config.xdg.configHome}/zsh`. Previously, it defaulted to the home
directory.
This means your Zsh configuration files (`.zshrc`, `.zshenv`, etc.) will be
moved to `~/.config/zsh` (or your configured XDG config home).
If you prefer the old behavior, you can explicitly set:
`programs.zsh.dotDir = config.home.homeDirectory;`
'';
}

View File

@@ -0,0 +1,10 @@
{ config, ... }:
{
time = "2026-01-02T00:03:48+00:00";
condition = config.services.mpd.enable;
message = ''
`MPD_HOST` and `MPD_PORT` environment variables are now set automatically.
This can be disabled with `services.mpd.enableSessionVariables = false`.
'';
}

View File

@@ -135,7 +135,7 @@ in
home.activation.xfconfSettings = lib.hm.dag.entryAfter [ "installPackages" ] (
let
mkCommand = channel: property: value: ''
run ${pkgs.xfce.xfconf}/bin/xfconf-query \
run ${pkgs.xfconf}/bin/xfconf-query \
${lib.escapeShellArgs (
[
"-c"

View File

@@ -82,7 +82,7 @@ in
};
uiScale = lib.mkOption {
type = with lib.types; nullOr (numbers.between 0.0 1.0);
type = with lib.types; nullOr (numbers.between 1.0 2.0);
default = null;
example = 1.0;
description = "User interface scale.";

View File

@@ -112,7 +112,7 @@ let
answer_keys: tuple[tuple[int, str], ...] = (${
lib.strings.concatMapStringsSep ", " (val: "(${toString val.ease}, '${val.key}')") cfg.answerKeys
})
}${if cfg.answerKeys != [ ] then "," else ""})
for ease, key in answer_keys:
profile_manager.set_answer_key(ease, key)

View File

@@ -185,7 +185,7 @@ in
extraCss = mkOption {
type = nullOr lines;
default = "";
default = null;
description = ''
Extra CSS lines to add to {file}`~/.config/anyrun/style.css`.
'';

View File

@@ -16,18 +16,13 @@ let
cfg = config.programs.gpg;
mkKeyValue =
key: value: if lib.isString value then "${key} ${value}" else lib.optionalString value key;
cfgText = lib.generators.toKeyValue {
inherit mkKeyValue;
listsAsDuplicateKeys = true;
} cfg.settings;
scdaemonCfgText = lib.generators.toKeyValue {
inherit mkKeyValue;
listsAsDuplicateKeys = true;
} cfg.scdaemonSettings;
toKeyValue =
settings:
lib.generators.toKeyValue {
mkKeyValue =
key: value: if lib.isString value then "${key} ${value}" else lib.optionalString value key;
listsAsDuplicateKeys = true;
} settings;
primitiveType = types.oneOf [
types.str
@@ -193,6 +188,7 @@ in
scdaemonSettings = mkOption {
type = types.attrsOf (types.either primitiveType (types.listOf types.str));
default = { };
example = literalExpression ''
{
disable-ccid = true;
@@ -207,6 +203,41 @@ in
'';
};
dirmngrSettings = mkOption {
type = types.attrsOf (types.either primitiveType (types.listOf types.str));
default = { };
example = literalExpression ''
{
allow-version-check = true;
keyserver = "ldaps://ldap.example.com";
}
'';
description = ''
Dirmngr configuration options. Available options are described
in
[
{manpage}`dirmngr(1)`
](https://www.gnupg.org/documentation/manuals/gnupg/Dirmngr-Options.html)
'';
};
gpgsmSettings = mkOption {
type = types.attrsOf (types.either primitiveType (types.listOf types.str));
default = { };
example = literalExpression ''
{
with-key-data = true;
}
'';
description = ''
GPGSM configuration options. Available options are described
in
[
{manpage}`gpgsm(1)`
](https://www.gnupg.org/documentation/manuals/gnupg/GPGSM-Options.html)
'';
};
homedir = mkOption {
type = types.path;
example = literalExpression ''"''${config.xdg.dataHome}/gnupg"'';
@@ -267,8 +298,7 @@ in
cert-digest-algo = mkDefault "SHA512";
s2k-digest-algo = mkDefault "SHA512";
s2k-cipher-algo = mkDefault "AES256";
charset = mkDefault "utf-8";
fixed-list-mode = mkDefault true;
display-charset = mkDefault "utf-8";
no-comments = mkDefault true;
no-emit-version = mkDefault true;
keyid-format = mkDefault "0xlong";
@@ -277,11 +307,6 @@ in
with-fingerprint = mkDefault true;
require-cross-certification = mkDefault true;
no-symkey-cache = mkDefault true;
use-agent = mkDefault true;
};
programs.gpg.scdaemonSettings = {
# no defaults for scdaemon
};
home.packages = [ cfg.package ];
@@ -289,9 +314,21 @@ in
GNUPGHOME = cfg.homedir;
};
home.file."${cfg.homedir}/gpg.conf".text = cfgText;
home.file."${cfg.homedir}/gpg.conf" = mkIf (cfg.settings != { }) {
text = toKeyValue cfg.settings;
};
home.file."${cfg.homedir}/scdaemon.conf".text = scdaemonCfgText;
home.file."${cfg.homedir}/scdaemon.conf" = mkIf (cfg.scdaemonSettings != { }) {
text = toKeyValue cfg.scdaemonSettings;
};
home.file."${cfg.homedir}/dirmngr.conf" = mkIf (cfg.dirmngrSettings != { }) {
text = toKeyValue cfg.dirmngrSettings;
};
home.file."${cfg.homedir}/gpgsm.conf" = mkIf (cfg.gpgsmSettings != { }) {
text = toKeyValue cfg.gpgsmSettings;
};
# Link keyring if keys are not mutable
home.file."${cfg.homedir}/pubring.kbx" = mkIf (!cfg.mutableKeys && cfg.publicKeys != [ ]) {

View File

@@ -24,7 +24,8 @@ let
meliAccounts = (lib.attrsets.mapAttrs (name: value: (mkMeliAccounts name value)) enabledAccounts);
mkMeliAccounts = (
name: account: {
name: account:
{
root_mailbox = "${config.accounts.email.maildirBasePath}/${account.maildir.path}";
format = "Maildir";
identity = account.address;
@@ -33,6 +34,14 @@ let
send_mail = mkSmtp account;
mailboxes = account.meli.mailboxAliases;
}
// lib.optionalAttrs (account.flavor == "fastmail.com") {
server_username = account.userName;
server_password_command = lib.concatMapStringsSep " " lib.escapeShellArg account.passwordCommand;
format = "jmap";
server_url = "https://api.fastmail.com/jmap/session";
use_token = true;
}
// account.meli.settings
);
mkSmtp = account: {
@@ -153,6 +162,14 @@ in
};
description = "Folder display name";
};
settings = mkOption {
type = types.submodule {
freeformType = tomlFormat.type;
};
default = { };
description = "Account specific meli configuration";
};
};
}
)
@@ -160,6 +177,15 @@ in
};
};
config = mkIf config.programs.meli.enable {
assertions = [
{
assertion = cfg.settings ? accounts == false;
message = ''
programs.meli.settings.accounts override the accounts.email values.
Use per-email accounts.email.<ACCOUNT>.meli.settings instead'';
}
];
home.packages = [ config.programs.meli.package ];
# Generate meli configuration from email accounts

View File

@@ -213,11 +213,17 @@ in
extraLuaConfig = mkOption {
type = types.lines;
default = "";
example = ''
vim.opt.nobackup = true
example = lib.literalExpression ''
let
nvimEarlyInit = lib.mkOrder 500 "set rtp+=vim.opt.rtp:prepend('/home/user/myplugin')";
nvimLateInit = lib.mkAfter "vim.opt.signcolumn = 'auto:1-3'";
in
lib.mkMerge [ nvimEarlyInit nvimLateInit ];
'';
description = ''
Custom lua lines.
Content to be added to {file}`init.lua`.
To specify the order, use `lib.mkOrder`, `lib.mkBefore`, `lib.mkAfter`.
'';
};
@@ -426,7 +432,10 @@ in
(concatMapStringsSep ";" luaPackages.getLuaPath resolvedExtraLuaPackages)
];
neovimConfig = pkgs.neovimUtils.makeNeovimConfig {
wrappedNeovim' = pkgs.wrapNeovimUnstable cfg.package {
withNodeJs = cfg.withNodeJs || cfg.coc.enable;
plugins = map suppressNotVimlConfig pluginsNormalized;
inherit (cfg)
extraPython3Packages
withPython3
@@ -434,34 +443,19 @@ in
withPerl
viAlias
vimAlias
extraName
autowrapRuntimeDeps
waylandSupport
;
withNodeJs = cfg.withNodeJs || cfg.coc.enable;
plugins = map suppressNotVimlConfig pluginsNormalized;
customRC = cfg.extraConfig;
neovimRcContent = cfg.extraConfig;
wrapperArgs =
cfg.extraWrapperArgs ++ extraMakeWrapperArgs ++ extraMakeWrapperLuaCArgs ++ extraMakeWrapperLuaArgs;
wrapRc = false;
};
wrappedNeovim' = pkgs.wrapNeovimUnstable cfg.package (
neovimConfig
// {
inherit (cfg)
extraName
autowrapRuntimeDeps
waylandSupport
withNodeJs
;
wrapperArgs =
neovimConfig.wrapperArgs
++ cfg.extraWrapperArgs
++ extraMakeWrapperArgs
++ extraMakeWrapperLuaCArgs
++ extraMakeWrapperLuaArgs;
wrapRc = false;
}
);
in
{
programs.neovim = {
generatedConfigViml = neovimConfig.neovimRcContent;
generatedConfigViml = cfg.extraConfig;
generatedConfigs =
let
@@ -484,29 +478,28 @@ in
shellAliases = mkIf cfg.vimdiffAlias { vimdiff = "nvim -d"; };
};
xdg.configFile =
let
hasLuaConfig = lib.hasAttr "lua" config.programs.neovim.generatedConfigs;
luaRcContent =
lib.optionalString (
wrappedNeovim'.initRc != ""
) "vim.cmd [[source ${pkgs.writeText "nvim-init-home-manager.vim" wrappedNeovim'.initRc}]]\n"
+ config.programs.neovim.extraLuaConfig
+ lib.optionalString hasLuaConfig config.programs.neovim.generatedConfigs.lua;
in
lib.mkMerge (
# writes runtime
(map (x: x.runtime) pluginsNormalized)
++ [
{
"nvim/init.lua" = mkIf (luaRcContent != "") { text = luaRcContent; };
programs.neovim.extraLuaConfig = lib.mkMerge [
(lib.mkIf (wrappedNeovim'.initRc != "") (
lib.mkBefore "vim.cmd [[source ${pkgs.writeText "nvim-init-home-manager.vim" wrappedNeovim'.initRc}]]"
))
(lib.mkIf (lib.hasAttr "lua" cfg.generatedConfigs) (lib.mkAfter cfg.generatedConfigs.lua))
];
"nvim/coc-settings.json" = mkIf cfg.coc.enable {
source = jsonFormat.generate "coc-settings.json" cfg.coc.settings;
};
}
]
);
xdg.configFile = lib.mkMerge (
# writes runtime
(map (x: x.runtime) pluginsNormalized)
++ [
{
"nvim/init.lua" = mkIf (cfg.extraLuaConfig != "") {
text = cfg.extraLuaConfig;
};
"nvim/coc-settings.json" = mkIf cfg.coc.enable {
source = jsonFormat.generate "coc-settings.json" cfg.coc.settings;
};
}
]
);
}
);
}

View File

@@ -66,10 +66,7 @@ in
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = pkgs.stdenv.hostPlatform.isLinux;
message = "niriswitcher is only available on Linux.";
}
(lib.hm.assertions.assertPlatform "programs.niriswitcher" pkgs lib.platforms.linux)
];
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];

View File

@@ -133,7 +133,7 @@ in
The attribute name becomes the command filename, and the value is either:
- Inline content as a string
- A path to a file containing the command content
Commands are stored in {file}`$XDG_CONFIG_HOME/.config/opencode/command/` directory.
Commands are stored in {file}`$XDG_CONFIG_HOME/opencode/command/` directory.
'';
example = lib.literalExpression ''
{
@@ -162,7 +162,7 @@ in
The attribute name becomes the agent filename, and the value is either:
- Inline content as a string
- A path to a file containing the agent content
Agents are stored in {file}`$XDG_CONFIG_HOME/.config/opencode/agent/` directory.
Agents are stored in {file}`$XDG_CONFIG_HOME/opencode/agent/` directory.
'';
example = lib.literalExpression ''
{
@@ -183,6 +183,49 @@ in
'';
};
skills = lib.mkOption {
type = lib.types.either (lib.types.attrsOf (lib.types.either lib.types.lines lib.types.path)) lib.types.path;
default = { };
description = ''
Custom agent skills for opencode.
This option can either be:
- An attribute set defining skills
- A path to a directory containing multiple skill folders
If an attribute set is used, the attribute name becomes the skill directory name,
and the value is either:
- Inline content as a string (creates `opencode/skill/<name>/SKILL.md`)
- A path to a file (creates `opencode/skill/<name>/SKILL.md`)
- A path to a directory (creates `opencode/skill/<name>/` with all files)
If a path is used, it is expected to contain one folder per skill name, each
containing a {file}`SKILL.md`. The directory is symlinked to
{file}`$XDG_CONFIG_HOME/opencode/skill/`.
See <https://opencode.ai/docs/skills/> for the documentation.
'';
example = lib.literalExpression ''
{
git-release = '''
---
name: git-release
description: Create consistent releases and changelogs
---
## What I do
- Draft release notes from merged PRs
- Propose a version bump
- Provide a copy-pasteable `gh release create` command
''';
# A skill can also be a directory containing SKILL.md and other files.
data-analysis = ./skills/data-analysis;
}
'';
};
themes = mkOption {
type = lib.types.attrsOf (lib.types.either jsonFormat.type lib.types.path);
default = { };
@@ -199,6 +242,13 @@ in
};
config = mkIf cfg.enable {
assertions = [
{
assertion = !lib.isPath cfg.skills || lib.pathIsDirectory cfg.skills;
message = "`programs.opencode.skills` must be a directory when set to a path";
}
];
home.packages = mkIf (cfg.package != null) [ cfg.package ];
xdg.configFile = {
@@ -227,6 +277,11 @@ in
text = cfg.rules;
})
);
"opencode/skill" = mkIf (lib.isPath cfg.skills) {
source = cfg.skills;
recursive = true;
};
}
// lib.mapAttrs' (
name: content:
@@ -240,6 +295,18 @@ in
if lib.isPath content then { source = content; } else { text = content; }
)
) cfg.agents
// lib.mapAttrs' (
name: content:
if lib.isPath content && lib.pathIsDirectory content then
lib.nameValuePair "opencode/skill/${name}" {
source = content;
recursive = true;
}
else
lib.nameValuePair "opencode/skill/${name}/SKILL.md" (
if lib.isPath content then { source = content; } else { text = content; }
)
) (if builtins.isAttrs cfg.skills then cfg.skills else { })
// lib.mapAttrs' (
name: content:
lib.nameValuePair "opencode/themes/${name}.json" (

View File

@@ -30,44 +30,42 @@ let
mapAttrsToList (name: value: ''${name}="${lib.escape [ ''"'' "\\" ] (toString value)}"'') envStr
);
bindOptions = {
address = mkOption {
type = types.str;
default = "localhost";
example = "example.org";
description = "The address where to bind the port.";
};
port = mkOption {
type = types.nullOr types.port;
default = null;
example = 8080;
description = "Specifies port number to bind on bind address.";
};
};
dynamicForwardModule = types.submodule { options = bindOptions; };
forwardModule = types.submodule {
options = {
bind = bindOptions;
host = {
mkAddressPortModule =
{
actionType,
nullableAddress ? actionType == "forward",
}:
types.submodule {
options = {
address = mkOption {
type = types.nullOr types.str;
default = null;
type = if nullableAddress then types.nullOr types.str else types.str;
default = if nullableAddress then null else "localhost";
example = "example.org";
description = "The address where to forward the traffic to.";
description = "The address to ${actionType} to.";
};
port = mkOption {
type = types.nullOr types.port;
default = null;
example = 80;
description = "Specifies port number to forward the traffic to.";
example = 8080;
description = "Specifies port number to ${actionType} to.";
};
};
};
dynamicForwardModule = mkAddressPortModule { actionType = "bind"; };
forwardModule = types.submodule {
options = {
bind = mkOption {
type = mkAddressPortModule { actionType = "bind"; };
description = "Local port binding options";
};
host = mkOption {
type = mkAddressPortModule { actionType = "forward"; };
description = "Host port binding options";
};
};
};
matchBlockModule = types.submodule {
@@ -383,6 +381,18 @@ let
example = "10m";
description = "Whether control socket should remain open in the background.";
};
kexAlgorithms = mkOption {
type = types.nullOr (types.listOf types.str);
default = null;
example = [
"curve25519-sha256@libssh.org"
"diffie-hellman-group-exchange-sha256"
];
description = ''
Specifies the available KEX (Key Exchange) algorithms.
'';
};
};
# config.host = mkDefault dagName;
@@ -430,6 +440,9 @@ let
++ map (f: " LocalForward" + addressPort f.bind + addressPort f.host) cf.localForwards
++ map (f: " RemoteForward" + addressPort f.bind + addressPort f.host) cf.remoteForwards
++ map (f: " DynamicForward" + addressPort f) cf.dynamicForwards
++ optional (
cf.kexAlgorithms != null
) " KexAlgorithms ${builtins.concatStringsSep "," cf.kexAlgorithms}"
++ [
(lib.generators.toKeyValue {
mkKeyValue = lib.generators.mkKeyValueDefault { } " ";

View File

@@ -12,6 +12,7 @@ let
packageVersion = if cfg.package != null then lib.getVersion cfg.package else null;
themeIsToml = lib.versionAtLeast packageVersion "0.15.0";
versionPost0_17 = lib.versionAtLeast packageVersion "0.17.0";
in
{
meta.maintainers = [ lib.maintainers.leiserfg ];
@@ -43,7 +44,12 @@ in
useLayerShell = lib.mkOption {
type = lib.types.bool;
default = true;
description = "If vicinae should use the layer shell";
description = ''
Whether vicinae should use the layer shell.
If you are using version 0.17 or newer, you should use
{option}.programs.vicinae.settings.launcher_window.layer_shell.enabled = false
instead.
'';
};
extensions = lib.mkOption {
@@ -127,27 +133,22 @@ in
settings = lib.mkOption {
inherit (jsonFormat) type;
default = { };
description = "Settings written as JSON to `~/.config/vicinae/vicinae.json.";
example = lib.literalExpression ''
{
faviconService = "twenty";
font = {
size = 10;
};
popToRootOnClose = false;
rootSearch = {
searchFiles = false;
};
favicon_service = "twenty";
font.normal.size = 10;
pop_to_root_on_close=false;
search_files_in_root= false;
theme = {
name = "vicinae-dark";
};
window = {
csd = true;
opacity = 0.95;
rounding = 10;
dark.name = "vicinae-dark";
light.name = "vicinae-light";
};
}
'';
description = ''
Settings written as JSON to {file}`~/.config/vicinae/settings.json`.
See {command}`vicinae config default`.
'';
};
};
@@ -158,6 +159,10 @@ in
assertion = cfg.systemd.enable -> cfg.package != null;
message = "{option}programs.vicinae.systemd.enable requires non null {option}programs.vicinae.package";
}
{
assertion = !cfg.useLayerShell -> !versionPost0_17;
message = ''After version 0.17, if you want to explicitly disable the use of layer shell, you need to set {option}.programs.vicinae.settings.launcher_window.layer_shell.enabled = false.'';
}
];
lib.vicinae.mkExtension = (
{
@@ -223,10 +228,11 @@ in
source = themeFormat.generate "vicinae-${name}-theme" theme;
}
) cfg.themes;
settingsPath = if versionPost0_17 then "vicinae/settings.json" else "vicinae/vicinae.json";
in
{
configFile = {
"vicinae/vicinae.json" = lib.mkIf (cfg.settings != { }) {
"${settingsPath}" = lib.mkIf (cfg.settings != { }) {
source = jsonFormat.generate "vicinae-settings" cfg.settings;
};
}
@@ -250,14 +256,16 @@ in
PartOf = [ cfg.systemd.target ];
};
Service = {
EnvironmentFile = pkgs.writeText "vicinae-env" ''
USE_LAYER_SHELL=${if cfg.useLayerShell then builtins.toString 1 else builtins.toString 0}
'';
Type = "simple";
ExecStart = "${lib.getExe' cfg.package "vicinae"} server";
Restart = "always";
RestartSec = 5;
KillMode = "process";
EnvironmentFile = lib.mkIf (!versionPost0_17) (
pkgs.writeText "vicinae-env" ''
USE_LAYER_SHELL=${if cfg.useLayerShell then builtins.toString 1 else builtins.toString 0}
''
);
};
Install = lib.mkIf cfg.systemd.autoStart {
WantedBy = [ cfg.systemd.target ];

View File

@@ -9,12 +9,27 @@ let
cfg = config.programs.yt-dlp;
renderSettings = lib.mapAttrsToList (
configAtom =
with types;
oneOf [
bool
int
str
];
renderSingleOption =
name: value:
if lib.isBool value then
if value then "--${name}" else "--no-${name}"
else
"--${name} ${toString value}"
"--${name} ${toString value}";
renderSettings = lib.mapAttrsToList (
name: value:
if lib.isList value then
lib.concatStringsSep "\n" (map (renderSingleOption name) value)
else
renderSingleOption name value
);
in
@@ -27,13 +42,7 @@ in
package = lib.mkPackageOption pkgs "yt-dlp" { };
settings = mkOption {
type =
with types;
attrsOf (oneOf [
bool
int
str
]);
type = with types; attrsOf (either configAtom (listOf configAtom));
default = { };
example = lib.literalExpression ''
{
@@ -42,6 +51,10 @@ in
sub-langs = "all";
downloader = "aria2c";
downloader-args = "aria2c:'-c -x8 -s8 -k1M'";
color = [
"stdout:no_color"
"stderr:always"
];
}
'';
description = ''

View File

@@ -2,6 +2,7 @@
config,
lib,
pkgs,
options,
...
}:
let
@@ -100,9 +101,18 @@ in
};
dotDir = mkOption {
default = homeDir;
defaultText = "`config.home.homeDirectory`";
example = "`\${config.xdg.configHome}/zsh`";
default =
if config.xdg.enable && lib.versionAtLeast config.home.stateVersion "26.05" then
"${config.xdg.configHome}/zsh"
else
homeDir;
defaultText = lib.literalExpression ''
if config.xdg.enable && lib.versionAtLeast config.home.stateVersion "26.05" then
"''${config.xdg.configHome}/zsh"
else
config.home.homeDirectory
'';
example = literalExpression ''"''${config.xdg.configHome}/zsh"'';
description = ''
Directory where the zsh configuration and more should be located,
relative to the users home directory. The default is the home
@@ -391,7 +401,24 @@ in
- config.xdg.dataHome (XDG data directory)
- config.xdg.cacheHome (XDG cache directory)
''
];
]
++
lib.optionals
(
config.xdg.enable
&& !lib.versionAtLeast config.home.stateVersion "26.05"
&& options.programs.zsh.dotDir.highestPrio >= 1500
)
[
''
The default value of `programs.zsh.dotDir` will change in future versions.
You are currently using the legacy default (home directory) because `home.stateVersion` is less than "26.05".
To silence this warning and lock in the current behavior, set:
programs.zsh.dotDir = config.home.homeDirectory;
To adopt the new behavior (XDG config directory), set:
programs.zsh.dotDir = "''${config.xdg.configHome}/zsh";
''
];
}
(mkIf (cfg.envExtra != "") {
@@ -412,7 +439,7 @@ in
(mkIf (dotDirAbs != homeDir) {
home.file."${dotDirRel}/.zshenv".text = ''
export ZDOTDIR=${dotDirAbs}
${config.lib.zsh.export "ZDOTDIR" dotDirAbs}
'';
# When dotDir is set, only use ~/.zshenv to source ZDOTDIR/.zshenv,
@@ -420,7 +447,7 @@ in
# already set correctly (by e.g. spawning a zsh inside a zsh), all env
# vars still get exported
home.file.".zshenv".text = ''
source ${dotDirAbs}/.zshenv
source ${lib.escapeShellArg "${dotDirAbs}/.zshenv"}
'';
})

View File

@@ -1,9 +1,12 @@
{ config, lib, ... }:
let
cfg = config.programs.zsh;
stripSlash = lib.removeSuffix "/";
in
rec {
homeDir = config.home.homeDirectory;
# Raw home directory, no trailing slash.
homeDir = stripSlash config.home.homeDirectory;
/*
Escape a path string for shell usage and remove trailing slashes.
@@ -18,10 +21,11 @@ rec {
cleanPathStr "/path/to/dir/" => "'/path/to/dir'"
cleanPathStr "path with spaces" => "'path with spaces'"
*/
cleanPathStr = pathStr: lib.escapeShellArg (lib.removeSuffix "/" pathStr);
cleanPathStr = pathStr: lib.escapeShellArg (stripSlash pathStr);
/*
Convert an absolute path to a relative path by stripping the home directory prefix.
Returns the raw path (unescaped) for use in home.file keys.
This function converts absolute paths within the home directory to relative paths
by removing the home directory prefix. Paths already relative are returned as-is.
@@ -30,19 +34,22 @@ rec {
Type: String -> String
Example:
mkRelPathStr "/home/user/config" => "'config'"
mkRelPathStr "config" => "'config'"
mkRelPathStr "/home/user/config" => "config"
mkRelPathStr "config" => "config"
mkRelPathStr "/home/user" => "."
mkRelPathStr "/etc/config" => <error>
*/
mkRelPathStr =
pathStr:
# is already a relative path
if (!lib.hasPrefix "/" pathStr) then
cleanPathStr pathStr
# is an absolute path within home dir
else if (lib.hasPrefix homeDir pathStr) then
cleanPathStr (lib.removePrefix "${homeDir}/" pathStr)
# is an absolute path not in home dir
let
normPath = stripSlash pathStr;
in
if (!lib.hasPrefix "/" normPath) then
normPath
else if normPath == homeDir then
"."
else if (lib.hasPrefix "${homeDir}/" normPath) then
lib.removePrefix "${homeDir}/" normPath
else
throw ''
Attempted to convert an absolute path not within home directory to a
@@ -54,47 +61,47 @@ rec {
'';
/*
Convert a relative path to an absolute path by prepending the home directory.
Convert a relative path to an absolute path.
Returns RAW path (unescaped).
This function ensures paths are absolute by prepending the home directory
to relative paths. Already absolute paths are returned unchanged (after cleaning).
This function does NOT support shell variables.
Type: String -> String
Example:
mkAbsPathStr "config" => "'/home/user/config'"
mkAbsPathStr "/absolute/path" => "'/absolute/path'"
mkAbsPathStr "config" => "/home/user/config"
mkAbsPathStr "/absolute/path" => "/absolute/path"
*/
mkAbsPathStr =
pathStr: cleanPathStr ((lib.optionalString (!lib.hasPrefix "/" pathStr) "${homeDir}/") + pathStr);
pathStr:
let
normPath = stripSlash pathStr;
in
if lib.hasPrefix "/" normPath then normPath else "${homeDir}/${normPath}";
/*
Convert a path to absolute form while preserving shell variables for runtime expansion.
Convert a path to absolute form while preserving shell variables.
Returns RAW path (unescaped) unless vars are present (then preserves vars).
This function handles both literal paths and shell variable expressions.
Shell variables (containing '$') are preserved unescaped to allow runtime expansion.
Literal paths are made absolute and properly escaped for shell usage.
Literal paths are made absolute.
Type: String -> String
Example:
mkShellVarPathStr "config" => "'/home/user/config'"
mkShellVarPathStr "config" => "/home/user/config"
mkShellVarPathStr "$HOME/config" => "$HOME/config"
mkShellVarPathStr "\${XDG_CONFIG_HOME:-$HOME/.config}/app" => "\${XDG_CONFIG_HOME:-$HOME/.config}/app"
*/
mkShellVarPathStr =
pathStr:
let
cleanPath = lib.removeSuffix "/" pathStr;
hasShellVars = lib.hasInfix "$" cleanPath;
normPath = stripSlash pathStr;
hasShellVars = lib.hasInfix "$" normPath;
in
if hasShellVars then
# Does not escape shell variables, allowing them to be expanded at runtime
cleanPath
else
# For literal paths, make them absolute if needed and escape them
cleanPathStr ((lib.optionalString (!lib.hasPrefix "/" cleanPath) "${homeDir}/") + cleanPath);
if hasShellVars then normPath else mkAbsPathStr normPath;
dotDirAbs = mkAbsPathStr cfg.dotDir;
dotDirRel = mkRelPathStr cfg.dotDir;
@@ -107,5 +114,5 @@ rec {
Type: String
*/
pluginsDir = dotDirAbs + (lib.optionalString (homeDir == dotDirAbs) "/.zsh") + "/plugins";
pluginsDir = dotDirAbs + (lib.optionalString (mkRelPathStr cfg.dotDir == ".") "/.zsh") + "/plugins";
}

View File

@@ -136,7 +136,7 @@ let
);
in
{
meta.maintainers = with lib.maintainers; [ foo-dogsquared ];
meta.maintainers = [ ];
options.services.activitywatch = {
enable = lib.mkEnableOption "ActivityWatch, an automated time tracker";

View File

@@ -117,6 +117,8 @@ in
systemd.user.services.easyeffects = {
Unit = {
Description = "Easyeffects daemon";
After = [ "graphical-session.target" ];
PartOf = [ "graphical-session.target" ];
};
Install.WantedBy = [ "graphical-session.target" ];

View File

@@ -107,10 +107,10 @@ in
'';
};
defaultEditor = mkOption rec {
defaultEditor = mkOption {
type = types.bool;
default = false;
example = !default;
example = true;
description = ''
Whether to configure {command}`emacsclient` as the default
editor using the {env}`EDITOR` and {env}`VISUAL`

View File

@@ -45,16 +45,18 @@ in
'';
example = lib.literalExpression ''
{
ipc = "on";
splash = false;
splash_offset = 2.0;
preload =
[ "/share/wallpapers/buttons.png" "/share/wallpapers/cat_pacman.png" ];
wallpaper = [
"DP-3,/share/wallpapers/buttons.png"
"DP-1,/share/wallpapers/cat_pacman.png"
{
monitor = "DP-3";
path = "/share/wallpapers/buttons.png";
fit_mode = "tile";
}
{
monitor = "DP-1";
path = "/share/wallpapers/cat_pacman.png";
}
];
}
'';

View File

@@ -29,7 +29,7 @@ in
default = { };
description = ''
Configuration settings for hyprshell. All the avaiblable
options can be found here: <https://github.com/H3rmt/hyprshell/blob/hyprshell-release/CONFIGURE.md#config-options>
options can be found here: <https://github.com/H3rmt/hyprshell/blob/hyprshell-release/docs/CONFIGURE.md#config-options>
'';
};
@@ -38,7 +38,7 @@ in
default = "";
description = ''
CSS file for customizing hyprshell. All the available
options can be found here: <https://github.com/H3rmt/hyprshell/blob/hyprshell-release/CONFIGURE.md#css>
options can be found here: <https://github.com/H3rmt/hyprshell/blob/hyprshell-release/docs/CONFIGURE.md#css>
'';
};

View File

@@ -8,7 +8,6 @@ let
inherit (lib) mkOption types;
cfg = config.services.linux-wallpaperengine;
in
{
meta.maintainers = [ lib.hm.maintainers.ckgxrg ];
@@ -105,10 +104,10 @@ in
config = lib.mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "services.linux-wallpaperengine" pkgs lib.platforms.linux)
({
{
assertion = cfg.wallpapers != null;
message = "linux-wallpaperengine: You must set at least one wallpaper";
})
}
];
home.packages = [ cfg.package ];
@@ -121,7 +120,7 @@ in
lib.cli.toGNUCommandLine { } {
screen-root = each.monitor;
inherit (each) scaling fps;
silent = each.audio.silent;
inherit (each.audio) silent;
noautomute = !each.audio.automute;
no-audio-processing = !each.audio.processing;
}
@@ -138,11 +137,12 @@ in
PartOf = [ "graphical-session.target" ];
};
Service = {
ExecStart =
lib.getExe cfg.package
+ (lib.optionalString (cfg.assetsPath != null) " --assets-dir ${cfg.assetsPath} ")
+ (lib.optionalString (cfg.clamping != null) "--clamping ${cfg.clamping} ")
+ (lib.strings.concatStringsSep " " args);
ExecStart = lib.concatStringsSep " " (
[ (lib.getExe cfg.package) ]
++ lib.optional (cfg.assetsPath != null) "--assets-dir ${cfg.assetsPath}"
++ lib.optional (cfg.clamping != null) "--clamping ${cfg.clamping}"
++ args
);
Restart = "on-failure";
};
Install = {

View File

@@ -75,7 +75,7 @@ let
in
{
meta.maintainers = [ lib.maintainers.foo-dogsquared ];
meta.maintainers = [ ];
options.services.mopidy = {
enable = lib.mkEnableOption "Mopidy music player daemon";

View File

@@ -22,6 +22,15 @@ in
package = lib.mkPackageOption pkgs "mpd" { };
enableSessionVariables = mkOption {
type = types.bool;
default = true;
description = ''
Whether to set {env}`MPD_HOST` {env}`MPD_PORT` environment variables
according to {option}`services.mpd.network`.
'';
};
musicDirectory = mkOption {
type = with types; either path str;
defaultText = lib.literalExpression ''
@@ -155,7 +164,13 @@ in
);
in
mkIf cfg.enable {
home.packages = [ cfg.package ];
home = {
packages = [ cfg.package ];
sessionVariables = mkIf cfg.enableSessionVariables {
MPD_HOST = mkIf (cfg.network.listenAddress != "any") cfg.network.listenAddress;
MPD_PORT = builtins.toString cfg.network.port;
};
};
services.mpd = lib.mkMerge [
(mkIf (lib.versionAtLeast config.home.stateVersion "22.11" && config.xdg.userDirs.enable) {

View File

@@ -103,7 +103,7 @@ let
settingsFormat = recollConfFormat { };
in
{
meta.maintainers = [ lib.maintainers.foo-dogsquared ];
meta.maintainers = [ ];
options.services.recoll = {
enable = lib.mkEnableOption "Recoll file index service";

View File

@@ -57,31 +57,33 @@ in
else
"$XDG_RUNTIME_DIR/${cfg.socket}";
# Preserve $SSH_AUTH_SOCK only if it stems from a forwarded agent,
# which is the case if both $SSH_AUTH_SOCK and $SSH_CONNECTION are
# set.
bashIntegration = ''
if [ -z "$SSH_AUTH_SOCK" ]; then
if [ -z "$SSH_AUTH_SOCK" -o -z "$SSH_CONNECTION" ]; then
export SSH_AUTH_SOCK=${socketPath}
fi
'';
fishIntegration = ''
if test -z "$SSH_AUTH_SOCK"
if test -z "$SSH_AUTH_SOCK"; or test -z "$SSH_CONNECTION"
set -x SSH_AUTH_SOCK ${socketPath}
end
'';
nushellIntegration =
if pkgs.stdenv.isDarwin then
''
if "SSH_AUTH_SOCK" not-in $env {
$env.SSH_AUTH_SOCK = $"(${lib.getExe pkgs.getconf} DARWIN_USER_TEMP_DIR)/${cfg.socket}"
}
''
else
''
if "SSH_AUTH_SOCK" not-in $env {
$env.SSH_AUTH_SOCK = $"($env.XDG_RUNTIME_DIR)/${cfg.socket}"
}
'';
let
unsetOrEmpty = var: ''("${var}" not-in $env) or ($env.${var} | is-empty)'';
socketPath =
if pkgs.stdenv.isDarwin then
''$"(${lib.getExe pkgs.getconf} DARWIN_USER_TEMP_DIR)/${cfg.socket}"''
else
''$"($env.XDG_RUNTIME_DIR)/${cfg.socket}"'';
in
''
if ${unsetOrEmpty "SSH_AUTH_SOCK"} or ${unsetOrEmpty "SSH_CONNECTION"} {
$env.SSH_AUTH_SOCK = ${socketPath}
}
'';
in
{
# $SSH_AUTH_SOCK has to be set early since other tools rely on it

View File

@@ -430,10 +430,7 @@ in
# Do not install any user services if username is root.
config = mkIf (cfg.enable && config.home.username != "root") {
assertions = [
{
assertion = pkgs.stdenv.isLinux;
message = "This module is only available on Linux.";
}
(lib.hm.assertions.assertPlatform "systemd" pkgs lib.platforms.linux)
];
xdg.configFile = mkMerge [

View File

@@ -274,6 +274,26 @@ in
sed "s|${pkg.out}|$out|g" "$src" > "$dsk"
done
# Patch systemd user services
for svc in "$out/share/systemd/user"/*.service ; do
if ! grep -q "${pkg.out}" "$svc"; then
continue
fi
src="$(readlink "$svc")"
rm "$svc"
sed "s|${pkg.out}|$out|g" "$src" > "$svc"
done
# Patch DBus services
for svc in "$out/share/dbus-1/services"/*.service ; do
if ! grep -q "${pkg.out}" "$svc"; then
continue
fi
src="$(readlink "$svc")"
rm "$svc"
sed "s|${pkg.out}|$out|g" "$src" > "$svc"
done
shopt -u nullglob # Revert nullglob back to its normal default state
'';
}))

View File

@@ -130,6 +130,13 @@ let
stateVersion = lib.mkDefault "18.09";
};
# NOTE: Added 2025-12-27
# Avoid option change deprecation warning
# Remove after deprecation period
programs.zsh.dotDir = lib.mkIf (config.home.stateVersion == "18.09") (
lib.mkDefault "/home/hm-user"
);
# Avoid including documentation since this will cause
# unnecessary rebuilds of the tests.
manual.manpages.enable = lib.mkDefault false;

View File

@@ -1,4 +1,5 @@
{
generators-hyprconf = ./tohyprconf.nix;
generators-tokdl = ./tokdl.nix;
generators-toscfg-empty = ./toscfg-empty.nix;
generators-toscfg-example = ./toscfg-example.nix;

View File

@@ -0,0 +1,93 @@
$important=123
attrs-section {
bool=true
float=0.800000
int=5
null=null
string=abc
}
combined-attrs-nested-section {
a {
a=123
}
a {
b=123
}
a {
c=123
}
b {
a=123
}
b {
b=123
}
b {
c=123
}
}
combined-list-nested-section {
b {
c {
abc=123
}
}
}
combined-list-nested-section {
bar {
baz {
aaa=111
}
}
}
list-section=foo
list-section=bar
list-section=baz
list-with-strings-and-attrs=abc
list-with-strings-and-attrs {
a=123
}
list-with-strings-and-attrs=foo
list-with-strings-and-attrs {
b=321
}
nested-attrs-section {
a {
b {
c {
abc=123
}
}
}
foo {
bar {
baz {
aaa=111
}
}
}
}
nested-list-section {
a=123
}
nested-list-section {
b=123
}
nested-list-section {
c=123
}

View File

@@ -0,0 +1,70 @@
{ lib, ... }:
{
home.file."tohyprconf-result.txt".text = lib.hm.generators.toHyprconf {
attrs = rec {
"$important" = 123;
list-section = [
"foo"
"bar"
"baz"
];
attrs-section = {
string = "abc";
int = 5;
float = 0.8;
bool = true;
null = null;
};
nested-attrs-section = {
a = {
b = {
c = {
abc = 123;
};
};
};
foo = {
bar = {
baz = {
aaa = 111;
};
};
};
};
nested-list-section = [
{ a = 123; }
{ b = 123; }
{ c = 123; }
];
combined-list-nested-section = [
nested-attrs-section.a
nested-attrs-section.foo
];
combined-attrs-nested-section = {
a = nested-list-section;
b = nested-list-section;
};
list-with-strings-and-attrs = [
"abc"
{ a = 123; }
"foo"
{ b = 321; }
];
};
};
nmt.script = ''
assertFileContent \
home-files/tohyprconf-result.txt \
${./tohyprconf-result.txt}
'';
}

View File

@@ -2,4 +2,5 @@
lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux {
anyrun = ./basic-config.nix;
anyrun-empty-css = ./empty-css.nix;
}

View File

@@ -0,0 +1,10 @@
{
programs.anyrun = {
enable = true;
config.plugins = [ ];
};
nmt.script = ''
assertPathNotExists home-files/.config/anyrun/style.css
'';
}

View File

@@ -3,4 +3,5 @@
gpg-mutable-keyfiles = ./mutable-keyfiles.nix;
gpg-multiple-keys-trust = ./multiple-keys-trust.nix;
gpg-override-defaults = ./override-defaults.nix;
gpg-other-settings = ./other-settings.nix;
}

View File

@@ -12,7 +12,7 @@
{
source = realPkgs.fetchurl {
url = "https://keys.openpgp.org/pks/lookup?op=get&options=mr&search=0x44CF42371ADF842E12F116EAA9D3F98FCCF5460B";
hash = "sha256-bSluCZh6ijwppigk8iF2BwWKZgq1WDbIjyYQRK772dM=";
hash = "sha256-csrFDI6QSPfNN+adOPEAupAtspYNBCybFZExvVS+vRY=";
};
trust = 1; # "unknown"
}

View File

@@ -0,0 +1,2 @@
keyserver ldaps://ldap.example.com
use-tor

View File

@@ -0,0 +1,3 @@
cipher-algo AES256
validation-model steed
with-md5-fingerprint

View File

@@ -0,0 +1,3 @@
application-priority openpgp p15 sc-hsm nks geldkarte dinsig
disable-ccid
reader-port 32769

View File

@@ -0,0 +1,32 @@
{
programs.gpg = {
enable = true;
scdaemonSettings = {
disable-ccid = true;
reader-port = "32769";
application-priority = "openpgp p15 sc-hsm nks geldkarte dinsig";
};
dirmngrSettings = {
use-tor = true;
keyserver = "ldaps://ldap.example.com";
};
gpgsmSettings = {
cipher-algo = "AES256";
with-md5-fingerprint = true;
validation-model = "steed";
};
};
nmt.script = ''
assertFileExists home-files/.gnupg/scdaemon.conf
assertFileExists home-files/.gnupg/dirmngr.conf
assertFileExists home-files/.gnupg/gpgsm.conf
assertFileContent home-files/.gnupg/scdaemon.conf ${./other-scdaemon.conf}
assertFileContent home-files/.gnupg/dirmngr.conf ${./other-dirmngr.conf}
assertFileContent home-files/.gnupg/gpgsm.conf ${./other-gpgsm.conf}
'';
}

View File

@@ -1,7 +1,6 @@
cert-digest-algo SHA512
charset utf-8
default-preference-list SHA512 SHA384 SHA256 AES256 AES192 AES ZLIB BZIP2 ZIP Uncompressed
fixed-list-mode
display-charset utf-8
keyid-format 0xlong
list-options show-uid-validity
@@ -16,6 +15,5 @@ s2k-digest-algo SHA512
throw-keyids
trusted-key 0xXXXXXXXXXXXXX
trusted-key 0xYYYYYYYYYYYYY
use-agent
verify-options show-uid-validity
with-fingerprint

View File

@@ -5,6 +5,9 @@ identity = "hm@example.com"
root_mailbox = "/home/hm-user/Mail/hm@example.com"
subscribed_mailboxes = ["Inbox", "Sent", "Trash", "Drafts"]
[accounts."hm@example.com".listing]
index_style = "compact"
[accounts."hm@example.com".mailboxes]
[accounts."hm@example.com".send_mail]

View File

@@ -16,7 +16,12 @@
};
accounts.email.accounts = {
"hm@example.com" = {
meli.enable = true;
meli = {
enable = true;
settings = {
listing.index_style = "compact";
};
};
smtp.port = 1848;
};
};

View File

@@ -9,6 +9,10 @@
opencode-agents-path = ./agents-path.nix;
opencode-commands-path = ./commands-path.nix;
opencode-mixed-content = ./mixed-content.nix;
opencode-skills-inline = ./skills-inline.nix;
opencode-skills-path = ./skills-path.nix;
opencode-skills-directory = ./skills-directory.nix;
opencode-skills-bulk-directory = ./skills-bulk-directory.nix;
opencode-themes-inline = ./themes-inline.nix;
opencode-themes-path = ./themes-path.nix;
opencode-mcp-integration = ./mcp-integration.nix;

View File

@@ -0,0 +1,10 @@
---
name: git-release
description: Create consistent releases and changelogs
---
## What I do
- Draft release notes from merged PRs
- Propose a version bump
- Provide a copy-pasteable `gh release create` command

View File

@@ -0,0 +1,9 @@
---
name: pdf-processing
description: Extract text and tables from PDF files
---
## What I do
- Extract text from PDFs
- Identify tables and structured data

View File

@@ -0,0 +1,9 @@
---
name: data-analysis
description: Help analyze datasets and results
---
## What I do
- Summarize datasets
- Suggest charts and metrics

View File

@@ -0,0 +1 @@
extra fixture file

View File

@@ -0,0 +1,15 @@
{
programs.opencode = {
enable = true;
skills = ./skills-bulk;
};
nmt.script = ''
assertFileExists home-files/.config/opencode/skill/git-release/SKILL.md
assertFileExists home-files/.config/opencode/skill/pdf-processing/SKILL.md
assertFileContent home-files/.config/opencode/skill/git-release/SKILL.md \
${./skills-bulk/git-release/SKILL.md}
assertFileContent home-files/.config/opencode/skill/pdf-processing/SKILL.md \
${./skills-bulk/pdf-processing/SKILL.md}
'';
}

View File

@@ -0,0 +1,6 @@
---
name: git-release
description: Create consistent releases and changelogs
---
This is the bulk skillsDir fixture for git-release.

View File

@@ -0,0 +1,6 @@
---
name: pdf-processing
description: Extract text and tables from PDF files
---
This is the bulk skillsDir fixture for pdf-processing.

View File

@@ -0,0 +1,15 @@
{
programs.opencode = {
enable = true;
skills = {
data-analysis = ./skill-dir/data-analysis;
};
};
nmt.script = ''
assertFileExists home-files/.config/opencode/skill/data-analysis/SKILL.md
assertFileExists home-files/.config/opencode/skill/data-analysis/notes.txt
assertFileContent home-files/.config/opencode/skill/data-analysis/SKILL.md \
${./skill-dir/data-analysis/SKILL.md}
'';
}

View File

@@ -0,0 +1,25 @@
{
programs.opencode = {
enable = true;
skills = {
git-release = ''
---
name: git-release
description: Create consistent releases and changelogs
---
## What I do
- Draft release notes from merged PRs
- Propose a version bump
- Provide a copy-pasteable `gh release create` command
'';
};
};
nmt.script = ''
assertFileExists home-files/.config/opencode/skill/git-release/SKILL.md
assertFileContent home-files/.config/opencode/skill/git-release/SKILL.md \
${./git-release-SKILL.md}
'';
}

View File

@@ -0,0 +1,14 @@
{
programs.opencode = {
enable = true;
skills = {
pdf-processing = ./pdf-processing-SKILL.md;
};
};
nmt.script = ''
assertFileExists home-files/.config/opencode/skill/pdf-processing/SKILL.md
assertFileContent home-files/.config/opencode/skill/pdf-processing/SKILL.md \
${./pdf-processing-SKILL.md}
'';
}

View File

@@ -15,6 +15,7 @@ Host xyz
RemoteForward [localhost]:8081 [10.0.0.2]:80
RemoteForward /run/user/1000/gnupg/S.gpg-agent.extra /run/user/1000/gnupg/S.gpg-agent
DynamicForward [localhost]:2839
KexAlgorithms sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,mlkem768x25519-sha256
Host ordered
Port 1

View File

@@ -34,6 +34,11 @@
host.address = "/run/user/1000/gnupg/S.gpg-agent";
}
];
kexAlgorithms = [
"sntrup761x25519-sha512"
"sntrup761x25519-sha512@openssh.com"
"mlkem768x25519-sha256"
];
dynamicForwards = [ { port = 2839; } ];
setEnv = {
FOO = "foo12";

View File

@@ -1,4 +1,5 @@
{ lib, pkgs, ... }:
lib.optionalAttrs (pkgs.stdenv.hostPlatform.isLinux) {
vicinae-pre17-settings = ./pre17-settings.nix;
vicinae-example-settings = ./example-settings.nix;
}

View File

@@ -8,7 +8,7 @@
programs.vicinae = {
enable = true;
systemd.enable = true;
useLayerShell = false;
settings = {
faviconService = "twenty";
font = {
@@ -80,11 +80,16 @@
];
};
test.asserts.assertions.expected = [
''After version 0.17, if you want to explicitly disable the use of layer shell, you need to set {option}.programs.vicinae.settings.launcher_window.layer_shell.enabled = false.''
];
nmt.script = ''
assertFileExists "home-files/.config/vicinae/vicinae.json"
assertFileExists "home-files/.config/vicinae/settings.json"
assertFileExists "home-files/.config/systemd/user/vicinae.service"
assertFileExists "home-files/.local/share/vicinae/themes/catppuccin-mocha.toml"
assertFileExists "home-files/.local/share/vicinae/extensions/gif-search/package.json"
assertFileExists "home-files/.local/share/vicinae/extensions/test-extension/package.json"
assertFileContent "home-files/.config/systemd/user/vicinae.service" ${./service.service}
'';
}

View File

@@ -0,0 +1,46 @@
{
pkgs,
config,
...
}:
{
programs.vicinae = {
enable = true;
systemd.enable = true;
package = pkgs.stdenv.mkDerivation {
pname = "fake-vicinae";
version = "0.10.0";
src = pkgs.emptyFile;
buildCommand = "mkdir -p $out";
meta = {
mainProgram = "vicinae";
};
};
settings = {
faviconService = "twenty";
font = {
size = 10;
};
popToRootOnClose = false;
rootSearch = {
searchFiles = false;
};
theme = {
name = "vicinae-dark";
};
window = {
csd = true;
opacity = 0.95;
rounding = 10;
};
};
};
nmt.script = ''
assertFileExists "home-files/.config/vicinae/vicinae.json"
assertFileExists "home-files/.config/systemd/user/vicinae.service"
assertFileContains "home-files/.config/systemd/user/vicinae.service" "EnvironmentFile"
'';
}

View File

@@ -0,0 +1,15 @@
[Install]
WantedBy=graphical-session.target
[Service]
ExecStart=@vicinae@/bin/vicinae server
KillMode=process
Restart=always
RestartSec=5
Type=simple
[Unit]
After=graphical-session.target
Description=Vicinae server daemon
Documentation=https://docs.vicinae.com
PartOf=graphical-session.target

View File

@@ -1,5 +1,4 @@
{ lib, pkgs, ... }:
lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux {
yt-dlp-simple-config = ./yt-dlp-simple-config.nix;
yt-dlp-extraConfig = ./yt-dlp-extraConfig.nix;
yt-dlp-config = ./yt-dlp-config.nix;
}

View File

@@ -1,3 +1,5 @@
--color stdout:no_color
--color stderr:always
--downloader aria2c
--downloader-args aria2c:'-c -x8 -s8 -k1M'
--no-embed-subs

View File

@@ -8,6 +8,10 @@
downloader = "aria2c";
downloader-args = "aria2c:'-c -x8 -s8 -k1M'";
trim-filenames = 30;
color = [
"stdout:no_color"
"stderr:always"
];
};
extraConfig = ''
--config-locations /home/user/.yt-dlp.conf
@@ -16,6 +20,6 @@
nmt.script = ''
assertFileExists home-files/.config/yt-dlp/config
assertFileContent home-files/.config/yt-dlp/config ${./yt-dlp-simple-config-expected}
assertFileContent home-files/.config/yt-dlp/config ${./yt-dlp-config-expected}
'';
}

View File

@@ -1,2 +0,0 @@
--config-locations /home/user/.yt-dlp.conf

View File

@@ -1,13 +0,0 @@
{
programs.yt-dlp = {
enable = true;
extraConfig = ''
--config-locations /home/user/.yt-dlp.conf
'';
};
nmt.script = ''
assertFileExists home-files/.config/yt-dlp/config
assertFileContent home-files/.config/yt-dlp/config ${./yt-dlp-extraConfig-expected}
'';
}

View File

@@ -3,6 +3,13 @@
zsh-aliases = ./aliases.nix;
zsh-dotdir-absolute = import ./dotdir.nix "absolute";
zsh-dotdir-default = import ./dotdir.nix "default";
zsh-dotdir-path-normalization-abs-no-slash = import ./dotdir.nix "abs-no-slash";
zsh-dotdir-path-normalization-abs-slash = import ./dotdir.nix "abs-slash";
zsh-dotdir-path-normalization-rel-no-slash = import ./dotdir.nix "rel-no-slash";
zsh-dotdir-path-normalization-rel-slash = import ./dotdir.nix "rel-slash";
zsh-dotdir-path-normalization-root-no-slash = import ./dotdir.nix "root-no-slash";
zsh-dotdir-path-normalization-root-slash = import ./dotdir.nix "root-slash";
zsh-dotdir-path-normalization-abs-space = import ./dotdir.nix "abs-space";
zsh-dotdir-relative = import ./dotdir.nix "relative";
zsh-dotdir-shell-variable = import ./dotdir.nix "shell-variable";
zsh-history-ignore-pattern = ./history-ignore-pattern.nix;
@@ -12,12 +19,15 @@
zsh-history-path-xdg-variable = import ./history-path.nix "xdg-variable";
zsh-history-path-zdotdir-variable = import ./history-path.nix "zdotdir-variable";
zsh-history-substring-search = ./history-substring-search.nix;
zsh-legacy-warning = ./legacy-warning.nix;
zsh-siteFunctions-mkcd = ./siteFunctions-mkcd.nix;
zsh-plugins = ./plugins.nix;
zsh-prezto = ./prezto.nix;
zsh-session-variables = ./session-variables.nix;
zsh-smart-formatting = ./smart-formatting.nix;
zsh-syntax-highlighting = ./syntax-highlighting.nix;
zsh-xdg-default = ./xdg-default.nix;
zsh-xdg-disabled = ./xdg-disabled.nix;
zsh-zprof = ./zprof.nix;
zshrc-contents-priorities = ./zshrc-content-priorities.nix;
}

View File

@@ -7,24 +7,46 @@ case:
}:
let
home = config.home.homeDirectory;
subDir = "subdir/subdir2";
dotDir =
dotDirCases = {
absolute = "${home}/${subDir}";
relative = subDir;
inherit (options.programs.zsh.dotDir) default;
shell-variable = "\${XDG_CONFIG_HOME:-$HOME/.config}/zsh";
# Path normalization cases
abs-no-slash = "${home}/subdir";
abs-slash = "${home}/subdir/";
rel-no-slash = "subdir";
rel-slash = "subdir/";
root-no-slash = "${home}";
root-slash = "${home}/";
abs-space = "${home}/subdir with space";
};
dotDir = dotDirCases.${case} or (abort "Unknown case: ${case}");
# Normalize absolute path to match module behavior (no trailing slash)
absDotDir =
let
subDir = "subdir/subdir2";
fullPath = if lib.hasPrefix "/" dotDir then dotDir else "${home}/${dotDir}";
in
if case == "absolute" then
"${home}/${subDir}"
else if case == "relative" then
subDir
else if case == "default" then
options.programs.zsh.dotDir.default
else if case == "shell-variable" then
"\${XDG_CONFIG_HOME:-\$HOME/.config}/zsh"
else
abort "Test condition not provided.";
lib.removeSuffix "/" fullPath;
absDotDir = lib.optionalString (!lib.hasPrefix home dotDir) "${home}/" + dotDir;
relDotDir = lib.removePrefix home dotDir;
# Calculate relative path for file location assertions
relDotDir =
let
# Use the normalized absDotDir to determine relative location
rawRel = lib.removePrefix home absDotDir;
in
if lib.hasPrefix "/" rawRel then lib.removePrefix "/" rawRel else rawRel;
isRelative = lib.elem case [
"relative"
"rel-no-slash"
"rel-slash"
];
in
{
config = {
@@ -33,33 +55,37 @@ in
inherit dotDir;
};
test.stubs.zsh = { };
test = {
stubs.zsh = { };
test.asserts.warnings.expected = lib.optionals (case == "relative") [
''
Using relative paths in programs.zsh.dotDir is deprecated and will be removed in a future release.
Current dotDir: subdir/subdir2
Consider using absolute paths or home-manager config options instead.
You can replace relative paths or environment variables with options like:
- config.home.homeDirectory (user's home directory)
- config.xdg.configHome (XDG config directory)
- config.xdg.dataHome (XDG data directory)
- config.xdg.cacheHome (XDG cache directory)
''
];
asserts = {
assertions.expected = lib.optionals (case == "shell-variable") [
''
programs.zsh.dotDir cannot contain shell variables as it is used for file creation at build time.
Current dotDir: ''${XDG_CONFIG_HOME:-''$HOME/.config}/zsh
Consider using an absolute path or home-manager config options instead.
You can replace shell variables with options like:
- config.home.homeDirectory (user's home directory)
- config.xdg.configHome (XDG config directory)
- config.xdg.dataHome (XDG data directory)
- config.xdg.cacheHome (XDG cache directory)
''
];
test.asserts.assertions.expected = lib.optionals (case == "shell-variable") [
''
programs.zsh.dotDir cannot contain shell variables as it is used for file creation at build time.
Current dotDir: ''${XDG_CONFIG_HOME:-''$HOME/.config}/zsh
Consider using an absolute path or home-manager config options instead.
You can replace shell variables with options like:
- config.home.homeDirectory (user's home directory)
- config.xdg.configHome (XDG config directory)
- config.xdg.dataHome (XDG data directory)
- config.xdg.cacheHome (XDG cache directory)
''
];
warnings.expected = lib.optionals isRelative [
''
Using relative paths in programs.zsh.dotDir is deprecated and will be removed in a future release.
Current dotDir: ${dotDir}
Consider using absolute paths or home-manager config options instead.
You can replace relative paths or environment variables with options like:
- config.home.homeDirectory (user's home directory)
- config.xdg.configHome (XDG config directory)
- config.xdg.dataHome (XDG data directory)
- config.xdg.cacheHome (XDG cache directory)
''
];
};
};
nmt.script =
if case == "shell-variable" then
@@ -70,17 +96,15 @@ in
else
lib.concatStringsSep "\n" [
# check dotDir entrypoint exists
"assertFileExists home-files/${relDotDir}/.zshenv"
"assertFileExists 'home-files/${if relDotDir == "" then "" else "${relDotDir}/"}.zshenv'"
# for non-default dotDir only:
(lib.optionalString (case != "default") ''
(lib.optionalString (absDotDir != home) ''
# check .zshenv in homeDirectory sources .zshenv in dotDir
assertFileRegex home-files/.zshenv \
"source [\"']\?${absDotDir}/.zshenv[\"']\?"
assertFileRegex home-files/.zshenv "source ${lib.escapeShellArg "${absDotDir}/.zshenv"}"
# check that .zshenv in dotDir exports ZDOTDIR
assertFileRegex home-files/${relDotDir}/.zshenv \
"export ZDOTDIR=[\"']\?${absDotDir}[\"']\?"
assertFileRegex 'home-files/${relDotDir}/.zshenv' "export ZDOTDIR=\"${absDotDir}\""
'')
];
};

View File

@@ -68,7 +68,7 @@ in
else if case == "zdotdir-variable" then
''
assertFileContains home-files/.config/zsh/.zshrc 'HISTFILE="$ZDOTDIR/.zsh_history"'
assertFileContains home-files/.config/zsh/.zshenv "export ZDOTDIR=${homeDir}/.config/zsh"
assertFileContains home-files/.config/zsh/.zshenv "export ZDOTDIR=\"${homeDir}/.config/zsh\""
''
else
''

View File

@@ -0,0 +1,29 @@
{
config = {
programs.zsh.enable = true;
xdg.enable = true;
# We use 25.05 to trigger the legacy warning (since < 26.05)
# AND to bypass the global fix in tests/default.nix (which checks for 18.09)
home.stateVersion = "25.05";
nmt.script = ''
assertFileExists home-files/.zshrc
# Verify that the warning is generated
# We check the evaluation output for the warning message
assertPathNotExists home-files/.config/zsh
'';
test.asserts.warnings.expected = [
''
The default value of `programs.zsh.dotDir` will change in future versions.
You are currently using the legacy default (home directory) because `home.stateVersion` is less than "26.05".
To silence this warning and lock in the current behavior, set:
programs.zsh.dotDir = config.home.homeDirectory;
To adopt the new behavior (XDG config directory), set:
programs.zsh.dotDir = "''${config.xdg.configHome}/zsh";
''
];
};
}

View File

@@ -0,0 +1,21 @@
{
config = {
programs.zsh.enable = true;
home.stateVersion = "26.05";
xdg.enable = true;
# With xdg.enable = true and new state version, dotDir should default to XDG config home
nmt.script = ''
assertFileExists home-files/.config/zsh/.zshenv
assertFileExists home-files/.config/zsh/.zshrc
# Verify global .zshenv points to the XDG location
assertFileExists home-files/.zshenv
assertFileRegex home-files/.zshenv "source /home/hm-user/.config/zsh/.zshenv"
# Verify ZDOTDIR is exported in the inner .zshenv
assertFileRegex home-files/.config/zsh/.zshenv "export ZDOTDIR=\"/home/hm-user/.config/zsh\""
'';
};
}

View File

@@ -0,0 +1,20 @@
{
config = {
programs.zsh.enable = true;
xdg.enable = false;
home.stateVersion = "26.05";
# With xdg.enable = false, dotDir should default to home directory regardless of state version
nmt.script = ''
assertFileExists home-files/.zshenv
assertFileExists home-files/.zshrc
# Should NOT exist in XDG location
assertPathNotExists home-files/.config/zsh
# Verify ZDOTDIR is NOT exported (or points to home if it is, but usually it isn't if dotDir is home)
assertFileNotRegex home-files/.zshenv "export ZDOTDIR="
'';
};
}

View File

@@ -13,6 +13,10 @@ animations {
enabled=true
}
bindm=$mod, mouse:272, movewindow
bindm=$mod, mouse:273, resizewindow
bindm=$mod ALT, mouse:272, resizewindow
decoration {
col.shadow=rgba(00000099)
shadow_offset=0 5
@@ -45,9 +49,6 @@ plugin {
dummy=plugin setting
}
}
bindm=$mod, mouse:272, movewindow
bindm=$mod, mouse:273, resizewindow
bindm=$mod ALT, mouse:272, resizewindow
# window resize
bind = $mod, S, submap, resize

View File

@@ -13,6 +13,10 @@ animations {
enabled=true
}
bindm=$mod, mouse:272, movewindow
bindm=$mod, mouse:273, resizewindow
bindm=$mod ALT, mouse:272, resizewindow
decoration {
col.shadow=rgba(00000099)
shadow_offset=0 5
@@ -48,9 +52,6 @@ plugin {
dummy=plugin setting
}
}
bindm=$mod, mouse:272, movewindow
bindm=$mod, mouse:273, resizewindow
bindm=$mod ALT, mouse:272, resizewindow
# window resize
bind = $mod, S, submap, resize

View File

@@ -10,4 +10,5 @@ input {
follow_mouse=1
kb_layout=ro
}
source=sourced.conf

View File

@@ -17,6 +17,7 @@ submap = reset
submap = resize
bind=, escape, submap, reset
bind=, return, submap, reset
binde=, right, resizeactive, 10 0
binde=, left, resizeactive, -10 0
binde=, up, resizeactive, 0 -10

View File

@@ -1,7 +1,8 @@
ipc=on
preload=/share/wallpapers/buttons.png
preload=/share/wallpapers/cat_pacman.png
splash=false
splash_offset=2.000000
wallpaper=DP-3,/share/wallpapers/buttons.png
wallpaper=DP-1,/share/wallpapers/cat_pacman.png
ipc=on
splash=false
splash_offset=2.000000

View File

@@ -3,4 +3,5 @@
lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux {
linux-wallpaperengine-basic-configuration = ./basic-configuration.nix;
linux-wallpaperengine-null-options = ./null-options.nix;
linux-wallpaperengine-missing-spaces = ./missing-spaces.nix;
}

View File

@@ -0,0 +1,11 @@
[Install]
WantedBy=graphical-session.target
[Service]
ExecStart=@linux-wallpaperengine@/bin/linux-wallpaperengine --screen-root HDMI-A-1 --bg 2902931482
Restart=on-failure
[Unit]
After=graphical-session.target
Description=Implementation of Wallpaper Engine on Linux
PartOf=graphical-session.target

View File

@@ -0,0 +1,17 @@
{
services.linux-wallpaperengine = {
enable = true;
wallpapers = [
{
monitor = "HDMI-A-1";
wallpaperId = "2902931482";
}
];
};
nmt.script = ''
assertFileContent \
home-files/.config/systemd/user/linux-wallpaperengine.service \
${./missing-spaces-expected.service}
'';
}