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:
parent
9de77227d7
commit
7c320a5325
7 changed files with 106 additions and 217 deletions
|
@ -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 = [
|
type = types.nullOr types.int;
|
||||||
"battery"
|
default = null;
|
||||||
"sway/mode"
|
example = 10;
|
||||||
"sway/workspaces"
|
description = "Margin value without unit.";
|
||||||
"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;
|
|
||||||
default = null;
|
|
||||||
example = 10;
|
|
||||||
description = "Margins 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,122 +228,62 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
config = let
|
config = let
|
||||||
writePrettyJSON = jsonFormat.generate;
|
# Removes nulls because Waybar ignores them.
|
||||||
|
# This is not recursive.
|
||||||
|
removeNulls = filterAttrs (_: v: v != null);
|
||||||
|
|
||||||
configSource = let
|
# Makes the actual valid configuration Waybar accepts
|
||||||
# Removes nulls because Waybar ignores them for most values
|
# (strips our custom settings before converting to JSON)
|
||||||
removeNulls = filterAttrs (_: v: v != null);
|
makeConfiguration = configuration:
|
||||||
|
let
|
||||||
|
# The "modules" option is not valid in the JSON
|
||||||
|
# as its descendants have to live at the top-level
|
||||||
|
settingsWithoutModules = removeAttrs configuration [ "modules" ];
|
||||||
|
settingsModules =
|
||||||
|
optionalAttrs (configuration.modules != { }) configuration.modules;
|
||||||
|
in removeNulls (settingsWithoutModules // settingsModules);
|
||||||
|
# The clean list of configurations
|
||||||
|
finalConfiguration = map makeConfiguration cfg.settings;
|
||||||
|
|
||||||
# Makes the actual valid configuration Waybar accepts
|
configSource = jsonFormat.generate "waybar-config.json" finalConfiguration;
|
||||||
# (strips our custom settings before converting to JSON)
|
|
||||||
makeConfiguration = configuration:
|
|
||||||
let
|
|
||||||
# The "modules" option is not valid in the JSON
|
|
||||||
# as its descendants have to live at the top-level
|
|
||||||
settingsWithoutModules = removeAttrs configuration [ "modules" ];
|
|
||||||
settingsModules =
|
|
||||||
optionalAttrs (configuration.modules != { }) configuration.modules;
|
|
||||||
in removeNulls (settingsWithoutModules // settingsModules);
|
|
||||||
# The clean list of configurations
|
|
||||||
finalConfiguration = map makeConfiguration cfg.settings;
|
|
||||||
in writePrettyJSON "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 = {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
43
tests/modules/programs/waybar/deprecated-modules-option.nix
Normal file
43
tests/modules/programs/waybar/deprecated-modules-option.nix
Normal 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": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
''
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
''
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
Loading…
Reference in a new issue