restructure module config to objects with enable + extra options

This commit is contained in:
Damocles 2026-04-12 17:36:38 +02:00
parent 4109078a91
commit 55ab5bc4e7
9 changed files with 123 additions and 117 deletions

View file

@ -69,20 +69,25 @@ frankly more than it deserves.
```nix ```nix
programs.nova-shell.modules = { programs.nova-shell.modules = {
weather = false; # also evicts wttrbar from your system weather.enable = false; # also evicts wttrbar from your system
bluetooth = false; # for people whose computers have ethernet ports and opinions bluetooth.enable = false; # for people whose computers have ethernet ports and opinions
backlight = false; # your desktop monitor does not have a backlight slider, probably backlight.enable = false; # your desktop monitor does not have a backlight slider, probably
battery = false; # see above, but for power battery.enable = false; # see above, but for power
temperature = false; # what you don't measure can't alarm you temperature.enable = false; # what you don't measure can't alarm you
disk = false; # the number will only make you anxious disk.enable = false; # the number will only make you anxious
power = false; # if you enjoy living dangerously without a logout button power.enable = false; # if you enjoy living dangerously without a logout button
# modules with extra config
backlight.step = 2; # brightness adjustment %
weather.args = [ "--nerd" "--location" "Berlin" ]; # wttrbar arguments
}; };
``` ```
Full list of things you can disable: `workspaces`, `tray`, `windowTitle`, Each module is an object with `enable` (default `true`) and optional extra
`clock`, `notifications`, `mpris`, `volume`, `bluetooth`, `backlight`, settings. Full list: `workspaces`, `tray`, `windowTitle`, `clock`,
`network`, `powerProfile`, `idleInhibitor`, `weather`, `temperature`, `cpu`, `notifications`, `mpris`, `volume`, `bluetooth`, `backlight`, `network`,
`memory`, `disk`, `battery`, `power`. `powerProfile`, `idleInhibitor`, `weather`, `temperature`, `cpu`, `memory`,
`disk`, `battery`, `power`.
### Theme ### Theme
@ -124,16 +129,6 @@ Full list of theme keys and their defaults:
| `radius` | `4` | Corner radius for flyouts and menus (px) | | `radius` | `4` | Corner radius for flyouts and menus (px) |
| `screenRadius` | `15` | Screen corner rounding, 0 to disable (px) | | `screenRadius` | `15` | Screen corner rounding, 0 to disable (px) |
### Weather
Wttrbar arguments are configurable. The default is `["--nerd"]` which gives
you nerd font weather icons, which is the only acceptable way to display
meteorological data.
```nix
programs.nova-shell.weatherArgs = [ "--nerd" "--location" "Berlin" ];
```
### Systemd service ### Systemd service
Enabled by default, bound to `graphical-session.target`. To attach it to Enabled by default, bound to `graphical-session.target`. To attach it to

View file

