This commit is contained in:
iofq 2025-09-16 22:43:17 -05:00
commit 5d2b1a868e
11 changed files with 4018 additions and 0 deletions

1
.envrc Normal file
View file

@ -0,0 +1 @@
use flake . -Lv

21
.github/workflows/main.yaml vendored Normal file
View file

@ -0,0 +1,21 @@
---
name: CI
on: [push, pull_request]
jobs:
check-generated-parsers:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: DeterminateSystems/nix-installer-action@main
- run: mv generated.nix generated.nix.old
- run: nix develop --command "generate-parsers"
- run: diff generated.nix generated.nix.old
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: DeterminateSystems/nix-installer-action@main
- run: nix run nixpkgs#nixfmt **/*.nix
- run: nix flake check
- run: nix build .

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
result

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 iofq
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

52
README.md Normal file
View file

@ -0,0 +1,52 @@
<div align="center">
<br/>
<br/>
<h1>nvim-treesitter-main</h1>
<p><strong>A Nixpkgs overlay for the nvim-treesitter plugin main branch rewrite</strong></p>
<div>
<img
alt="License"
src="https://img.shields.io/github/license/iofq/nvim-treesitter-main?style=for-the-badge&logo=starship&color=ee999f&logoColor=D9E0EE&labelColor=302D41"
/>
<img
alt="Stars"
src="https://img.shields.io/github/stars/iofq/nvim-treesitter-main?style=for-the-badge&logo=starship&color=c69ff5&logoColor=D9E0EE&labelColor=302D41"
/>
</div>
</div>
## Overview
The [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter/tree/main) main branch is a full, incompatible rewrite of the project, and the existing `master` branch is all but abandoned.
The `nixpkgs` `nvim-treesitter` plugin is not well equipped to handle the migration today, nor would it be a good idea to switch everyone over given the still-nascent ecosystem around the rewrite. Regardless, you're here because you're both a Nix and Neovim user, and you like to live on the bleeding edge.
**nvim-treesitter-main** is a flake that builds the new `main` branch `nvim-treesitter`, along with all of the parser versions from the [`parsers.lua`](https://github.com/nvim-treesitter/nvim-treesitter/blob/main/lua/nvim-treesitter/parsers.lua) file, as recommended by the project.
## Usage
In your flake.nix:
```nix
inputs = {
nvim-treesitter-main.url = "github:iofq/nvim-treesitter-main";
};
# ... and import the overlay
pkgs = import nixpkgs {
inherit system;
overlays = [
inputs.nvim-treesitter-main.overlays.default
];
};
```
## Updating
To update the list of parsers in `generated.nix`:
```bash
nix flake update
nix develop --command "generate-parsers"
```
This runs a lua script similar to the old [update.py](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/utils/nvim-treesitter/update.py), but uses the `nvim-treesitter` as a source for version info instead of the NURR json file.

45
flake.lock generated Normal file
View file

@ -0,0 +1,45 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1759381078,
"narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nvim-treesitter": {
"flake": false,
"locked": {
"lastModified": 1759376029,
"narHash": "sha256-Cu6Wg9SKJpYAkp8DPAXe4Rf9OSSWW2wNdmCkYtl//fw=",
"owner": "nvim-treesitter",
"repo": "nvim-treesitter",
"rev": "99bd52ba56a4b7c9a8cc50a6140180755e76fac6",
"type": "github"
},
"original": {
"owner": "nvim-treesitter",
"ref": "main",
"repo": "nvim-treesitter",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"nvim-treesitter": "nvim-treesitter"
}
}
},
"root": "root",
"version": 7
}

63
flake.nix Normal file
View file

@ -0,0 +1,63 @@
{
description = "nvim-treesitter main branch overlay";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
nvim-treesitter = {
url = "github:nvim-treesitter/nvim-treesitter/main";
flake = false;
};
};
outputs =
{ self, ... }@inputs:
let
supportedSystems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
forEachSupportedSystem =
f:
inputs.nixpkgs.lib.genAttrs supportedSystems (
system:
f {
pkgs = import inputs.nixpkgs {
inherit system;
};
}
);
in
{
overlays = {
default = (import ./overlay.nix { inherit inputs; });
};
devShells = forEachSupportedSystem (
{ pkgs, ... }:
{
default = pkgs.mkShell {
packages = [
(import ./generate-parsers { inherit inputs pkgs; })
];
};
}
);
packages = forEachSupportedSystem (
{ pkgs, ... }:
let
pkgs' = import inputs.nixpkgs {
inherit (pkgs) system;
overlays = (pkgs.overlays or [ ]) ++ [
(import ./overlay.nix { inherit inputs; })
];
};
in
rec {
nvim-treesitter = pkgs'.vimPlugins.nvim-treesitter.withAllGrammars;
default = nvim-treesitter;
}
);
};
}

View file

