refactor: rework nix flake

Co-authored-by: Amaan Qureshi <amaanq12@gmail.com>
This commit is contained in:
faukah 2025-09-07 10:49:54 +02:00 committed by Amaan Qureshi
parent e9e4316569
commit e4e643086b
No known key found for this signature in database
12 changed files with 569 additions and 655 deletions

2
.gitignore vendored
View file

@ -36,3 +36,5 @@ docs/assets/js/tree-sitter.js
.build
build
zig-*
/result

View file

@ -1,115 +0,0 @@
{
perSystem =
{
self',
pkgs,
lib,
src,
version,
crossTargets,
...
}:
let
buildCliFor =
targetPkgs:
let
isCross = targetPkgs.stdenv.hostPlatform != pkgs.stdenv.buildPlatform;
in
targetPkgs.rustPlatform.buildRustPackage {
inherit src version;
pname = "tree-sitter-cli";
nativeBuildInputs = [
pkgs.pkg-config
pkgs.nodejs_22
]
++ lib.optionals (!isCross) [ pkgs.installShellFiles ];
cargoLock.lockFile = ../../Cargo.lock;
preBuild = ''
rm -rf test/fixtures
mkdir -p test/fixtures
cp -r ${self'.packages.test-grammars}/fixtures/* test/fixtures/
chmod -R u+w test/fixtures
'';
preCheck = "export HOME=$TMPDIR";
doCheck = !isCross;
postInstall = lib.optionalString (!isCross) ''
installShellCompletion --cmd tree-sitter \
--bash <($out/bin/tree-sitter complete --shell bash) \
--zsh <($out/bin/tree-sitter complete --shell zsh) \
--fish <($out/bin/tree-sitter complete --shell fish)
'';
meta = with lib; {
description = "Tree-sitter CLI - A tool for developing, testing, and using Tree-sitter parsers";
longDescription = ''
Tree-sitter is a parser generator tool and an incremental parsing library.
It can build a concrete syntax tree for a source file and efficiently update
the syntax tree as the source file is edited. This package provides the CLI
tool for developing, testing, and using Tree-sitter parsers.
'';
homepage = "https://tree-sitter.github.io/tree-sitter";
changelog = "https://github.com/tree-sitter/tree-sitter/releases/tag/v${version}";
license = licenses.mit;
maintainers = [ maintainers.amaanq ];
platforms = platforms.all;
mainProgram = "tree-sitter";
};
};
crossPackages = lib.mapAttrs (name: targetPkgs: buildCliFor targetPkgs) crossTargets;
in
{
packages = {
cli = buildCliFor pkgs;
}
// (lib.mapAttrs' (name: pkg: lib.nameValuePair "cli-${name}" pkg) crossPackages)
// {
rust-fmt =
pkgs.runCommand "rust-fmt-check"
{
nativeBuildInputs = [
pkgs.cargo
pkgs.rustfmt
];
}
''
cd ${src}
cargo fmt --all --check
touch $out
'';
rust-clippy = pkgs.rustPlatform.buildRustPackage {
inherit src version;
pname = "rust-clippy-check";
cargoLock.lockFile = ../../Cargo.lock;
nativeBuildInputs = [
pkgs.pkg-config
pkgs.clippy
pkgs.cmake
pkgs.clang
pkgs.libclang
];
buildPhase = ''
export HOME=$TMPDIR
export LIBCLANG_PATH="${pkgs.libclang.lib}/lib"
cargo xtask clippy
'';
installPhase = ''
touch $out
'';
doCheck = false;
};
};
};
}

60
crates/cli/package.nix Normal file
View file