@ -5,7 +5,7 @@ import "." as M
M.BarSection { M.BarSection {
id: root id: root
spacing: M.Theme.moduleSpacing spacing: M.Theme.moduleSpacing
opacity: M.Modules.backlight && percent > 0 ? 1 : 0 opacity: M.Modules.backlight.enable && percent > 0 ? 1 : 0
visible: opacity > 0 visible: opacity > 0
tooltip: "Brightness: " + root.percent + "%" tooltip: "Brightness: " + root.percent + "%"
@ -22,7 +22,8 @@ M.BarSection {
} }
function adjust(delta) { function adjust(delta) {
adjProc.cmd = delta > 0 ? "light -A 5" : "light -U 5"; const step = M.Modules.backlight.step || 5;
adjProc.cmd = delta > 0 ? "light -A " + step : "light -U " + step;
adjProc.running = true; adjProc.running = true;
} }

View file

@ -53,8 +53,8 @@ PanelWindow {
M.BarGroup { M.BarGroup {
borderColor: M.Theme.base0D borderColor: M.Theme.base0D
M.Clock { visible: M.Modules.clock } M.Clock { visible: M.Modules.clock.enable }
M.Notifications { visible: M.Modules.notifications } M.Notifications { visible: M.Modules.notifications.enable }
} }
} }
@ -67,17 +67,17 @@ PanelWindow {
M.BarGroup { M.BarGroup {
borderColor: M.Theme.base0D borderColor: M.Theme.base0D
M.Workspaces { bar: bar; visible: M.Modules.workspaces } M.Workspaces { bar: bar; visible: M.Modules.workspaces.enable }
} }
M.BarGroup { M.BarGroup {
borderColor: M.Theme.base0D borderColor: M.Theme.base0D
M.Tray { bar: bar; visible: M.Modules.tray } M.Tray { bar: bar; visible: M.Modules.tray.enable }
} }
M.BarGroup { M.BarGroup {
borderColor: M.Theme.base0D borderColor: M.Theme.base0D
M.WindowTitle { M.WindowTitle {
Layout.maximumWidth: 400 Layout.maximumWidth: 400
visible: M.Modules.windowTitle visible: M.Modules.windowTitle.enable
} }
} }
Item { Layout.fillWidth: true } Item { Layout.fillWidth: true }
@ -96,13 +96,13 @@ PanelWindow {
M.BarGroup { M.BarGroup {
borderColor: M.Theme.base0E borderColor: M.Theme.base0E
M.Mpris {} M.Mpris {}
M.Volume { visible: M.Modules.volume } M.Volume { visible: M.Modules.volume.enable }
} }
// Connectivity // Connectivity
M.BarGroup { M.BarGroup {
borderColor: M.Theme.base0D borderColor: M.Theme.base0D
M.Network { visible: M.Modules.network } M.Network { visible: M.Modules.network.enable }
M.Bluetooth {} M.Bluetooth {}
} }
@ -110,25 +110,25 @@ PanelWindow {
M.BarGroup { M.BarGroup {
borderColor: M.Theme.base0A borderColor: M.Theme.base0A
M.Backlight {} M.Backlight {}
M.PowerProfile { visible: M.Modules.powerProfile } M.PowerProfile { visible: M.Modules.powerProfile.enable }
M.IdleInhibitor { visible: M.Modules.idleInhibitor } M.IdleInhibitor { visible: M.Modules.idleInhibitor.enable }
} }
// Stats // Stats
M.BarGroup { M.BarGroup {
borderColor: M.Theme.base08 borderColor: M.Theme.base08
M.Cpu { visible: M.Modules.cpu } M.Cpu { visible: M.Modules.cpu.enable }
M.Memory { visible: M.Modules.memory } M.Memory { visible: M.Modules.memory.enable }
M.Temperature { visible: M.Modules.temperature } M.Temperature { visible: M.Modules.temperature.enable }
M.Weather { visible: M.Modules.weather } M.Weather { visible: M.Modules.weather.enable }
M.Disk { visible: M.Modules.disk } M.Disk { visible: M.Modules.disk.enable }
} }
// Power // Power
M.BarGroup { M.BarGroup {
borderColor: M.Theme.base08 borderColor: M.Theme.base08
M.Battery {} M.Battery {}
M.Power { bar: bar; visible: M.Modules.power } M.Power { bar: bar; visible: M.Modules.power.enable }
} }
} }
} }

View file