@ -0,0 +1,30 @@
{ inputs, pkgs, ... }:
with pkgs;
stdenv.mkDerivation {
pname = "generate-parsers";
version = "1.0";
nativeBuildInputs = [
pkgs.makeWrapper
];
src = ./generate-parsers.lua;
unpackPhase = ":";
installPhase = ''
mkdir -p $out/bin
echo "#!${pkgs.luajit}/bin/luajit" > $out/bin/generate-parsers
cat $src >> $out/bin/generate-parsers
chmod +x $out/bin/generate-parsers
wrapProgram $out/bin/generate-parsers \
--add-flag ${inputs.nvim-treesitter}/lua/nvim-treesitter/parsers.lua \
--add-flag "generated.nix" \
--prefix PATH : "${
pkgs.lib.makeBinPath [
pkgs.nurl
pkgs.nixfmt
]
}"
'';
}

View file

@ -0,0 +1,71 @@
local function fmt_grammar(grammar)
local lines = {
string.format('%s = buildGrammar {', grammar.language),
string.format('language = "%s";', grammar.language),
string.format('version = "%s";', grammar.version),
string.format('src = %s;', grammar.src),
string.format('meta.homepage = "%s";', grammar.meta.homepage),
}
if grammar.generate then table.insert(lines, string.format('generate = %s;', grammar.generate)) end
if grammar.location then table.insert(lines, string.format('location = "%s";', grammar.location)) end
table.insert(lines, "};")
return table.concat(lines, "\n")
end
local function generate_grammars(g)
local output = {}
for name, p in pairs(g) do
if p.install_info then
local out = assert(
io.popen(
string.format(
"nurl %s %s",
p.install_info.url,
p.install_info.revision
)
)
)
local grammar = {
version = "0.0.0+rev=" .. p.install_info.revision,
language = name,
src = out:read("*a"),
meta = {
homepage = p.install_info.url,
},
}
out:close()
if p.install_info.generate then
grammar.generate = p.install_info.generate
end
if p.install_info.location then
grammar.location = p.install_info.location
end
table.insert(output, fmt_grammar(grammar))
end
end
table.sort(output)
return table.concat(output)
end
local function header()
local out = assert(io.popen("nurl -Ls ','"):read("*a"))
return string.format([[
# This file was generated by generate-parsers.lua for nvim-treesitter-main
{ buildGrammar, %s }: {
]], out)
end
local parsers = dofile(arg[1])
local output_path = arg[2]
local file = assert(io.open(output_path, "w"))
file:write(header())
file:write(generate_grammars(parsers))
file:write("}") -- footer
file:close()
assert(os.execute("nixfmt " .. output_path))

3630
generated.nix Normal file

File diff suppressed because it is too large Load diff

83
overlay.nix Normal file
View file

@ -0,0 +1,83 @@
{ inputs, ... }:
final: prev:
with prev;
let
inherit (neovimUtils) grammarToPlugin;
overrides = prev: {
};
generatedGrammars =
let
generated = callPackage ./generated.nix {
inherit (tree-sitter) buildGrammar;
};
in
lib.overrideExisting generated (overrides generated);
generatedDerivations = lib.filterAttrs (_: lib.isDerivation) generatedGrammars;
# add aliases so grammars from `tree-sitter` are overwritten in `withPlugins`
# for example, for ocaml_interface, the following aliases will be added
# ocaml-interface
# tree-sitter-ocaml-interface
# tree-sitter-ocaml_interface
builtGrammars =
generatedGrammars
// lib.concatMapAttrs (
k: v:
let
replaced = lib.replaceStrings [ "_" ] [ "-" ] k;
in
{
"tree-sitter-${k}" = v;
}
// lib.optionalAttrs (k != replaced) {
${replaced} = v;
"tree-sitter-${replaced}" = v;
}
) generatedDerivations;
allGrammars = lib.attrValues generatedDerivations;
# Usage:
# pkgs.vimPlugins.nvim-treesitter.withPlugins (p: [ p.c p.java ... ])
# or for all grammars:
# pkgs.vimPlugins.nvim-treesitter.withAllGrammars
withPlugins =
f:
final.vimPlugins.nvim-treesitter.overrideAttrs {
passthru.dependencies = map grammarToPlugin (f (tree-sitter.builtGrammars // builtGrammars));
};
withAllGrammars = withPlugins (_: allGrammars);
in
{
vimPlugins = prev.vimPlugins.extend (
final': prev': {
nvim-treesitter = prev.vimPlugins.nvim-treesitter.overrideAttrs (old: rec {
src = inputs.nvim-treesitter;
name = "${old.pname}-${src.rev}";
postPatch = "";
# ensure runtime queries get linked to RTP (:TSInstall does this too)
postInstall = "
mkdir -p $out/queries
cp -a $src/runtime/queries/* $out/queries
";
passthru = (prev.nvim-treesitter.passthru or { }) // {
inherit
builtGrammars
allGrammars
grammarToPlugin
withPlugins
withAllGrammars
;
grammarPlugins = lib.mapAttrs (_: grammarToPlugin) generatedDerivations;
};
nvimSkipModules = [ "nvim-treesitter._meta.parsers" ];
});
}
);
}