Compare commits

..

52 Commits

Author SHA1 Message Date
Robert Helgesson
fb4c7e7ed2 ghostty: use the systemd X-Base option 2026-01-09 20:53:05 +01:00
Robert Helgesson
ef0a84e496 systemd: add unit option Unit.X-Base 2026-01-09 20:53:05 +01:00
Michael Farber Brodsky
0e4217b2c4 news: add workstyle entry 2026-01-09 10:17:21 -05:00
Michael Farber Brodsky
90e53291cb workstyle: add module 2026-01-09 10:17:21 -05:00
Michael Farber Brodsky
480b0b2b81 maintainers: add farberbrodsky 2026-01-09 10:17:21 -05:00
Thierry Delafontaine
b52d47d670 news: add podman darwin support entry 2026-01-09 09:15:55 -05:00
Thierry Delafontaine
f4bcc1ae1c podman: add darwin support with machine management
- restructure module from `podman-linux` to platform-agnostic `podman`
- move linux-specific implementation to `modules/services/podman/linux/`
- add darwin module with declarative machine management
- implement launchd-based watchdog for auto-starting machines
- maintains backward compatibility with existing linux functionality
2026-01-09 09:15:55 -05:00
Benjamin Saunders
297a085108 PULL_REQUEST_TEMPLATE: update treefmt shell
Previously, following these instructions lead to a failure with:

Error: failed to create composite formatter: failed to initialise formatter nixf-diagnose: formatter command not found in PATH: error looking up 'nixf-diagnose'
2026-01-08 22:40:51 -05:00
Lena Fuhrimann
cd6e96d56e hyprland: import XDG_SESSION_TYPE for systemd 2026-01-08 16:53:03 -05:00
Thierry Delafontaine
b1b1c68033 opencode: add custom tools support
Adds support for custom tools - user-defined functions that the LLM can
call during conversations. Custom tools work alongside opencode's built-in
tools and are configured through the new `tools` option.

The configuration follows the same pattern as other opencode settings like
`agents` and `commands`, supporting:
- Inline TypeScript content
- Individual file paths
- Bulk directory imports
2026-01-08 16:32:29 -05:00
Thierry Delafontaine
081234b704 opencode: support directory-based configuration for commands, agents, and themes
The `commands`, `agents`, and `themes` options now accept either an
attribute set (existing behavior) or a path to a directory containing
multiple files. When a directory path is provided, it is symlinked to
the appropriate `$XDG_CONFIG_HOME/opencode/` subdirectory.

This change aligns with the existing `skills` option implementation and
provides a more convenient way to manage multiple configuration files
without needing to define each one individually in Nix.
2026-01-08 16:32:29 -05:00
Austin Horstman
2be878259a makefile: add nixf-diagnose
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 16:30:04 -05:00
Austin Horstman
fa6de26b4d treewide: nixf-diagnose cleanup
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 16:30:04 -05:00
Austin Horstman
9fff37e6ff flake: add nixf-diagnose to treefmt
Start off conservative ignoring more things. Handle the simple auto-fix
things initially.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 16:30:04 -05:00
Austin Horstman
a2cc7b0bab less: migrate to lib.cli.toCommandLineGNU
Migrates from the deprecated toCommandLine to toCommandLineGNU.

This changes the output format to use GNU-style options with equals
(--wheel-lines=3). Both formats were verified to work correctly with less.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 14:56:14 -05:00
Benedikt Rips
37158e5267 vesktop: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
cd74467526 streamlink: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
72476602b9 sapling: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
e926e27968 rbw: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
db116ceb76 qutebrowser: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
f7b2bdf042 pueue: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
a1a11393d9 pistol: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
802ce0a7b1 mullvad-vpn: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
e69fbc243a lazygit: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
ebab435f3e lazydocker: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
bacad23b8c kubecolor: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
6067be4770 kitty: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Benedikt Rips
12a723df97 gurk-rs: deduplicate platform-dependent files 2026-01-08 14:49:34 -05:00
Austin Horstman
40deed4ffe ci: validate-maintainers all-maintainers update
Might as well, can't hurt.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 13:57:12 -05:00
Austin Horstman
9500721e96 maintainers: update all-maintainers
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 13:57:12 -05:00
Austin Horstman
db105fadc4 maintainers: rrvsh moved to nixpkgs
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 13:57:12 -05:00
Austin Horstman
609846bfd2 maintainers: nickthegroot moved to nixpkgs
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 13:57:12 -05:00
Austin Horstman
2db6bcc7ca ci: validate-maintainers on flake.lock update
Keep missing conflicts from nixpkgs updates.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 13:57:12 -05:00
Jure Varlec
a3ac4bb1f8 generic-linux-gpu: put systemd unit in lib/systemd
This is where unit files are expected to be, making GPU setup compatible
with things like selinux. Fixes #8438. The `resources/` directory was
kept because it is expected to be used in the future.
2026-01-08 13:15:31 -05:00
Xinyang Li
47db0fde35 ssh-agent: add allowedPKCS11Providers option 2026-01-08 13:10:56 -05:00
Michael Strobel
3351348827 sftpman: add missing options
- `authType` is missing the `authentication-agent` enum value
- `mountDestPath` is missing completely
2026-01-08 12:31:15 -05:00
NAHO
7688293f06 home-manager: update copyright year 2026-01-08 12:29:25 -05:00
Austin Horstman
92394f9dea difftastic: migrate to lib.cli.toCommandLineShellGNU
Migrates from the deprecated toCommandLineShell to toCommandLineShellGNU.

This changes the output format to use GNU-style concatenated options
(--color=always) with shell escaping for git config values. Both formats
were verified to work correctly with difftastic.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 11:44:04 -05:00
Austin Horstman
fb6a8404ee redshift-gammastep: migrate to lib.cli.toCommandLineShellGNU
Migrates from the deprecated toCommandLineShell to toCommandLineShellGNU.

This changes the output format from space-separated short options
(-c /path) to concatenated GNU-style options (-c/path). Both formats
were verified to work correctly with redshift and gammastep.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 11:21:16 -05:00
Austin Horstman
9afe77a70b wlsunset: migrate to lib.cli.toCommandLineShellGNU
Migrates from the deprecated toGNUCommandLineShell to toCommandLineShellGNU.

This changes the output format from space-separated short options
(-t 3500) to concatenated GNU-style options (-t3500). Both formats
were verified to work correctly with wlsunset.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 11:18:42 -05:00
Austin Horstman
246b8eaffb linux-wallpaperengine: migrate to lib.cli.toCommandLineGNU
Replace deprecated lib.cli.toGNUCommandLine with lib.cli.toCommandLineGNU. 
Should support the GNU style of convention.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 10:17:17 -06:00
Austin Horstman
f9ce7c5234 bemenu: migrate to lib.cli.toCommandLineShellGNU
Migrates from the deprecated toCommandLineShell to toCommandLineShellGNU.

This changes the output format to use GNU-style concatenated options
(--line-height=28) and adds shell escaping for values with special
characters (e.g., '#1e1e2e' becomes '--ab=#1e1e2e'). The format
was verified to work correctly with bemenu.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 11:11:43 -05:00
Benedikt Rips
d1da1de5c2 lib.darwin: simplify assertInterval 2026-01-08 14:29:57 +01:00
Ian Chamberlain
af7f14ddf7 fish: expose session variables package
This allows fish users to source the `hm-session-vars.fish` if they are
not using the generated `config.fish` (which now sources the same file).
2026-01-08 10:25:35 +01:00
Austin Horstman
46c9af8a92 fish: migrate to lib.cli.toCommandLineShell
Replace deprecated lib.cli.toGNUCommandLineShell with the new
lib.cli.toCommandLineShell API, migrating from the old mkOption
parameter format to the new optionFormat function.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-08 10:14:18 +01:00
Amneesh
a630bbdedd mpd: fix incorrect use of mkIf (#8504)
Currently, if cfg.network.listenAddress is set to "any", MPD_HOST causes
partial evaluation which fails the sanity check while trying to build a
home-manager generation. Hence make a separate attrset for MPD_HOST
which will be evaluated conditionally and then concatenated.

Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
2026-01-07 23:51:16 -06:00
home-manager-ci[bot]
86e0f6f227 flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/9f0c42f8bc7151b8e7e5840fb3bd454ad850d8c5?narHash=sha256-UWYqmD7JFBEDBHWYcqE6s6c77pWdcU/i%2BbwD6XxMb8A%3D' (2026-01-05)
  → 'github:NixOS/nixpkgs/5912c1772a44e31bf1c63c0390b90501e5026886?narHash=sha256-Mj3d3PfwltLmukFal5i3fFt27L6NiKXdBezC1EBuZs4%3D' (2026-01-07)
2026-01-08 00:37:14 -05:00
Brian E
d4c406cfa8 Translate using Weblate (Faroese)
Currently translated at 23.5% (4 of 17 strings)

Translate using Weblate (Faroese)

Currently translated at 12.8% (5 of 39 strings)

Co-authored-by: Brian E <brianellingsgaard9@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/home-manager/cli/fo/
Translate-URL: https://hosted.weblate.org/projects/home-manager/modules/fo/
Translation: Home Manager/Home Manager CLI
Translation: Home Manager/Home Manager Modules
2026-01-08 00:01:18 -05:00
Robert Helgesson
4fee4bd14b ghostty: reload service on configuration change 2026-01-07 17:22:44 -05:00
Austin Horstman
c068188a8e tests: output store path even for success
Useful when trying to double check the contents of a test directory even
when the tests are passing. ie: stub a test and see the stuff you want
to assert/validate.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-07 13:50:01 -05:00
Austin Horstman
bdaa374383 tests/hyprpaper: update basic configuration
Show the newer format and test the proper generation of config.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-07 11:07:21 -05:00
Austin Horstman
d28cc9f4a6 hyprpaper: add monitor importantPrefix
New config requires monitor at top of generated block.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2026-01-07 10:56:09 -05:00
221 changed files with 2314 additions and 820 deletions

View File

@@ -22,7 +22,7 @@ Also make sure to read the guidelines found at
- [ ] Change is backwards compatible.
- [ ] Code formatted with `nix fmt` or
`nix-shell -p treefmt nixfmt deadnix keep-sorted --run treefmt`.
`nix-shell -p treefmt nixfmt deadnix keep-sorted nixf-diagnose --run treefmt`.
- [ ] Code tested through `nix run .#tests -- test-all` or
`nix-shell --pure tests -A run.all`.

2
.github/labeler.yml vendored
View File

@@ -165,7 +165,7 @@
"containers":
- changed-files:
- any-glob-to-any-file:
- modules/services/podman-linux/**/*
- modules/services/podman/linux/**/*
- modules/programs/distrobox.nix
- modules/programs/docker-cli.nix
"desktop-ui":

View File

@@ -1,7 +1,10 @@
name: Validate maintainers.nix
on:
pull_request:
paths: ["modules/lib/maintainers.nix"]
paths:
- "modules/lib/maintainers.nix"
- "flake.lock"
- "all-maintainers.nix"
workflow_dispatch:
inputs:
run_tests:

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2017-2025 Home Manager contributors
Copyright (c) 2017-2026 Home Manager contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -17,4 +17,4 @@ test-install:
HOME=$(shell mktemp -d) NIX_PATH=${NIX_PATH} nix-shell . -A install
format:
nix-shell -p treefmt nixfmt deadnix keep-sorted --run "treefmt --config-file ./treefmt.toml"
nix-shell -p treefmt nixfmt deadnix keep-sorted nixf-diagnose --run "treefmt --config-file ./treefmt.toml"

View File

@@ -19,6 +19,11 @@
email = "da157@voidq.com";
github = "0xda157";
githubId = 153149335;
keys = [
{
fingerprint = "5A66 FF95 36DE B501 DDD2 1647 B7AC 1B10 365D 45FF";
}
];
matrix = "@da157:catgirl.cloud";
name = "0xda157";
source = "nixpkgs";
@@ -65,14 +70,6 @@
name = "Alex";
source = "home-manager";
};
AndersonTorres = {
email = "torres.anderson.85@protonmail.com";
github = "AndersonTorres";
githubId = 5954806;
matrix = "@anderson_torres:matrix.org";
name = "Anderson Torres";
source = "nixpkgs";
};
AndreasMager = {
email = "andreas@mager.eu";
github = "AndreasMager";
@@ -1760,7 +1757,7 @@
github = "nickthegroot";
githubId = 1966472;
name = "Nick DeGroot";
source = "home-manager";
source = "nixpkgs";
};
nikp123 = {
email = "nikp123@users.noreply.github.com";
@@ -2012,7 +2009,7 @@
github = "rrvsh";
githubId = 20300874;
name = "Mohammad Rafiq";
source = "home-manager";
source = "nixpkgs";
};
rszamszur = {
email = "radoslawszamszur@gmail.com";

View File

@@ -110,8 +110,7 @@ let
in
pkgs.buildPackages.nixosOptionsDoc (
{
options =
if includeModuleSystemOptions then options else builtins.removeAttrs options [ "_module" ];
options = if includeModuleSystemOptions then options else removeAttrs options [ "_module" ];
transformOptions =
opt:
opt
@@ -133,7 +132,7 @@ let
) opt.declarations;
};
}
// builtins.removeAttrs args [
// removeAttrs args [
"modules"
"includeModuleSystemOptions"
]

