waybar: fix null modules-{left,center,right} error

- Change the `attrsOf unspecified` to `pkgs.formats.json`
- Add missing default modules
- Expand the `with lib` with every function used
- Add inline documentation about the generated warnings
This commit is contained in:
Nicolas Berbiche 2020-11-15 17:29:36 -05:00 committed by Robert Helgesson
parent 4f20ee61c2
commit 964f698095
No known key found for this signature in database
GPG key ID: 36BDAA14C2797E89

View file

@ -1,18 +1,28 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
inherit (lib)
attrByPath attrNames concatMap concatMapStringsSep elem filter filterAttrs
flip foldl' hasPrefix mergeAttrs optionalAttrs stringLength subtractLists
types unique;
inherit (lib.options) literalExample mkEnableOption mkOption;
inherit (lib.modules) mkIf mkMerge;
cfg = config.programs.waybar; cfg = config.programs.waybar;
# Used when generating warnings # Used when generating warnings
modulesPath = "programs.waybar.settings.[].modules"; modulesPath = "programs.waybar.settings.[].modules";
jsonFormat = pkgs.formats.json { };
# Taken from <https://github.com/Alexays/Waybar/blob/adaf84304865e143e4e83984aaea6f6a7c9d4d96/src/factory.cpp> # Taken from <https://github.com/Alexays/Waybar/blob/adaf84304865e143e4e83984aaea6f6a7c9d4d96/src/factory.cpp>
defaultModuleNames = [ defaultModuleNames = [
"sway/mode" "sway/mode"
"sway/workspaces" "sway/workspaces"
"sway/window" "sway/window"
"sway/language"
"wlr/taskbar" "wlr/taskbar"
"river/tags"
"idle_inhibitor" "idle_inhibitor"
"memory" "memory"
"cpu" "cpu"
@ -23,6 +33,7 @@ let
"backlight" "backlight"
"pulseaudio" "pulseaudio"
"mpd" "mpd"
"sndio"
"temperature" "temperature"
"bluetooth" "bluetooth"
"battery" "battery"
@ -92,8 +103,8 @@ let
}; };
modules-left = mkOption { modules-left = mkOption {
type = nullOr (listOf str); type = listOf str;
default = null; default = [ ];
description = "Modules that will be displayed on the left."; description = "Modules that will be displayed on the left.";
example = literalExample '' example = literalExample ''
[ "sway/workspaces" "sway/mode" "wlr/taskbar" ] [ "sway/workspaces" "sway/mode" "wlr/taskbar" ]
@ -101,8 +112,8 @@ let
}; };
modules-center = mkOption { modules-center = mkOption {
type = nullOr (listOf str); type = listOf str;
default = null; default = [ ];
description = "Modules that will be displayed in the center."; description = "Modules that will be displayed in the center.";
example = literalExample '' example = literalExample ''
[ "sway/window" ] [ "sway/window" ]
@ -110,8 +121,8 @@ let
}; };
modules-right = mkOption { modules-right = mkOption {
type = nullOr (listOf str); type = listOf str;
default = null; default = [ ];
description = "Modules that will be displayed on the right."; description = "Modules that will be displayed on the right.";
example = literalExample '' example = literalExample ''
[ "mpd" "custom/mymodule#with-css-id" "temperature" ] [ "mpd" "custom/mymodule#with-css-id" "temperature" ]
@ -119,7 +130,7 @@ let
}; };
modules = mkOption { modules = mkOption {
type = attrsOf unspecified; type = jsonFormat.type;
default = { }; default = { };
description = "Modules configuration."; description = "Modules configuration.";
example = literalExample '' example = literalExample ''
@ -169,7 +180,7 @@ in {
package = mkOption { package = mkOption {
type = package; type = package;
default = pkgs.waybar; default = pkgs.waybar;
defaultText = literalExample "${pkgs.waybar}"; defaultText = "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 module.
''; '';
@ -243,11 +254,7 @@ in {
}; };
config = let config = let
# Inspired by https://github.com/NixOS/nixpkgs/pull/89781 writePrettyJSON = jsonFormat.generate;
writePrettyJSON = name: x:
pkgs.runCommandLocal name { } ''
${pkgs.jq}/bin/jq . > $out <<<${escapeShellArg (builtins.toJSON x)}
'';
configSource = let configSource = let
# Removes nulls because Waybar ignores them for most values # Removes nulls because Waybar ignores them for most values
@ -259,8 +266,7 @@ in {
let let
# The "modules" option is not valid in the JSON # The "modules" option is not valid in the JSON
# as its descendants have to live at the top-level # as its descendants have to live at the top-level
settingsWithoutModules = settingsWithoutModules = removeAttrs configuration [ "modules" ];
filterAttrs (n: _: n != "modules") configuration;
settingsModules = settingsModules =
optionalAttrs (configuration.modules != { }) configuration.modules; optionalAttrs (configuration.modules != { }) configuration.modules;
in removeNulls (settingsWithoutModules // settingsModules); in removeNulls (settingsWithoutModules // settingsModules);
@ -268,6 +274,15 @@ in {
finalConfiguration = map makeConfiguration cfg.settings; finalConfiguration = map makeConfiguration cfg.settings;
in writePrettyJSON "waybar-config.json" finalConfiguration; 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 warnings = let
mkUnreferencedModuleWarning = name: mkUnreferencedModuleWarning = name:
"The module '${name}' defined in '${modulesPath}' is not referenced " "The module '${name}' defined in '${modulesPath}' is not referenced "
@ -288,9 +303,6 @@ in {
+ "module name. A custom module's name must start with 'custom/' " + "module name. A custom module's name must start with 'custom/' "
+ "like 'custom/mymodule' for instance"; + "like 'custom/mymodule' for instance";
# Find all modules in `modules-{left,center,right}` and `modules` not declared/referenced.
# `cfg.settings` is a list of Waybar configurations
# and we need to preserve the index for appropriate warnings
allFaultyModules = flip map cfg.settings (settings: allFaultyModules = flip map cfg.settings (settings:
let let
allModules = unique allModules = unique
@ -308,10 +320,10 @@ in {
undefinedModules = subtractLists declaredModules nonDefaultModules; undefinedModules = subtractLists declaredModules nonDefaultModules;
# Check for invalid module names # Check for invalid module names
invalidModuleNames = invalidModuleNames =
filter (m: !isValidCustomModuleName m) (attrNames settings.modules); filter (m: !isValidCustomModuleName m) declaredModules;
in { in {
# The Waybar bar configuration (since config.settings is a list) # The Waybar bar configuration (since config.settings is a list)
settings = settings; inherit settings;
undef = undefinedModules; undef = undefinedModules;
unref = unreferencedModules; unref = unreferencedModules;
invalidName = invalidModuleNames; invalidName = invalidModuleNames;