summaryrefslogtreecommitdiffstats
path: root/modules/plugins/treesitter/config.nix
blob: 1ff82f69b5aee5bdd735e919eac83b1d7a7fa8e5 (plain)
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
{
  config,
  lib,
  pkgs,
  ...
}: let
  inherit (lib) mkIf foldl' mapAttrsToList;
  inherit (lib.strings) optionalString;
  inherit (lib.lists) optionals optional partition;
  inherit (lib.nvim.dag) entryAfter;
  inherit (lib.nvim.lua) toLuaObject;

  cfg = config.vim.treesitter;
in {
  config = mkIf cfg.enable {
    vim = {
      startPlugins = ["nvim-treesitter"];

      # cmp-treesitter doesn't work on blink.cmp
      autocomplete.nvim-cmp = mkIf config.vim.autocomplete.nvim-cmp.enable {
        sources = {treesitter = "[Treesitter]";};
        sourcePlugins = ["cmp-treesitter"];
      };

      extraPackages = mkIf cfg.vendorCLI [
        (pkgs.symlinkJoin {
          name = "tree-sitter";
          paths = [pkgs.tree-sitter];
          meta.mainProgram = "tree-sitter";
          buildInputs = [pkgs.makeBinaryWrapper];
          postBuild = "wrapProgram $out/bin/tree-sitter --prefix PATH : ${pkgs.gcc}/bin";
        })
      ];

      treesitter.grammars = optionals cfg.addDefaultGrammars cfg.defaultGrammars;

      pluginRC = {
        treesitter-autocommands = entryAfter ["basic"] ''
          vim.api.nvim_create_augroup("nvf_treesitter", { clear = true })

          ${lib.optionalString cfg.highlight.enable ''
            -- Enable treesitter highlighting for all filetypes
            vim.api.nvim_create_autocmd("FileType", {
              group = "nvf_treesitter",
              pattern = "*",
              callback = function()
                pcall(vim.treesitter.start)
              end,
            })
          ''}

          ${lib.optionalString cfg.indent.enable ''
            -- Enable treesitter highlighting for all filetypes
            vim.api.nvim_create_autocmd("FileType", {
              group = "nvf_treesitter",
              pattern = ${toLuaObject cfg.indent.pattern},
              callback = function(args)
            ${optionalString (builtins.length cfg.indent.excludes > 0) ''
              local ft = vim.bo[args.buf].filetype
              if vim.tbl_contains(${toLuaObject cfg.indent.excludes}, ft) then
                return
              end
            ''}
                vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()"
              end,
            })
          ''}

          ${lib.optionalString cfg.fold ''
            -- Enable treesitter folding for all filetypes
            vim.api.nvim_create_autocmd("FileType", {
              group = "nvf_treesitter",
              pattern = "*",
              callback = function()
                vim.wo[0][0].foldmethod = "expr"
                vim.wo[0][0].foldexpr = "v:lua.vim.treesitter.foldexpr()"
              end,
            })
          ''}
        '';
        treesitter-filetype-mappings = entryAfter ["basic"] ''
          for lang, ft in pairs(${toLuaObject cfg.filetypeMappings}) do
            vim.treesitter.language.register(lang, ft)
          end
        '';
      };

      additionalRuntimePaths = mkIf (cfg.queries != []) (
        let
          mkQueryGroup = entries:
            foldl' (acc: entry:
              foldl' (inner: filetype: let
                path = "queries/${filetype}/${entry.type}.scm";
                prev = inner.${path} or "";
                query = ''${optionalString (entry.loadtype == "extends") "; extends\n"} ${entry.query} '';
              in
                inner // {${path} = prev + query;})
              acc
              entry.filetypes)
            {}
            entries;

          mkQueryRuntimePath = name: queries:
            pkgs.linkFarm "treesitter-queries-${name}" (mapAttrsToList (path: query: {
                name = path;
                path = pkgs.writeText path query;
              })
              queries);

          inherit (partition (entry: entry.loadtype == "overwrite") cfg.queries) right wrong;
          overwriteQueries = mkQueryGroup right;
          extendsQueries = mkQueryGroup wrong;
        in
          optional (overwriteQueries != {}) {
            path = mkQueryRuntimePath "overwrite" overwriteQueries;
            position = "prepend";
          }
          ++ optional (extendsQueries != {}) {
            path = mkQueryRuntimePath "extends" extendsQueries;
            position = "append";
          }
      );
    };
  };
}