View File

@@ -17,8 +17,11 @@ way. In Bash and Z shell this can be done by adding
to your `.profile` and `.zshrc` files, respectively. The
`hm-session-vars.sh` file should work in most Bourne-like shells. For
fish shell, it is possible to source it using [the foreign-env
plugin](https://github.com/oh-my-fish/plugin-foreign-env)
plugin](https://github.com/oh-my-fish/plugin-foreign-env) or using the builtin
[babelfish](https://github.com/bouk/babelfish)-translated variables:
``` bash
fenv source "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh" > /dev/null
# or
source "$HOME/.nix-profile/etc/profile.d/hm-session-vars.fish"
```

6
flake.lock generated
View File

@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1767640445,
"narHash": "sha256-UWYqmD7JFBEDBHWYcqE6s6c77pWdcU/i+bwD6XxMb8A=",
"lastModified": 1767767207,
"narHash": "sha256-Mj3d3PfwltLmukFal5i3fFt27L6NiKXdBezC1EBuZs4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "9f0c42f8bc7151b8e7e5840fb3bd454ad850d8c5",
"rev": "5912c1772a44e31bf1c63c0390b90501e5026886",
"type": "github"
},
"original": {

View File

@@ -57,6 +57,7 @@
nixfmt
deadnix
keep-sorted
nixf-diagnose
];
settings = pkgs.lib.importTOML ./treefmt.toml;
}

View File

@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: Home Manager\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2025-07-22 10:59+0200\n"
"PO-Revision-Date: 2025-11-30 14:00+0000\n"
"PO-Revision-Date: 2026-01-07 17:01+0000\n"
"Last-Translator: Brian E <brianellingsgaard9@gmail.com>\n"
"Language-Team: Faroese <https://hosted.weblate.org/projects/home-manager/cli/"
"fo/>\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.15-dev\n"
"X-Generator: Weblate 5.15.1\n"
#. translators: For example: "home-manager: missing argument for --cores"
#: home-manager/home-manager:16
@@ -41,10 +41,12 @@ msgid ""
"Keeping your Home Manager %s in %s is deprecated,\n"
"please move it to %s"
msgstr ""
"At hava Heimvørðurin %s í %s er fyrnast,\n"
"vinarliga flyt hann til %s"
#: home-manager/home-manager:99
msgid "No configuration file found. Please create one at %s"
msgstr ""
msgstr "Eingin samansetingsfíla funni. Vinarliga stovna ein hjá %s"
#: home-manager/home-manager:114
msgid "Home Manager not found at %s."

View File

@@ -31,7 +31,7 @@ let
modules = [ configuration ] ++ hmModules;
class = "homeManager";
specialArgs = {
modulesPath = builtins.toString ./.;
modulesPath = toString ./.;
}
// extraSpecialArgs;
};

View File

@@ -192,7 +192,7 @@ in
++ lib.optionals (cfg.quickPhraseFiles != { }) [
(pkgs.linkFarm "quickPhraseFiles" (
lib.mapAttrs' (
name: value: lib.nameValuePair ("share/fcitx5/data/quickphrase.d/${name}.mb") value
name: value: lib.nameValuePair "share/fcitx5/data/quickphrase.d/${name}.mb" value
) cfg.quickPhraseFiles
))
];

View File

@@ -13,12 +13,9 @@ let
mergeDefinitions
;
inherit (builtins)
map
filter
length
deepSeq
throw
toString
concatLists
;
inherit (lib.options) showDefs;

View File

@@ -63,12 +63,12 @@ let
intervalsString = lib.concatStringsSep ", " intervals;
assertInterval = option: interval: pkgs: {
assertion = (!pkgs.stdenv.isDarwin) || (lib.elem interval intervals);
message = "On Darwin ${option} must be one of: ${intervalsString}.";
assertion = pkgs.stdenv.isDarwin -> lib.elem interval intervals;
message = "On Darwin, ${option} must be one of: ${intervalsString}.";
};
intervalDocumentation = ''
On Darwin it must be one of: ${intervalsString}, which are implemented as defined in {manpage}`systemd.time(7)`.
On Darwin, it must be one of: ${intervalsString}, which are implemented as defined in {manpage}`systemd.time(7)`.
'';
in
{

View File

@@ -175,6 +175,12 @@
github = "exzombie";
githubId = 11456290;
};
farberbrodsky = {
name = "Michael Farber Brodsky";
email = "misha@farberbrodsky.com";
github = "farberbrodsky";
githubId = 36243759;
};
fendse = {
email = "46252070+Fendse@users.noreply.github.com";
github = "Fendse";
@@ -423,12 +429,6 @@
github = "natecox";
githubId = 2782695;
};
nickthegroot = {
name = "Nick DeGroot";
email = "nick@nickthegroot.com";
github = "nickthegroot";
githubId = 1966472;
};
nikp123 = {
name = "nikp123";
email = "nikp123@users.noreply.github.com";
@@ -507,12 +507,6 @@
github = "Rosuavio";
githubId = 7164552;
};
rrvsh = {
name = "Mohammad Rafiq";
email = "rafiq@rrv.sh";
github = "rrvsh";
githubId = 20300874;
};
rszamszur = {
name = "Radosław Szamszur";
email = "radoslawszamszur@gmail.com";

View File

@@ -278,7 +278,7 @@ in
else if builtins.isString value then
"<const>${value}</const>"
else
throw ("expected bool or string but got ${builtins.typeOf value}: ${toString value}");
throw "expected bool or string but got ${builtins.typeOf value}: ${toString value}";
in
''
<match target="font">
@@ -338,7 +338,7 @@ in
xdg.configFile = lib.mapAttrs' (
name: config:
lib.nameValuePair "fontconfig/conf.d/${builtins.toString config.priority}-hm-${config.label}.conf" {
lib.nameValuePair "fontconfig/conf.d/${toString config.priority}-hm-${config.label}.conf" {
inherit (config) enable text;
source = lib.mkIf (config.source != null) config.source;
}

View File

@@ -72,7 +72,7 @@ let
fileList ++ subdirFiles;
newsFiles = collectNixFiles ./news;
newsEntries = builtins.map (
newsEntries = map (
newsFile:
let
imported = import newsFile;

View File

@@ -0,0 +1,34 @@
{
config,
lib,
pkgs,
...
}:
{
time = "2025-11-04T15:44:03+00:00";
condition = true;
message = ''
The 'services.podman' module now supports Darwin (macOS) with declarative
machine management.
On Darwin, podman requires running containers inside a virtual machine.
The new configuration options allow you to declaratively manage podman
machines with automatic creation, configuration, and startup.
By default, a machine named 'podman-machine-default' will be created
automatically. You can customize machines or disable the default with:
services.podman.useDefaultMachine = false;
services.podman.machines = {
"my-machine" = {
cpus = 4;
memory = 8192;
diskSize = 100;
autoStart = true;
};
};
The module includes a launchd-based watchdog service that automatically
starts configured machines on login and keeps them running.
'';
}

View File

@@ -0,0 +1,12 @@
{ pkgs, ... }:
{
time = "2026-01-05T11:57:57+00:00";
condition = pkgs.stdenv.hostPlatform.isLinux;
message = ''
A new module is available: 'programs.workstyle'.
Workstyle dynamically renames Sway/i3/Hyprland workspaces to indicate
which programs are running in each one. For example, with a font icon.
'';
}

View File

@@ -47,9 +47,9 @@ in
desktop: terminals:
# Map desktop name such as GNOME to `.config/gnome-xdg-terminals.list`,
# default to `.config/xdg-terminals.list`.
lib.nameValuePair (
"${if desktop == "default" then "" else "${lib.toLower desktop}-"}xdg-terminals.list"
) { text = lib.concatLines terminals; }
lib.nameValuePair "${
if desktop == "default" then "" else "${lib.toLower desktop}-"
}xdg-terminals.list" { text = lib.concatLines terminals; }
) cfg.settings;
};
}

View File

@@ -8,7 +8,7 @@ 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-07-22 10:59+0200\n"
"PO-Revision-Date: 2025-11-30 14:00+0000\n"
"PO-Revision-Date: 2026-01-07 17:01+0000\n"
"Last-Translator: Brian E <brianellingsgaard9@gmail.com>\n"
"Language-Team: Faroese <https://hosted.weblate.org/projects/home-manager/"
"modules/fo/>\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.15-dev\n"
"X-Generator: Weblate 5.15.1\n"
#: modules/files.nix:206
msgid "Creating home file links in %s"
@@ -33,7 +33,7 @@ msgstr "Stovni nýggjan profil ættarlið"
#: modules/home-environment.nix:650
msgid "No change so reusing latest profile generation"
msgstr ""
msgstr "Eingin broyting. Seinastið umhvarv ættarlið er enn í brúk"
#: modules/home-environment.nix:699
msgid ""

View File

@@ -104,7 +104,7 @@ in
};
stylesets = mkOption {
type = with types; attrsOf (sectionsOrLines);
type = with types; attrsOf sectionsOrLines;
default = { };
example = literalExpression ''
{ default = { ui = { "tab.selected.reverse" = "toggle"; }; }; };

View File

@@ -6,9 +6,7 @@
}:
let
inherit (builtins)
map
toJSON
toString
substring
stringLength
;

View File

@@ -54,7 +54,7 @@ in
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
home.sessionVariables = lib.mkIf (cfg.settings != { }) {
BEMENU_OPTS = lib.cli.toGNUCommandLineShell { } cfg.settings;
BEMENU_OPTS = lib.cli.toCommandLineShellGNU { } cfg.settings;
};
};
}

View File

