polybar: allow config to be more nix-like (#1430)

Polybar's config format is a bit strange, and lists in particular are
annoying to handle. This enables using normal nix lists and nested
attrsets instead.

This change is not backwards-compatible, because the INI converter
converts lists of strings to space-separated values, and this does
something else. I expect that this is only relevant for the
`modules-left` etc bar setting, but that's enough to break things :(.
This commit is contained in:
Nadrieril 2021-02-20 17:34:59 +00:00 committed by GitHub
parent 55030c8302
commit da92360208
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 118 additions and 2 deletions

View file

@ -1852,6 +1852,17 @@ in
A new module is available: 'programs.sbt'.
'';
}
{
time = "2021-02-20T00:00:00+00:00";
condition = config.services.polybar.enable;
message = ''
The polybar configuration can now be written in a more nix-friendly format.
The new 'services.polybar.settings' option is an alternative to
'services.polybar.config' that supports nested keys and converts nix
lists to polybar-style 'foo-0, foo-1, ...' lists.
'';
}
];
};
}

View file

@ -9,6 +9,36 @@ let
eitherStrBoolIntList = with types;
either str (either bool (either int (listOf str)));
# Convert a key/val pair to the insane format that polybar uses.
# Each input key/val pair may return several output key/val pairs.
convertPolybarKeyVal = key: val:
# Convert { foo = [ "a" "b" ]; }
# to {
# foo-0 = "a";
# foo-1 = "b";
# }
if isList val then
concatLists (imap0 (i: convertPolybarKeyVal "${key}-${toString i}") val)
# Convert {
# foo.text = "a";
# foo.font = 1;
# } to {
# foo = "a";
# foo-font = 1;
# }
else if isAttrs val && !lib.isDerivation val then
concatLists (mapAttrsToList
(k: convertPolybarKeyVal (if k == "text" then key else "${key}-${k}"))
val)
# Base case
else
[ (nameValuePair key val) ];
convertPolybarSection = _: attrs:
listToAttrs (concatLists (mapAttrsToList convertPolybarKeyVal attrs));
# Converts an attrset to INI text, quoting values as expected by polybar.
# This does no more fancy conversion.
toPolybarIni = generators.toINI {
mkKeyValue = key: value:
let
@ -24,8 +54,11 @@ let
in "${key}=${value'}";
};
configFile = pkgs.writeText "polybar.conf"
(toPolybarIni cfg.config + "\n" + cfg.extraConfig);
configFile = pkgs.writeText "polybar.conf" ''
${toPolybarIni cfg.config}
${toPolybarIni (mapAttrs convertPolybarSection cfg.settings)}
${cfg.extraConfig}
'';
in {
options = {
@ -54,6 +87,7 @@ in {
description = ''
Polybar configuration. Can be either path to a file, or set of attributes
that will be used to create the final configuration.
See also <option>services.polybar.settings</option> for a more nix-friendly format.
'';
default = { };
example = literalExample ''
@ -77,6 +111,56 @@ in {
'';
};
settings = mkOption {
type = types.attrsOf types.attrs;
description = ''
Polybar configuration. This takes a nix attrset and converts it to the
strange data format that polybar uses.
Each entry will be converted to a section in the output file.
Several things are treated specially: nested keys are converted
to dash-separated keys; the special <literal>text</literal> key is ignored as a nested key,
to allow mixing different levels of nesting; and lists are converted to
polybar's <literal>foo-0, foo-1, ...</literal> format.
</para><para>
For example:
<programlisting language="nix">
"module/volume" = {
type = "internal/pulseaudio";
format.volume = "&lt;ramp-volume&gt; &lt;label-volume&gt;";
label.muted.text = "🔇";
label.muted.foreground = "#666";
ramp.volume = ["🔈" "🔉" "🔊"];
click.right = "pavucontrol &amp;";
}
</programlisting>
becomes:
<programlisting language="ini">
[module/volume]
type=internal/pulseaudio
format-volume=&lt;ramp-volume&gt; &lt;label-volume&gt;
label-muted=🔇
label-muted-foreground=#666
ramp-volume-0=🔈
ramp-volume-1=🔉
ramp-volume-2=🔊
click-right=pavucontrol &amp;
</programlisting>
'';
default = { };
example = literalExample ''
{
"module/volume" = {
type = "internal/pulseaudio";
format.volume = "<ramp-volume> <label-volume>";
label.muted.text = "🔇";
label.muted.foreground = "#666";
ramp.volume = ["🔈" "🔉" "🔊"];
click.right = "pavucontrol &";
};
}
'';
};
extraConfig = mkOption {
type = types.lines;
description = "Additional configuration to add.";

View file

@ -12,6 +12,16 @@ label=%time% %date%
time=%H:%M
type=internal/date
[module/volume]
click-right=pavucontrol &
format-volume=<ramp-volume> <label-volume>
label-muted=🔇
label-muted-foreground=#666
ramp-volume-0=🔈
ramp-volume-1=🔉
ramp-volume-2=🔊
type=internal/pulseaudio
[module/date]
type = internal/date
interval = 5
@ -19,3 +29,4 @@ date = "%d.%m.%y"
time = %H:%M
format-prefix-foreground = ${colors.foreground-alt}
label = %time% %date%

View file

@ -22,6 +22,16 @@
label = "%time% %date%";
};
};
settings = {
"module/volume" = {
type = "internal/pulseaudio";
format.volume = "<ramp-volume> <label-volume>";
label.muted.text = "🔇";
label.muted.foreground = "#666";
ramp.volume = [ "🔈" "🔉" "🔊" ];
click.right = "pavucontrol &";
};
};
extraConfig = ''
[module/date]
type = internal/date