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
+ ''
+ }
+ '';
+ };
+}