summary refs log tree commit diff
path: root/pkgs/applications/editors/helix/grammars.nix
blob: be764ac756936f2f8b8f1b2ca614d806242a8068 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
{
  stdenv,
  lib,
  runCommand,
  includeGrammarIf ? _: true,
  fetchFromGitHub,
  fetchgit,
  ...
}: let
  # similiar to https://github.com/helix-editor/helix/blob/23.05/grammars.nix
  grammars = builtins.fromJSON (builtins.readFile ./language-grammars.json);
  isGitGrammar = grammar:
    builtins.hasAttr "source" grammar
    && builtins.hasAttr "git" grammar.source
    && builtins.hasAttr "rev" grammar.source;
  isGitHubGrammar = grammar: lib.hasPrefix "https://github.com" grammar.source.git;
  toGitHubFetcher = url: let
    match = builtins.match "https://github\.com/([^/]*)/([^/]*)/?" url;
  in {
    owner = builtins.elemAt match 0;
    repo = builtins.elemAt match 1;
  };
  gitGrammars = builtins.filter isGitGrammar grammars;
  buildGrammar = grammar: let
    gh = toGitHubFetcher grammar.source.git;
    sourceGit = fetchgit {
      url = grammar.source.git;
      inherit (grammar.source) rev sha256;
    };
    sourceGitHub = fetchFromGitHub {
      owner = gh.owner;
      repo = gh.repo;
      inherit (grammar.source) rev sha256;
    };
    source =
      if isGitHubGrammar grammar
      then sourceGitHub
      else sourceGit;
  in
    stdenv.mkDerivation rec {
      # similar to tree-sitter grammar generation
      pname = "helix-tree-sitter-grammar-${grammar.name}";
      version = grammar.source.rev;

      src =
        if builtins.hasAttr "subpath" grammar.source
        then "${source}/${grammar.source.subpath}"
        else source;

      dontUnpack = true;
      dontConfigure = true;

      FLAGS = [
        "-I${src}/src"
        "-g"
        "-O3"
        "-fPIC"
        "-fno-exceptions"
        "-Wl,-z,relro,-z,now"
      ];

      NAME = grammar.name;

      buildPhase = ''
        runHook preBuild

        if [[ -e "$src/src/scanner.cc" ]]; then
          $CXX -c "$src/src/scanner.cc" -o scanner.o $FLAGS
        elif [[ -e "$src/src/scanner.c" ]]; then
          $CC -c "$src/src/scanner.c" -o scanner.o $FLAGS
        fi

        $CC -c "$src/src/parser.c" -o parser.o $FLAGS
        $CXX -shared -o $NAME.so *.o

        runHook postBuild
      '';

      installPhase = ''
        runHook preInstall
        mkdir $out
        mv $NAME.so $out/
        runHook postInstall
      '';

      # Strip failed on darwin: strip: error: symbols referenced by indirect symbol table entries that can't be stripped
      fixupPhase = lib.optionalString stdenv.isLinux ''
        runHook preFixup
        $STRIP $out/$NAME.so
        runHook postFixup
      '';
    };
  grammarsToBuild = builtins.filter includeGrammarIf gitGrammars;
  builtGrammars =
    builtins.map (grammar: {
      inherit (grammar) name;
      artifact = buildGrammar grammar;
    })
    grammarsToBuild;
  grammarLinks =
    builtins.map (grammar: "ln -s ${grammar.artifact}/${grammar.name}.so $out/${grammar.name}.so")
    builtGrammars;
in
  runCommand "helix-tree-sitter-grammars" {} ''
    mkdir -p $out
    ${builtins.concatStringsSep "\n" grammarLinks}
  ''