@ -0,0 +1,60 @@
{
lib,
src,
rustPlatform,
version,
pkg-config,
nodejs_22,
test-grammars,
stdenv,
installShellFiles,
}:
let
isCross = stdenv.targetPlatform == stdenv.buildPlatform;
in
rustPlatform.buildRustPackage {
pname = "tree-sitter-cli";
inherit src version;
nativeBuildInputs = [
pkg-config
nodejs_22
]
++ lib.optionals (!isCross) [ installShellFiles ];
cargoLock.lockFile = ../../Cargo.lock;
preBuild = ''
rm -rf test/fixtures
mkdir -p test/fixtures
cp -r ${test-grammars}/fixtures/* test/fixtures/
chmod -R u+w test/fixtures
'';
preCheck = "export HOME=$TMPDIR";
doCheck = !isCross;
postInstall = lib.optionalString (!isCross) ''
installShellCompletion --cmd tree-sitter \
--bash <($out/bin/tree-sitter complete --shell bash) \
--zsh <($out/bin/tree-sitter complete --shell zsh) \
--fish <($out/bin/tree-sitter complete --shell fish)
'';
meta = {
description = "Tree-sitter CLI - A tool for developing, testing, and using Tree-sitter parsers";
longDescription = ''
Tree-sitter is a parser generator tool and an incremental parsing library.
It can build a concrete syntax tree for a source file and efficiently update
the syntax tree as the source file is edited. This package provides the CLI
tool for developing, testing, and using Tree-sitter parsers.
'';
homepage = "https://tree-sitter.github.io/tree-sitter";
changelog = "https://github.com/tree-sitter/tree-sitter/releases/tag/v${version}";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ amaanq ];
platforms = lib.platforms.all;
mainProgram = "tree-sitter";
};
}

View file

@ -1,38 +0,0 @@
{
perSystem =
{
pkgs,
lib,
src,
version,
...
}:
{
packages.docs = pkgs.stdenv.mkDerivation {
inherit src version;
pname = "tree-sitter-docs";
nativeBuildInputs = [
pkgs.mdbook
pkgs.mdbook-admonish
];
buildPhase = ''
cd docs
mdbook build
'';
installPhase = ''
mkdir -p $out/share/doc
cp -r book $out/share/doc/tree-sitter
'';
meta = {
description = "Tree-sitter documentation";
homepage = "https://tree-sitter.github.io/tree-sitter";
license = lib.licenses.mit;
};
};
};
}

33
docs/package.nix Normal file
View file

@ -0,0 +1,33 @@
{
stdenv,
lib,
version,
mdbook,
mdbook-admonish,
}:
stdenv.mkDerivation {
inherit version;
src = ./.;
pname = "tree-sitter-docs";
nativeBuildInputs = [
mdbook
mdbook-admonish
];
buildPhase = ''
mdbook build
'';
installPhase = ''
mkdir -p $out/share/doc
cp -r book $out/share/doc/tree-sitter
'';
meta = {
description = "Tree-sitter documentation";
homepage = "https://tree-sitter.github.io/tree-sitter";
license = lib.licenses.mit;
};
}

73
flake.lock generated
View file

@ -1,44 +1,5 @@
{
"nodes": {
"fenix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
"lastModified": 1756795219,
"narHash": "sha256-tKBQtz1JLKWrCJUxVkHKR+YKmVpm0KZdJdPWmR2slQ8=",
"owner": "nix-community",
"repo": "fenix",
"rev": "80dbdab137f2809e3c823ed027e1665ce2502d74",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "fenix",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1756770412,
"narHash": "sha256-+uWLQZccFHwqpGqr2Yt5VsW/PbeJVTn9Dk6SHWhNRPw=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "4524271976b625a4a605beefd893f270620fd751",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1756787288,
@ -55,44 +16,10 @@
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1754788789,
"narHash": "sha256-x2rJ+Ovzq0sCMpgfgGaaqgBSwY+LST+WbZ6TytnT9Rk=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "a73b9c743612e4244d865a2fdee11865283c04e6",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixpkgs.lib",
"type": "github"
}
},
"root": {
"inputs": {
"fenix": "fenix",
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs"
}
},
"rust-analyzer-src": {
"flake": false,
"locked": {
"lastModified": 1756597274,
"narHash": "sha256-wfaKRKsEVQDB7pQtAt04vRgFphkVscGRpSx3wG1l50E=",
"owner": "rust-lang",
"repo": "rust-analyzer",
"rev": "21614ed2d3279a9aa1f15c88d293e65a98991b30",
"type": "github"
},
"original": {
"owner": "rust-lang",
"ref": "nightly",
"repo": "rust-analyzer",
"type": "github"
}
}
},
"root": "root",

488
flake.nix
View file

@ -1,111 +1,80 @@
{
description = "Tree-sitter - A parser generator tool and an incremental parsing library";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-parts.url = "github:hercules-ci/flake-parts";
fenix = {
url = "github:nix-community/fenix";
inputs.nixpkgs.follows = "nixpkgs";
};
};
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
outputs =
inputs@{ flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
inputs:
let
inherit (inputs.nixpkgs) lib;
inherit (inputs) self;
systems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
eachSystem = lib.genAttrs systems;
pkgsFor = inputs.nixpkgs.legacyPackages;
imports = [
./crates/cli/flake.nix
./lib/flake.nix
./lib/binding_web/flake.nix
./docs/flake.nix
];
version = "0.26.0";
perSystem =
{
self',
pkgs,
lib,
system,
...
}:
fs = lib.fileset;
src = fs.toSource {
root = ./.;
fileset = fs.difference (fs.gitTracked ./.) (
fs.unions [
./.envrc
./flake.lock
./FUNDING.json
./README.md
./Dockerfile
(fs.fileFilter (file: lib.strings.hasInfix ".git" file.name) ./.)
(fs.fileFilter (file: file.hasExt "nix") ./.)
]
);
};
fixturesJson = lib.importJSON ./test/fixtures/fixtures.json;
grammarHashes = {
bash = "sha256-vRaN/mNfpR+hdv2HVS1bzaW0o+HGjizRFsk3iinICJE=";
c = "sha256-gmzbdwvrKSo6C1fqTJFGxy8x0+T+vUTswm7F5sojzKc=";
cpp = "sha256-tP5Tu747V8QMCEBYwOEmMQUm8OjojpJdlRmjcJTbe2k=";
embedded-template = "sha256-nBQain0Lc21jOgQFfvkyq615ZmT8qdMxtqIoUcOcO3A=";
go = "sha256-y7bTET8ypPczPnMVlCaiZuswcA7vFrDOc2jlbfVk5Sk=";
html = "sha256-Pd5Me1twLGOrRB3pSMVX9M8VKenTK0896aoLznjNkGo=";
java = "sha256-OvEO1BLZLjP3jt4gar18kiXderksFKO0WFXDQqGLRIY=";
javascript = "sha256-2Jj/SUG+k8lHlGSuPZvHjJojvQFgDiZHZzH8xLu7suE=";
jsdoc = "sha256-Azzb2zBjAfwbEmAEO1YqhpaxtzbXmRjfIzRla2Hx+24=";
json = "sha256-DNZC2cTy1C8OaMOpEHM6NoRtOIbLaBf0CLXXWCKODlw=";
php = "sha256-jI7yzcoHS/tNxUqJI4aD1rdEZV3jMn1GZD0J+81Dyf0=";
python = "sha256-71Od4sUsxGEvTwmXX8hBvzqD55hnXkVJublrhp1GICg=";
ruby = "sha256-iu3MVJl0Qr/Ba+aOttmEzMiVY6EouGi5wGOx5ofROzA=";
rust = "sha256-y3sJURlSTM7LRRN5WGIAeslsdRZU522Tfcu6dnXH/XQ=";
typescript = "sha256-CU55+YoFJb6zWbJnbd38B7iEGkhukSVpBN7sli6GkGY=";
};
grammarSpecs = lib.listToAttrs (
map (fixture: {
name = lib.elemAt fixture 0;
value = {
rev = lib.elemAt fixture 1;
sha256 = grammarHashes.${lib.elemAt fixture 0};
};
}) fixturesJson
);
filesWithExtension =
ext:
fs.toSource {
root = ./.;
fileset = fs.fileFilter (file: (file.hasExt ext) && file.type == "regular") ./.;
};
in
{
packages = eachSystem (
system:
let
version = "0.26.0";
fenix = inputs.fenix.packages.${system};
rustToolchain = fenix.complete.withComponents [
"cargo"
"clippy"
"rust-src"
"rustc"
"rustfmt"
];
src = pkgs.lib.cleanSourceWith {
src = ./.;
filter =
name: type:
let
baseName = baseNameOf name;
in
!(
lib.elem baseName [
"target"
"node_modules"
".git"
".direnv"
"flake.lock"
]
|| lib.hasPrefix "result" baseName
);
};
fixturesJson = lib.importJSON ./test/fixtures/fixtures.json;
grammarHashes = {
bash = "sha256-vRaN/mNfpR+hdv2HVS1bzaW0o+HGjizRFsk3iinICJE=";
c = "sha256-gmzbdwvrKSo6C1fqTJFGxy8x0+T+vUTswm7F5sojzKc=";
cpp = "sha256-tP5Tu747V8QMCEBYwOEmMQUm8OjojpJdlRmjcJTbe2k=";
embedded-template = "sha256-nBQain0Lc21jOgQFfvkyq615ZmT8qdMxtqIoUcOcO3A=";
go = "sha256-y7bTET8ypPczPnMVlCaiZuswcA7vFrDOc2jlbfVk5Sk=";
html = "sha256-Pd5Me1twLGOrRB3pSMVX9M8VKenTK0896aoLznjNkGo=";
java = "sha256-OvEO1BLZLjP3jt4gar18kiXderksFKO0WFXDQqGLRIY=";
javascript = "sha256-2Jj/SUG+k8lHlGSuPZvHjJojvQFgDiZHZzH8xLu7suE=";
jsdoc = "sha256-Azzb2zBjAfwbEmAEO1YqhpaxtzbXmRjfIzRla2Hx+24=";
json = "sha256-DNZC2cTy1C8OaMOpEHM6NoRtOIbLaBf0CLXXWCKODlw=";
php = "sha256-jI7yzcoHS/tNxUqJI4aD1rdEZV3jMn1GZD0J+81Dyf0=";
python = "sha256-71Od4sUsxGEvTwmXX8hBvzqD55hnXkVJublrhp1GICg=";
ruby = "sha256-iu3MVJl0Qr/Ba+aOttmEzMiVY6EouGi5wGOx5ofROzA=";
rust = "sha256-y3sJURlSTM7LRRN5WGIAeslsdRZU522Tfcu6dnXH/XQ=";
typescript = "sha256-CU55+YoFJb6zWbJnbd38B7iEGkhukSVpBN7sli6GkGY=";
};
grammarSpecs = lib.listToAttrs (
map (fixture: {
name = lib.elemAt fixture 0;
value = {
rev = lib.elemAt fixture 1;
sha256 = grammarHashes.${lib.elemAt fixture 0};
};
}) fixturesJson
);
fetchGrammar =
name: rev: sha256:
pkgs.fetchFromGitHub {
owner = "tree-sitter";
repo = "tree-sitter-${name}";
inherit rev sha256;
};
testGrammars = lib.mapAttrs (name: spec: fetchGrammar name spec.rev spec.sha256) grammarSpecs;
pkgs = pkgsFor.${system};
crossTargets = {
aarch64-linux = pkgs.pkgsCross.aarch64-multiplatform;
armv7l-linux = pkgs.pkgsCross.armv7l-hf-multiplatform;
@ -126,16 +95,26 @@
x86_64-darwin = pkgs.pkgsCross.x86_64-darwin;
aarch64-darwin = pkgs.pkgsCross.aarch64-darwin;
});
in
{
_module.args = {
inherit src version crossTargets;
};
default = self.packages.${system}.cli;
packages = {
default = self'.packages.cli;
docs = pkgs.callPackage ./docs/package.nix { inherit version; };
test-grammars = pkgs.stdenv.mkDerivation {
test-grammars =
let
fetchGrammar =
name: rev: sha256:
pkgs.fetchFromGitHub {
owner = "tree-sitter";
repo = "tree-sitter-${name}";
inherit rev sha256;
};
testGrammars = lib.mapAttrs (name: spec: fetchGrammar name spec.rev spec.sha256) grammarSpecs;
in
pkgs.stdenv.mkDerivation {
inherit src version;
pname = "test-grammars";
@ -152,120 +131,219 @@
cp -r test/fixtures $out/fixtures
'';
};
wasm-test-grammars = pkgs.callPackage ./lib/binding_web/wasm-test-grammars.nix {
inherit src version;
inherit (self.packages.${system}) cli test-grammars;
};
apps = {
default = self'.apps.cli;
web-tree-sitter = pkgs.callPackage ./lib/binding_web/package.nix {
inherit src version;
inherit (self.packages.${system}) wasm-test-grammars;
};
cli = {
type = "app";
program = "${self'.packages.cli}/bin/tree-sitter";
meta.description = "Tree-sitter CLI for developing, testing, and using parsers";
};
lib = pkgs.callPackage ./lib/package.nix {
inherit src version;
};
docs = {
type = "app";
program = "${pkgs.writeShellScript "docs" ''
cli = pkgs.callPackage ./crates/cli/package.nix {
inherit src version;
inherit (self.packages.${system}) test-grammars;
};
}
// (lib.mapAttrs' (arch: pkg: {
name = "cli-${arch}";
value = pkg.callPackage ./crates/cli/package.nix {
inherit src version;
inherit (self.packages.${system}) test-grammars;
};
}) crossTargets)
// (lib.mapAttrs' (arch: pkg: {
name = "lib-${arch}";
value = pkg.callPackage ./lib/package.nix {
inherit src version;
};
}) crossTargets)
);
apps = eachSystem (
system:
let
pkgs = pkgsFor.${system};
in
{
default = self.apps.${system}.cli;
cli = {
type = "app";
program = "${lib.getExe self.packages.${system}.cli}";
meta.description = "Tree-sitter CLI for developing, testing, and using parsers";
};
docs = {
type = "app";
program = lib.getExe (
pkgs.writeShellScriptBin "docs" ''
echo "📚 Serving documentation at http://localhost:3000"
cd docs && ${pkgs.mdbook}/bin/mdbook serve
''}";
meta.description = "Serve Tree-sitter documentation locally";
};
format = {
type = "app";
program = toString (
pkgs.writeShellScript "format-all" ''
set -e
echo "Formatting..."
echo ""
echo " Rust..."
${pkgs.cargo}/bin/cargo fmt --all
echo " Nix..."
${pkgs.nixfmt-rfc-style}/bin/nixfmt *.nix crates/cli/*.nix lib/*.nix lib/binding_web/*.nix docs/*.nix
echo " Web (TypeScript/JavaScript)..."
cd lib/binding_web && ${pkgs.nodejs_22}/bin/npm install --silent && ${pkgs.nodejs_22}/bin/npm run lint:fix
cd ../..
echo ""
echo "Formatting complete"
''
);
meta.description = "Format all Rust and Nix code";
};
lint = {
type = "app";
program = toString (
pkgs.writeShellScript "lint-all" ''
set -e
echo "Linting code..."
echo ""
echo " Checking Rust formatting..."
${pkgs.cargo}/bin/cargo fmt --all --check
echo " Running clippy..."
${pkgs.cargo}/bin/cargo clippy --workspace --all-targets -- -D warnings
echo " Checking Nix formatting..."
${pkgs.nixfmt-rfc-style}/bin/nixfmt --check *.nix crates/cli/*.nix lib/*.nix lib/binding_web/*.nix docs/*.nix
echo " Checking Web code..."
cd lib/binding_web && ${pkgs.nodejs_22}/bin/npm install --silent && ${pkgs.nodejs_22}/bin/npm run lint
cd ../..
echo ""
echo "Linting complete"
''
);
meta.description = "Run all linting checks";
};
cd docs && ${lib.getExe pkgs.mdbook} serve
''
);
meta.description = "Serve Tree-sitter documentation locally";
};
checks = {
inherit (self'.packages)
cli
lib
web-tree-sitter
web-lint
rust-fmt
rust-clippy
;
nix-fmt =
pkgs.runCommand "nix-fmt-check"
{
nativeBuildInputs = [ pkgs.nixfmt-rfc-style ];
}
''
cd ${src}
nixfmt --check *.nix crates/cli/*.nix lib/*.nix lib/binding_web/*.nix docs/*.nix
touch $out
'';
format = {
type = "app";
program = lib.getExe (
pkgs.writeShellScriptBin "format-all" ''
set -e
echo "Formatting..."
echo ""
echo " Rust..."
${lib.getExe pkgs.cargo} fmt --all
echo " Nix..."
${lib.getExe pkgs.nixfmt} ${filesWithExtension "nix"}
echo " Web (TypeScript/JavaScript)..."
cd lib/binding_web && ${pkgs.nodejs_22}/bin/npm install --silent && ${pkgs.nodejs_22}/bin/npm run lint:fix
cd ../..
echo ""
echo "Formatting complete"
''
);
meta.description = "Format all Rust and Nix code";
};
formatter = pkgs.nixfmt-rfc-style;
lint = {
type = "app";
program = lib.getExe (
pkgs.writeShellScriptBin "lint-all" ''
set -e
echo "Linting code..."
echo ""
echo " Checking Rust formatting..."
${lib.getExe pkgs.cargo} fmt --all --check
echo " Running clippy..."
${lib.getExe pkgs.cargo} clippy --workspace --all-targets -- -D warnings
echo " Checking Nix formatting..."
${lib.getExe pkgs.nixfmt} --check ${filesWithExtension "nix"}
echo " Checking Web code..."
cd lib/binding_web && ${lib.getExe' pkgs.nodejs_22 "npm"} install --silent && ${lib.getExe' pkgs.nodejs_22 "npm"} run lint
cd ../..
echo ""
echo "Linting complete"
''
);
meta.description = "Run all linting checks";
};
}
);
devShells.default = pkgs.mkShell {
buildInputs = [
pkgs.cargo
pkgs.rustc
pkgs.clippy
pkgs.rust-analyzer
pkgs.rustfmt
pkgs.cargo-cross
checks = eachSystem (
system:
let
pkgs = pkgsFor.${system};
in
{
inherit (self.packages.${system})
cli
lib
web-tree-sitter
;
pkgs.cmake
pkgs.gnumake
pkgs.pkg-config
pkgs.clang
pkgs.libclang
nix-fmt = pkgs.runCommandNoCC "nix-fmt-check" { } ''
${lib.getExe self.formatter.${system}} --check ${filesWithExtension "nix"}
touch $out
'';
rust-fmt = pkgs.runCommandNoCC "rust-fmt-check" { } ''
${lib.getExe pkgs.rustfmt} --check
touch $out
'';
pkgs.nodejs_22
pkgs.nodePackages.typescript
pkgs.emscripten
pkgs.pkgsCross.wasi32.stdenv.cc
rust-clippy = pkgs.rustPlatform.buildRustPackage {
inherit src version;
pkgs.mdbook
pkgs.mdbook-admonish
pname = "rust-clippy-check";
pkgs.git
pkgs.nixfmt-rfc-style
cargoLock.lockFile = ./Cargo.lock;
nativeBuildInputs = with pkgs; [
pkg-config
clippy
cmake
clang
libclang
];
buildPhase = ''
export HOME=$TMPDIR
export LIBCLANG_PATH="${pkgs.libclang.lib}/lib"
cargo xtask clippy
'';
installPhase = ''
touch $out
'';
doCheck = false;
};
web-lint = pkgs.buildNpmPackage {
inherit src version;
pname = "web-tree-sitter-lint";
npmDepsHash = "sha256-y0GobcskcZTmju90TM64GjeWiBmPFCrTOg0yfccdB+Q=";
postPatch = ''
cp lib/binding_web/package{,-lock}.json .
'';
buildPhase = ''
cd lib/binding_web
npm run lint
'';
installPhase = ''
touch $out
'';
meta.description = "Lint check for web-tree-sitter TypeScript/JavaScript code";
};
}
);
formatter = eachSystem (system: pkgsFor.${system}.nixfmt);
devShells = eachSystem (
system:
let
pkgs = pkgsFor.${system};
in
{
default = pkgs.mkShell {
buildInputs = with pkgs; [
cargo
rustc
clippy
rust-analyzer
rustfmt
cargo-cross
cmake
gnumake
pkg-config
clang
libclang
nodejs_22
nodePackages.typescript
emscripten
pkgsCross.wasi32.stdenv.cc
mdbook
mdbook-admonish
git
nixfmt
];
shellHook = ''
@ -311,9 +389,13 @@
echo "Version: ${version}"
'';
RUST_BACKTRACE = 1;
LIBCLANG_PATH = "${pkgs.libclang.lib}/lib";
env = {
RUST_BACKTRACE = 1;
LIBCLANG_PATH = "${pkgs.libclang.lib}/lib";
TREE_SITTER_WASI_SDK_PATH = "${pkgs.pkgsCross.wasi32.stdenv.cc}";
};
};
};
}
);
};
}

View file

@ -1,158 +0,0 @@
{
perSystem =
{
self',
pkgs,
lib,
src,
version,
...
}:
let
grammars = [
"bash"
"c"
"cpp"
"embedded-template"
"html"
"javascript"
"json"
"python"
"rust"
"typescript"
];
wasmTestGrammars = pkgs.stdenv.mkDerivation {
inherit src version;
pname = "wasm-test-grammars";
nativeBuildInputs = [
self'.packages.cli
pkgs.pkgsCross.wasi32.stdenv.cc
pkgs.nodejs_22
];
buildPhase = ''
export HOME=$TMPDIR
export TREE_SITTER_WASI_SDK_PATH=${pkgs.pkgsCross.wasi32.stdenv.cc}
export NIX_LDFLAGS=""
cp -r ${self'.packages.test-grammars}/fixtures .
chmod -R u+w fixtures
for grammar in ${lib.concatStringsSep " " grammars}; do
if [ -d "fixtures/grammars/$grammar" ]; then
echo "Building WASM for $grammar"
if [ "$grammar" = "typescript" ]; then
tree-sitter build --wasm -o "tree-sitter-typescript.wasm" "fixtures/grammars/$grammar/typescript"
tree-sitter build --wasm -o "tree-sitter-tsx.wasm" "fixtures/grammars/$grammar/tsx"
else
tree-sitter build --wasm -o "tree-sitter-$grammar.wasm" "fixtures/grammars/$grammar"
fi
fi
done
'';
installPhase = ''
mkdir -p $out
for wasm in *.wasm; do
if [ -f "$wasm" ]; then
echo "Installing $wasm"
cp "$wasm" $out/
fi
done
'';
};
in
{
packages = {
web-tree-sitter = pkgs.buildNpmPackage {
inherit src version;
pname = "web-tree-sitter";
npmDepsHash = "sha256-y0GobcskcZTmju90TM64GjeWiBmPFCrTOg0yfccdB+Q=";
nativeBuildInputs = [
pkgs.rustPlatform.cargoSetupHook
pkgs.cargo
pkgs.pkg-config
pkgs.emscripten
];
cargoDeps = pkgs.rustPlatform.importCargoLock {
lockFile = ../../Cargo.lock;
};
doCheck = true;
postPatch = ''
cp lib/binding_web/package{,-lock}.json .
'';
buildPhase = ''
cd lib/binding_web
CJS=true npm run build
CJS=true npm run build:debug
npm run build:debug
npm run build
'';
checkPhase = ''
cd ../../
mkdir -p target/release
for grammar in ${wasmTestGrammars}/*.wasm; do
if [ -f "$grammar" ]; then
cp "$grammar" target/release/
fi
done
cd lib/binding_web && npm test
'';
meta = {
description = "web-tree-sitter - WebAssembly bindings to the Tree-sitter parsing library.";
longDescription = ''
web-tree-sitter provides WebAssembly bindings to the Tree-sitter parsing library.
It can build a concrete syntax tree for a source file and efficiently update
the syntax tree as the source file is edited. This package provides the WebAssembly bindings
and a JavaScript API for using them in web browsers
'';
homepage = "https://tree-sitter.github.io/tree-sitter";
changelog = "https://github.com/tree-sitter/tree-sitter/releases/tag/v${version}";
license = lib.licenses.mit;
maintainers = [ lib.maintainers.amaanq ];
platforms = lib.platforms.all;
};
};
web-lint = pkgs.buildNpmPackage {
inherit src version;
pname = "web-tree-sitter-lint";
npmDepsHash = "sha256-y0GobcskcZTmju90TM64GjeWiBmPFCrTOg0yfccdB+Q=";
postPatch = ''
cp lib/binding_web/package{,-lock}.json .
'';
buildPhase = ''
cd lib/binding_web
npm run lint
'';
installPhase = ''
touch $out
'';
meta = {
description = "Lint check for web-tree-sitter TypeScript/JavaScript code";
};
};
};
};
}

View file

@ -0,0 +1,73 @@
{
wasm-test-grammars,
lib,
buildNpmPackage,
rustPlatform,
cargo,
pkg-config,
emscripten,
src,
version,
}:
buildNpmPackage {
inherit src version;
pname = "web-tree-sitter";
npmDepsHash = "sha256-y0GobcskcZTmju90TM64GjeWiBmPFCrTOg0yfccdB+Q=";
nativeBuildInputs = [
rustPlatform.cargoSetupHook
cargo
pkg-config
emscripten
];
cargoDeps = rustPlatform.importCargoLock {
lockFile = ../../Cargo.lock;
};
doCheck = true;
postPatch = ''
cp lib/binding_web/package{,-lock}.json .
'';
buildPhase = ''
pushd lib/binding_web
CJS=true npm run build
CJS=true npm run build:debug
npm run build:debug
npm run build
popd
mkdir -p target/release
for grammar in ${wasm-test-grammars}/*.wasm; do
if [ -f "$grammar" ]; then
cp "$grammar" target/release/
fi
done
'';
checkPhase = ''
cd lib/binding_web && npm test
'';
meta = {
description = "web-tree-sitter - WebAssembly bindings to the Tree-sitter parsing library.";
longDescription = ''
web-tree-sitter provides WebAssembly bindings to the Tree-sitter parsing library.
It can build a concrete syntax tree for a source file and efficiently update
the syntax tree as the source file is edited. This package provides the WebAssembly bindings
and a JavaScript API for using them in web browsers
'';
homepage = "https://tree-sitter.github.io/tree-sitter";
changelog = "https://github.com/tree-sitter/tree-sitter/releases/tag/v${version}";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ amaanq ];
platforms = lib.platforms.all;
};
}

View file

@ -0,0 +1,67 @@
{
cli,
lib,
nodejs_22,
pkgsCross,
src,
stdenv,
test-grammars,
version,
}:
let
grammars = [
"bash"
"c"
"cpp"
"embedded-template"
"html"
"javascript"
"json"
"python"
"rust"
"typescript"
];
in
stdenv.mkDerivation {
inherit src version;
pname = "wasm-test-grammars";
nativeBuildInputs = [
cli
pkgsCross.wasi32.stdenv.cc
nodejs_22
];
buildPhase = ''
export HOME=$TMPDIR
export TREE_SITTER_WASI_SDK_PATH=${pkgsCross.wasi32.stdenv.cc}
export NIX_LDFLAGS=""
cp -r ${test-grammars}/fixtures .
chmod -R u+w fixtures
for grammar in ${lib.concatStringsSep " " grammars}; do
if [ -d "fixtures/grammars/$grammar" ]; then
echo "Building WASM for $grammar"
if [ "$grammar" = "typescript" ]; then
tree-sitter build --wasm -o "tree-sitter-typescript.wasm" "fixtures/grammars/$grammar/typescript"
tree-sitter build --wasm -o "tree-sitter-tsx.wasm" "fixtures/grammars/$grammar/tsx"
else
tree-sitter build --wasm -o "tree-sitter-$grammar.wasm" "fixtures/grammars/$grammar"
fi
fi
done
'';
installPhase = ''
mkdir -p $out
for wasm in *.wasm; do
if [ -f "$wasm" ]; then
echo "Installing $wasm"
cp "$wasm" $out/
fi
done
'';
}

View file

@ -1,68 +0,0 @@
{
perSystem =
{
pkgs,
lib,
src,
version,
crossTargets,
...
}:
let
buildLibFor =
targetPkgs:
let
isCross = targetPkgs.stdenv.hostPlatform != pkgs.stdenv.buildPlatform;
in
targetPkgs.stdenv.mkDerivation {
inherit src version;
pname = "tree-sitter";
nativeBuildInputs = [
targetPkgs.cmake
targetPkgs.pkg-config
];
sourceRoot = "source/lib";
cmakeFlags = [
"-DBUILD_SHARED_LIBS=ON"
"-DCMAKE_INSTALL_LIBDIR=lib"
"-DCMAKE_INSTALL_INCLUDEDIR=include"
"-DTREE_SITTER_FEATURE_WASM=OFF"
];
enableParallelBuilding = true;
postInstall = ''
mkdir -p $out/{lib/pkgconfig,share/tree-sitter}
substituteInPlace $out/lib/pkgconfig/tree-sitter.pc \
--replace-fail "\''${prefix}" "$out" 2>/dev/null
'';
meta = {
description = "Tree-sitter incremental parsing library";
longDescription = ''
Tree-sitter is a parser generator tool and an incremental parsing library.
It can build a concrete syntax tree for a source file and efficiently update
the syntax tree as the source file is edited. This package provides the core
C library that can be used to parse source code using Tree-sitter grammars.
'';
homepage = "https://tree-sitter.github.io/tree-sitter";
changelog = "https://github.com/tree-sitter/tree-sitter/releases/tag/v${version}";
license = lib.licenses.mit;
maintainers = [ lib.maintainers.amaanq ];
platforms = lib.platforms.all;
};
};
crossPackages = lib.mapAttrs (name: targetPkgs: buildLibFor targetPkgs) crossTargets;
in
{
packages = {
lib = buildLibFor pkgs;
}
// (lib.mapAttrs' (name: pkg: lib.nameValuePair "lib-${name}" pkg) crossPackages);
};
}

49
lib/package.nix Normal file
View file

@ -0,0 +1,49 @@
{
stdenv,
cmake,
pkg-config,
src,
version,
lib,
}:
stdenv.mkDerivation {
inherit src version;
pname = "tree-sitter";
nativeBuildInputs = [
cmake
pkg-config
];
sourceRoot = "source/lib";
cmakeFlags = [
"-DBUILD_SHARED_LIBS=ON"
"-DCMAKE_INSTALL_LIBDIR=lib"
"-DCMAKE_INSTALL_INCLUDEDIR=include"
"-DTREE_SITTER_FEATURE_WASM=OFF"
];
enableParallelBuilding = true;
postInstall = ''
mkdir -p $out/{lib/pkgconfig,share/tree-sitter}
substituteInPlace $out/lib/pkgconfig/tree-sitter.pc \
--replace-fail "\''${prefix}" "$out" 2>/dev/null
'';
meta = {
description = "Tree-sitter incremental parsing library";
longDescription = ''
Tree-sitter is a parser generator tool and an incremental parsing library.
It can build a concrete syntax tree for a source file and efficiently update
the syntax tree as the source file is edited. This package provides the core
C library that can be used to parse source code using Tree-sitter grammars.
'';
homepage = "https://tree-sitter.github.io/tree-sitter";
changelog = "https://github.com/tree-sitter/tree-sitter/releases/tag/v${version}";
license = lib.licenses.mit;
maintainers = [ lib.maintainers.amaanq ];
platforms = lib.platforms.all;
};
}