summaryrefslogtreecommitdiffstats
path: root/modules/wrapper/lazy/config.nix
blob: eed8c851bca552e5023d0eccafdb8f8ce792189e (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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
{
  lib,
  config,
  ...
}: let
  inherit (builtins) toJSON typeOf head length filter concatLists concatStringsSep tryEval;
  inherit (lib.attrsets) mapAttrsToList;
  inherit (lib.modules) mkIf mkMerge;
  inherit (lib.generators) mkLuaInline;
  inherit (lib.strings) optionalString;
  inherit (lib.nvim.lua) toLuaObject;
  cfg = config.vim.lazy;

  toLuaLznKeySpec = keySpec:
    (removeAttrs keySpec ["key" "lua" "action"])
    // {
      "@1" = keySpec.key;
      "@2" =
        if keySpec.lua
        then mkLuaInline keySpec.action
        else keySpec.action;
    };

  toLuaLznSpec = name: spec: let
    packageName =
      if typeOf spec.package == "string"
      then spec.package
      else if (spec.package ? pname && (tryEval spec.package.pname).success)
      then spec.package.pname
      else spec.package.name;
  in
    (removeAttrs spec ["package" "setupModule" "setupOpts" "setupCond" "keys"])
    // {
      "@1" =
        if spec.package != null && packageName != name && spec.load == null
        then
          abort ''
            vim.lazy.plugins.${name} does not match the package name ${packageName}.

            Please either:
            - rename it to vim.lazy.plugins.${packageName}, or
            - if you intend to use a custom loader, specify a
              vim.lazy.plugins.${name}.load function.
          ''
        else if spec.package == null && spec.load == null
        then
          abort ''
            vim.lazy.plugins.${name} has null package but no load function given.

            Please either specify a package, or (if you know what you're doing) provide a
            custom load function.
          ''
        else name;
      beforeAll =
        if spec.beforeAll != null
        then
          mkLuaInline ''
            function()
              ${spec.beforeAll}
            end
          ''
        else null;
      before =
        if spec.before != null
        then
          mkLuaInline ''
            function()
              ${spec.before}
            end
          ''
        else null;

      after =
        if spec.setupModule == null && spec.after == null
        then null
        else let
          setupCall = "require(${toJSON spec.setupModule}).setup(${toLuaObject spec.setupOpts})";
          conditionalSetup =
            if spec.setupCond != null
            then ''
              if (${spec.setupCond}) then
                ${setupCall}
              end''
            else setupCall;
        in
          mkLuaInline ''
            function()
              ${optionalString (spec.beforeSetup != null) spec.beforeSetup}
              ${optionalString (spec.setupModule != null) conditionalSetup}
              ${optionalString (spec.after != null) spec.after}
            end
          '';

      load =
        if spec.load != null
        then
          mkLuaInline ''
            function(name)
              ${spec.load}
            end
          ''
        else null;

      keys =
        if typeOf spec.keys == "list" && length spec.keys > 0 && typeOf (head spec.keys) == "set"
        then map toLuaLznKeySpec (filter (keySpec: keySpec.key != null) spec.keys)
        # empty list or str or (listOf str)
        else spec.keys;
    };
  lznSpecs = mapAttrsToList toLuaLznSpec cfg.plugins;

  pluginPackages = filter (x: x != null) (mapAttrsToList (_: plugin: plugin.package) cfg.plugins);

  specToNotLazyConfig = _: spec: let
    setupCall = "require(${toJSON spec.setupModule}).setup(${toLuaObject spec.setupOpts})";
    conditionalSetup =
      if spec.setupCond != null
      then ''
        if (${spec.setupCond}) then
          ${setupCall}
        end''
      else setupCall;
  in ''
    do
      ${optionalString (spec.before != null) spec.before}
      ${optionalString (spec.setupModule != null) conditionalSetup}
      ${optionalString (spec.after != null) spec.after}
    end
  '';

  specToKeymaps = _: spec:
    if typeOf spec.keys == "list"
    then map (x: removeAttrs x ["ft"]) (filter (lznKey: lznKey.action != null && lznKey.ft == null) spec.keys)
    else if spec.keys == null || typeOf spec.keys == "string"
    then []
    else [spec.keys];

  notLazyConfig =
    concatStringsSep "\n"
    (mapAttrsToList specToNotLazyConfig cfg.plugins);

  beforeAllJoined =
    concatStringsSep "\n"
    (filter (x: x != null) (mapAttrsToList (_: spec: spec.beforeAll) cfg.plugins));
in {
  config.vim = mkMerge [
    (mkIf cfg.enable {
      startPlugins = ["lz-n" "lzn-auto-require"];

      optPlugins = pluginPackages;
      augroups = [{name = "nvf_lazy_file_hooks";}];
      autocmds = [
        {
          event = ["BufReadPost" "BufNewFile" "BufWritePre"];
          group = "nvf_lazy_file_hooks";
          command = "doautocmd User LazyFile";
          once = true;
        }
      ];

      lazy.builtLazyConfig = ''
        ${optionalString (length lznSpecs > 0) "require('lz.n').load(${toLuaObject lznSpecs})"}
        ${optionalString cfg.enableLznAutoRequire "require('lzn-auto-require').enable()"}
      '';
    })

    (mkIf (!cfg.enable) {
      startPlugins = pluginPackages;
      lazy.builtLazyConfig = ''
        ${beforeAllJoined}
        ${notLazyConfig}
      '';
      keymaps = concatLists (mapAttrsToList specToKeymaps cfg.plugins);
    })
  ];
}