@@ -281,7 +281,7 @@ in
) supportedBrowsers;
config = lib.mkMerge (
builtins.map (browser: browserConfig browser config.programs.${browser}) (
map (browser: browserConfig browser config.programs.${browser}) (
builtins.attrNames supportedBrowsers
)
);

View File

@@ -129,7 +129,7 @@ in
enable = lib.mkDefault true;
iniContent =
let
difftCommand = "${lib.getExe cfg.package} ${lib.cli.toGNUCommandLineShell { } cfg.options}";
difftCommand = "${lib.getExe cfg.package} ${lib.cli.toCommandLineShellGNU { } cfg.options}";
in
mkMerge [
{

View File

@@ -16,8 +16,7 @@ let
generateConfig = lib.generators.toKeyValue {
mkKeyValue =
name: value:
if lib.isString value then ''${name}="${value}"'' else "${name}=${builtins.toString value}";
name: value: if lib.isString value then ''${name}="${value}"'' else "${name}=${toString value}";
};
iniFormat = pkgs.formats.ini { listsAsDuplicateKeys = true; };

View File

@@ -103,7 +103,7 @@ in
{
name = path;
value = {
source = jsonFormat.generate "config.json" (ctx);
source = jsonFormat.generate "config.json" ctx;
};
}
) cfg.contexts;

View File

@@ -471,7 +471,7 @@ in
order = mkOption {
type = with types; uniq (listOf str);
apply = builtins.map migrateEngineNameToIdV7;
apply = map migrateEngineNameToIdV7;
default = [ ];
example = [
"ddg"

View File

@@ -301,20 +301,13 @@ let
let
name = if isAttrs def && def.name != null then def.name else attrName;
mods =
lib.cli.toGNUCommandLineShell
{
mkOption =
k: v:
if v == null then
[ ]
else if k == "set-cursor" then
[ "--${k}=${lib.generators.mkValueStringDefault { } v}" ]
else
[
"--${k}"
(lib.generators.mkValueStringDefault { } v)
];
}
lib.cli.toCommandLineShell
(optionName: {
option = "--${optionName}";
sep = if optionName == "set-cursor" then "=" else null;
explicitBool = false;
formatArg = lib.generators.mkValueStringDefault { };
})
{
inherit (def)
position
@@ -395,12 +388,14 @@ let
passAsFile = [ "text" ];
} "env HOME=$(mktemp -d) fish_indent < $textPath > $out";
translatedSessionVariables = pkgs.runCommandLocal "hm-session-vars.fish" { } ''
sessionVarsFile = "etc/profile.d/hm-session-vars.fish";
sessionVarsPkg = pkgs.runCommandLocal "hm-session-vars.fish" { } ''
mkdir -p "$(dirname $out/${sessionVarsFile})"
(echo "function setup_hm_session_vars;"
${pkgs.buildPackages.babelfish}/bin/babelfish \
<${config.home.sessionVariablesPackage}/etc/profile.d/hm-session-vars.sh
<${config.home.sessionVariablesPackage}/etc/profile.d/hm-session-vars.sh
echo "end"
echo "setup_hm_session_vars") > $out
echo "setup_hm_session_vars") > $out/${sessionVarsFile}
'';
in
@@ -598,11 +593,25 @@ in
<https://fishshell.com/docs/current/completions.html>.
'';
};
programs.fish.sessionVariablesPackage = mkOption {
type = types.package;
internal = true;
description = ''
The package containing the translated {file}`hm-session-vars.fish` file.
'';
};
};
config = mkIf cfg.enable (
lib.mkMerge [
{ home.packages = [ cfg.package ]; }
{
home.packages = [
cfg.package
cfg.sessionVariablesPackage
];
programs.fish.sessionVariablesPackage = sessionVarsPkg;
}
(mkIf cfg.generateCompletions (
let
@@ -618,7 +627,7 @@ in
package
]
++ lib.filter (p: p != null) (
builtins.map (outName: package.${outName} or null) config.home.extraOutputsToInstall
map (outName: package.${outName} or null) config.home.extraOutputsToInstall
);
nativeBuildInputs = [ pkgs.python3 ];
buildInputs = [ cfg.package ];
@@ -715,7 +724,7 @@ in
set -q __fish_home_manager_config_sourced; and exit
set -g __fish_home_manager_config_sourced 1
source ${translatedSessionVariables}
source ${cfg.sessionVariablesPackage}/${sessionVarsFile}
${cfg.shellInit}

View File

@@ -11,7 +11,7 @@ let
tomlFormat = pkgs.formats.toml { };
in
{
meta.maintainers = [ lib.hm.maintainers.rrvsh ];
meta.maintainers = [ lib.maintainers.rrvsh ];
options.programs.gemini-cli = {
enable = lib.mkEnableOption "gemini-cli";

View File

@@ -204,7 +204,7 @@ in
xdg.dataFile."gh/extensions" = mkIf (cfg.extensions != [ ]) {
source = pkgs.linkFarm "gh-extensions" (
builtins.map (p: {
map (p: {
name = p.pname;
path = "${p}/bin";
}) cfg.extensions

View File

@@ -225,13 +225,18 @@ in
}
];
xdg.configFile."systemd/user/app-com.mitchellh.ghostty.service".source =
"${cfg.package}/share/systemd/user/app-com.mitchellh.ghostty.service";
xdg.configFile."systemd/user/app-com.mitchellh.ghostty.service.d/overrides.conf".text = ''
[Unit]
X-SwitchMethod=keep-old
'';
systemd.user.services."app-com.mitchellh.ghostty" = {
Unit = {
X-Base = "${cfg.package}/share/systemd/user/app-com.mitchellh.ghostty.service";
X-SwitchMethod = "keep-old";
X-Reload-Triggers =
let
storePathOf = name: config.xdg.configFile.${name}.source;
in
lib.optionals (cfg.settings != { }) [ (storePathOf "ghostty/config") ]
++ lib.mapAttrsToList (name: _: storePathOf "ghostty/themes/${name}") cfg.themes;
};
};
dbus.packages = [ cfg.package ];
})

View File

@@ -7,6 +7,8 @@
let
tomlFormat = pkgs.formats.toml { };
cfg = config.programs.gurk-rs;
configDir =
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Application Support" else config.xdg.configHome;
in
{
meta.maintainers = [ lib.maintainers.da157 ];
@@ -46,9 +48,8 @@ in
config = lib.mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
home.file."${
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Application Support" else config.xdg.configHome
}/gurk/gurk.toml".source =
lib.mkIf (cfg.settings != { }) (tomlFormat.generate "gurk-config" cfg.settings);
home.file."${configDir}/gurk/gurk.toml" = lib.mkIf (cfg.settings != { }) {
source = tomlFormat.generate "gurk-config" cfg.settings;
};
};
}

View File

@@ -9,7 +9,7 @@ let
iniFormat = pkgs.formats.ini { };
in
{
meta.maintainers = with lib.maintainers; [ ];
meta.maintainers = [ ];
options.programs.havoc = {
enable = lib.mkEnableOption "Havoc terminal";

View File

@@ -70,7 +70,7 @@ in
"mako"
];
in
builtins.map (name: {
map (name: {
assertion = !config.services.${name}.enable;
message = ''
Only one notification daemon can be enabled at once. You have enabled

View File

@@ -139,7 +139,7 @@ in
in
lib.hm.dag.entryAfter [ "linkGeneration" ] ''
# Ensure that settings.json exists.
mkdir -p ${builtins.dirOf configPath}
mkdir -p ${dirOf configPath}
touch ${configPath}
# Config has to be written to temporary variable because jq cannot edit files in place.
config="$(jq -s '.[0] + .[1]' ${configPath} ${newConfig})"

View File

@@ -14,7 +14,7 @@ let
renderSettings =
with lib.generators;
toINI {
mkKeyValue = mkKeyValueDefault rec {
mkKeyValue = mkKeyValueDefault {
mkValueString =
v:
if lib.isList v then
@@ -139,7 +139,7 @@ in
let
makePath =
baseDir: subDir:
builtins.toString (
toString (
/.
+ lib.concatStringsSep "/" [
baseDir

View File

@@ -341,16 +341,13 @@ in
# See https://sw.kovidgoyal.net/kitty/conf.html
${cfg.extraConfig}
'';
}
// lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux {
onChange = ''
${pkgs.procps}/bin/pkill -USR1 -u $USER kitty || true
'';
}
// lib.optionalAttrs pkgs.stdenv.hostPlatform.isDarwin {
onChange = ''
/usr/bin/pkill -USR1 -u $USER kitty || true
'';
onChange =
let
prefix = if pkgs.stdenv.hostPlatform.isDarwin then "/usr" else pkgs.procps;
in
''
${prefix}/bin/pkill -USR1 -u $USER kitty || true
'';
};
xdg.configFile."kitty/quick-access-terminal.conf" = mkIf (cfg.quickAccessTerminalConfig != { }) {

View File

@@ -9,7 +9,6 @@ let
cfg = config.programs.kubecolor;
yamlFormat = pkgs.formats.yaml { };
inherit (pkgs.stdenv.hostPlatform) isDarwin;
in
{
@@ -50,18 +49,20 @@ in
config =
let
preferXdgDirectories = config.home.preferXdgDirectories && (!isDarwin || config.xdg.enable);
preferXdgDirectories =
config.home.preferXdgDirectories && (!pkgs.stdenv.hostPlatform.isDarwin || config.xdg.enable);
configDir =
if preferXdgDirectories then
"${config.xdg.configHome}/kube"
else if pkgs.stdenv.hostPlatform.isDarwin then
"Library/Application Support/kube"
else
".kube";
# https://github.com/kubecolor/kubecolor/pull/145
configPathSuffix =
if
cfg.package.pname == "kubecolor"
&& lib.strings.toInt (lib.versions.major cfg.package.version) == 0
&& lib.strings.toInt (lib.versions.minor cfg.package.version) < 4
then
"kube/"
else
"kube/color.yaml";
configPathSuffix = lib.optionalString (
cfg.package.pname == "kubecolor" && lib.versionOlder (lib.getVersion cfg.package) "0.4"
) "color.yaml";
in
mkIf cfg.enable {
@@ -73,31 +74,10 @@ in
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
home.sessionVariables =
if preferXdgDirectories then
{
KUBECOLOR_CONFIG = "${config.xdg.configHome}/${configPathSuffix}";
}
else if isDarwin then
{
KUBECOLOR_CONFIG = "${config.home.homeDirectory}/Library/Application Support/${configPathSuffix}";
}
else
{ };
home.sessionVariables.KUBECOLOR_CONFIG = "${configDir}/${configPathSuffix}";
xdg.configFile = mkIf preferXdgDirectories {
"kube/color.yaml" = mkIf (cfg.settings != { }) {
source = yamlFormat.generate "kubecolor-settings" cfg.settings;
};
};
home.file = mkIf (!preferXdgDirectories) {
"Library/Application Support/kube/color.yaml" = mkIf (isDarwin && cfg.settings != { }) {
source = yamlFormat.generate "kubecolor-settings" cfg.settings;
};
".kube/color.yaml" = mkIf (!isDarwin && cfg.settings != { }) {
source = yamlFormat.generate "kubecolor-settings" cfg.settings;
};
home.file."${configDir}/color.yaml" = mkIf (cfg.settings != { }) {
source = yamlFormat.generate "kubecolor-settings" cfg.settings;
};
home.shellAliases = lib.mkIf (cfg.enableAlias && (cfg.package != null)) {

View File

@@ -201,7 +201,7 @@ let
plugins:
pkgs.linkFarm "lapce-plugins" (
builtins.listToAttrs (
builtins.map (
map (
{
author,
name,

View File

@@ -11,7 +11,11 @@ let
yamlFormat = pkgs.formats.yaml { };
inherit (pkgs.stdenv.hostPlatform) isDarwin;
configDir =
if pkgs.stdenv.hostPlatform.isDarwin && !config.xdg.enable then
"Library/Application Support/jesseduffield"
else
config.xdg.configHome;
in
{
@@ -51,16 +55,8 @@ in
config = lib.mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
home.file."Library/Application Support/jesseduffield/lazydocker/config.yml" =
lib.mkIf (cfg.settings != { } && (isDarwin && !config.xdg.enable))
{
source = yamlFormat.generate "lazydocker-config" cfg.settings;
};
xdg.configFile."lazydocker/config.yml" =
lib.mkIf (cfg.settings != { } && !(isDarwin && !config.xdg.enable))
{
source = yamlFormat.generate "lazydocker-config" cfg.settings;
};
home.file."${configDir}/lazydocker/config.yml" = lib.mkIf (cfg.settings != { }) {
source = yamlFormat.generate "lazydocker-config" cfg.settings;
};
};
}

View File

@@ -11,8 +11,11 @@ let
yamlFormat = pkgs.formats.yaml { };
inherit (pkgs.stdenv.hostPlatform) isDarwin;
configDir =
if pkgs.stdenv.hostPlatform.isDarwin && !config.xdg.enable then
"Library/Application Support"
else
config.xdg.configHome;
in
{
meta.maintainers = [
@@ -71,17 +74,10 @@ in
config = mkIf cfg.enable {
home.packages = mkIf (cfg.package != null) [ cfg.package ];
home.file."Library/Application Support/lazygit/config.yml" =
mkIf (cfg.settings != { } && (isDarwin && !config.xdg.enable))
{
source = yamlFormat.generate "lazygit-config" cfg.settings;
};
xdg.configFile."lazygit/config.yml" =
mkIf (cfg.settings != { } && !(isDarwin && !config.xdg.enable))
{
source = yamlFormat.generate "lazygit-config" cfg.settings;
};
home.file."${configDir}/lazygit/config.yml" = {
enable = cfg.settings != { };
source = yamlFormat.generate "lazygit-config" cfg.settings;
};
programs =
let

View File

@@ -45,7 +45,7 @@ in
];
attrs = attrsOf (either scalar (listOf scalar));
in
coercedTo attrs (lib.cli.toGNUCommandLine { }) (listOf str);
coercedTo attrs (lib.cli.toCommandLineGNU { }) (listOf str);
default = [ ];
description = "Options to be set via {env}`$LESS`.";
example = {

View File

@@ -82,7 +82,7 @@ in
package = lib.mkPackageOption pkgs "meli" { };
includes = mkOption {
type = with types; listOf (str);
type = with types; listOf str;
description = "Paths of the various meli configuration files to include.";
default = [ ];
};

View File

@@ -7,6 +7,8 @@
let
cfg = config.programs.mullvad-vpn;
jsonFormat = pkgs.formats.json { };
configDir =
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Application Support" else config.xdg.configHome;
in
{
meta.maintainers = [ lib.maintainers.da157 ];
@@ -42,11 +44,8 @@ in
config = lib.mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
home.file."${
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Application Support" else config.xdg.configHome
}/Mullvad VPN/gui_settings.json" =
lib.mkIf (cfg.settings != { }) {
source = jsonFormat.generate "mullvad-gui-settings" cfg.settings;
};
home.file."${configDir}/Mullvad VPN/gui_settings.json" = lib.mkIf (cfg.settings != { }) {
source = jsonFormat.generate "mullvad-gui-settings" cfg.settings;
};
};
}

View File

@@ -13,7 +13,7 @@ let
renderSettings = settings: lib.concatStringsSep ";" (lib.mapAttrsToList renderSetting settings);
pluginModule = types.submodule ({
pluginModule = types.submodule {
options = {
src = mkOption {
type = with types; nullOr path;
@@ -46,7 +46,7 @@ let
'';
};
};
});
};
in
{
meta.maintainers = with lib.maintainers; [ thiagokokada ];

View File

@@ -254,7 +254,7 @@ in
cssSnippets =
let
checkCssPath = path: lib.filesystem.pathIsRegularFile path && lib.strings.hasSuffix ".css" path;
toCssName = path: lib.strings.removeSuffix ".css" (builtins.baseNameOf path);
toCssName = path: lib.strings.removeSuffix ".css" (baseNameOf path);
cssSnippetsOptions =
{ config, ... }:
{
@@ -423,7 +423,7 @@ in
source = (pkgs.formats.json { }).generate "appearance.json" (
vault.settings.appearance
// {
enabledCssSnippets = builtins.map (snippet: snippet.name) enabledCssSnippets;
enabledCssSnippets = map (snippet: snippet.name) enabledCssSnippets;
}
// lib.attrsets.optionalAttrs (activeTheme != null) {
cssTheme = getManifest activeTheme;
@@ -438,14 +438,14 @@ in
{
name = "${vault.target}/.obsidian/core-plugins.json";
value.source = (pkgs.formats.json { }).generate "core-plugins.json" (
builtins.map (plugin: plugin.name) vault.settings.corePlugins
map (plugin: plugin.name) vault.settings.corePlugins
);
}
{
name = "${vault.target}/.obsidian/core-plugins-migration.json";
value.source = (pkgs.formats.json { }).generate "core-plugins-migration.json" (
builtins.listToAttrs (
builtins.map (name: {
map (name: {
inherit name;
value = builtins.any (plugin: name == plugin.name && plugin.enable) vault.settings.corePlugins;
}) corePlugins
@@ -453,7 +453,7 @@ in
);
}
]
++ builtins.map (plugin: {
++ map (plugin: {
name = "${vault.target}/.obsidian/${plugin.name}.json";
value.source = (pkgs.formats.json { }).generate "${plugin.name}.json" plugin.settings;
}) (builtins.filter (plugin: plugin.settings != { }) vault.settings.corePlugins);
@@ -464,25 +464,25 @@ in
{
name = "${vault.target}/.obsidian/community-plugins.json";
value.source = (pkgs.formats.json { }).generate "community-plugins.json" (
builtins.map getManifest (builtins.filter (plugin: plugin.enable) vault.settings.communityPlugins)
map getManifest (builtins.filter (plugin: plugin.enable) vault.settings.communityPlugins)
);
}
]
++ builtins.map (plugin: {
++ map (plugin: {
name = "${vault.target}/.obsidian/plugins/${getManifest plugin}";
value = {
source = plugin.pkg;
recursive = true;
};
}) vault.settings.communityPlugins
++ builtins.map (plugin: {
++ map (plugin: {
name = "${vault.target}/.obsidian/plugins/${getManifest plugin}/data.json";
value.source = (pkgs.formats.json { }).generate "data.json" plugin.settings;
}) (builtins.filter (plugin: plugin.settings != { }) vault.settings.communityPlugins);
mkCssSnippets =
vault:
builtins.map (snippet: {
map (snippet: {
name = "${vault.target}/.obsidian/snippets/${snippet.name}.css";
value =
if snippet.source != null then
@@ -497,7 +497,7 @@ in
mkThemes =
vault:
builtins.map (theme: {
map (theme: {
name = "${vault.target}/.obsidian/themes/${getManifest theme}";
value.source = theme.pkg;
}) vault.settings.themes;
@@ -509,7 +509,7 @@ in
mkExtraFiles =
vault:
builtins.map (file: {
map (file: {
name = "${vault.target}/.obsidian/${file.target}";
value =
if file.source != null then
@@ -524,7 +524,7 @@ in
in
builtins.listToAttrs (
lib.lists.flatten (
builtins.map (vault: [
map (vault: [
(mkApp vault)
(mkAppearance vault)
(mkCorePlugins vault)
@@ -540,7 +540,7 @@ in
xdg.configFile."obsidian/obsidian.json".source = (pkgs.formats.json { }).generate "obsidian.json" {
vaults = builtins.listToAttrs (
builtins.map (vault: {
map (vault: {
name = builtins.hashString "md5" vault.target;
value = {
path = "${config.home.homeDirectory}/${vault.target}";

View File

@@ -126,14 +126,22 @@ in
};
commands = lib.mkOption {
type = lib.types.attrsOf (lib.types.either lib.types.lines lib.types.path);
type = lib.types.either (lib.types.attrsOf (lib.types.either lib.types.lines lib.types.path)) lib.types.path;
default = { };
description = ''
Custom commands for opencode.
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/opencode/command/` directory.
This option can either be:
- An attribute set defining commands
- A path to a directory containing multiple command files
If an attribute set is used, the attribute name becomes the command filename,
and the value is either:
- Inline content as a string (creates `opencode/command/<name>.md`)
- A path to a file (creates `opencode/command/<name>.md`)
If a path is used, it is expected to contain command files.
The directory is symlinked to {file}`$XDG_CONFIG_HOME/opencode/command/`.
'';
example = lib.literalExpression ''
{
@@ -155,14 +163,22 @@ in
};
agents = lib.mkOption {
type = lib.types.attrsOf (lib.types.either lib.types.lines lib.types.path);
type = lib.types.either (lib.types.attrsOf (lib.types.either lib.types.lines lib.types.path)) lib.types.path;
default = { };
description = ''
Custom agents for opencode.
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/opencode/agent/` directory.
This option can either be:
- An attribute set defining agents
- A path to a directory containing multiple agent files
If an attribute set is used, the attribute name becomes the agent filename,
and the value is either:
- Inline content as a string (creates `opencode/agent/<name>.md`)
- A path to a file (creates `opencode/agent/<name>.md`)
If a path is used, it is expected to contain agent files.
The directory is symlinked to {file}`$XDG_CONFIG_HOME/opencode/agent/`.
'';
example = lib.literalExpression ''
{
@@ -227,26 +243,94 @@ in
};
themes = mkOption {
type = lib.types.attrsOf (lib.types.either jsonFormat.type lib.types.path);
type = lib.types.either (lib.types.attrsOf (lib.types.either jsonFormat.type lib.types.path)) lib.types.path;
default = { };
description = ''
Custom themes for opencode. The attribute name becomes the theme
filename, and the value is either:
- An attribute set, that is converted to a json
- A path to a file containing the content
Themes are stored in {file}`$XDG_CONFIG_HOME/opencode/themes/` directory.
Custom themes for opencode.
This option can either be:
- An attribute set defining themes
- A path to a directory containing multiple theme files
If an attribute set is used, the attribute name becomes the theme filename,
and the value is either:
- An attribute set that is converted to a JSON file (creates `opencode/themes/<name>.json`)
- A path to a file (creates `opencode/themes/<name>.json`)
If a path is used, it is expected to contain theme files.
The directory is symlinked to {file}`$XDG_CONFIG_HOME/opencode/themes/`.
Set `programs.opencode.settings.theme` to enable the custom theme.
See <https://opencode.ai/docs/themes/> for the documentation.
'';
};
tools = lib.mkOption {
type = lib.types.either (lib.types.attrsOf (lib.types.either lib.types.lines lib.types.path)) lib.types.path;
default = { };
description = ''
Custom tools for opencode.
This option can either be:
- An attribute set defining tools
- A path to a directory containing multiple tool files
If an attribute set is used, the attribute name becomes the tool filename,
and the value is either:
- Inline content as a string (creates `opencode/tool/<name>.ts`)
- A path to a file (creates `opencode/tool/<name>.ts` or `opencode/tool/<name>.js`)
If a path is used, it is expected to contain tool files.
The directory is symlinked to {file}`$XDG_CONFIG_HOME/opencode/tool/`.
See <https://opencode.ai/docs/tools/> for the documentation.
'';
example = lib.literalExpression ''
{
database-query = '''
import { tool } from "@opencode-ai/plugin"
export default tool({
description: "Query the project database",
args: {
query: tool.schema.string().describe("SQL query to execute"),
},
async execute(args) {
// Your database logic here
return `Executed query: ''${args.query}`
},
})
''';
# Or reference an existing file
api-client = ./tools/api-client.ts;
}
'';
};
};
config = mkIf cfg.enable {
assertions = [
{
assertion = !lib.isPath cfg.commands || lib.pathIsDirectory cfg.commands;
message = "`programs.opencode.commands` must be a directory when set to a path";
}
{
assertion = !lib.isPath cfg.agents || lib.pathIsDirectory cfg.agents;
message = "`programs.opencode.agents` must be a directory when set to a path";
}
{
assertion = !lib.isPath cfg.tools || lib.pathIsDirectory cfg.tools;
message = "`programs.opencode.tools` must be a directory when set to a path";
}
{
assertion = !lib.isPath cfg.skills || lib.pathIsDirectory cfg.skills;
message = "`programs.opencode.skills` must be a directory when set to a path";
}
{
assertion = !lib.isPath cfg.themes || lib.pathIsDirectory cfg.themes;
message = "`programs.opencode.themes` must be a directory when set to a path";
}
];
home.packages = mkIf (cfg.package != null) [ cfg.package ];
@@ -278,23 +362,55 @@ in
})
);
"opencode/command" = mkIf (lib.isPath cfg.commands) {
source = cfg.commands;
recursive = true;
};
"opencode/agent" = mkIf (lib.isPath cfg.agents) {
source = cfg.agents;
recursive = true;
};
"opencode/tool" = mkIf (lib.isPath cfg.tools) {
source = cfg.tools;
recursive = true;
};
"opencode/skill" = mkIf (lib.isPath cfg.skills) {
source = cfg.skills;
recursive = true;
};
"opencode/themes" = mkIf (lib.isPath cfg.themes) {
source = cfg.themes;
recursive = true;
};
}
// lib.mapAttrs' (
name: content:
lib.nameValuePair "opencode/command/${name}.md" (
if lib.isPath content then { source = content; } else { text = content; }
)
) cfg.commands
// lib.mapAttrs' (
name: content:
lib.nameValuePair "opencode/agent/${name}.md" (
if lib.isPath content then { source = content; } else { text = content; }
)
) cfg.agents
// lib.optionalAttrs (builtins.isAttrs cfg.commands) (
lib.mapAttrs' (
name: content:
lib.nameValuePair "opencode/command/${name}.md" (
if lib.isPath content then { source = content; } else { text = content; }
)
) cfg.commands
)
// lib.optionalAttrs (builtins.isAttrs cfg.agents) (
lib.mapAttrs' (
name: content:
lib.nameValuePair "opencode/agent/${name}.md" (
if lib.isPath content then { source = content; } else { text = content; }
)
) cfg.agents
)
// lib.optionalAttrs (builtins.isAttrs cfg.tools) (
lib.mapAttrs' (
name: content:
lib.nameValuePair "opencode/tool/${name}.ts" (
if lib.isPath content then { source = content; } else { text = content; }
)
) cfg.tools
)
// lib.mapAttrs' (
name: content:
if lib.isPath content && lib.pathIsDirectory content then
@@ -307,23 +423,25 @@ in
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" (
if lib.isPath content then
{
source = content;
}
else
{
source = jsonFormat.generate "opencode-${name}.json" (
{
"$schema" = "https://opencode.ai/theme.json";
}
// content
);
}
)
) cfg.themes;
// lib.optionalAttrs (builtins.isAttrs cfg.themes) (
lib.mapAttrs' (
name: content:
lib.nameValuePair "opencode/themes/${name}.json" (
if lib.isPath content then
{
source = content;
}
else
{
source = jsonFormat.generate "opencode-${name}.json" (
{
"$schema" = "https://opencode.ai/theme.json";
}
// content
);
}
)
) cfg.themes
);
};
}

View File

@@ -19,7 +19,7 @@ let
in
{
meta.maintainers = [ lib.hm.maintainers.nickthegroot ];
meta.maintainers = [ lib.maintainers.nickthegroot ];
options.programs.pgcli = {
enable = mkEnableOption "pgcli";

View File

@@ -9,6 +9,9 @@ let
cfg = config.programs.pistol;
configDir =
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Preferences" else config.xdg.configHome;
configFile = lib.concatStringsSep "\n" (
map (
{
@@ -74,31 +77,23 @@ in
};
config = mkIf cfg.enable (
lib.mkMerge [
config = mkIf cfg.enable {
assertions = [
{
assertions = [
{
assertion = lib.all (
{ fpath, mime, ... }: (fpath != "" && mime == "") || (fpath == "" && mime != "")
) cfg.associations;
message = ''
Each entry in programs.pistol.associations must contain exactly one
of fpath or mime.
'';
}
];
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
assertion = lib.all (
{ fpath, mime, ... }: (fpath != "" && mime == "") || (fpath == "" && mime != "")
) cfg.associations;
message = ''
Each entry in programs.pistol.associations must contain exactly one
of fpath or mime.
'';
}
];
(mkIf (cfg.associations != [ ] && pkgs.stdenv.hostPlatform.isDarwin) {
home.file."Library/Preferences/pistol/pistol.conf".text = configFile;
})
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
(mkIf (cfg.associations != [ ] && !pkgs.stdenv.hostPlatform.isDarwin) {
xdg.configFile."pistol/pistol.conf".text = configFile;
})
]
);
home.file."${configDir}/pistol/pistol.conf" = mkIf (cfg.associations != [ ]) {
text = configFile;
};
};
}

View File

@@ -19,11 +19,11 @@ let
valueToString =
value:
if builtins.isList value then
builtins.concatStringsSep "," (builtins.map valueToString value)
builtins.concatStringsSep "," (map valueToString value)
else if builtins.isAttrs value then
valueToString (lib.mapAttrsToList (key: val: "${valueToString key}=${valueToString val}") value)
else
builtins.toString value;
toString value;
modulesArgument = optionalString (cfg.modules != null) " -modules ${valueToString cfg.modules}";

View File

@@ -27,7 +27,7 @@ let
else if builtins.isList v then
"[${concatStringsSep ", " (map pythonize v)}]"
else
builtins.toString v;
toString v;
formatDictLine =
o: n: v:
@@ -336,22 +336,20 @@ in
greasemonkeyDir = lib.optionals (
cfg.greasemonkey != [ ]
) pkgs.linkFarmFromDrvs "greasemonkey-userscripts" cfg.greasemonkey;
configDir =
if pkgs.stdenv.hostPlatform.isDarwin then
".qutebrowser"
else
"${config.xdg.configHome}/qutebrowser";
in
mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
home.file.".qutebrowser/config.py" = mkIf pkgs.stdenv.hostPlatform.isDarwin {
text = qutebrowserConfig;
};
home.file.".qutebrowser/quickmarks" =
mkIf (cfg.quickmarks != { } && pkgs.stdenv.hostPlatform.isDarwin)
{
text = quickmarksFile;
};
xdg.configFile."qutebrowser/config.py" = mkIf pkgs.stdenv.hostPlatform.isLinux {
home.file."${configDir}/config.py" = {
text = qutebrowserConfig;
}
// lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux {
onChange = ''
hash="$(echo -n "$USER" | md5sum | cut -d' ' -f1)"
socket="''${XDG_RUNTIME_DIR:-/run/user/$UID}/qutebrowser/ipc-$hash"
@@ -371,22 +369,12 @@ in
'';
};
xdg.configFile."qutebrowser/quickmarks" =
mkIf (cfg.quickmarks != { } && pkgs.stdenv.hostPlatform.isLinux)
{
text = quickmarksFile;
};
home.file."${configDir}/quickmarks" = mkIf (cfg.quickmarks != { }) {
text = quickmarksFile;
};
home.file.".qutebrowser/greasemonkey" =
mkIf (cfg.greasemonkey != [ ] && pkgs.stdenv.hostPlatform.isDarwin)
{
source = greasemonkeyDir;
};
xdg.configFile."qutebrowser/greasemonkey" =
mkIf (cfg.greasemonkey != [ ] && pkgs.stdenv.hostPlatform.isLinux)
{
source = greasemonkeyDir;
};
home.file."${configDir}/greasemonkey" = mkIf (cfg.greasemonkey != [ ]) {
source = greasemonkeyDir;
};
};
}

View File

@@ -168,7 +168,7 @@ in
}
{
assertion = cfg.uri.web-rad.enable -> cfg.uri.web-rad.browser != null;
message = "Could not detect preferred browser. Please set `${builtins.toString opt.uri.web-rad.browser}`.";
message = "Could not detect preferred browser. Please set `${toString opt.uri.web-rad.browser}`.";
}
{
assertion =

View File

@@ -71,7 +71,7 @@ in
home.file.".rbenv/plugins" = mkIf (cfg.plugins != [ ]) {
source = pkgs.linkFarm "rbenv-plugins" (
builtins.map (p: {
map (p: {
name = p.name;
path = p.src;
}) cfg.plugins

View File

@@ -10,7 +10,6 @@ let
jsonFormat = pkgs.formats.json { };
inherit (lib) mkOption types;
inherit (pkgs.stdenv.hostPlatform) isDarwin;
settingsModule = types.submodule {
freeformType = jsonFormat.type;
@@ -62,6 +61,9 @@ let
};
};
};
configDir =
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Application Support" else config.xdg.configHome;
in
{
meta.maintainers = with lib.maintainers; [ ambroisie ];
@@ -93,21 +95,11 @@ in
};
};
config = lib.mkIf cfg.enable (
lib.mkMerge [
{
home.packages = [ cfg.package ];
}
config = lib.mkIf cfg.enable {
home.packages = [ cfg.package ];
# Only manage configuration if not empty
(lib.mkIf (cfg.settings != null && !isDarwin) {
xdg.configFile."rbw/config.json".source = jsonFormat.generate "rbw-config.json" cfg.settings;
})
(lib.mkIf (cfg.settings != null && isDarwin) {
home.file."Library/Application Support/rbw/config.json".source =
jsonFormat.generate "rbw-config.json" cfg.settings;
})
]
);
home.file."${configDir}/rbw/config.json" = lib.mkIf (cfg.settings != null) {
source = jsonFormat.generate "rbw-config.json" cfg.settings;
};
};
}

View File

@@ -135,7 +135,7 @@ let
modes = map (mode: if isString mode then mode else "${mode.name}:${mode.path}") cfg.modes;
in
{
meta.maintainers = with lib.maintainers; [ ];
meta.maintainers = [ ];
options.programs.rofi = {
enable = lib.mkEnableOption "Rofi: A window switcher, application launcher and dmenu replacement";

View File

@@ -11,6 +11,9 @@ let
iniFormat = pkgs.formats.ini { };
configDir =
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Preferences" else config.xdg.configHome;
in
{
meta.maintainers = [ lib.maintainers.pbar ];
@@ -55,32 +58,22 @@ in
{
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
programs.sapling.iniContent.ui = {
username = cfg.userName + " <" + cfg.userEmail + ">";
programs.sapling.iniContent = {
alias = mkIf (cfg.aliases != { }) cfg.aliases;
ui.username = cfg.userName + " <" + cfg.userEmail + ">";
};
home.file."${configDir}/sapling/sapling.conf" = mkIf (cfg.iniContent != { }) {
source = iniFormat.generate "sapling.conf" cfg.iniContent;
};
}
(mkIf (!pkgs.stdenv.isDarwin) {
xdg.configFile."sapling/sapling.conf".source = iniFormat.generate "sapling.conf" cfg.iniContent;
})
(mkIf (pkgs.stdenv.isDarwin) {
home.file."Library/Preferences/sapling/sapling.conf".source =
iniFormat.generate "sapling.conf" cfg.iniContent;
})
(mkIf (cfg.aliases != { }) {
programs.sapling.iniContent.alias = cfg.aliases;
})
(mkIf (lib.isAttrs cfg.extraConfig) {
programs.sapling.iniContent = cfg.extraConfig;
})
(mkIf (lib.isString cfg.extraConfig && !pkgs.stdenv.isDarwin) {
xdg.configFile."sapling/sapling.conf".text = cfg.extraConfig;
})
(mkIf (lib.isString cfg.extraConfig && pkgs.stdenv.isDarwin) {
home.file."Library/Preferences/sapling/sapling.conf".text = cfg.extraConfig;
(mkIf (lib.isString cfg.extraConfig) {
home.file."${configDir}/sapling/sapling.conf".text = cfg.extraConfig;
})
]
);

View File

@@ -40,6 +40,12 @@ let
description = "The remote path to mount.";
};
mountDestPath = mkOption {
type = types.nullOr types.str;
default = null;
description = "The path on the current machine where the remote path would be mounted.";
};
authType = mkOption {
type = types.enum [
"password"
@@ -47,6 +53,7 @@ let
"hostbased"
"keyboard-interactive"
"gssapi-with-mic"
"authentication-agent"
];
default = "publickey";
description = "The authentication method to use.";

View File

@@ -158,7 +158,7 @@ in
prjConf =
lib.attrsets.mapAttrs' (
name: value:
(lib.attrsets.nameValuePair (if name == "beforeStart" then "before_start" else name) (value))
(lib.attrsets.nameValuePair (if name == "beforeStart" then "before_start" else name) value)
) v
// {
session = k;

View File

@@ -9,6 +9,11 @@ let
cfg = config.programs.streamlink;
configDir =
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Application Support" else config.xdg.configHome;
dataDir =
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Application Support" else config.xdg.dataHome;
renderSettings =
settings:
lib.concatLines (
@@ -18,9 +23,9 @@ let
if (builtins.isBool value) then
if value then name else ""
else if (builtins.isList value) then
lib.concatStringsSep "\n" (builtins.map (item: "${name}=${builtins.toString item}") value)
lib.concatStringsSep "\n" (map (item: "${name}=${toString item}") value)
else
"${name}=${builtins.toString value}"
"${name}=${toString value}"
) settings
)
);
@@ -130,72 +135,36 @@ in
};
};
config = lib.mkIf cfg.enable (
lib.mkMerge [
{ home.packages = lib.mkIf (cfg.package != null) [ cfg.package ]; }
config = lib.mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
(lib.mkIf pkgs.stdenv.hostPlatform.isLinux {
xdg.configFile = {
"streamlink/config" = lib.mkIf (cfg.settings != { }) {
text = renderSettings cfg.settings;
};
home.file = {
"${configDir}/streamlink/config" = lib.mkIf (cfg.settings != { }) {
text = renderSettings cfg.settings;
};
}
// (lib.mapAttrs' (
name: value:
lib.nameValuePair "${configDir}/streamlink/config.${name}" (
lib.mkIf (value.settings != { }) {
text = renderSettings value.settings;
}
// (lib.mapAttrs' (
name: value:
lib.nameValuePair "streamlink/config.${name}" (
lib.mkIf (value.settings != { }) {
text = renderSettings value.settings;
)
) cfg.plugins)
// (lib.mapAttrs' (
name: value:
lib.nameValuePair "${dataDir}/streamlink/plugins/${name}.py" (
lib.mkIf (value.src != null) (
if (builtins.isPath value.src) then
{
source = value.src;
}
)
) cfg.plugins);
xdg.dataFile = lib.mapAttrs' (
name: value:
lib.nameValuePair "streamlink/plugins/${name}.py" (
lib.mkIf (value.src != null) (
if (builtins.isPath value.src) then
{
source = value.src;
}
else
{
text = value.src;
}
)
)
) cfg.plugins;
})
(lib.mkIf pkgs.stdenv.hostPlatform.isDarwin {
home.file = {
"Library/Application Support/streamlink/config" = lib.mkIf (cfg.settings != { }) {
text = renderSettings cfg.settings;
};
}
// (lib.mapAttrs' (
name: value:
lib.nameValuePair "Library/Application Support/streamlink/config.${name}" (
lib.mkIf (value.settings != { }) {
text = renderSettings value.settings;
else
{
text = value.src;
}
)
) cfg.plugins)
// (lib.mapAttrs' (
name: value:
lib.nameValuePair "Library/Application Support/streamlink/plugins/${name}.py" (
lib.mkIf (value.src != null) (
if (builtins.isPath value.src) then
{
source = value.src;
}
else
{
text = value.src;
}
)
)
) cfg.plugins);
})
]
);
)
)
) cfg.plugins);
};
}

View File

@@ -85,8 +85,7 @@ in
if v == false then
""
else
(if v == true then n else n + "=" + (if builtins.isPath v then "${v}" else builtins.toString v))
+ "\n"
(if v == true then n else n + "=" + (if builtins.isPath v then "${v}" else toString v)) + "\n"
) cfg.settings
);
};

View File

@@ -183,14 +183,12 @@ let
3;
"mail.smtpserver.smtp_${id}.username" = account.userName;
}
// builtins.foldl' (a: b: a // b) { } (
builtins.map (address: toThunderbirdSMTP account address) addresses
)
// builtins.foldl' (a: b: a // b) { } (map (address: toThunderbirdSMTP account address) addresses)
// optionalAttrs (account.smtp != null && account.primary) {
"mail.smtp.defaultserver" = "smtp_${id}";
}
// builtins.foldl' (a: b: a // b) { } (
builtins.map (address: toThunderbirdIdentity account address) addresses
map (address: toThunderbirdIdentity account address) addresses
)
// account.thunderbird.settings id;

View File

@@ -69,7 +69,7 @@ in
let
conf =
optional (cfg.host != null) ''set -g tmate-server-host "${cfg.host}"''
++ optional (cfg.port != null) "set -g tmate-server-port ${builtins.toString cfg.port}"
++ optional (cfg.port != null) "set -g tmate-server-port ${toString cfg.port}"
++ optional (
cfg.dsaFingerprint != null
) ''set -g tmate-server-ed25519-fingerprint "${cfg.dsaFingerprint}"''

View File

@@ -92,9 +92,12 @@ in
};
};
config = lib.mkIf cfg.enable (
config =
let
config =
configDir =
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Application Support" else config.xdg.configHome;
configFiles =
lib.attrsets.unionOfDisjoint
{
"vesktop/settings.json" = lib.mkIf (cfg.settings != { }) {
@@ -117,16 +120,11 @@ in
) cfg.vencord.themes
);
in
lib.mkMerge [
{
home.packages = [
(cfg.package.override { withSystemVencord = cfg.vencord.useSystem; })
];
}
(lib.mkIf (!pkgs.stdenv.hostPlatform.isDarwin) { xdg.configFile = config; })
(lib.mkIf pkgs.stdenv.hostPlatform.isDarwin {
home.file = lib.mapAttrs' (n: v: lib.nameValuePair "Library/Application Support/${n}" v) config;
})
]
);
lib.mkIf cfg.enable {
home.packages = [
(cfg.package.override { withSystemVencord = cfg.vencord.useSystem; })
];
home.file = lib.mapAttrs' (n: lib.nameValuePair "${configDir}/${n}") configFiles;
};
}

View File

@@ -240,7 +240,7 @@ in
dataFile =
builtins.listToAttrs (
builtins.map (item: {
map (item: {
name = "vicinae/extensions/${item.name}";
value.source = item;
}) cfg.extensions
@@ -263,7 +263,7 @@ in
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}
USE_LAYER_SHELL=${if cfg.useLayerShell then toString 1 else toString 0}
''
);
};

View File

@@ -517,7 +517,7 @@ in
else
{ };
# Merge MCP servers: transformed servers + user servers, with user servers taking precedence
mergedServers = transformedMcpServers // ((v.userMcp.servers or { }));
mergedServers = transformedMcpServers // (v.userMcp.servers or { });
# Merge all MCP config
mergedMcpConfig =
v.userMcp // (lib.optionalAttrs (mergedServers != { }) { servers = mergedServers; });

View File

@@ -301,7 +301,7 @@ in
{
assertions = [
(lib.hm.assertions.assertPlatform "programs.waybar" pkgs lib.platforms.linux)
({
{
assertion =
if lib.versionAtLeast config.home.stateVersion "22.05" then
all (x: !hasAttr "modules" x || x.modules == null) settings
@@ -311,7 +311,7 @@ in
The `programs.waybar.settings.[].modules` option has been removed.
It is now possible to declare modules in the configuration without nesting them under the `modules` option.
'';
})
}
];
home.packages = [ cfg.package ];

View File

@@ -58,7 +58,7 @@ in
xdg.configFile."waylogout/config" = lib.mkIf (cfg.settings != { }) {
text = lib.concatStrings (
lib.mapAttrsToList (
n: v: if v == false then "" else (if v == true then n else n + "=" + builtins.toString v) + "\n"
n: v: if v == false then "" else (if v == true then n else n + "=" + toString v) + "\n"
) cfg.settings
);
};

View File

@@ -0,0 +1,94 @@
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) literalExpression mkOption mkEnableOption;
inherit (lib.modules) mkIf;
cfg = config.programs.workstyle;
tomlFormat = pkgs.formats.toml { };
configFile = tomlFormat.generate "config.toml" cfg.settings;
in
{
meta.maintainers = with lib.hm.maintainers; [ farberbrodsky ];
options.programs.workstyle = {
enable = mkEnableOption "Workstyle";
package = lib.mkPackageOption pkgs "workstyle" { };
systemd = {
enable = mkEnableOption "Workstyle systemd integration";
debug = mkEnableOption "Workstyle debug logs";
target = mkOption {
type = lib.types.str;
default = config.wayland.systemd.target;
defaultText = literalExpression "config.wayland.systemd.target";
example = "sway-session.target";
description = ''
The systemd target that will automatically start the Workstyle 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.
'';
};
};
settings = lib.mkOption {
inherit (tomlFormat) type;
default = { };
description = "Configuration for workstyle";
example = literalExpression ''
{
# Config for workstyle
# Format: "pattern" = "icon";
# The pattern will be used to match against the application name, class_id or WM_CLASS.
# The icon will be used to represent that application.
# Note if multiple patterns are present in the same application name,
# precedence is given in order of apparition in this file.
kitty = "T";
firefox = "B";
other = {
fallback_icon = "F";
deduplicate_icons = false;
separator = ": ";
};
}
'';
};
};
config = lib.mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "programs.workstyle" pkgs lib.platforms.linux)
];
home.packages = [ cfg.package ];
xdg.configFile."workstyle/config.toml" = mkIf (cfg.settings != { }) { source = configFile; };
systemd.user.services.workstyle = mkIf cfg.systemd.enable {
Unit = {
Description = "workstyle autostart";
BindsTo = [ cfg.systemd.target ];
# This is not necessary: workstyle reloads the config file after every window event.
# It might become necessary in the future.
# X-Restart-Triggers = mkIf (cfg.settings != { }) [ "${configFile}" ];
};
Service = {
ExecStart = "${cfg.package}/bin/workstyle";
Restart = "always";
RestartSec = 3;
Environment = mkIf (cfg.systemd.debug) "RUST_LOG=debug";
};
Install.WantedBy = [ cfg.systemd.target ];
};
};
}

View File

@@ -35,7 +35,7 @@ let
'';
}
else
builtins.dirOf value;
dirOf value;
makePluginSearchPath = p: "${p}/?/init.lua;${p}/?.lua";
@@ -46,9 +46,9 @@ let
searchPaths = map makePluginSearchPath wrappedPlugins;
pluginSearchPath = lib.concatStringsSep ";" searchPaths;
in
(''
''
package.path = "${pluginSearchPath};" .. package.path
'')
''
else
"\n";

View File

@@ -127,7 +127,7 @@ in
};
Service = {
Environment = with pkgs; "PATH=${makeBinPath cfg.extraPackages}";
Environment = "PATH=${makeBinPath cfg.extraPackages}";
ExecStart = "${cfg.package}/bin/fusuma";
};

View File

@@ -64,7 +64,10 @@ in
importantPrefixes = lib.mkOption {
type = with lib.types; listOf str;
default = [ "$" ];
default = [
"$"
"monitor"
];
example = [ "$" ];
description = ''
List of prefix of attributes to source at the top of the config.

View File

@@ -117,7 +117,7 @@ in
args = lib.lists.forEach cfg.wallpapers (
each:
lib.concatStringsSep " " (
lib.cli.toGNUCommandLine { } {
lib.cli.toCommandLineGNU { } {
screen-root = each.monitor;
inherit (each) scaling fps;
inherit (each.audio) silent;
@@ -125,9 +125,11 @@ in
no-audio-processing = !each.audio.processing;
}
++ each.extraOptions
++ [
"--bg"
each.wallpaperId
]
)
# This has to be the last argument in each group
+ " --bg ${each.wallpaperId}"
);
in
{

View File

@@ -166,10 +166,14 @@ in
mkIf cfg.enable {
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;
};
sessionVariables = mkIf cfg.enableSessionVariables (
{
MPD_PORT = toString cfg.network.port;
}
// lib.optionalAttrs (cfg.network.listenAddress != "any") {
MPD_HOST = cfg.network.listenAddress;
}
);
};
services.mpd = lib.mkMerge [

View File

@@ -0,0 +1,23 @@
{ lib }:
{
assertPlatform =
module: config: pkgs: platforms:
let
modulePath = lib.splitString "." module;
isEmpty = x: x == false || x == null || x == { } || x == [ ] || x == "";
in
{
assertion =
(isEmpty (lib.attrByPath modulePath null config))
|| (lib.elem pkgs.stdenv.hostPlatform.system platforms);
message =
let
platformsStr = lib.concatStringsSep "\n" (map (p: " - ${p}") (lib.sort (a: b: a < b) platforms));
in
''
The module ${module} does not support your platform. It only supports
${platformsStr}'';
};
}

View File

@@ -0,0 +1,301 @@
{
config,
lib,
pkgs,
...
}:
let
inherit (lib)
attrNames
concatStringsSep
filterAttrs
mapAttrs'
mkIf
mkOption
mkMerge
nameValuePair
optionalString
types
;
assertions = import ./assertions.nix { inherit lib; };
cfg = config.services.podman;
machineDefinitionType = types.submodule {
options = {
cpus = mkOption {
type = types.nullOr types.ints.positive;
default = null;
example = 2;
description = "Number of CPUs to allocate to the machine. If null, uses podman's default.";
};
diskSize = mkOption {
type = types.nullOr types.ints.positive;
default = null;
example = 200;
description = "Disk size in GB for the machine. If null, uses podman's default.";
};
image = mkOption {
type = types.nullOr types.str;
default = null;
description = "Bootable image to use for the machine. If null, uses podman's default.";
};
memory = mkOption {
type = types.nullOr types.ints.positive;
default = null;
example = 8192;
description = "Memory in MB to allocate to the machine. If null, uses podman's default.";
};
rootful = mkOption {
type = types.nullOr types.bool;
default = null;
example = true;
description = ''
Whether to run the machine in rootful mode. If null, uses podman's default.
Rootful mode runs containers as root inside the VM.
'';
};
swap = mkOption {
type = types.nullOr types.ints.positive;
default = null;
example = 2048;
description = "Swap size in MB for the machine. If null, uses podman's default.";
};
timezone = mkOption {
type = types.nullOr types.str;
default = null;
example = "UTC";
description = "Timezone to set in the machine. If null, uses podman's default.";
};
username = mkOption {
type = types.nullOr types.str;
default = null;
example = "user";
description = "Username used in the machine image. If null, uses podman's default.";
};
volumes = mkOption {
type = types.listOf types.str;
default = [ ];
example = [
"/Users:/Users"
"/private:/private"
"/var/folders:/var/folders"
];
description = ''
Volumes to mount in the machine, specified as source:target pairs.
If empty, podman will use its default volume mounts.
'';
};
autoStart = mkOption {
type = types.bool;
default = true;
example = false;
description = "Whether to automatically start this machine on login.";
};
watchdogInterval = mkOption {
type = types.ints.positive;
default = 30;
example = 60;
description = "Interval in seconds to check if the machine is running";
};
};
};
mkWatchdogScript =
name: machine:
pkgs.writeShellScript "podman-machine-watchdog-${name}" ''
set -euo pipefail
MACHINE_NAME="${name}"
INTERVAL=${toString machine.watchdogInterval}
PODMAN="${lib.getExe cfg.package}"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >&2
}
check_and_start() {
local state
state=$($PODMAN machine inspect "$MACHINE_NAME" --format '{{.State}}' 2>/dev/null || echo "unknown")
case "$state" in
running)
return 0
;;
stopped|unknown)
log "Machine '$MACHINE_NAME' is starting..."
if $PODMAN machine start "$MACHINE_NAME" 2>&1 | while IFS= read -r line; do log "$line"; done; then
log "Machine '$MACHINE_NAME' started successfully"
return 0
else
log "Failed to start machine '$MACHINE_NAME'"
return 1
fi
;;
*)
log "Machine '$MACHINE_NAME' is $state"
return 1
;;
esac
}
log "Starting watchdog for machine '$MACHINE_NAME' (check interval: ''${INTERVAL}s)"
while true; do
check_and_start || true
sleep "$INTERVAL"
done
'';
in
{
options.services.podman = {
useDefaultMachine = mkOption {
type = types.bool;
default = pkgs.stdenv.hostPlatform.isDarwin;
description = ''
Whether to create and use the default podman machine.
The default machine will be named `podman-machine-default` and configured with podmans default values.
'';
readOnly = pkgs.stdenv.hostPlatform.isLinux;
};
machines = mkOption {
type = types.attrsOf machineDefinitionType;
default = { };
description = "Declarative podman machine configurations.";
example = lib.literalExpression ''
{
"dev-machine" = {
cpus = 4;
diskSize = 100;
memory = 8192;
swap = 2048;
timezone = "UTC";
volumes = [
"/Users:/Users"
"/private:/private"
];
autoStart = true;
watchdogInterval = 30;
};
"testing" = {
cpus = 2;
diskSize = 50;
image = "ghcr.io/your-org/custom-image:latest";
memory = 4096;
username = "podman";
autoStart = false;
};
}
'';
};
};
config =
let
podmanCmd = lib.getExe cfg.package;
allMachines =
cfg.machines
// (
if cfg.useDefaultMachine then
{
"podman-machine-default" = {
cpus = null;
diskSize = null;
image = null;
memory = null;
rootful = null;
swap = null;
timezone = null;
username = null;
volumes = [ ];
autoStart = true;
watchdogInterval = 30;
};
}
else
{ }
);
autoStartMachines = filterAttrs (_name: machine: machine.autoStart) allMachines;
in
mkIf cfg.enable (mkMerge [
{
assertions = [
(assertions.assertPlatform "services.podman.useDefaultMachine" config pkgs lib.platforms.darwin)
(assertions.assertPlatform "services.podman.machines" config pkgs lib.platforms.darwin)
];
}
(mkIf pkgs.stdenv.isDarwin {
home.activation.podmanMachines =
let
mkMachineInitScript =
name: machine:
let
# Automatically mount host's container config into the VM
username = if isNull machine.username then "core" else machine.username;
configVolume = "$HOME/.config/containers:/home/${username}/.config/containers";
allVolumes = [ configVolume ] ++ machine.volumes;
in
''
if ! ${podmanCmd} machine list --format '{{.Name}}' 2>/dev/null | sed 's/\*$//' | grep -q '^${name}$'; then
echo "Creating podman machine: ${name}"
${podmanCmd} machine init ${name} \
${optionalString (machine.cpus != null) "--cpus ${toString machine.cpus}"} \
${optionalString (machine.diskSize != null) "--disk-size ${toString machine.diskSize}"} \
${optionalString (machine.image != null) "--image ${machine.image}"} \
${optionalString (machine.memory != null) "--memory ${toString machine.memory}"} \
${optionalString ((machine.rootful != null) && machine.rootful) "--rootful"} \
${optionalString (machine.swap != null) "--swap ${toString machine.swap}"} \
${optionalString (machine.timezone != null) "--timezone \"${machine.timezone}\""} \
${optionalString (machine.username != null) "--username \"${machine.username}\""} \
${concatStringsSep " " (map (v: "--volume \"${v}\"") allVolumes)}
fi
'';
in
lib.hm.dag.entryAfter [ "writeBoundary" ] ''
PATH="${cfg.package}/bin:$PATH"
${concatStringsSep "\n" (lib.mapAttrsToList mkMachineInitScript allMachines)}
MANAGED_MACHINES="${concatStringsSep " " (attrNames allMachines)}"
EXISTING_MACHINES=$(${podmanCmd} machine list --format '{{.Name}}' 2>/dev/null | sed 's/\*$//' || echo "")
for machine in $EXISTING_MACHINES; do
if [[ ! " $MANAGED_MACHINES " =~ " $machine " ]]; then
echo "Removing unmanaged podman machine: $machine"
${podmanCmd} machine stop "$machine" 2>/dev/null || true
${podmanCmd} machine rm -f "$machine"
fi
done
'';
launchd.agents = mapAttrs' (
name: machine:
nameValuePair "podman-machine-${name}" {
enable = true;
config = {
ProgramArguments = [ "${mkWatchdogScript name machine}" ];
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
ProcessType = "Background";
RunAtLoad = true;
};
}
) autoStartMachines;
})
]);
}

View File

@@ -1,7 +1,7 @@
{
config,
pkgs,
lib,
pkgs,
...
}:
let
@@ -12,21 +12,19 @@ in
meta.maintainers = [
lib.hm.maintainers.bamhm182
lib.maintainers.n-hass
lib.maintainers.delafthi
];
imports = [
./builds.nix
./containers.nix
./images.nix
./install-quadlet.nix
./networks.nix
./services.nix
./volumes.nix
./linux/default.nix
./darwin.nix
];
options.services.podman = {
enable = lib.mkEnableOption "Podman, a daemonless container engine";
package = lib.mkPackageOption pkgs "podman" { };
settings = {
containers = lib.mkOption {
type = toml.type;
@@ -94,14 +92,14 @@ in
};
config = lib.mkIf cfg.enable {
assertions = [ (lib.hm.assertions.assertPlatform "podman" pkgs lib.platforms.linux) ];
home.packages = [ cfg.package ];
services.podman.settings.storage = {
storage.driver = lib.mkDefault "overlay";
};
services.podman.settings.storage.storage.driver = lib.mkDefault "overlay";
# Configuration files are written to `$XDG_CONFIG_HOME/.config/containers`
# On Linux: podman reads them directly from this location
# On Darwin: these files are automatically mounted into the podman machine VM
# (see darwin.nix for the volume mount configuration)
xdg.configFile = {
"containers/policy.json".source =
if cfg.settings.policy != { } then

View File

@@ -5,7 +5,13 @@
...
}:
let
inherit (lib) mkOption types;
inherit (lib)
mkIf
mkOption
mkMerge
types
;
assertions = import ../assertions.nix { inherit lib; };
cfg = config.services.podman;
@@ -182,10 +188,17 @@ in
let
buildQuadlets = lib.mapAttrsToList toQuadletInternal cfg.builds;
in
lib.mkIf cfg.enable {
services.podman.internal.quadletDefinitions = buildQuadlets;
assertions = lib.flatten (map (build: build.assertions) buildQuadlets);
mkIf cfg.enable (mkMerge [
{
assertions = [
(assertions.assertPlatform "services.podman.builds" config pkgs lib.platforms.linux)
];
}
(mkIf pkgs.stdenv.hostPlatform.isLinux {
services.podman.internal.quadletDefinitions = buildQuadlets;
assertions = lib.flatten (map (build: build.assertions) buildQuadlets);
xdg.configFile."podman/images.manifest".text = podman-lib.generateManifestText buildQuadlets;
};
xdg.configFile."podman/images.manifest".text = podman-lib.generateManifestText buildQuadlets;
})
]);
}

View File

@@ -5,7 +5,13 @@
...
}:
let
inherit (lib) mkOption types;
inherit (lib)
mkIf
mkOption
mkMerge
types
;
assertions = import ../assertions.nix { inherit lib; };
cfg = config.services.podman;
@@ -401,12 +407,19 @@ in
let
containerQuadlets = lib.mapAttrsToList toQuadletInternal cfg.containers;
in
lib.mkIf cfg.enable {
services.podman.internal.quadletDefinitions = containerQuadlets;
assertions = lib.flatten (map (container: container.assertions) containerQuadlets);
mkIf cfg.enable (mkMerge [
{
assertions = [
(assertions.assertPlatform "services.podman.containers" config pkgs lib.platforms.linux)
];
}
(mkIf pkgs.stdenv.hostPlatform.isLinux {
services.podman.internal.quadletDefinitions = containerQuadlets;
assertions = lib.flatten (map (container: container.assertions) containerQuadlets);
# manifest file
xdg.configFile."podman/containers.manifest".text =
podman-lib.generateManifestText containerQuadlets;
};
# manifest file
xdg.configFile."podman/containers.manifest".text =
podman-lib.generateManifestText containerQuadlets;
})
]);
}

View File

@@ -0,0 +1,12 @@
{
imports = [
./options.nix
./builds.nix
./containers.nix
./images.nix
./install-quadlet.nix
./networks.nix
./services.nix
./volumes.nix
];
}

View File

@@ -5,7 +5,13 @@
...
}:
let
inherit (lib) mkOption types;
inherit (lib)
mkIf
mkOption
mkMerge
types
;
assertions = import ../assertions.nix { inherit lib; };
cfg = config.services.podman;
@@ -165,8 +171,15 @@ in
let
imageQuadlets = lib.mapAttrsToList toQuadletInternal cfg.images;
in
lib.mkIf cfg.enable {
services.podman.internal.quadletDefinitions = imageQuadlets;
assertions = lib.flatten (map (image: image.assertions) imageQuadlets);
};
mkIf cfg.enable (mkMerge [
{
assertions = [
(assertions.assertPlatform "services.podman.images" config pkgs lib.platforms.linux)
];
}
(mkIf pkgs.stdenv.hostPlatform.isLinux {
services.podman.internal.quadletDefinitions = imageQuadlets;
assertions = lib.flatten (map (image: image.assertions) imageQuadlets);
})
]);
}

View File

@@ -99,7 +99,7 @@ in
{
imports = [ ./options.nix ];
config = lib.mkIf cfg.enable {
config = lib.mkIf (cfg.enable && pkgs.stdenv.hostPlatform.isLinux) {
home.file = generateSystemdFileLinks allUnitFiles;
# if the length of builtQuadlets is 0, then we don't need register the activation script

View File

@@ -5,7 +5,13 @@
...
}:
let
inherit (lib) mkOption types;
inherit (lib)
mkIf
mkOption
mkMerge
types
;
assertions = import ../assertions.nix { inherit lib; };
cfg = config.services.podman;
@@ -180,10 +186,17 @@ in
let
networkQuadlets = lib.mapAttrsToList toQuadletInternal cfg.networks;
in
lib.mkIf cfg.enable {
services.podman.internal.quadletDefinitions = networkQuadlets;
assertions = lib.flatten (map (network: network.assertions) networkQuadlets);
mkIf cfg.enable (mkMerge [
{
assertions = [
(assertions.assertPlatform "services.podman.networks" config pkgs lib.platforms.linux)
];
}
(mkIf pkgs.stdenv.hostPlatform.isLinux {
services.podman.internal.quadletDefinitions = networkQuadlets;
assertions = lib.flatten (map (network: network.assertions) networkQuadlets);
xdg.configFile."podman/networks.manifest".text = podman-lib.generateManifestText networkQuadlets;
};
xdg.configFile."podman/networks.manifest".text = podman-lib.generateManifestText networkQuadlets;
})
]);
}

View File

@@ -1,37 +1,47 @@
{ lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkEnableOption mkIf mkOption;
assertions = import ../assertions.nix { inherit lib; };
cfg = config.services.podman;
# Define the systemd service type
quadletInternalType = lib.types.submodule {
options = {
assertions = lib.mkOption {
assertions = mkOption {
type = with lib.types; listOf unspecified;
default = [ ];
internal = true;
description = "List of Nix type assertions.";
};
dependencies = lib.mkOption {
dependencies = mkOption {
type = with lib.types; listOf package;
default = [ ];
internal = true;
description = "List of systemd service dependencies.";
};
resourceType = lib.mkOption {
resourceType = mkOption {
type = lib.types.str;
default = "";
internal = true;
description = "The type of the podman Quadlet resource.";
};
serviceName = lib.mkOption {
serviceName = mkOption {
type = lib.types.str;
internal = true;
description = "The name of the systemd service.";
};
source = lib.mkOption {
source = mkOption {
type = lib.types.str;
internal = true;
description = "The quadlet source file content.";
@@ -42,13 +52,13 @@ in
{
options.services.podman = {
internal = {
quadletDefinitions = lib.mkOption {
quadletDefinitions = mkOption {
type = lib.types.listOf quadletInternalType;
default = { };
internal = true;
description = "List of quadlet source file content and service names.";
};
builtQuadlets = lib.mkOption {
builtQuadlets = mkOption {
type = with lib.types; attrsOf package;
default = { };
internal = true;
@@ -56,8 +66,11 @@ in
};
};
package = lib.mkPackageOption pkgs "podman" { };
enableTypeChecks = lib.mkEnableOption "type checks for podman quadlets";
enableTypeChecks = mkEnableOption "type checks for podman quadlets";
};
config = mkIf cfg.enable {
assertions = [
(assertions.assertPlatform "services.podman.enableTypeChecks" config pkgs lib.platforms.linux)
];
};
}

View File

@@ -23,9 +23,9 @@ let
${k}='' (mapAttrsToList normalizeKeyValue v))
else
builtins.toString v;
toString v;
in
if builtins.isNull v then "" else "${k}=${v'}";
if isNull v then "" else "${k}=${v'}";
primitiveAttrs = with types; attrsOf (either primitive (listOf primitive));
primitiveList = with types; listOf primitive;

View File

@@ -5,20 +5,23 @@
...
}:
let
inherit (lib) mkIf mkOption mkMerge;
assertions = import ../assertions.nix { inherit lib; };
cfg = config.services.podman;
in
{
options.services.podman = {
autoUpdate = {
enable = lib.mkOption {
enable = mkOption {
type = lib.types.bool;
default = false;
default = pkgs.stdenv.hostPlatform.isLinux;
description = "Automatically update the podman images.";
};
onCalendar = lib.mkOption {
onCalendar = mkOption {
type = lib.types.str;
default = "Sun *-*-* 00:00";
default = lib.optionalString pkgs.stdenv.hostPlatform.isLinux "Sun *-*-* 00:00";
description = ''
The systemd `OnCalendar` expression for the update. See
{manpage}`systemd.time(7)` for a description of the format.
@@ -27,9 +30,14 @@ in
};
};
config = lib.mkIf cfg.enable (
lib.mkMerge [
(lib.mkIf cfg.autoUpdate.enable {
config = mkIf cfg.enable (mkMerge [
{
assertions = [
(assertions.assertPlatform "services.podman.networks" config pkgs lib.platforms.linux)
];
}
(mkIf pkgs.stdenv.hostPlatform.isLinux (mkMerge [
(mkIf cfg.autoUpdate.enable {
systemd.user.services."podman-auto-update" = {
Unit = {
Description = "Podman auto-update service";
@@ -86,6 +94,6 @@ in
}:/bin
'';
}
]
);
]))
]);
}

View File

@@ -5,7 +5,13 @@
...
}:
let
inherit (lib) mkOption types;
inherit (lib)
mkIf
mkOption
mkMerge
types
;
assertions = import ../assertions.nix { inherit lib; };
cfg = config.services.podman;
@@ -192,10 +198,17 @@ in
let
volumeQuadlets = lib.mapAttrsToList toQuadletInternal cfg.volumes;
in
lib.mkIf cfg.enable {
services.podman.internal.quadletDefinitions = volumeQuadlets;
assertions = lib.flatten (map (volume: volume.assertions) volumeQuadlets);
mkIf cfg.enable (mkMerge [
{
assertions = [
(assertions.assertPlatform "services.podman.volumes" config pkgs lib.platforms.linux)
];
}
(mkIf pkgs.stdenv.hostPlatform.isLinux {
services.podman.internal.quadletDefinitions = volumeQuadlets;
assertions = lib.flatten (map (volume: volume.assertions) volumeQuadlets);
xdg.configFile."podman/volumes.manifest".text = podman-lib.generateManifestText volumeQuadlets;
};
xdg.configFile."podman/volumes.manifest".text = podman-lib.generateManifestText volumeQuadlets;
})
]);
}

View File

@@ -15,7 +15,7 @@ let
''}
USE_BACKUP="${if cfg.useBackup then "yes" else "no"}"
BACKUP_LIMIT=${builtins.toString cfg.backupLimit}
BACKUP_LIMIT=${toString cfg.backupLimit}
'';
in
{

View File

@@ -7,6 +7,8 @@
let
cfg = config.services.pueue;
yamlFormat = pkgs.formats.yaml { };
configDir =
if pkgs.stdenv.hostPlatform.isDarwin then "Library/Application Support" else config.xdg.configHome;
configFile = yamlFormat.generate "pueue.yaml" ({ shared = { }; } // cfg.settings);
pueuedBin = "${cfg.package}/bin/pueued";
in
@@ -38,7 +40,7 @@ in
config = lib.mkIf cfg.enable {
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
xdg.configFile."pueue/pueue.yml" = lib.mkIf pkgs.stdenv.isLinux { source = configFile; };
home.file."${configDir}/pueue/pueue.yml".source = configFile;
systemd.user = lib.mkIf (cfg.package != null) {
services.pueued = {
@@ -55,12 +57,6 @@ in
};
};
# This is the default configuration file location for pueue on
# darwin (https://github.com/Nukesor/pueue/wiki/Configuration)
home.file."Library/Application Support/pueue/pueue.yml" = lib.mkIf pkgs.stdenv.isDarwin {
source = configFile;
};
launchd.agents.pueued = lib.mkIf (cfg.package != null) {
enable = true;

View File

@@ -103,7 +103,7 @@ in
StopWhenUnneeded = cfg.node.lazy.enable;
ConditionPathExists = radicleKeyPair;
};
Service = mkMerge ([
Service = mkMerge [
{
Slice = "session.slice";
ExecStart = "${getExe' cfg.node.package "radicle-node"} ${cfg.node.args}";
@@ -182,7 +182,7 @@ in
"~@setuid"
];
}
]);
];
};
"radicle-node-proxy" = mkIf cfg.node.lazy.enable {
Unit = {

View File

@@ -239,7 +239,7 @@ in
configFullPath = config.xdg.configHome + "/${xdgConfigFilePath}";
in
"${cfg.package}/bin/${command} "
+ lib.cli.toGNUCommandLineShell { } {
+ lib.cli.toCommandLineShellGNU { } {
v = cfg.enableVerboseLogging;
c = configFullPath;
};

View File

@@ -37,6 +37,17 @@ in
'';
};
pkcs11Whitelist = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = lib.literalExpression ''[ "''${pkgs.tpm2-pkcs11}/lib/*" ]'';
description = ''
Specify a list of approved path patterns for PKCS#11 and FIDO authenticator middleware libraries. When using the -s or -S options with {manpage}`ssh-add(1)`, only libraries matching these patterns will be accepted.
See {manpage}`ssh-agent(1)`.
'';
};
enableBashIntegration = lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableZshIntegration = lib.hm.shell.mkZshIntegrationOption { inherit config; };
@@ -101,6 +112,10 @@ in
lib.optionalString (
cfg.defaultMaximumIdentityLifetime != null
) " -t ${toString cfg.defaultMaximumIdentityLifetime}"
}${
lib.optionalString (
cfg.pkcs11Whitelist != [ ]
) " -P '${lib.concatStringsSep "," cfg.pkcs11Whitelist}'"
}";
};
@@ -114,6 +129,10 @@ in
lib.optionalString (
cfg.defaultMaximumIdentityLifetime != null
) " -t ${toString cfg.defaultMaximumIdentityLifetime}"
}${
lib.optionalString (
cfg.pkcs11Whitelist != [ ]
) " -P '${lib.concatStringsSep "," cfg.pkcs11Whitelist}'"
}''
];
KeepAlive = {
@@ -124,7 +143,5 @@ in
RunAtLoad = true;
};
};
};
}

View File

@@ -130,6 +130,7 @@ in
- `HYPRLAND_INSTANCE_SIGNATURE`
- `WAYLAND_DISPLAY`
- `XDG_CURRENT_DESKTOP`
- `XDG_SESSION_TYPE`
'';
};
@@ -140,6 +141,7 @@ in
"HYPRLAND_INSTANCE_SIGNATURE"
"WAYLAND_DISPLAY"
"XDG_CURRENT_DESKTOP"
"XDG_SESSION_TYPE"
];
example = [ "--all" ];
description = ''
@@ -359,7 +361,7 @@ in
) cfg.submaps;
submapWarnings = lib.mapAttrsToList (submapName: nonBinds: ''
wayland.windowManager.hyprland.submaps."${submapName}".settings: found non-bind entries: [${builtins.toString nonBinds}], which will have no effect in a submap
wayland.windowManager.hyprland.submaps."${submapName}".settings: found non-bind entries: [${toString nonBinds}], which will have no effect in a submap
'') (lib.filterAttrs (n: v: v != [ ]) submapWarningsAttrset);
in
submapWarnings ++ lib.optional inconsistent warning;

View File

@@ -98,7 +98,7 @@ let
attrName = builtins.substring 1 999 k; # Remove "@" prefix
attrValue = value.${k};
in
" ${attrName}=\"${escape (builtins.toString attrValue)}\""
" ${attrName}=\"${escape (toString attrValue)}\""
) attrKeys
);
@@ -125,7 +125,7 @@ let
# All other primitive values: wrap in start/end tag
else
"<${name}>${escape (builtins.toString value)}</${name}>";
"<${name}>${escape (toString value)}</${name}>";
generateXML = name: config: extraConfig: ''
<?xml version="1.0" encoding="UTF-8"?>
@@ -139,7 +139,7 @@ let
else if name == "labwc_config" then
lib.mapAttrsToList generateRc
else
builtins.throw "error ${name} is neither openbox_menu nor labwc_config"
throw "error ${name} is neither openbox_menu nor labwc_config"
)
config
)

View File

@@ -134,7 +134,7 @@ in
Service = {
ExecStart =
let
args = lib.cli.toGNUCommandLineShell { } {
args = lib.cli.toCommandLineShellGNU { } {
t = cfg.temperature.night;
T = cfg.temperature.day;
g = cfg.gamma;

View File

@@ -12,12 +12,14 @@ let
inherit (lib)
any
attrValues
filterAttrs
hm
isBool
literalExpression
mapAttrs
mkEnableOption
mkIf
mkMerge
mkEnableOption
mkOption
types
;
@@ -28,7 +30,7 @@ let
mkPathSafeName = lib.replaceStrings [ "@" ":" "\\" "[" "]" ] [ "-" "-" "-" "" "" ];
removeIfEmpty =
attrs: names: lib.filterAttrs (name: value: !(builtins.elem name names) || value != "") attrs;
attrs: names: filterAttrs (name: value: !(builtins.elem name names) || value != "") attrs;
toSystemdIni = lib.generators.toINI {
listsAsDuplicateKeys = true;
@@ -46,36 +48,70 @@ let
filename = "${name}.${style}";
pathSafeName = mkPathSafeName filename;
# The actual unit content (or unit override content if a base is
# specified).
finalConfig =
let
# Filters out fields that are set to `null` or empty list. Also
# make sure the `Unit.X-Base` field is skipped.
shouldKeepField =
section: key: value:
value != null && value != [ ] && !(section == "Unit" && key == "X-Base");
# Filters out empty sections.
shouldKeepSection = _: value: value != { };
filteredFields = mapAttrs (section: filterAttrs (shouldKeepField section)) serviceCfg;
filteredSections = filterAttrs shouldKeepSection filteredFields;
in
filteredSections;
finalConfigIni = toSystemdIni finalConfig;
# Needed because systemd derives unit names from the ultimate
# link target.
source =
generatedSource =
pkgs.writeTextFile {
name = pathSafeName;
text = toSystemdIni (
lib.filterAttrs (_: v: v != { }) (
lib.mapAttrs (_: lib.filterAttrs (_: v: v != null && v != [ ])) serviceCfg
)
);
text = finalConfigIni;
destination = "/${filename}";
}
+ "/${filename}";
hasBaseSource = serviceCfg.Unit.X-Base != null;
source = if hasBaseSource then serviceCfg.Unit.X-Base else generatedSource;
install = variant: target: {
name = "systemd/user/${target}.${variant}/${filename}";
value = { inherit source; };
};
in
lib.singleton {
name = "systemd/user/${filename}";
value = { inherit source; };
}
[
{
name = "systemd/user/${filename}";
value = { inherit source; };
}
# Produce the overrides file if the main unit file is produced by X-Base.
# Note, we always create an overrides file even if no overrides are
# present. This simplifies the implementation somewhat as we don't have to
# check whether the unit settings attribute set is empty. The check would
# force the attribute set which may cause infinite recursion if it
# contains references to `config`.
{
name = "systemd/user/${filename}.d/overrides.conf";
value = lib.mkIf hasBaseSource {
source = generatedSource;
};
}
]
++ map (install "wants") (serviceCfg.Install.WantedBy or [ ])
++ map (install "requires") (serviceCfg.Install.RequiredBy or [ ]);
buildServices =
style: serviceCfgs: lib.concatLists (lib.mapAttrsToList (buildService style) serviceCfgs);
servicesStartTimeoutMs = builtins.toString cfg.servicesStartTimeoutMs;
servicesStartTimeoutMs = toString cfg.servicesStartTimeoutMs;
unitBaseType =
unitKind: mod:
@@ -98,6 +134,53 @@ let
imports = [
{
options.Unit = {
X-Base = mkOption {
type = types.nullOr types.path;
default = null;
example = literalExpression "\${pkgs.example}/share/systemd/user/example.service";
description = ''
::: {.warning}
This is an experimental option, it may be removed or its
behavior changed at any time!
:::
Path to unit file that should be used as a base definition. This
unit file will be copied to the Nix store (if not already there)
and linked into the user's environment. Any other fields
specified for this unit will be placed in an overrides file.
The `Unit.X-Base` field is filtered out from when the output
files are generated.
The filename of the base unit file _must_ be the same as the
unit name. That is, if you specify a base file for
`systemd.user.services."foo"`, then the base file must be
`foo.service`.
As a specific example, consider the following configuration:
``` nix
systemd.user.services.example = {
Unit.X-Base = "''${pkgs.example}/share/systemd/user/example.service";
Service.ExecStartPre = "''${pkgs.coreutils}/bin/sleep 1m"
};
```
After activation the user will have two new managed files in
their home directory:
`.config/systemd/user/example.service`
: This will point to the `X-Base` file.
`.config/systemd/user/example.service.d/overrides.conf`
: This will contain the specified overrides, in this case
``` ini
[Service]
ExecStartPre=/nix/store/...-coreutils/bin/sleep 1m
```
'';
};
Description = mkOption {
type = types.nullOr types.str;
default = null;

View File

@@ -18,13 +18,14 @@ stdenv.mkDerivation {
src = ./.;
patchPhase = ''
substituteInPlace non-nixos-gpu* \
--replace '@@resources@@' "$out/resources" \
--replace '@@statedir@@' '${nixStateDirectory}' \
--replace '@@env@@' "${nonNixosGpuEnv}"
--replace-quiet '@@resources@@' "$out/resources" \
--replace-quiet '@@statedir@@' '${nixStateDirectory}' \
--replace-quiet '@@systemddir@@' "$out/lib/systemd/system" \
--replace-quiet '@@env@@' "${nonNixosGpuEnv}"
'';
installPhase = ''
mkdir -p $out/{bin,resources}
mkdir -p $out/{bin,resources,lib/systemd/system}
cp non-nixos-gpu-setup $out/bin
cp non-nixos-gpu.service $out/resources
cp non-nixos-gpu.service $out/lib/systemd/system
'';
}

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