diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a5e943be..fed61725 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -69,6 +69,8 @@ /modules/programs/i3status.nix @JustinLovinger +/modules/programs/i3status-rust.nix @workflow + /modules/programs/keychain.nix @marsam /modules/programs/lesspipe.nix @rycee diff --git a/modules/misc/news.nix b/modules/misc/news.nix index 92e716b4..e42d0f6b 100644 --- a/modules/misc/news.nix +++ b/modules/misc/news.nix @@ -1728,6 +1728,14 @@ in A new module is available: 'services.caffeine'. ''; } + + { + time = "2020-11-05T22:59:21+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'programs.i3status-rust'. + ''; + } ]; }; } diff --git a/modules/modules.nix b/modules/modules.nix index 75145e48..e7aab60f 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -75,6 +75,7 @@ let (loadModule ./programs/home-manager.nix { }) (loadModule ./programs/htop.nix { }) (loadModule ./programs/i3status.nix { }) + (loadModule ./programs/i3status-rust.nix { condition = hostPlatform.isLinux; }) (loadModule ./programs/info.nix { }) (loadModule ./programs/irssi.nix { }) (loadModule ./programs/lieer.nix { }) diff --git a/modules/programs/i3status-rust.nix b/modules/programs/i3status-rust.nix new file mode 100644 index 00000000..5f44c818 --- /dev/null +++ b/modules/programs/i3status-rust.nix @@ -0,0 +1,265 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.i3status-rust; + + restartI3 = '' + i3Socket=''${XDG_RUNTIME_DIR:-/run/user/$UID}/i3/ipc-socket.* + if [ -S $i3Socket ]; then + echo "Reloading i3" + $DRY_RUN_CMD ${config.xsession.windowManager.i3.package}/bin/i3-msg -s $i3Socket restart 1>/dev/null + fi + ''; + + settingsFormat = pkgs.formats.toml { }; + +in { + meta.maintainers = [ maintainers.farlion ]; + + options.programs.i3status-rust = { + enable = mkEnableOption "a replacement for i3-status written in Rust"; + + bars = mkOption { + type = types.attrsOf (types.submodule { + options = { + + blocks = mkOption { + type = settingsFormat.type; + default = [ + { + block = "disk_space"; + path = "/"; + alias = "/"; + info_type = "available"; + unit = "GB"; + interval = 60; + warning = 20.0; + alert = 10.0; + } + { + block = "memory"; + display_type = "memory"; + format_mem = "{Mup}%"; + format_swap = "{SUp}%"; + } + { + block = "cpu"; + interval = 1; + } + { + block = "load"; + interval = 1; + format = "{1m}"; + } + { block = "sound"; } + { + block = "time"; + interval = 60; + format = "%a %d/%m %R"; + } + ]; + description = '' + Configuration blocks to add to i3status-rust + config. See + + for block options. + ''; + example = literalExample '' + [ + { + block = "disk_space"; + path = "/"; + alias = "/"; + info_type = "available"; + unit = "GB"; + interval = 60; + warning = 20.0; + alert = 10.0; + } + { + block = "sound"; + format = "{output_name} {volume}%"; + on_click = "pavucontrol --tab=3"; + mappings = { + "alsa_output.pci-0000_00_1f.3.analog-stereo" = ""; + "bluez_sink.70_26_05_DA_27_A4.a2dp_sink" = "" + }; + } + ]; + ''; + }; + + settings = mkOption { + type = settingsFormat.type; + default = { }; + description = '' + Any extra options to add to i3status-rust + config. + ''; + example = literalExample '' + { + theme = { + name = "solarized-dark"; + overrides = { + idle_bg = "#123456"; + idle_fg = "#abcdef"; + }; + }; + } + ''; + }; + + icons = mkOption { + type = types.str; + default = "none"; + description = '' + The icons set to use. See + + for a list of available icon sets. + ''; + example = "awesome5"; + }; + + theme = mkOption { + type = types.str; + default = "plain"; + description = '' + The theme to use. See + + for a list of available themes. + ''; + example = "gruvbox-dark"; + }; + }; + }); + + default = { + default = { + blocks = [ + { + block = "disk_space"; + path = "/"; + alias = "/"; + info_type = "available"; + unit = "GB"; + interval = 60; + warning = 20.0; + alert = 10.0; + } + { + block = "memory"; + display_type = "memory"; + format_mem = "{Mup}%"; + format_swap = "{SUp}%"; + } + { + block = "cpu"; + interval = 1; + } + { + block = "load"; + interval = 1; + format = "{1m}"; + } + { block = "sound"; } + { + block = "time"; + interval = 60; + format = "%a %d/%m %R"; + } + ]; + }; + }; + description = '' + Attribute set of i3status-rust bars, each with their own configuration. + Each bar name generates a config file suffixed with + the bar's name from the attribute set, like so: + config-name.toml. + + This way, multiple config files can be generated, such as for having a + top and a bottom bar. + + See + + i3status-rust + 1 + + for options. + ''; + example = literalExample '' + bottom = { + blocks = [ + { + block = "disk_space"; + path = "/"; + alias = "/"; + info_type = "available"; + unit = "GB"; + interval = 60; + warning = 20.0; + alert = 10.0; + } + { + block = "memory"; + display_type = "memory"; + format_mem = "{Mup}%"; + format_swap = "{SUp}%"; + } + { + block = "cpu"; + interval = 1; + } + { + block = "load"; + interval = 1; + format = "{1m}"; + } + { block = "sound"; } + { + block = "time"; + interval = 60; + format = "%a %d/%m %R"; + } + ]; + settings = { + theme = { + name = "solarized-dark"; + overrides = { + idle_bg = "#123456"; + idle_fg = "#abcdef"; + }; + }; + }; + icons = "awesome5"; + theme = "gruvbox-dark"; + }; + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.i3status-rust; + defaultText = literalExample "pkgs.i3status-rust"; + description = "Package providing i3status-rust"; + }; + + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile = mapAttrs' (cfgFileSuffix: cfg: + nameValuePair ("i3status-rust/config-${cfgFileSuffix}.toml") ({ + onChange = mkIf config.xsession.windowManager.i3.enable restartI3; + + source = settingsFormat.generate ("config-${cfgFileSuffix}.toml") ({ + theme = cfg.theme; + icons = cfg.icons; + block = cfg.blocks; + } // cfg.settings); + })) cfg.bars; + }; +} diff --git a/tests/default.nix b/tests/default.nix index 6ece9dfd..3bbe8820 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -86,6 +86,7 @@ import nmt { ./modules/programs/autorandr ./modules/programs/firefox ./modules/programs/getmail + ./modules/programs/i3status-rust ./modules/programs/ncmpcpp-linux ./modules/programs/neovim # Broken package dependency on Darwin. ./modules/programs/rofi diff --git a/tests/modules/programs/i3status-rust/default.nix b/tests/modules/programs/i3status-rust/default.nix new file mode 100644 index 00000000..50d8c7b8 --- /dev/null +++ b/tests/modules/programs/i3status-rust/default.nix @@ -0,0 +1,6 @@ +{ + i3status-rust-with-default = ./with-default.nix; + i3status-rust-with-custom = ./with-custom.nix; + i3status-rust-with-extra-settings = ./with-extra-settings.nix; + i3status-rust-with-multiple-bars = ./with-multiple-bars.nix; +} diff --git a/tests/modules/programs/i3status-rust/with-custom.nix b/tests/modules/programs/i3status-rust/with-custom.nix new file mode 100644 index 00000000..4ced6add --- /dev/null +++ b/tests/modules/programs/i3status-rust/with-custom.nix @@ -0,0 +1,186 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.i3status-rust = { + enable = true; + bars = { + custom = { + blocks = [ + { + block = "disk_space"; + path = "/"; + alias = "/"; + info_type = "available"; + unit = "GB"; + interval = 60; + warning = 20.0; + alert = 10.0; + } + { + block = "memory"; + display_type = "memory"; + format_mem = "{Mug}GB ({Mup}%)"; + format_swap = "{SUp}%"; + } + { + block = "cpu"; + interval = 1; + format = "{barchart}"; + } + { + block = "load"; + interval = 1; + format = "{1m} {5m}"; + } + { + block = "temperature"; + collapsed = true; + interval = 10; + format = "{min}° min, {max}° max, {average}° avg"; + chip = "*-isa-*"; + } + { + block = "networkmanager"; + ap_format = "{ssid} @ {strength}%"; + on_click = "kcmshell5 kcm_networkmanagement"; + } + { + block = "net"; + device = "enp9s0u2u1u2c2"; + speed_up = true; + interval = 5; + } + { + block = "speedtest"; + bytes = true; + } + { + block = "xrandr"; + interval = + 6000; # Because running the commands causes screen lag, see https://github.com/greshake/i3status-rust/issues/668 + } + { + block = "sound"; + format = "{output_name} {volume}%"; + on_click = "pavucontrol --tab=3"; + mappings = { + "alsa_output.pci-0000_00_1f.3.analog-stereo" = ""; + "bluez_sink.70_26_05_DA_27_A4.a2dp_sink" = ""; + }; + } + { + block = "music"; + player = "spotify"; + buttons = [ "play" "prev" "next" ]; + on_collapsed_click = "i3-msg '[class=Spotify] focus'"; + } + { + block = "time"; + interval = 60; + format = "%a %d.%m %R"; + } + { block = "battery"; } + ]; + + icons = "awesome5"; + + theme = "gruvbox-dark"; + }; + }; + }; + + nixpkgs.overlays = [ + (self: super: { + i3status-rust = pkgs.writeScriptBin "dummy-i3status-rust" ""; + }) + ]; + + nmt.script = '' + assertFileExists home-files/.config/i3status-rust/config-custom.toml + assertFileContent home-files/.config/i3status-rust/config-custom.toml \ + ${ + pkgs.writeText "i3status-rust-expected-config" '' + icons = "awesome5" + theme = "gruvbox-dark" + [[block]] + alert = 10 + alias = "/" + block = "disk_space" + info_type = "available" + interval = 60 + path = "/" + unit = "GB" + warning = 20 + + [[block]] + block = "memory" + display_type = "memory" + format_mem = "{Mug}GB ({Mup}%)" + format_swap = "{SUp}%" + + [[block]] + block = "cpu" + format = "{barchart}" + interval = 1 + + [[block]] + block = "load" + format = "{1m} {5m}" + interval = 1 + + [[block]] + block = "temperature" + chip = "*-isa-*" + collapsed = true + format = "{min}° min, {max}° max, {average}° avg" + interval = 10 + + [[block]] + ap_format = "{ssid} @ {strength}%" + block = "networkmanager" + on_click = "kcmshell5 kcm_networkmanagement" + + [[block]] + block = "net" + device = "enp9s0u2u1u2c2" + interval = 5 + speed_up = true + + [[block]] + block = "speedtest" + bytes = true + + [[block]] + block = "xrandr" + interval = 6000 + + [[block]] + block = "sound" + format = "{output_name} {volume}%" + on_click = "pavucontrol --tab=3" + + [block.mappings] + "alsa_output.pci-0000_00_1f.3.analog-stereo" = "" + "bluez_sink.70_26_05_DA_27_A4.a2dp_sink" = "" + + [[block]] + block = "music" + buttons = ["play", "prev", "next"] + on_collapsed_click = "i3-msg '[class=Spotify] focus'" + player = "spotify" + + [[block]] + block = "time" + format = "%a %d.%m %R" + interval = 60 + + [[block]] + block = "battery" + '' + } + ''; + }; +} diff --git a/tests/modules/programs/i3status-rust/with-default.nix b/tests/modules/programs/i3status-rust/with-default.nix new file mode 100644 index 00000000..b62c248c --- /dev/null +++ b/tests/modules/programs/i3status-rust/with-default.nix @@ -0,0 +1,58 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.i3status-rust = { enable = true; }; + + nixpkgs.overlays = [ + (self: super: { + i3status-rust = pkgs.writeScriptBin "dummy-i3status-rust" ""; + }) + ]; + + nmt.script = '' + assertFileExists home-files/.config/i3status-rust/config-default.toml + assertFileContent home-files/.config/i3status-rust/config-default.toml \ + ${ + pkgs.writeText "i3status-rust-expected-config" '' + icons = "none" + theme = "plain" + [[block]] + alert = 10 + alias = "/" + block = "disk_space" + info_type = "available" + interval = 60 + path = "/" + unit = "GB" + warning = 20 + + [[block]] + block = "memory" + display_type = "memory" + format_mem = "{Mup}%" + format_swap = "{SUp}%" + + [[block]] + block = "cpu" + interval = 1 + + [[block]] + block = "load" + format = "{1m}" + interval = 1 + + [[block]] + block = "sound" + + [[block]] + block = "time" + format = "%a %d/%m %R" + interval = 60 + '' + } + ''; + }; +} diff --git a/tests/modules/programs/i3status-rust/with-extra-settings.nix b/tests/modules/programs/i3status-rust/with-extra-settings.nix new file mode 100644 index 00000000..16f3428a --- /dev/null +++ b/tests/modules/programs/i3status-rust/with-extra-settings.nix @@ -0,0 +1,202 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.i3status-rust = { + enable = true; + bars = { + extra-settings = { + blocks = [ + { + block = "disk_space"; + path = "/"; + alias = "/"; + info_type = "available"; + unit = "GB"; + interval = 60; + warning = 20.0; + alert = 10.0; + } + { + block = "memory"; + display_type = "memory"; + format_mem = "{Mug}GB ({Mup}%)"; + format_swap = "{SUp}%"; + } + { + block = "cpu"; + interval = 1; + format = "{barchart}"; + } + { + block = "load"; + interval = 1; + format = "{1m} {5m}"; + } + { + block = "temperature"; + collapsed = true; + interval = 10; + format = "{min}° min, {max}° max, {average}° avg"; + chip = "*-isa-*"; + } + { + block = "networkmanager"; + ap_format = "{ssid} @ {strength}%"; + on_click = "kcmshell5 kcm_networkmanagement"; + } + { + block = "net"; + device = "enp9s0u2u1u2c2"; + speed_up = true; + interval = 5; + } + { + block = "speedtest"; + bytes = true; + } + { + block = "xrandr"; + interval = + 6000; # Because running the commands causes screen lag, see https://github.com/greshake/i3status-rust/issues/668 + } + { + block = "sound"; + format = "{output_name} {volume}%"; + on_click = "pavucontrol --tab=3"; + mappings = { + "alsa_output.pci-0000_00_1f.3.analog-stereo" = ""; + "bluez_sink.70_26_05_DA_27_A4.a2dp_sink" = ""; + }; + } + { + block = "music"; + player = "spotify"; + buttons = [ "play" "prev" "next" ]; + on_collapsed_click = "i3-msg '[class=Spotify] focus'"; + } + { + block = "time"; + interval = 60; + format = "%a %d.%m %R"; + } + { block = "battery"; } + ]; + + icons = "awesome5"; + + settings = { + theme = { + name = "solarized-dark"; + overrides = { + idle_bg = "#123456"; + idle_fg = "#abcdef"; + }; + }; + }; + + theme = "gruvbox-dark"; + }; + }; + }; + + nixpkgs.overlays = [ + (self: super: { + i3status-rust = pkgs.writeScriptBin "dummy-i3status-rust" ""; + }) + ]; + + nmt.script = '' + assertFileExists home-files/.config/i3status-rust/config-extra-settings.toml + assertFileContent home-files/.config/i3status-rust/config-extra-settings.toml \ + ${ + pkgs.writeText "i3status-rust-expected-config" '' + icons = "awesome5" + [[block]] + alert = 10 + alias = "/" + block = "disk_space" + info_type = "available" + interval = 60 + path = "/" + unit = "GB" + warning = 20 + + [[block]] + block = "memory" + display_type = "memory" + format_mem = "{Mug}GB ({Mup}%)" + format_swap = "{SUp}%" + + [[block]] + block = "cpu" + format = "{barchart}" + interval = 1 + + [[block]] + block = "load" + format = "{1m} {5m}" + interval = 1 + + [[block]] + block = "temperature" + chip = "*-isa-*" + collapsed = true + format = "{min}° min, {max}° max, {average}° avg" + interval = 10 + + [[block]] + ap_format = "{ssid} @ {strength}%" + block = "networkmanager" + on_click = "kcmshell5 kcm_networkmanagement" + + [[block]] + block = "net" + device = "enp9s0u2u1u2c2" + interval = 5 + speed_up = true + + [[block]] + block = "speedtest" + bytes = true + + [[block]] + block = "xrandr" + interval = 6000 + + [[block]] + block = "sound" + format = "{output_name} {volume}%" + on_click = "pavucontrol --tab=3" + + [block.mappings] + "alsa_output.pci-0000_00_1f.3.analog-stereo" = "" + "bluez_sink.70_26_05_DA_27_A4.a2dp_sink" = "" + + [[block]] + block = "music" + buttons = ["play", "prev", "next"] + on_collapsed_click = "i3-msg '[class=Spotify] focus'" + player = "spotify" + + [[block]] + block = "time" + format = "%a %d.%m %R" + interval = 60 + + [[block]] + block = "battery" + + [theme] + name = "solarized-dark" + + [theme.overrides] + idle_bg = "#123456" + idle_fg = "#abcdef" + '' + } + ''; + }; +} diff --git a/tests/modules/programs/i3status-rust/with-multiple-bars.nix b/tests/modules/programs/i3status-rust/with-multiple-bars.nix new file mode 100644 index 00000000..9cbbe285 --- /dev/null +++ b/tests/modules/programs/i3status-rust/with-multiple-bars.nix @@ -0,0 +1,106 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.i3status-rust = { + enable = true; + + bars = { + + top = { + blocks = [ + { + block = "disk_space"; + path = "/"; + alias = "/"; + info_type = "available"; + unit = "GB"; + interval = 60; + warning = 20.0; + alert = 10.0; + } + { + block = "memory"; + display_type = "memory"; + format_mem = "{Mug}GB ({Mup}%)"; + format_swap = "{SUp}%"; + } + ]; + }; + + bottom = { + blocks = [ + { + block = "cpu"; + interval = 1; + format = "{barchart}"; + } + { + block = "load"; + interval = 1; + format = "{1m} {5m}"; + } + ]; + icons = "awesome5"; + + theme = "gruvbox-dark"; + }; + + }; + + }; + + nixpkgs.overlays = [ + (self: super: { + i3status-rust = pkgs.writeScriptBin "dummy-i3status-rust" ""; + }) + ]; + + nmt.script = '' + assertFileExists home-files/.config/i3status-rust/config-top.toml + assertFileContent home-files/.config/i3status-rust/config-top.toml \ + ${ + pkgs.writeText "i3status-rust-expected-config" '' + icons = "none" + theme = "plain" + [[block]] + alert = 10 + alias = "/" + block = "disk_space" + info_type = "available" + interval = 60 + path = "/" + unit = "GB" + warning = 20 + + [[block]] + block = "memory" + display_type = "memory" + format_mem = "{Mug}GB ({Mup}%)" + format_swap = "{SUp}%" + '' + } + + assertFileExists home-files/.config/i3status-rust/config-bottom.toml + assertFileContent \ + home-files/.config/i3status-rust/config-bottom.toml \ + ${ + pkgs.writeText "i3status-rust-expected-config" '' + icons = "awesome5" + theme = "gruvbox-dark" + [[block]] + block = "cpu" + format = "{barchart}" + interval = 1 + + [[block]] + block = "load" + format = "{1m} {5m}" + interval = 1 + '' + } + ''; + }; +}