1
0
Fork 0
mirror of https://github.com/nix-community/home-manager synced 2024-12-02 16:09:46 +01:00

waybar: make module a freeform module, remove warnings

The `style` option now also accepts a path instead of a text
configuration.

Keeping up with new Waybar options is annoying, so make the module a
freeform module.

The `modules` option will be removed in release 22.05.

The logic to generate warnings for modules and everything was
removed. I don't want to maintain the code that generates these
warnings anymore.
This commit is contained in:
Nicolas Berbiche 2021-11-18 17:59:20 -05:00
parent 9de77227d7
commit 7c320a5325
No known key found for this signature in database
GPG key ID: FA5696EDF35DA0B6
7 changed files with 106 additions and 217 deletions

View file

@ -2,72 +2,26 @@
let let
inherit (lib) inherit (lib)
any attrByPath attrNames concatMap concatMapStringsSep elem elemAt filter all filterAttrs hasAttr isStorePath literalExpression optionalAttrs types;
filterAttrs flip foldl' hasPrefix head length literalExpression mergeAttrs
optionalAttrs stringLength subtractLists types unique;
inherit (lib.options) mkEnableOption mkOption; inherit (lib.options) mkEnableOption mkOption;
inherit (lib.modules) mkIf mkMerge; inherit (lib.modules) mkIf mkMerge;
cfg = config.programs.waybar; cfg = config.programs.waybar;
# Used when generating warnings
modulesPath = "programs.waybar.settings.[].modules";
jsonFormat = pkgs.formats.json { }; jsonFormat = pkgs.formats.json { };
# Taken from <https://github.com/Alexays/Waybar/blob/cc3acf8102c71d470b00fd55126aef4fb335f728/src/factory.cpp> (2020/10/10) mkMargin = name:
# Order is preserved from the file for easier matching mkOption {
defaultModuleNames = [
"battery"
"sway/mode"
"sway/workspaces"
"sway/window"
"sway/language"
"wlr/taskbar"
"river/tags"
"idle_inhibitor"
"memory"
"cpu"
"clock"
"disk"
"tray"
"network"
"backlight"
"pulseaudio"
"mpd"
"sndio"
"temperature"
"bluetooth"
];
# Allow specifying a CSS id after the default module name
isValidDefaultModuleName = x:
any (name:
let
res = builtins.split name x;
# if exact match of default module name
in if res == [ "" [ ] ] || res == [ "" [ ] "" ] then
true
else
head res == "" && length res >= 3 && hasPrefix "#" (elemAt res 2))
defaultModuleNames;
isValidCustomModuleName = x: hasPrefix "custom/" x && stringLength x > 7;
margins = let
mkMargin = name: {
"margin-${name}" = mkOption {
type = types.nullOr types.int; type = types.nullOr types.int;
default = null; default = null;
example = 10; example = 10;
description = "Margins value without unit."; description = "Margin value without unit.";
}; };
};
margins = map mkMargin [ "top" "left" "bottom" "right" ];
in foldl' mergeAttrs { } margins;
waybarBarConfig = with lib.types; waybarBarConfig = with types;
submodule { submodule {
freeformType = jsonFormat.type;
options = { options = {
layer = mkOption { layer = mkOption {
type = nullOr (enum [ "top" "bottom" ]); type = nullOr (enum [ "top" "bottom" ]);
@ -164,7 +118,10 @@ let
example = "20 5"; example = "20 5";
}; };
inherit (margins) margin-top margin-left margin-bottom margin-right; margin-left = mkMargin "left";
margin-right = mkMargin "right";
margin-bottom = mkMargin "bottom";
margin-top = mkMargin "top";
name = mkOption { name = mkOption {
type = nullOr str; type = nullOr str;
@ -192,9 +149,9 @@ in {
package = mkOption { package = mkOption {
type = package; type = package;
default = pkgs.waybar; default = pkgs.waybar;
defaultText = "pkgs.waybar"; defaultText = literalExpression "pkgs.waybar";
description = '' description = ''
Waybar package to use. Set to <code>null</code> to use the default module. Waybar package to use. Set to <code>null</code> to use the default package.
''; '';
}; };
@ -241,12 +198,17 @@ in {
systemd.enable = mkEnableOption "Waybar systemd integration"; systemd.enable = mkEnableOption "Waybar systemd integration";
style = mkOption { style = mkOption {
type = nullOr str; type = nullOr (either path str);
default = null; default = null;
description = '' description = ''
CSS style of the bar. CSS style of the bar.
</para>
<para>
See <link xlink:href="https://github.com/Alexays/Waybar/wiki/Configuration"/> See <link xlink:href="https://github.com/Alexays/Waybar/wiki/Configuration"/>
for the documentation. for the documentation.
</para>
<para>
If the value is set to a path literal, then the path will be used as the css file.
''; '';
example = '' example = ''
* { * {
@ -266,10 +228,8 @@ in {
}; };
config = let config = let
writePrettyJSON = jsonFormat.generate; # Removes nulls because Waybar ignores them.
# This is not recursive.
configSource = let
# Removes nulls because Waybar ignores them for most values
removeNulls = filterAttrs (_: v: v != null); removeNulls = filterAttrs (_: v: v != null);
# Makes the actual valid configuration Waybar accepts # Makes the actual valid configuration Waybar accepts
@ -284,104 +244,46 @@ in {
in removeNulls (settingsWithoutModules // settingsModules); in removeNulls (settingsWithoutModules // settingsModules);
# The clean list of configurations # The clean list of configurations
finalConfiguration = map makeConfiguration cfg.settings; finalConfiguration = map makeConfiguration cfg.settings;
in writePrettyJSON "waybar-config.json" finalConfiguration;
# configSource = jsonFormat.generate "waybar-config.json" finalConfiguration;
# Warnings are generated based on the following things:
# 1. A `module` is referenced in any of `modules-{left,center,right}` that is neither
# a default module name nor defined in `modules`.
# 2. A `module` is defined in `modules` but is not referenced in either of
# `modules-{left,center,right}`.
# 3. A custom `module` configuration is defined in `modules` but has an invalid name
# for a custom module (i.e. not "custom/my-module-name").
#
warnings = let
mkUnreferencedModuleWarning = name:
"The module '${name}' defined in '${modulesPath}' is not referenced "
+ "in either `modules-left`, `modules-center` or `modules-right` of Waybar's options";
mkUndefinedModuleWarning = settings: name:
let
# Locations where the module is undefined (a combination modules-{left,center,right})
locations = flip filter [ "left" "center" "right" ]
(x: elem name settings."modules-${x}");
mkPath = loc: "'${modulesPath}-${loc}'";
# The modules-{left,center,right} configuration that includes
# an undefined module
path = concatMapStringsSep " and " mkPath locations;
in "The module '${name}' defined in ${path} is neither "
+ "a default module or a custom module declared in '${modulesPath}'";
mkInvalidModuleNameWarning = name:
"The custom module '${name}' defined in '${modulesPath}' is not a valid "
+ "module name. A custom module's name must start with 'custom/' "
+ "like 'custom/mymodule' for instance";
allFaultyModules = flip map cfg.settings (settings:
let
allModules = unique
(concatMap (x: attrByPath [ "modules-${x}" ] [ ] settings) [
"left"
"center"
"right"
]);
declaredModules = attrNames settings.modules;
# Modules declared in `modules` but not referenced in `modules-{left,center,right}`
unreferencedModules = subtractLists allModules declaredModules;
# Modules listed in modules-{left,center,right} that are not default modules
nonDefaultModules =
filter (x: !isValidDefaultModuleName x) allModules;
# Modules referenced in `modules-{left,center,right}` but not declared in `modules`
undefinedModules = subtractLists declaredModules nonDefaultModules;
# Check for invalid module names
invalidModuleNames = filter
(m: !isValidCustomModuleName m && !isValidDefaultModuleName m)
declaredModules;
in {
# The Waybar bar configuration (since config.settings is a list)
inherit settings;
undef = undefinedModules;
unref = unreferencedModules;
invalidName = invalidModuleNames;
});
allWarnings = flip concatMap allFaultyModules
({ settings, undef, unref, invalidName }:
let
unreferenced = map mkUnreferencedModuleWarning unref;
undefined = map (mkUndefinedModuleWarning settings) undef;
invalid = map mkInvalidModuleNameWarning invalidName;
in undefined ++ unreferenced ++ invalid);
in allWarnings;
in mkIf cfg.enable (mkMerge [ in mkIf cfg.enable (mkMerge [
{ {
assertions = [ assertions = [
(lib.hm.assertions.assertPlatform "programs.waybar" pkgs (lib.hm.assertions.assertPlatform "programs.waybar" pkgs
lib.platforms.linux) lib.platforms.linux)
({
assertion =
if lib.versionAtLeast config.home.stateVersion "22.05" then
all (x: !hasAttr "modules" x) cfg.settings
else
true;
message = ''
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 ]; home.packages = [ cfg.package ];
}
(mkIf (cfg.settings != [ ]) { xdg.configFile."waybar/config" = mkIf (cfg.settings != [ ]) {
# Generate warnings about defined but unreferenced modules
inherit warnings;
xdg.configFile."waybar/config" = {
source = configSource; source = configSource;
onChange = '' onChange = ''
${pkgs.procps}/bin/pkill -u $USER -USR2 waybar || true ${pkgs.procps}/bin/pkill -u $USER -USR2 waybar || true
''; '';
}; };
})
(mkIf (cfg.style != null) { xdg.configFile."waybar/style.css" = mkIf (cfg.style != null) {
xdg.configFile."waybar/style.css" = { source = if builtins.isPath cfg.style || isStorePath cfg.style then
text = cfg.style; cfg.style
else
pkgs.writeText "waybar/style.css" cfg.style;
onChange = '' onChange = ''
${pkgs.procps}/bin/pkill -u $USER -USR2 waybar || true ${pkgs.procps}/bin/pkill -u $USER -USR2 waybar || true
''; '';
}; };
}) }
(mkIf cfg.systemd.enable { (mkIf cfg.systemd.enable {
systemd.user.services.waybar = { systemd.user.services.waybar = {

View file

@ -3,5 +3,5 @@
./systemd-with-graphical-session-target.nix; ./systemd-with-graphical-session-target.nix;
waybar-styling = ./styling.nix; waybar-styling = ./styling.nix;
waybar-settings-complex = ./settings-complex.nix; waybar-settings-complex = ./settings-complex.nix;
waybar-warnings = ./warnings-tests.nix; waybar-deprecated-modules-option = ./deprecated-modules-option.nix;
} }

View file

@ -0,0 +1,43 @@
{ config, lib, pkgs, ... }:
with lib;
{
config = {
home.stateVersion = "22.05";
programs.waybar = {
package = config.lib.test.mkStubPackage { outPath = "@waybar@"; };
enable = true;
settings = [{
modules-center = [ "test" ];
modules = { "test" = { }; };
}];
};
test.asserts.assertions.expected = [''
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.
''];
nmt.script = ''
assertPathNotExists home-files/.config/waybar/style.css
assertFileContent \
home-files/.config/waybar/config \
${
builtins.toFile "waybar-deprecated-modules-option.json" ''
[
{
"modules-center": [
"test"
],
"modules-left": [],
"modules-right": [],
"test": {}
}
]
''
}
'';
};
}

View file

@ -4,6 +4,8 @@ with lib;
{ {
config = { config = {
home.stateVersion = "21.11";
programs.waybar = { programs.waybar = {
package = config.lib.test.mkStubPackage { outPath = "@waybar@"; }; package = config.lib.test.mkStubPackage { outPath = "@waybar@"; };
enable = true; enable = true;

View file

@ -4,6 +4,8 @@ with lib;
{ {
config = { config = {
home.stateVersion = "21.11";
programs.waybar = { programs.waybar = {
package = config.lib.test.mkStubPackage { outPath = "@waybar@"; }; package = config.lib.test.mkStubPackage { outPath = "@waybar@"; };
enable = true; enable = true;

View file

@ -4,6 +4,8 @@ with lib;
{ {
config = { config = {
home.stateVersion = "21.11";
programs.waybar = { programs.waybar = {
package = config.lib.test.mkStubPackage { outPath = "@waybar@"; }; package = config.lib.test.mkStubPackage { outPath = "@waybar@"; };
enable = true; enable = true;

View file

@ -1,62 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
{
config = {
programs.waybar = {
package = config.lib.test.mkStubPackage { outPath = "@waybar@"; };
enable = true;
settings = [{
modules-left = [ "custom/my-module" ];
modules-center =
[ "this_module_is_not_a_valid_default_module_nor_custom_module" ];
modules-right = [
"battery#bat1" # CSS identifier is allowed
"custom/this_custom_module_doesn't_have_a_definition_in_modules"
];
modules = {
"custom/this_module_is_not_referenced" = { };
"battery#bat1" = { };
"custom/my-module" = { };
};
}];
};
test.asserts.warnings.expected = [
"The module 'this_module_is_not_a_valid_default_module_nor_custom_module' defined in 'programs.waybar.settings.[].modules-center' is neither a default module or a custom module declared in 'programs.waybar.settings.[].modules'"
"The module 'custom/this_custom_module_doesn't_have_a_definition_in_modules' defined in 'programs.waybar.settings.[].modules-right' is neither a default module or a custom module declared in 'programs.waybar.settings.[].modules'"
"The module 'custom/this_module_is_not_referenced' defined in 'programs.waybar.settings.[].modules' is not referenced in either `modules-left`, `modules-center` or `modules-right` of Waybar's options"
];
nmt.script = ''
assertPathNotExists home-files/.config/waybar/style.css
assertFileContent \
home-files/.config/waybar/config \
${
pkgs.writeText "expected-json" ''
[
{
"battery#bat1": {},
"custom/my-module": {},
"custom/this_module_is_not_referenced": {},
"modules-center": [
"this_module_is_not_a_valid_default_module_nor_custom_module"
],
"modules-left": [
"custom/my-module"
],
"modules-right": [
"battery#bat1",
"custom/this_custom_module_doesn't_have_a_definition_in_modules"
]
}
]
''
}
'';
};
}