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