Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hyprland: init module #14

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 141 additions & 0 deletions modules/collection/programs/hyprland.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
{
lib,
osConfig,
config,
...
}: let
inherit (lib.attrsets) filterAttrs mapAttrsToList;
inherit (lib.lists) any isList;
inherit (lib.modules) mkIf;
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.rum.generators) toHyprconf;
inherit (lib.strings) concatStringsSep hasPrefix optionalString stringLength;
inherit (lib.types) attrs either listOf package path;

inherit (osConfig.programs) hyprland;

cfg = config.rum.programs.hyprland;

toEnv = env:
if isList env
then concatStringsSep ":" (map toString env)
else toString env;

filterEnvVars = filterPrefixes: vars: let
filteredVars =
if filterPrefixes == []
then vars
else
filterAttrs
(name: _: any (prefix: hasPrefix prefix name) filterPrefixes)
vars;
in
concatStringsSep "\n"
(mapAttrsToList (name: value: "export ${name}=\"${toEnv value}\"") filteredVars);

# taken from https://github.com/hyprwm/Hyprland/blob/f4b148df1e2d8edc96bd878a4cfde32ca6515ac8/nix/module.nix#L185-L197
pluginsToHyprconf = plugins:
toHyprconf {
attrs = {
plugin = let
mkEntry = entry:
if lib.types.package.check entry
then "${entry}/lib/lib${entry.pname}.so"
else entry;
in
map mkEntry cfg.plugins;
};
inherit (cfg) importantPrefixes;
};
in {
options.rum.programs.hyprland = {
enable = mkEnableOption ''
Hyprland
'';

settings = mkOption {
type = attrs;
example = {
"$mod" = "SUPER";
decoration = {
rounding = "3";
};
};
default = {};
description = ''
Hyprland configuration written in Nix. Entries with the same key
should be written as lists. Variables' and colors' names should be
quoted. See <https://wiki.hyprland.org> for more examples.
'';
};

plugins = mkOption {
type = listOf (either package path);
default = [];
description = ''
List of Hyprland plugins to use. Can either be packages or
absolute plugin paths.
'';
};

importantPrefixes = lib.mkOption {
type = with lib.types; listOf str;
default = ["$" "bezier" "name"];
example = ["$" "bezier"];
description = ''
List of prefix of attributes to source at the top of the config.
'';
};
};

config = mkIf cfg.enable {
files = {
".config/hypr/hyprland.conf".text =
optionalString (cfg.plugins != [])
(pluginsToHyprconf cfg.plugins)
+ optionalString (cfg.settings != {})
(toHyprconf {
attrs = cfg.settings;
inherit (cfg) importantPrefixes;
})
+ optionalString (config.environment.sessionVariables != {} && (!hyprland.withUWSM))
(toHyprconf {
attrs.env =
# https://wiki.hyprland.org/Configuring/Environment-variables/#xdg-specifications
[
"XDG_CURRENT_DESKTOP,Hyprland"
"XDG_SESSION_TYPE,wayland"
"XDG_SESSION_DESKTOP,Hyprland"
]
++ mapAttrsToList (key: value: "${key},${value}") config.environment.sessionVariables;
});

/*
uwsm environment variables are advised to be separated
(see https://wiki.hyprland.org/Configuring/Environment-variables/)
*/
".config/uwsm/env".text =
mkIf (
(config.environment.sessionVariables != {})
&& hyprland.withUWSM
)
(filterEnvVars []
config.environment.sessionVariables);

".config/uwsm/env-hyprland".text = let
/*
this is needed as we're using a predicate so we don't create an empty file
(improvements are welcome)
*/
filteredVars =
filterEnvVars ["HYPRLAND_" "AQ_"] config.environment.sessionVariables;
in
mkIf (
(config.environment.sessionVariables != {})
&& hyprland.withUWSM
&& stringLength filteredVars != 0
)
filteredVars;
};
};
}
68 changes: 67 additions & 1 deletion modules/lib/generators.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,71 @@
{lib}: {
{lib}: let
in {
# generatorName = {...}: {
# function
# };

# basically 1:1 taken from https://github.com/nix-community/home-manager/blob/master/modules/services/window-managers/hyprland.nix
toHyprconf = {
attrs,
indentLevel ? 0,
importantPrefixes ? ["$"],
}: let
inherit
(lib)
all
concatMapStringsSep
concatStrings
concatStringsSep
filterAttrs
foldl
generators
hasPrefix
isAttrs
isList
mapAttrsToList
replicate
;

initialIndent = concatStrings (replicate indentLevel " ");

toHyprconf' = indent: attrs: let
sections =
filterAttrs (n: v: isAttrs v || (isList v && all isAttrs v)) attrs;

mkSection = n: attrs:
if lib.isList attrs
then (concatMapStringsSep "\n" (a: mkSection n a) attrs)
else ''
${indent}${n} {
${toHyprconf' " ${indent}" attrs}${indent}}
'';

mkFields = generators.toKeyValue {
listsAsDuplicateKeys = true;
inherit indent;
};

allFields =
filterAttrs (n: v: !(isAttrs v || (isList v && all isAttrs v)))
attrs;

isImportantField = n: _:
foldl (acc: prev:
if hasPrefix prev n
then true
else acc)
false
importantPrefixes;

importantFields = filterAttrs isImportantField allFields;

fields =
builtins.removeAttrs allFields
(mapAttrsToList (n: _: n) importantFields);
in
mkFields importantFields
+ concatStringsSep "\n" (mapAttrsToList mkSection sections)
+ mkFields fields;
in
toHyprconf' initialIndent attrs;
}