@ -6,7 +6,7 @@ import "." as M
M.BarSection { M.BarSection {
id: root id: root
spacing: M.Theme.moduleSpacing spacing: M.Theme.moduleSpacing
opacity: M.Modules.battery && (UPower.displayDevice?.isLaptopBattery ?? false) ? 1 : 0 opacity: M.Modules.battery.enable && (UPower.displayDevice?.isLaptopBattery ?? false) ? 1 : 0
visible: opacity > 0 visible: opacity > 0
tooltip: { tooltip: {
const state = root.charging ? "Charging" : "Discharging"; const state = root.charging ? "Charging" : "Discharging";

View file

@ -5,7 +5,7 @@ import "." as M
M.BarSection { M.BarSection {
id: root id: root
spacing: M.Theme.moduleSpacing spacing: M.Theme.moduleSpacing
opacity: M.Modules.bluetooth && root.state !== "unavailable" ? 1 : 0 opacity: M.Modules.bluetooth.enable && root.state !== "unavailable" ? 1 : 0
visible: opacity > 0 visible: opacity > 0
tooltip: { tooltip: {
if (root.state === "off") if (root.state === "off")

View file

@ -7,27 +7,25 @@ import Quickshell.Io
QtObject { QtObject {
id: root id: root
property bool workspaces: true property var workspaces: ({ enable: true })
property bool tray: true property var tray: ({ enable: true })
property bool windowTitle: true property var windowTitle: ({ enable: true })
property bool clock: true property var clock: ({ enable: true })
property bool notifications: true property var notifications: ({ enable: true })
property bool mpris: true property var mpris: ({ enable: true })
property bool volume: true property var volume: ({ enable: true })
property bool bluetooth: true property var bluetooth: ({ enable: true })
property bool backlight: true property var backlight: ({ enable: true, step: 5 })
property bool network: true property var network: ({ enable: true })
property bool powerProfile: true property var powerProfile: ({ enable: true })
property bool idleInhibitor: true property var idleInhibitor: ({ enable: true })
property bool weather: true property var weather: ({ enable: true, args: ["--nerd"] })
property bool temperature: true property var temperature: ({ enable: true })
property bool cpu: true property var cpu: ({ enable: true })
property bool memory: true property var memory: ({ enable: true })
property bool disk: true property var disk: ({ enable: true })
property bool battery: true property var battery: ({ enable: true })
property bool power: true property var power: ({ enable: true })
property var weatherArgs: ["--nerd"]
property FileView _file: FileView { property FileView _file: FileView {
path: (Quickshell.env("XDG_CONFIG_HOME") || (Quickshell.env("HOME") + "/.config")) + "/nova-shell/modules.json" path: (Quickshell.env("XDG_CONFIG_HOME") || (Quickshell.env("HOME") + "/.config")) + "/nova-shell/modules.json"
@ -44,10 +42,12 @@ QtObject {
return; return;
} }
for (const k of Object.keys(data)) { for (const k of Object.keys(data)) {
if (k in root && typeof root[k] === "boolean") if (!(k in root)) continue;
root[k] = data[k]; const v = data[k];
} if (typeof v === "object" && v !== null)
if (Array.isArray(data.weatherArgs)) root[k] = Object.assign({}, root[k], v);
root.weatherArgs = data.weatherArgs; else if (typeof v === "boolean")
root[k] = Object.assign({}, root[k], { enable: v });
}
} }
} }

View file

@ -5,7 +5,7 @@ import "." as M
M.BarSection { M.BarSection {
id: root id: root
spacing: M.Theme.moduleSpacing spacing: M.Theme.moduleSpacing
opacity: M.Modules.mpris && player !== null ? 1 : 0 opacity: M.Modules.mpris.enable && player !== null ? 1 : 0
visible: opacity > 0 visible: opacity > 0
tooltip: { tooltip: {
const p = root.player; const p = root.player;

View file

@ -12,7 +12,7 @@ M.BarSection {
Process { Process {
id: proc id: proc
running: true running: true
command: ["wttrbar"].concat(M.Modules.weatherArgs) command: ["wttrbar"].concat(M.Modules.weather.args)
stdout: StdioCollector { stdout: StdioCollector {
onStreamFinished: { onStreamFinished: {
try { try {

View file

@ -52,13 +52,24 @@ in
description = "nova-shell package to use."; description = "nova-shell package to use.";
}; };
modules = lib.mkOption { modules =
description = "Enable or disable individual bar modules."; let
moduleOpt =
name: extra:
lib.mkOption {
default = { }; default = { };
description = "Configuration for the ${name} module.";
type = lib.types.submodule { type = lib.types.submodule {
options = options = {
lib.genAttrs enable = lib.mkOption {
[ type = lib.types.bool;
default = true;
description = "Enable the ${name} module.";
};
} // extra;
};
};
simpleModules = lib.genAttrs [
"workspaces" "workspaces"
"tray" "tray"
"windowTitle" "windowTitle"
@ -67,30 +78,28 @@ in
"mpris" "mpris"
"volume" "volume"
"bluetooth" "bluetooth"
"backlight"
"network" "network"
"powerProfile" "powerProfile"
"idleInhibitor" "idleInhibitor"
"weather"
"temperature" "temperature"
"cpu" "cpu"
"memory" "memory"
"disk" "disk"
"battery" "battery"
"power" "power"
] ] (name: moduleOpt name { });
( in
name: simpleModules
lib.mkOption { // {
type = lib.types.bool; backlight = moduleOpt "backlight" {
default = true; step = lib.mkOption {
description = "Enable the ${name} module."; type = lib.types.int;
} default = 5;
); description = "Brightness adjustment step (%).";
}; };
}; };
weather = moduleOpt "weather" {
weatherArgs = lib.mkOption { args = lib.mkOption {
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
default = [ "--nerd" ]; default = [ "--nerd" ];
description = "Arguments passed to wttrbar."; description = "Arguments passed to wttrbar.";
@ -100,6 +109,8 @@ in
"Berlin" "Berlin"
]; ];
}; };
};
};
theme = lib.mkOption { theme = lib.mkOption {
type = lib.types.attrsOf lib.types.anything; type = lib.types.attrsOf lib.types.anything;
@ -131,11 +142,10 @@ in
self.packages.${pkgs.stdenv.hostPlatform.system}.nova-shell-cli self.packages.${pkgs.stdenv.hostPlatform.system}.nova-shell-cli
pkgs.nerd-fonts.symbols-only pkgs.nerd-fonts.symbols-only
] ]
++ lib.optional cfg.modules.weather pkgs.wttrbar; ++ lib.optional cfg.modules.weather.enable pkgs.wttrbar;
xdg.configFile."nova-shell/modules.json".source = xdg.configFile."nova-shell/modules.json".source =
(pkgs.formats.json { }).generate "nova-shell-modules.json" (pkgs.formats.json { }).generate "nova-shell-modules.json" cfg.modules;
(cfg.modules // { weatherArgs = cfg.weatherArgs; });
xdg.configFile."nova-shell/theme.json".source = xdg.configFile."nova-shell/theme.json".source =
let let