fresh-editor 0.1.44

A lightweight, fast terminal-based text editor with LSP support and TypeScript plugins
Documentation
{
  description = "Fresh - A lightweight, fast terminal-based text editor with LSP support and TypeScript plugins";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";

    crane.url = "github:ipetkov/crane";

    flake-utils.url = "github:numtide/flake-utils";

    rust-overlay = {
      url = "github:oxalica/rust-overlay";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = { self, nixpkgs, crane, flake-utils, rust-overlay, ... }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = import nixpkgs {
          inherit system;
          overlays = [ (import rust-overlay) ];
        };

        # Use stable Rust from rust-overlay for reproducibility
        rustToolchain = pkgs.rust-bin.stable.latest.default.override {
          extensions = [ "rust-src" "rust-analyzer" ];
        };

        craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchain;

        # Source filtering: include Cargo files plus additional files needed by build.rs
        # and include_str!/include_bytes! macros
        src = pkgs.lib.cleanSourceWith {
          src = ./.;
          filter = path: type:
            # Include types/ directory for build.rs (fresh.d.ts.template)
            (pkgs.lib.hasInfix "/types/" path) ||
            # Include queries/ for tree-sitter indent queries (include_str!)
            (pkgs.lib.hasInfix "/queries/" path) ||
            # Include docs/ for help manual (include_str!)
            (pkgs.lib.hasInfix "/docs/" path) ||
            # Include keymaps/ for keymap configs (include_str!)
            (pkgs.lib.hasInfix "/keymaps/" path) ||
            # Include plugins/ directory for build.rs output
            (pkgs.lib.hasInfix "/plugins/" path) ||
            # Include standard crane/cargo files
            (craneLib.filterCargoSources path type);
        };

        # Prefetch rusty_v8 static library to avoid network access during build
        # We validate the hash on the compressed download, then decompress for rusty_v8
        librusty_v8 = let
          v8_version = "142.2.0";
          arch = pkgs.stdenv.hostPlatform.rust.rustcTarget;
        in pkgs.stdenv.mkDerivation {
          name = "librusty_v8-${v8_version}";
          src = pkgs.fetchurl {
            url = "https://github.com/denoland/rusty_v8/releases/download/v${v8_version}/librusty_v8_release_${arch}.a.gz";
            sha256 = {
              x86_64-linux = "sha256-xHmofo8wTNg88/TuC2pX2OHDRYtHncoSvSBnTV65o+0=";
              aarch64-linux = "sha256-24q6wX8RTRX1tMGqgcz9/wN3Y+hWxM2SEuVrYhECyS8=";
              x86_64-darwin = "sha256-u7fImeadycU1gS5m+m35WZA/G2SOdPrLOMafY54JwY4=";
              aarch64-darwin = "sha256-XvJ7M5XxOzmevv+nPpy/mvEDD1MfHr986bImvDG0o4U=";
            }.${system} or (throw "Unsupported system: ${system}");
          };
          nativeBuildInputs = [ pkgs.gzip ];
          dontUnpack = true;
          installPhase = ''
            gzip -d -c $src > $out
          '';
        };

        # Common arguments for crane builds
        commonArgs = {
          inherit src;
          strictDeps = true;

          # Build inputs needed for compilation
          # Note: On Darwin, frameworks (Security, SystemConfiguration, CoreServices) and
          # libiconv are now provided automatically by the stdenv's default SDK.
          # See: https://discourse.nixos.org/t/the-darwin-sdks-have-been-updated/55295
          buildInputs = with pkgs; [
            # Required for various crates
            openssl
          ];

          nativeBuildInputs = with pkgs; [
            pkg-config
            # For tree-sitter grammars that need C compilation
            clang
          ];

          # Environment variables
          LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
          # Point to prefetched rusty_v8 library to avoid download during build
          RUSTY_V8_ARCHIVE = librusty_v8;
        };

        # Build dependencies separately for better caching
        cargoArtifacts = craneLib.buildDepsOnly commonArgs;

        # Build the actual package
        fresh = craneLib.buildPackage (commonArgs // {
          inherit cargoArtifacts;

          # Include runtime assets
          postInstall = ''
            # Copy queries (tree-sitter syntax queries)
            if [ -d queries ]; then
              mkdir -p $out/share/fresh-editor
              cp -r queries $out/share/fresh-editor/
            fi

            # Copy themes
            if [ -d themes ]; then
              cp -r themes $out/share/fresh-editor/
            fi

            # Copy keymaps
            if [ -d keymaps ]; then
              cp -r keymaps $out/share/fresh-editor/
            fi

            # Copy plugins
            if [ -d plugins ]; then
              cp -r plugins $out/share/fresh-editor/
            fi
          '';
        });
      in
      {
        checks = {
          # Build the package as a check
          inherit fresh;

          # Run clippy
          fresh-clippy = craneLib.cargoClippy (commonArgs // {
            inherit cargoArtifacts;
            cargoClippyExtraArgs = "--all-targets -- --deny warnings";
          });

          # Run tests
          fresh-test = craneLib.cargoTest (commonArgs // {
            inherit cargoArtifacts;
          });

          # Check formatting
          fresh-fmt = craneLib.cargoFmt {
            inherit src;
          };
        };

        packages = {
          default = fresh;
          fresh = fresh;
        };

        apps.default = flake-utils.lib.mkApp {
          drv = fresh;
        } // { meta.description = "Fresh terminal-based text editor"; };

        devShells.default = craneLib.devShell {
          # Inherit inputs from the main build
          checks = self.checks.${system};

          # Additional development tools
          packages = with pkgs; [
            # Rust tools (already included via toolchain, but explicit for clarity)
            rustToolchain
            cargo-watch
            cargo-edit

            # For development
            pkg-config
            clang

            # For tree-sitter grammar development
            tree-sitter

            # Useful for debugging
            lldb
          ] ++ pkgs.lib.optionals pkgs.stdenv.isLinux [
            # Linux-specific dev tools
            valgrind
            strace
          ];

          # Set up environment
          LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
        };
      });
}