1
{
2
stdenv,
3
lib,
4
runCommand,
5
includeGrammarIf ? _: true,
6
grammarOverlays ? [],
7
...
8
}: let
9
languagesConfig =
10
builtins.fromTOML (builtins.readFile ./languages.toml);
11
isGitGrammar = grammar:
12
builtins.hasAttr "source" grammar
13
&& builtins.hasAttr "git" grammar.source
14
&& builtins.hasAttr "rev" grammar.source;
15
isGitHubGrammar = grammar: lib.hasPrefix "https://github.com" grammar.source.git;
16
toGitHubFetcher = url: let
17
match = builtins.match "https://github\.com/([^/]*)/([^/]*)/?" url;
18
in {
19
owner = builtins.elemAt match 0;
20
repo = builtins.elemAt match 1;
21
};
22
# If `use-grammars.only` is set, use only those grammars.
23
# If `use-grammars.except` is set, use all other grammars.
24
# Otherwise use all grammars.
25
useGrammar = grammar:
26
if languagesConfig ? use-grammars.only
27
then builtins.elem grammar.name languagesConfig.use-grammars.only
28
else if languagesConfig ? use-grammars.except
29
then !(builtins.elem grammar.name languagesConfig.use-grammars.except)
30
else true;
31
grammarsToUse = builtins.filter useGrammar languagesConfig.grammar;
32
gitGrammars = builtins.filter isGitGrammar grammarsToUse;
33
buildGrammar = grammar: let
34
gh = toGitHubFetcher grammar.source.git;
35
sourceGit = builtins.fetchTree {
36
type = "git";
37
url = grammar.source.git;
38
rev = grammar.source.rev;
39
ref = grammar.source.ref or "HEAD";
40
shallow = true;
41
};
42
sourceGitHub = builtins.fetchTree {
43
type = "github";
44
owner = gh.owner;
45
repo = gh.repo;
46
inherit (grammar.source) rev;
47
};
48
source =
49
if isGitHubGrammar grammar
50
then sourceGitHub
51
else sourceGit;
52
in
53
stdenv.mkDerivation {
54
# see https://github.com/NixOS/nixpkgs/blob/fbdd1a7c0bc29af5325e0d7dd70e804a972eb465/pkgs/development/tools/parsing/tree-sitter/grammar.nix
55
56
pname = "helix-tree-sitter-${grammar.name}";
57
version = grammar.source.rev;
58
59
src = source;
60
sourceRoot =
61
if builtins.hasAttr "subpath" grammar.source
62
then "source/${grammar.source.subpath}"
63
else "source";
64
65
dontConfigure = true;
66
67
FLAGS = [
68
"-Isrc"
69
"-g"
70
"-O3"
71
"-fPIC"
72
"-fno-exceptions"
73
"-Wl,-z,relro,-z,now"
74
];
75
76
NAME = grammar.name;
77
78
buildPhase = ''
79
runHook preBuild
80
81
if [[ -e src/scanner.cc ]]; then
82
$CXX -c src/scanner.cc -o scanner.o $FLAGS
83
elif [[ -e src/scanner.c ]]; then
84
$CC -c src/scanner.c -o scanner.o $FLAGS
85
fi
86
87
$CC -c src/parser.c -o parser.o $FLAGS
88
$CXX -shared -o $NAME.so *.o
89
90
ls -al
91
92
runHook postBuild
93
'';
94
95
installPhase = ''
96
runHook preInstall
97
mkdir $out
98
mv $NAME.so $out/
99
runHook postInstall
100
'';
101
102
# Strip failed on darwin: strip: error: symbols referenced by indirect symbol table entries that can't be stripped
103
fixupPhase = lib.optionalString stdenv.isLinux ''
104
runHook preFixup
105
$STRIP $out/$NAME.so
106
runHook postFixup
107
'';
108
};
109
grammarsToBuild = builtins.filter includeGrammarIf gitGrammars;
110
builtGrammars =
111
builtins.map (grammar: {
112
inherit (grammar) name;
113
value = buildGrammar grammar;
114
})
115
grammarsToBuild;
116
extensibleGrammars =
117
lib.makeExtensible (self: builtins.listToAttrs builtGrammars);
118
overlaidGrammars =
119
lib.pipe extensibleGrammars
120
(builtins.map (overlay: grammar: grammar.extend overlay) grammarOverlays);
121
grammarLinks =
122
lib.mapAttrsToList
123
(name: artifact: "ln -s ${artifact}/${name}.so $out/${name}.so")
124
(lib.filterAttrs (n: v: lib.isDerivation v) overlaidGrammars);
125
in
126
runCommand "consolidated-helix-grammars" {} ''
127
mkdir -p $out
128
${builtins.concatStringsSep "\n" grammarLinks}
129
''
130