From 86f74f11739ec96dc0f7a906a29f699c178463c2 Mon Sep 17 00:00:00 2001 From: elwrcl Date: Sat, 15 Aug 2026 14:05:00 +0300 Subject: [PATCH] nix: flake, package, nixos and home-manager modules --- flake.lock | 27 +++++ flake.nix | 61 +++++++++++ nix/home-module.nix | 33 ++++++ nix/nixos-module.nix | 31 ++++++ nix/package.nix | 45 ++++++++ nix/settings.nix | 255 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 452 insertions(+) create mode 100755 flake.lock create mode 100755 flake.nix create mode 100755 nix/home-module.nix create mode 100755 nix/nixos-module.nix create mode 100755 nix/package.nix create mode 100755 nix/settings.nix diff --git a/flake.lock b/flake.lock new file mode 100755 index 0000000..0ee7307 --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1781577229, + "narHash": "sha256-lrp67w8AulE9Ks53n27I45ADSzbOCn4H+CNW1Ck8B+8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "567a49d1913ce81ac6e9582e3553dd90a955875f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100755 index 0000000..bc30834 --- /dev/null +++ b/flake.nix @@ -0,0 +1,61 @@ +{ + description = "nyi fetch"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = + { + self, + nixpkgs, + }: + + let + systems = [ + "x86_64-linux" + "aarch64-linux" + "aarch64-darwin" + "x86_64-darwin" + ]; + forAllSystems = nixpkgs.lib.genAttrs systems; + in + { + packages = forAllSystems ( + system: + let + pkgs = nixpkgs.legacyPackages.${system}; + in + { + default = pkgs.callPackage ./nix/package.nix { }; + } + ); + + devShells = forAllSystems ( + system: + let + pkgs = nixpkgs.legacyPackages.${system}; + in + { + default = pkgs.mkShell { + packages = with pkgs; [ + cargo + rustc + clippy + rustfmt + rust-analyzer + fastfetch + ]; + }; + } + ); + + formatter = forAllSystems (system: nixpkgs.legacyPackages.${system}.nixfmt-tree); + overlays.default = final: prev: { + nyi = final.callPackage ./nix/package.nix { }; + }; + + homeManagerModules.default = import ./nix/home-module.nix; + nixosModules.default = import ./nix/nixos-module.nix; + }; +} diff --git a/nix/home-module.nix b/nix/home-module.nix new file mode 100755 index 0000000..d5cc0df --- /dev/null +++ b/nix/home-module.nix @@ -0,0 +1,33 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.programs.nyi; + settings = import ./settings.nix { inherit lib; }; +in +{ + options.programs.nyi = settings.options // { + enable = lib.mkEnableOption "nyi"; + + package = lib.mkOption { + type = lib.types.package; + default = pkgs.callPackage ./package.nix { }; + defaultText = lib.literalExpression "pkgs.callPackage ./package.nix { }"; + description = "The nyi package to install."; + }; + }; + + config = lib.mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."nyi/config".text = settings.render cfg; + + xdg.configFile."nyi/logo.txt" = lib.mkIf (cfg.logo != null) { + text = settings.renderLogo cfg; + }; + }; +} diff --git a/nix/nixos-module.nix b/nix/nixos-module.nix new file mode 100755 index 0000000..f08e1b9 --- /dev/null +++ b/nix/nixos-module.nix @@ -0,0 +1,31 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.programs.nyi; + settings = import ./settings.nix { inherit lib; }; +in +{ + options.programs.nyi = settings.options // { + enable = lib.mkEnableOption "nyi"; + + package = lib.mkOption { + type = lib.types.package; + default = pkgs.callPackage ./package.nix { }; + defaultText = lib.literalExpression "pkgs.callPackage ./package.nix { }"; + description = "The nyi package to install."; + }; + }; + + config = lib.mkIf cfg.enable { + environment.systemPackages = [ cfg.package ]; + environment.etc."xdg/nyi/config".text = settings.render cfg; + environment.etc."xdg/nyi/logo.txt" = lib.mkIf (cfg.logo != null) { + text = settings.renderLogo cfg; + }; + }; +} diff --git a/nix/package.nix b/nix/package.nix new file mode 100755 index 0000000..00daf2a --- /dev/null +++ b/nix/package.nix @@ -0,0 +1,45 @@ +{ + lib, + stdenv, + rustPlatform, + makeWrapper, + fastfetch, + + # linux + pciutils, +}: + +rustPlatform.buildRustPackage (finalAttrs: { + pname = "nyi"; + version = lib.fileContents ../VERSION; + __structuredAttrs = true; + strictDeps = true; + src = lib.fileset.toSource { + root = ../.; + fileset = lib.fileset.unions [ + ../Cargo.toml + ../Cargo.lock + ../VERSION + ../src + ]; + }; + + cargoLock.lockFile = ../Cargo.lock; + env.NYI_CODENAME = "nyiotxa"; + nativeBuildInputs = [ makeWrapper ]; + postInstall = '' + wrapProgram $out/bin/nyi \ + --prefix PATH : ${ + lib.makeBinPath ([ fastfetch ] ++ lib.optionals stdenv.hostPlatform.isLinux [ pciutils ]) + } + ''; + + meta = { + description = "Animated 3D fetch with cool features"; + homepage = "https://github.com/elwrcl/nyi"; + changelog = "https://github.com/elwrcl/nyi/releases/tag/v${finalAttrs.version}"; + license = lib.licenses.isc; + mainProgram = "nyi"; + platforms = lib.platforms.unix; + }; +}) diff --git a/nix/settings.nix b/nix/settings.nix new file mode 100755 index 0000000..90df85c --- /dev/null +++ b/nix/settings.nix @@ -0,0 +1,255 @@ +{ lib }: + +let + inherit (lib) types mkOption; + + infoFields = [ + "os" + "host" + "kernel" + "uptime" + "packages" + "shell" + "display" + "wm" + "theme" + "icons" + "font" + "cursor" + "terminal" + "cpu" + "gpu" + "memory" + "swap" + "disk" + "ip" + "battery" + "locale" + "colors" + ]; + + colorDoc = '' + Accepts `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white`, + or a raw ANSI number such as `"38;5;213"`. + ''; +in +rec { + inherit infoFields; + + options = { + info = mkOption { + type = types.listOf (types.enum infoFields); + default = infoFields; + example = [ + "os" + "kernel" + "uptime" + "cpu" + "memory" + ]; + description = '' + info fields to display, in the order given. Only the fields listed + here are shown. + ''; + }; + + labelColor = mkOption { + type = types.str; + default = "magenta"; + example = "38;5;213"; + description = "color used for info labels. " + colorDoc; + }; + + separator = mkOption { + type = types.str; + default = "-"; + description = '' + String repeated to draw the underline below the `user@host` title. + Set to `""` to leave the line blank. + ''; + }; + + box = mkOption { + type = types.bool; + default = false; + description = "Draw a Unicode border box around the info block."; + }; + + shading = mkOption { + type = types.nullOr types.str; + default = null; + example = ".,-~:;=!*#$@"; + description = '' + Shading ramp, dimmest character first. Supports UTF-8. Setting this + implies the `ascii` shading mode. + ''; + }; + + shadingMode = mkOption { + type = types.nullOr ( + types.enum [ + "ascii" + "blocks" + "sextants" + ] + ); + default = null; + description = '' + `ascii` (the default) maps brightness onto the character ramp. + `blocks` samples a 2x2 grid per cell and `sextants` a 2x3 one, for + sharper edges. Sextants need a terminal that draws the Symbols for + Legacy Computing block (kitty, Ghostty, foot, NewTerm). + ''; + }; + + logoOuter = mkOption { + type = types.nullOr types.str; + default = null; + example = "magenta"; + description = '' + color of the extruded sides, for logos that carry no ANSI colors of + their own. '' + + colorDoc; + }; + + logoInner = mkOption { + type = types.nullOr types.str; + default = null; + example = "white"; + description = "color of the front and back faces. " + colorDoc; + }; + + light = mkOption { + type = types.nullOr ( + types.enum [ + "top-left" + "top-right" + "top" + "left" + "right" + "front" + "bottom-left" + "bottom-right" + ] + ); + default = null; + description = "light direction for the 3D shading."; + }; + + spin = mkOption { + type = types.nullOr ( + types.enum [ + "x" + "y" + "xy" + ] + ); + default = null; + description = "axes the logo rotates around."; + }; + + speed = mkOption { + type = types.nullOr types.float; + default = null; + description = "rotation speed multiplier. Higher is faster."; + }; + + size = mkOption { + type = types.nullOr types.float; + default = null; + description = "logo scale, from 0.5 to 5.0."; + }; + + height = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + render height in rows. left unset, nyi matches the number of info + lines. + ''; + }; + + depth = mkOption { + type = types.nullOr types.float; + default = null; + description = '' + 3D extrusion depth, 0.1 to 10.0. left unset nyi scales it + from the logo's character variance so flat logos don't look + paper-thin. + ''; + }; + + disks = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ + "/home" + "/data" + ]; + description = '' + extra mount points to report beyond `/`, up to 8. Setting any turns + the `disk` field on even if it isn't in {option}`info`. + ''; + }; + + logo = mkOption { + type = types.nullOr types.lines; + default = null; + description = '' + custom ASCII/Unicode logo, written to `nyi/logo.txt`. Denser + characters (`@`, `M`, `#`) become taller in the relief. + ''; + }; + + logoDistro = mkOption { + type = types.nullOr types.str; + default = null; + example = "nixos"; + description = '' + distro name whose color scheme {option}`logo` should use, emitted as + the `# distro:` hint line. Ignored unless {option}`logo` is set. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + extra lines appended verbatim to the generated config file, for + settings this module doesn't cover yet. + ''; + }; + }; + + /* + the generated config file lines come first so their order is the + display order; settings are order-independent to the parser. + */ + render = + cfg: + let + settings = lib.filterAttrs (_: v: v != null) { + label_color = cfg.labelColor; + separator = cfg.separator; + box = if cfg.box then "1" else "0"; + shading = cfg.shading; + shading_mode = cfg.shadingMode; + logo_outer = cfg.logoOuter; + logo_inner = cfg.logoInner; + light = cfg.light; + spin = cfg.spin; + speed = if cfg.speed != null then toString cfg.speed else null; + size = if cfg.size != null then toString cfg.size else null; + height = if cfg.height != null then toString cfg.height else null; + depth = if cfg.depth != null then toString cfg.depth else null; + }; + in + lib.concatStringsSep "\n" ( + cfg.info ++ map (d: "disk=${d}") cfg.disks ++ lib.mapAttrsToList (k: v: "${k}=${v}") settings + ) + + "\n" + + cfg.extraConfig; + + renderLogo = + cfg: lib.optionalString (cfg.logoDistro != null) "# distro: ${cfg.logoDistro}\n" + cfg.logo; +}