diff --git a/README.md b/README.md index 7e913de..12f6b59 100644 --- a/README.md +++ b/README.md @@ -119,8 +119,35 @@ A flake is included with the repo which can be used with Home Manager. # And configure programs.ironbar = { enable = true; - config = {}; - style = ""; + systemd = true; + config = { + # An example: + monitors = { + DP-1 = { + anchor_to_edges = true; + position = "top"; + height = 16; + start = [ + { type = "clock"; } + ]; + end = [ + { + type = "tray"; + icon_size = 16; + } + ]; + }; + }; + }; + style = /* css */ '' + /* An example */ + * { + font-family: Noto Sans Nerd Font, sans-serif; + font-size: 16px; + border: none; + border-radius: 0; + } + ''; package = inputs.ironbar; features = ["feature" "another_feature"]; }; diff --git a/flake.lock b/flake.lock index f400faa..b6dd18b 100644 --- a/flake.lock +++ b/flake.lock @@ -15,6 +15,39 @@ "type": "github" } }, + "flake-compat": { + "locked": { + "lastModified": 1733328505, + "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1743550720, + "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "c621e8422220273271f52058f618c94e405bb0f5", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, "naersk": { "inputs": { "nixpkgs": "nixpkgs" @@ -49,6 +82,21 @@ "type": "github" } }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1743296961, + "narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, "nixpkgs_2": { "locked": { "lastModified": 1745930157, @@ -68,6 +116,8 @@ "root": { "inputs": { "crane": "crane", + "flake-compat": "flake-compat", + "flake-parts": "flake-parts", "naersk": "naersk", "nixpkgs": "nixpkgs_2", "rust-overlay": "rust-overlay" diff --git a/flake.nix b/flake.nix index 33bced5..15ab0dd 100644 --- a/flake.nix +++ b/flake.nix @@ -3,40 +3,75 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; - + flake-parts.url = "github:hercules-ci/flake-parts"; + flake-compat.url = "github:edolstra/flake-compat"; rust-overlay = { url = "github:oxalica/rust-overlay"; inputs.nixpkgs.follows = "nixpkgs"; }; - - crane = { - url = "github:ipetkov/crane"; - }; - + crane.url = "github:ipetkov/crane"; naersk.url = "github:nix-community/naersk"; }; - outputs = { self, nixpkgs, rust-overlay, crane, naersk, ... }: - let - inherit (nixpkgs) lib; - - genSystems = lib.genAttrs [ "aarch64-linux" "x86_64-linux" ]; - - pkgsFor = system: - import nixpkgs { - inherit system; - - overlays = [ self.overlays.default rust-overlay.overlays.default ]; - }; - + outputs = inputs @ { + self, + nixpkgs, + rust-overlay, + crane, + naersk, + flake-parts, + ... + }: + flake-parts.lib.mkFlake {inherit inputs;} (let mkRustToolchain = pkgs: pkgs.rust-bin.stable.latest.default.override { - extensions = [ "rust-src" ]; + extensions = ["rust-src"]; + }; + in { + systems = [ + "aarch64-linux" + "x86_64-linux" + ]; + + imports = [ + ./nix/devshell.nix + ]; + + perSystem = { + system, + config, + pkgs, + lib, + ... + }: { + _module.args.pkgs = import nixpkgs { + inherit system; + overlays = [ + self.overlays.default + rust-overlay.overlays.default + ]; }; - in { - overlays.default = final: prev: - let + # Packages + packages = { + ironbar = pkgs.ironbar; + default = pkgs.ironbar; + }; + + # Apps + apps = { + ironbar = { + type = "app"; + program = lib.getExe pkgs.ironbar; + }; + default = config.apps.ironbar; + }; + }; + + flake = { + overlays.default = final: prev: let + inherit (nixpkgs) lib; + rust = mkRustToolchain final; craneLib = (crane.mkLib final).overrideToolchain rust; @@ -53,176 +88,52 @@ props = builtins.fromTOML (builtins.readFile ./Cargo.toml); - mkDate = longDate: - (lib.concatStringsSep "-" [ - (builtins.substring 0 4 longDate) - (builtins.substring 4 2 longDate) - (builtins.substring 6 2 longDate) - ]); + mkDate = longDate: (lib.concatStringsSep "-" [ + (builtins.substring 0 4 longDate) + (builtins.substring 4 2 longDate) + (builtins.substring 6 2 longDate) + ]); builder = "naersk"; in { ironbar = let - version = props.package.version + "+date=" - + (mkDate (self.lastModifiedDate or "19700101")) + "_" + version = + props.package.version + + "+date=" + + (mkDate (self.lastModifiedDate or "19700101")) + + "_" + (self.shortRev or "dirty"); - in if builder == "crane" then - prev.callPackage ./nix/default.nix { - inherit version; - inherit rustPlatform; - builderName = builder; - builder = craneLib; - } - else if builder == "naersk" then - prev.callPackage ./nix/default.nix { - inherit version; - inherit rustPlatform; - builderName = builder; - builder = naersk'; - } - else - prev.callPackage ./nix/default.nix { - inherit version; - inherit rustPlatform; - builderName = builder; - }; + in + if builder == "crane" + then + prev.callPackage ./nix/package.nix { + inherit version; + inherit rustPlatform; + builderName = builder; + builder = craneLib; + } + else if builder == "naersk" + then + prev.callPackage ./nix/package.nix { + inherit version; + inherit rustPlatform; + builderName = builder; + builder = naersk'; + } + else + prev.callPackage ./nix/package.nix { + inherit version; + inherit rustPlatform; + builderName = builder; + }; }; - packages = genSystems (system: - let pkgs = pkgsFor system; - in (self.overlays.default pkgs pkgs) // { - default = self.packages.${system}.ironbar; - }); - - apps = genSystems (system: - let pkgs = pkgsFor system; - in rec { - ironbar = { - type = "app"; - program = "${pkgs.ironbar}/bin/ironbar"; - }; - - default = ironbar; - }); - - devShells = genSystems (system: - let - pkgs = pkgsFor system; - rust = mkRustToolchain pkgs; - - in { - default = pkgs.mkShell { - packages = with pkgs; [ - rust - rust-analyzer-unwrapped - gcc - gtk3 - gtk-layer-shell - pkg-config - openssl - gdk-pixbuf - glib - glib-networking - shared-mime-info - adwaita-icon-theme - hicolor-icon-theme - gsettings-desktop-schemas - libxkbcommon - libdbusmenu-gtk3 - libpulseaudio - libinput - libevdev - luajit - luajitPackages.lgi - ]; - - RUST_SRC_PATH = "${rust}/lib/rustlib/src/rust/library"; - }; - - }); - - homeManagerModules.default = { config, lib, pkgs, ... }: - let - cfg = config.programs.ironbar; - defaultIronbarPackage = - self.packages.${pkgs.hostPlatform.system}.default; - jsonFormat = pkgs.formats.json { }; - in { - options.programs.ironbar = { - enable = lib.mkEnableOption "ironbar status bar"; - - package = lib.mkOption { - type = with lib.types; package; - default = defaultIronbarPackage; - description = "The package for ironbar to use."; - }; - - systemd = lib.mkOption { - type = lib.types.bool; - default = pkgs.stdenv.isLinux; - description = "Whether to enable to systemd service for ironbar."; - }; - - style = lib.mkOption { - type = lib.types.either (lib.types.lines) (lib.types.path); - default = ""; - description = "The stylesheet to apply to ironbar."; - }; - - config = lib.mkOption { - type = jsonFormat.type; - default = { }; - description = "The config to pass to ironbar."; - }; - - features = lib.mkOption { - type = lib.types.listOf lib.types.nonEmptyStr; - default = [ ]; - description = "The features to be used."; - }; - - }; - config = let pkg = cfg.package.override { features = cfg.features; }; - in lib.mkIf cfg.enable { - home.packages = [ pkg ]; - - xdg.configFile = { - "ironbar/config.json" = lib.mkIf (cfg.config != "") { - source = jsonFormat.generate "ironbar-config" cfg.config; - }; - - "ironbar/style.css" = lib.mkIf (cfg.style != "") ( - if builtins.isPath cfg.style || lib.isStorePath cfg.style then - { source = cfg.style; } - else - { text = cfg.style; } - ); - }; - - systemd.user.services.ironbar = lib.mkIf cfg.systemd { - Unit = { - Description = "Systemd service for Ironbar"; - Requires = [ "graphical-session.target" ]; - }; - - Service = { - Type = "simple"; - ExecStart = "${pkg}/bin/ironbar"; - }; - - Install.WantedBy = with config.wayland.windowManager; [ - (lib.mkIf hyprland.systemd.enable "hyprland-session.target") - (lib.mkIf sway.systemd.enable "sway-session.target") - (lib.mkIf river.systemd.enable "river-session.target") - ]; - }; - }; - }; - }; + homeManagerModules.default = import ./nix/module.nix self; + }; + }); nixConfig = { - extra-substituters = [ "https://cache.garnix.io" ]; - extra-trusted-public-keys = - [ "cache.garnix.io:CTFPyKSLcx5RMJKfLo5EEPUObbA78b0YQ2DTCJXqr9g=" ]; + extra-substituters = ["https://cache.garnix.io"]; + extra-trusted-public-keys = ["cache.garnix.io:CTFPyKSLcx5RMJKfLo5EEPUObbA78b0YQ2DTCJXqr9g="]; }; } diff --git a/nix/default.nix b/nix/default.nix deleted file mode 100644 index 18ba622..0000000 --- a/nix/default.nix +++ /dev/null @@ -1,144 +0,0 @@ -{ - gtk3, - gdk-pixbuf, - librsvg, - webp-pixbuf-loader, - gobject-introspection, - glib-networking, - glib, - shared-mime-info, - gsettings-desktop-schemas, - wrapGAppsHook, - gtk-layer-shell, - gnome, - libxkbcommon, - libdbusmenu-gtk3, - libpulseaudio, - libinput, - libevdev, - openssl, - luajit, - luajitPackages, - pkg-config, - installShellFiles, - adwaita-icon-theme, - hicolor-icon-theme, - rustPlatform, - lib, - version ? "git", - features ? [], - builderName ? "nix", - builder ? {}, -}: let - hasFeature = f: features == [ ] || builtins.elem f features; - - basePkg = rec { - inherit version; - - pname = "ironbar"; - - src = builtins.path { - name = "ironbar"; - path = lib.cleanSource ../.; - }; - - nativeBuildInputs = [ - pkg-config - wrapGAppsHook - gobject-introspection - installShellFiles - ]; - - buildInputs = [ - gtk3 - gdk-pixbuf - glib - gtk-layer-shell - glib-networking - shared-mime-info - adwaita-icon-theme - hicolor-icon-theme - gsettings-desktop-schemas - libxkbcommon ] - ++ lib.optionals (hasFeature "http") [ openssl ] - ++ lib.optionals (hasFeature "tray") [ libdbusmenu-gtk3 ] - ++ lib.optionals (hasFeature "volume")[ libpulseaudio ] - ++ lib.optionals (hasFeature "cairo") [ luajit ] - ++ lib.optionals (hasFeature "keyboard") [ libinput libevdev ]; - - propagatedBuildInputs = [ gtk3 ]; - - lgi = luajitPackages.lgi; - - gappsWrapperArgs = '' - # Thumbnailers - --prefix XDG_DATA_DIRS : "${gdk-pixbuf}/share" - --prefix XDG_DATA_DIRS : "${librsvg}/share" - --prefix XDG_DATA_DIRS : "${webp-pixbuf-loader}/share" - --prefix XDG_DATA_DIRS : "${shared-mime-info}/share" - - # gtk-launch - --suffix PATH : "${lib.makeBinPath [ gtk3 ]}" - '' - + lib.optionalString (hasFeature "cairo") '' - --prefix LUA_PATH : "./?.lua;${lgi}/share/lua/5.1/?.lua;${lgi}/share/lua/5.1/?/init.lua;${luajit}/share/lua/5.1/\?.lua;${luajit}/share/lua/5.1/?/init.lua" - --prefix LUA_CPATH : "./?.so;${lgi}/lib/lua/5.1/?.so;${luajit}/lib/lua/5.1/?.so;${luajit}/lib/lua/5.1/loadall.so" - ''; - - preFixup = '' - gappsWrapperArgs+=( - ${gappsWrapperArgs} - ) - ''; - - postInstall = '' - installShellCompletion --cmd ironbar \ - --bash target/completions/ironbar.bash \ - --fish target/completions/ironbar.fish \ - --zsh target/completions/_ironbar - ''; - - passthru = { - updateScript = gnome.updateScript { - packageName = pname; - attrPath = "gnome.${pname}"; - }; - }; - - meta = with lib; { - homepage = "https://github.com/JakeStanger/ironbar"; - description = - "Customisable gtk-layer-shell wlroots/sway bar written in rust."; - license = licenses.mit; - platforms = platforms.linux; - mainProgram = "ironbar"; - }; - - }; - - flags = let - noDefault = if features == [ ] then "" else "--no-default-features"; - - featuresStr = if features == [ ] then - "" - else - ''-F "${builtins.concatStringsSep "," features}"''; - - in [ noDefault featuresStr ]; -in if builderName == "naersk" then - builder.buildPackage (basePkg // { cargoBuildOptions = old: old ++ flags; }) -else if builderName == "crane" then - builder.buildPackage (basePkg // { - cargoExtraArgs = builtins.concatStringsSep " " flags; - doCheck = false; - }) -else - rustPlatform.buildRustPackage (basePkg // { - buildNoDefaultFeatures = features != [ ]; - - buildFeatures = features; - cargoDeps = rustPlatform.importCargoLock { lockFile = ../Cargo.lock; }; - cargoLock.lockFile = ../Cargo.lock; - cargoLock.outputHashes."stray-0.1.3" = - "sha256-7mvsWZFmPWti9AiX67h6ZlWiVVRZRWIxq3pVaviOUtc="; - }) diff --git a/nix/devshell.nix b/nix/devshell.nix new file mode 100644 index 0000000..186f928 --- /dev/null +++ b/nix/devshell.nix @@ -0,0 +1,25 @@ +{ + perSystem = { pkgs, ... }: { + devShells.default = pkgs.mkShell { + packages = with pkgs; [ + cargo + clippy + rustfmt + gtk3 + gtk-layer-shell + gcc + openssl + libdbusmenu-gtk3 + libpulseaudio + libinput + libevdev + luajit + luajitPackages.lgi + ]; + + nativeBuildInputs = with pkgs; [ + pkg-config + ]; + }; + }; +} diff --git a/nix/module.nix b/nix/module.nix new file mode 100644 index 0000000..88582e5 --- /dev/null +++ b/nix/module.nix @@ -0,0 +1,88 @@ +self: { + config, + lib, + pkgs, + ... +}: let + cfg = config.programs.ironbar; + defaultIronbarPackage = self.packages.${pkgs.hostPlatform.system}.default; + jsonFormat = pkgs.formats.json {}; +in { + options.programs.ironbar = { + enable = lib.mkEnableOption "ironbar status bar"; + + package = lib.mkOption { + type = with lib.types; package; + default = defaultIronbarPackage; + apply = pkg: pkg.override {features = cfg.features;}; + description = "The package for ironbar to use."; + }; + + systemd = lib.mkEnableOption "systemd service for ironbar."; + + style = lib.mkOption { + type = lib.types.either (lib.types.lines) (lib.types.path); + default = ""; + description = "The stylesheet to apply to ironbar."; + }; + + config = lib.mkOption { + type = jsonFormat.type; + default = {}; + description = "The config to pass to ironbar."; + }; + + features = lib.mkOption { + type = lib.types.listOf lib.types.nonEmptyStr; + default = []; + description = "The features to be used."; + }; + }; + + config = lib.mkIf cfg.enable { + home.packages = [ + cfg.package + ]; + + xdg.configFile = { + "ironbar/config.json" = lib.mkIf (cfg.config != "") { + onChange = "${lib.getExe cfg.package} reload"; + source = jsonFormat.generate "ironbar-config" cfg.config; + }; + + "ironbar/style.css" = lib.mkIf (cfg.style != "") ( + if builtins.isPath cfg.style || lib.isStorePath cfg.style + then {source = cfg.style;} + else {text = cfg.style;} + ); + }; + + systemd.user.services.ironbar = lib.mkIf cfg.systemd { + Unit = { + Description = "Systemd service for Ironbar"; + Documentation = "https://github.com/JakeStanger/ironbar"; + PartOf = [ + config.wayland.systemd.target + "tray.target" + ]; + After = [config.wayland.systemd.target]; + ConditionEnvironment = "WAYLAND_DISPLAY"; + }; + + Service = { + ExecReload = "${lib.getExe cfg.package} reload"; + ExecStart = "${lib.getExe cfg.package}"; + KillMode = "mixed"; + Restart = "on-failure"; + }; + + Install.WantedBy = [ + config.wayland.systemd.target + "tray.target" + (lib.mkIf config.wayland.windowManager.hyprland.enable "hyprland-session.target") + (lib.mkIf config.wayland.windowManager.sway.enable "sway-session.target") + (lib.mkIf config.wayland.windowManager.river.enable "river-session.target") + ]; + }; + }; +} diff --git a/nix/package.nix b/nix/package.nix new file mode 100644 index 0000000..c77b817 --- /dev/null +++ b/nix/package.nix @@ -0,0 +1,166 @@ +{ + gtk3, + gdk-pixbuf, + librsvg, + webp-pixbuf-loader, + gobject-introspection, + glib-networking, + glib, + shared-mime-info, + gsettings-desktop-schemas, + wrapGAppsHook, + gtk-layer-shell, + gnome, + libxkbcommon, + libdbusmenu-gtk3, + libpulseaudio, + libinput, + libevdev, + openssl, + luajit, + luajitPackages, + pkg-config, + installShellFiles, + adwaita-icon-theme, + hicolor-icon-theme, + rustPlatform, + lib, + version ? "git", + features ? [], + builderName ? "nix", + builder ? {}, +}: let + hasFeature = f: features == [] || builtins.elem f features; + + basePkg = rec { + inherit version; + + pname = "ironbar"; + + src = let + fs = lib.fileset; + root = ../.; + nixRelated = fs.fileFilter (file: file.hasExt "nix" || file.name == "flake.lock") root; + cicdRelated = fs.unions [ + (lib.path.append root "Dockerfile") + (lib.path.append root ".github") + ]; + ideRelated = fs.unions [ + (lib.path.append root ".idea") + ]; + in fs.toSource { + inherit root; + # NOTE: can possibly filter out more + fileset = fs.difference root (fs.unions [ + nixRelated + cicdRelated + ideRelated + ]); + }; + + nativeBuildInputs = [ + pkg-config + wrapGAppsHook + gobject-introspection + installShellFiles + ]; + + buildInputs = + [ + gtk3 + gdk-pixbuf + glib + gtk-layer-shell + glib-networking + shared-mime-info + adwaita-icon-theme + hicolor-icon-theme + gsettings-desktop-schemas + libxkbcommon + ] + ++ lib.optionals (hasFeature "http") [openssl] + ++ lib.optionals (hasFeature "tray") [libdbusmenu-gtk3] + ++ lib.optionals (hasFeature "volume") [libpulseaudio] + ++ lib.optionals (hasFeature "cairo") [luajit] + ++ lib.optionals (hasFeature "keyboard") [libinput libevdev]; + + propagatedBuildInputs = [gtk3]; + + lgi = luajitPackages.lgi; + + gappsWrapperArgs = + '' + # Thumbnailers + --prefix XDG_DATA_DIRS : "${gdk-pixbuf}/share" + --prefix XDG_DATA_DIRS : "${librsvg}/share" + --prefix XDG_DATA_DIRS : "${webp-pixbuf-loader}/share" + --prefix XDG_DATA_DIRS : "${shared-mime-info}/share" + + # gtk-launch + --suffix PATH : "${lib.makeBinPath [gtk3]}" + '' + + lib.optionalString (hasFeature "cairo") '' + --prefix LUA_PATH : "./?.lua;${lgi}/share/lua/5.1/?.lua;${lgi}/share/lua/5.1/?/init.lua;${luajit}/share/lua/5.1/\?.lua;${luajit}/share/lua/5.1/?/init.lua" + --prefix LUA_CPATH : "./?.so;${lgi}/lib/lua/5.1/?.so;${luajit}/lib/lua/5.1/?.so;${luajit}/lib/lua/5.1/loadall.so" + ''; + + preFixup = '' + gappsWrapperArgs+=( + ${gappsWrapperArgs} + ) + ''; + + postInstall = '' + installShellCompletion --cmd ironbar \ + --bash target/completions/ironbar.bash \ + --fish target/completions/ironbar.fish \ + --zsh target/completions/_ironbar + ''; + + passthru = { + updateScript = gnome.updateScript { + packageName = pname; + attrPath = "gnome.${pname}"; + }; + }; + + meta = with lib; { + homepage = "https://github.com/JakeStanger/ironbar"; + description = "Customisable gtk-layer-shell wlroots/sway bar written in rust."; + license = licenses.mit; + platforms = platforms.linux; + mainProgram = "ironbar"; + }; + }; + + flags = let + noDefault = + if features == [] + then "" + else "--no-default-features"; + + featuresStr = + if features == [] + then "" + else ''-F "${builtins.concatStringsSep "," features}"''; + in [noDefault featuresStr]; +in + if builderName == "naersk" + then builder.buildPackage (basePkg // {cargoBuildOptions = old: old ++ flags;}) + else if builderName == "crane" + then + builder.buildPackage (basePkg + // { + cargoExtraArgs = builtins.concatStringsSep " " flags; + doCheck = false; + }) + else + rustPlatform.buildRustPackage (basePkg + // { + buildNoDefaultFeatures = features != []; + + buildFeatures = features; + cargoDeps = rustPlatform.importCargoLock {lockFile = ../Cargo.lock;}; + cargoLock.lockFile = ../Cargo.lock; + cargoLock.outputHashes."stray-0.1.3" = "sha256-7mvsWZFmPWti9AiX67h6ZlWiVVRZRWIxq3pVaviOUtc="; + }) diff --git a/shell.nix b/shell.nix index 71c2cda..ea7b69b 100644 --- a/shell.nix +++ b/shell.nix @@ -1,23 +1,13 @@ -{ pkgs ? import {} }: - -pkgs.mkShell { - buildInputs = with pkgs; [ - cargo - clippy - rustfmt - gtk3 - gtk-layer-shell - gcc - openssl - libdbusmenu-gtk3 - libpulseaudio - libinput - libevdev - luajit - luajitPackages.lgi - ]; - - nativeBuildInputs = with pkgs; [ - pkg-config - ]; -} \ No newline at end of file +(import + ( + let + lock = builtins.fromJSON (builtins.readFile ./flake.lock); + nodeName = lock.nodes.root.inputs.flake-compat; + in + fetchTarball { + url = lock.nodes.${nodeName}.locked.url or "https://github.com/edolstra/flake-compat/archive/${lock.nodes.${nodeName}.locked.rev}.tar.gz"; + sha256 = lock.nodes.${nodeName}.locked.narHash; + } + ) + { src = ./.; } +).shellNix