Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1{
2 lib,
3 stdenv,
4 fetchgit,
5 fetchFromGitHub,
6 nix-update-script,
7 runCommand,
8 which,
9 rustPlatform,
10 emscripten,
11 openssl,
12 pkg-config,
13 callPackage,
14 linkFarm,
15 substitute,
16 installShellFiles,
17 buildPackages,
18 enableShared ? !stdenv.hostPlatform.isStatic,
19 enableStatic ? stdenv.hostPlatform.isStatic,
20 webUISupport ? false,
21 extraGrammars ? { },
22
23 # tests
24 lunarvim,
25}:
26
27let
28 # to update:
29 # 1) change all these hashes
30 # 2) nix-build -A tree-sitter.updater.update-all-grammars
31 # 3) Set GITHUB_TOKEN env variable to avoid api rate limit (Use a Personal Access Token from https://github.com/settings/tokens It does not need any permissions)
32 # 4) run the ./result script that is output by that (it updates ./grammars)
33 version = "0.25.6";
34 hash = "sha256-2/DF2xyiKi5HAqqeGt1TIMvAWFfZgcfVccK4zrTqq88=";
35
36 src = fetchFromGitHub {
37 owner = "tree-sitter";
38 repo = "tree-sitter";
39 tag = "v${version}";
40 inherit hash;
41 fetchSubmodules = true;
42 };
43
44 update-all-grammars = callPackage ./update.nix { };
45
46 fetchGrammar =
47 v:
48 fetchgit {
49 inherit (v)
50 url
51 rev
52 sha256
53 fetchSubmodules
54 ;
55 };
56
57 grammars = runCommand "grammars" { } (
58 ''
59 mkdir $out
60 ''
61 + (lib.concatStrings (
62 lib.mapAttrsToList (
63 name: grammar: "ln -s ${grammar.src or (fetchGrammar grammar)} $out/${name}\n"
64 ) (import ./grammars { inherit lib; })
65 ))
66 );
67
68 buildGrammar = callPackage ./grammar.nix { };
69
70 builtGrammars =
71 let
72 build =
73 name: grammar:
74 buildGrammar {
75 language = grammar.language or name;
76 inherit version;
77 src = grammar.src or (fetchGrammar grammar);
78 location = grammar.location or null;
79 generate = grammar.generate or false;
80 };
81 grammars' = import ./grammars { inherit lib; } // extraGrammars;
82 grammars =
83 grammars'
84 // {
85 tree-sitter-latex = grammars'.tree-sitter-latex // {
86 generate = true;
87 };
88 }
89 // {
90 tree-sitter-ocaml = grammars'.tree-sitter-ocaml // {
91 location = "grammars/ocaml";
92 };
93 }
94 // {
95 tree-sitter-ocaml-interface = grammars'.tree-sitter-ocaml // {
96 location = "grammars/interface";
97 };
98 }
99 // {
100 tree-sitter-org-nvim = grammars'.tree-sitter-org-nvim // {
101 language = "tree-sitter-org";
102 };
103 }
104 // {
105 tree-sitter-typescript = grammars'.tree-sitter-typescript // {
106 location = "typescript";
107 };
108 }
109 // {
110 tree-sitter-tsx = grammars'.tree-sitter-typescript // {
111 location = "tsx";
112 };
113 }
114 // {
115 tree-sitter-markdown = grammars'.tree-sitter-markdown // {
116 location = "tree-sitter-markdown";
117 };
118 }
119 // {
120 tree-sitter-markdown-inline = grammars'.tree-sitter-markdown // {
121 language = "tree-sitter-markdown_inline";
122 location = "tree-sitter-markdown-inline";
123 };
124 }
125 // {
126 tree-sitter-php = grammars'.tree-sitter-php // {
127 location = "php";
128 };
129 }
130 // {
131 tree-sitter-sql = grammars'.tree-sitter-sql // {
132 generate = true;
133 };
134 };
135 in
136 lib.mapAttrs build grammars;
137
138 # Usage:
139 # pkgs.tree-sitter.withPlugins (p: [ p.tree-sitter-c p.tree-sitter-java ... ])
140 #
141 # or for all grammars:
142 # pkgs.tree-sitter.withPlugins (_: allGrammars)
143 # which is equivalent to
144 # pkgs.tree-sitter.withPlugins (p: builtins.attrValues p)
145 withPlugins =
146 grammarFn:
147 let
148 grammars = grammarFn builtGrammars;
149 in
150 linkFarm "grammars" (
151 map (
152 drv:
153 let
154 name = lib.strings.getName drv;
155 in
156 {
157 name =
158 (lib.strings.replaceStrings [ "-" ] [ "_" ] (
159 lib.strings.removePrefix "tree-sitter-" (lib.strings.removeSuffix "-grammar" name)
160 ))
161 + ".so";
162 path = "${drv}/parser";
163 }
164 ) grammars
165 );
166
167 allGrammars = builtins.attrValues builtGrammars;
168
169in
170rustPlatform.buildRustPackage {
171 pname = "tree-sitter";
172 inherit src version;
173
174 cargoHash = "sha256-sGh16M7cbT5ct1sT2FcUUoIQFcoOftTuQ0aSCjtkTEs=";
175
176 buildInputs = [
177 installShellFiles
178 ]
179 ++ lib.optionals webUISupport [
180 openssl
181 ];
182 nativeBuildInputs = [
183 which
184 ]
185 ++ lib.optionals webUISupport [
186 emscripten
187 pkg-config
188 ];
189
190 patches = lib.optionals (!webUISupport) [
191 (substitute {
192 src = ./remove-web-interface.patch;
193 })
194 ];
195
196 postPatch = lib.optionalString webUISupport ''
197 substituteInPlace cli/loader/src/lib.rs \
198 --replace-fail 'let emcc_name = if cfg!(windows) { "emcc.bat" } else { "emcc" };' 'let emcc_name = "${lib.getExe' emscripten "emcc"}";'
199 '';
200
201 # Compile web assembly with emscripten. The --debug flag prevents us from
202 # minifying the JavaScript; passing it allows us to side-step more Node
203 # JS dependencies for installation.
204 preBuild = lib.optionalString webUISupport ''
205 mkdir -p .emscriptencache
206 export EM_CACHE=$(pwd)/.emscriptencache
207 cargo run --package xtask -- build-wasm --debug
208 '';
209
210 postInstall = ''
211 PREFIX=$out make install
212 ${lib.optionalString (!enableShared) "rm $out/lib/*.so{,.*}"}
213 ${lib.optionalString (!enableStatic) "rm $out/lib/*.a"}
214 ''
215 + lib.optionalString (stdenv.buildPlatform.canExecute stdenv.hostPlatform) ''
216 installShellCompletion --cmd tree-sitter \
217 --bash <("$out/bin/tree-sitter" complete --shell bash) \
218 --zsh <("$out/bin/tree-sitter" complete --shell zsh) \
219 --fish <("$out/bin/tree-sitter" complete --shell fish)
220 ''
221 + lib.optionalString (!stdenv.buildPlatform.canExecute stdenv.hostPlatform) ''
222 installShellCompletion --cmd tree-sitter \
223 --bash "${buildPackages.tree-sitter}"/share/bash-completion/completions/*.bash \
224 --zsh "${buildPackages.tree-sitter}"/share/zsh/site-functions/* \
225 --fish "${buildPackages.tree-sitter}"/share/fish/*/*
226 '';
227
228 # test result: FAILED. 120 passed; 13 failed; 0 ignored; 0 measured; 0 filtered out
229 doCheck = false;
230
231 passthru = {
232 updater = {
233 inherit update-all-grammars;
234 };
235 inherit
236 grammars
237 buildGrammar
238 builtGrammars
239 withPlugins
240 allGrammars
241 ;
242
243 updateScript = nix-update-script { };
244
245 tests = {
246 # make sure all grammars build
247 builtGrammars = lib.recurseIntoAttrs builtGrammars;
248
249 inherit lunarvim;
250 };
251 };
252
253 meta = {
254 homepage = "https://github.com/tree-sitter/tree-sitter";
255 description = "Parser generator tool and an incremental parsing library";
256 mainProgram = "tree-sitter";
257 changelog = "https://github.com/tree-sitter/tree-sitter/releases/tag/v${version}";
258 longDescription = ''
259 Tree-sitter is a parser generator tool and an incremental parsing library.
260 It can build a concrete syntax tree for a source file and efficiently update the syntax tree as the source file is edited.
261
262 Tree-sitter aims to be:
263
264 * General enough to parse any programming language
265 * Fast enough to parse on every keystroke in a text editor
266 * Robust enough to provide useful results even in the presence of syntax errors
267 * Dependency-free so that the runtime library (which is written in pure C) can be embedded in any application
268 '';
269 license = lib.licenses.mit;
270 maintainers = with lib.maintainers; [
271 Profpatsch
272 uncenter
273 ];
274 };
275}