|
14 | 14 | applyExtraConfig = "It has been moved to `lib.plugins.utils`";
|
15 | 15 | mkConfigAt = "It has been moved to `lib.plugins.utils`";
|
16 | 16 | };
|
| 17 | + internal = lib.mkOption { internal = true; }; |
17 | 18 | in
|
18 | 19 | {
|
19 | 20 | # Evaluate nixvim modules, checking warnings and assertions
|
|
52 | 53 | helpers = self;
|
53 | 54 | } // extraSpecialArgs;
|
54 | 55 | };
|
| 56 | + |
| 57 | + # Create a module configuring a plugin's integration with blink.cmp |
| 58 | + mkBlinkPluginModule = |
| 59 | + { |
| 60 | + # The plugin's option location-path |
| 61 | + loc ? [ |
| 62 | + "plugins" |
| 63 | + pluginName |
| 64 | + ], |
| 65 | + # Name of the plugin, used in documentation |
| 66 | + pluginName, |
| 67 | + # Name of the module blink should import |
| 68 | + # i.e. `sources.providers.<name>.module` |
| 69 | + module ? pluginName, |
| 70 | + # The default for `blink.settings.name` |
| 71 | + # i.e. `sources.providers.<name>.name` |
| 72 | + # TODO: consider doing some pre-processing to the default source name, |
| 73 | + # e.g. removing `-cmp` or `blink-` prefix/suffix? |
| 74 | + sourceName, |
| 75 | + # The default for `blink.key` |
| 76 | + # i.e. the attr name for `sources.providers.<name>` |
| 77 | + key ? lib.strings.toLower sourceName, |
| 78 | + # Whether to enable the blink completion provider by default |
| 79 | + enableProvider ? true, |
| 80 | + # Defaults for the corresponding source options |
| 81 | + enableDefault ? true, |
| 82 | + enableCmdline ? false, |
| 83 | + enabledFiletypes ? { }, |
| 84 | + # Whether the plugin's settings should be used as the provider's `opts` |
| 85 | + usePluginSettings ? true, |
| 86 | + settingsExample ? { |
| 87 | + score_offset = -7; |
| 88 | + fallbacks = [ ]; |
| 89 | + }, |
| 90 | + }: |
| 91 | + { config, options, ... }: |
| 92 | + let |
| 93 | + pluginCfg = lib.getAttrFromPath loc config; |
| 94 | + cfg = pluginCfg.blink; |
| 95 | + pluginOpts = lib.getAttrFromPath loc options; |
| 96 | + opt = pluginOpts.blink; |
| 97 | + opts = opt.type.getSubOptions opt.loc; |
| 98 | + in |
| 99 | + { |
| 100 | + options = lib.setAttrByPath loc { |
| 101 | + blink = lib.mkOption { |
| 102 | + description = "Configure blink.cmp options for ${pluginName}."; |
| 103 | + default = { }; |
| 104 | + example = { |
| 105 | + enable = false; |
| 106 | + cmdline = true; |
| 107 | + }; |
| 108 | + type = lib.types.submodule { |
| 109 | + options = { |
| 110 | + enable = lib.mkOption { |
| 111 | + type = lib.types.bool; |
| 112 | + default = enableProvider; |
| 113 | + example = !enableProvider; |
| 114 | + description = '' |
| 115 | + Whether to integrate this plugin with blink.cmp. |
| 116 | + ''; |
| 117 | + }; |
| 118 | + key = lib.mkOption { |
| 119 | + type = lib.types.str; |
| 120 | + default = key; |
| 121 | + description = '' |
| 122 | + The key to use for ${pluginName}'s blink.cmp provider. |
| 123 | + This is the id you should use when including this provider in completion source lists. |
| 124 | + Must be unique. |
| 125 | + ''; |
| 126 | + }; |
| 127 | + default = lib.mkOption { |
| 128 | + type = lib.types.bool; |
| 129 | + default = enableDefault; |
| 130 | + example = !enableDefault; |
| 131 | + description = '' |
| 132 | + Whether to include this plugin in the `default` completion source list. |
| 133 | + ''; |
| 134 | + }; |
| 135 | + cmdline = lib.mkOption { |
| 136 | + type = lib.types.bool; |
| 137 | + default = enableCmdline; |
| 138 | + example = !enableCmdline; |
| 139 | + description = '' |
| 140 | + Whether to include this plugin in the `cmdline` completion source list. |
| 141 | + ''; |
| 142 | + }; |
| 143 | + filetypes = lib.mkOption { |
| 144 | + type = lib.types.attrsOf lib.types.bool; |
| 145 | + # Only include `true` attrs in the final value |
| 146 | + apply = lib.filterAttrs (_: lib.id); |
| 147 | + default = enabledFiletypes; |
| 148 | + # TODO: example |
| 149 | + description = '' |
| 150 | + Whether to include this plugin in the specific `per_filetype` completion source lists. |
| 151 | + ''; |
| 152 | + }; |
| 153 | + settings = lib.mkOption { |
| 154 | + default = { }; |
| 155 | + description = '' |
| 156 | + Settings for the blink.cmp completion provider. |
| 157 | + ''; |
| 158 | + example = settingsExample; |
| 159 | + type = lib.types.submodule [ |
| 160 | + { |
| 161 | + options = { |
| 162 | + enabled = internal; |
| 163 | + module = internal; |
| 164 | + }; |
| 165 | + config = { |
| 166 | + name = lib.mkDefault sourceName; |
| 167 | + inherit module; |
| 168 | + # One-way alias for `plugin.*.settings` -> `plugin.*.blink.settings.opts` |
| 169 | + # Use mkAliasDefinitions to preserve override priorities |
| 170 | + opts = lib.mkIf usePluginSettings (lib.modules.mkAliasDefinitions pluginOpts.settings); |
| 171 | + }; |
| 172 | + } |
| 173 | + (import ../plugins/by-name/blink-cmp/provider-config.nix lib) |
| 174 | + ]; |
| 175 | + }; |
| 176 | + }; |
| 177 | + }; |
| 178 | + }; |
| 179 | + }; |
| 180 | + config = lib.mkIf (pluginCfg.enable && cfg.enable) { |
| 181 | + plugins.blink-cmp.settings.sources = { |
| 182 | + # Use mkAliasDefinitions to preserve override priorities |
| 183 | + providers.${cfg.key} = lib.modules.mkAliasDefinitions opts.settings; |
| 184 | + default = lib.mkIf cfg.default [ cfg.key ]; |
| 185 | + # FIXME: the reference shows `cmdline` should/could be defined as a function |
| 186 | + # https://cmp.saghen.dev/configuration/reference.html#sources |
| 187 | + cmdline = lib.mkIf cfg.cmdline [ cfg.key ]; |
| 188 | + per_filetype = lib.mkIf (cfg.filetypes != { }) ( |
| 189 | + builtins.mapAttrs (_: _: [ cfg.key ]) cfg.filetypes |
| 190 | + ); |
| 191 | + }; |
| 192 | + }; |
| 193 | + }; |
| 194 | + |
| 195 | + # Create a module configuring a plugin's integration with nvim-cmp and blink.cmp |
| 196 | + mkCmpPluginModule = |
| 197 | + { |
| 198 | + # The plugin's option location-path |
| 199 | + loc ? [ |
| 200 | + "plugins" |
| 201 | + pluginName |
| 202 | + ], |
| 203 | + # Name of the plugin, used in documentation |
| 204 | + pluginName, |
| 205 | + # The nvim-cmp source name |
| 206 | + # TODO: can we compute a sane default for sourceName? |
| 207 | + sourceName, |
| 208 | + # Defaults for the corresponding cmp options |
| 209 | + enableDefault ? true, |
| 210 | + enableCmdline ? false, |
| 211 | + enabledFiletypes ? { }, |
| 212 | + # Whether to include a `blink` option at all |
| 213 | + offerBlinkCompatibility ? true, |
| 214 | + # Defaults for the blink compatibility option |
| 215 | + enableBlinkProvider ? false, |
| 216 | + enableBlinkDefault ? false, |
| 217 | + enableBlinkCmdline ? false, |
| 218 | + enabledBlinkFiletypes ? { }, |
| 219 | + # Whether the plugin's settings should be used as the blink provider's `opts` |
| 220 | + usePluginSettingsForBlink ? false, |
| 221 | + # The key to use with blink, |
| 222 | + # i.e. the attr name for `sources.providers.<name>` |
| 223 | + # TODO: should this default to pluginName or sourceName? |
| 224 | + blinkProviderKey ? lib.strings.toLower pluginName, |
| 225 | + }: |
| 226 | + { config, options, ... }: |
| 227 | + let |
| 228 | + pluginOpt = lib.getAttrFromPath loc options; |
| 229 | + pluginCfg = lib.getAttrFromPath loc config; |
| 230 | + blinkOpt = pluginOpt.blink.type.getSubOptions pluginOpt.blink.loc; |
| 231 | + blinkCfg = pluginCfg.blink; |
| 232 | + cfg = pluginCfg.cmp; |
| 233 | + toSourceDef = v: lib.optionalAttrs (builtins.isAttrs v) v // { inherit (cfg) name; }; |
| 234 | + toSources = v: { sources = [ (toSourceDef v) ]; }; |
| 235 | + in |
| 236 | + { |
| 237 | + imports = lib.optionals offerBlinkCompatibility [ |
| 238 | + (lib.nixvim.modules.mkBlinkPluginModule { |
| 239 | + inherit loc pluginName sourceName; |
| 240 | + key = blinkProviderKey; |
| 241 | + module = "blink.compat.source"; |
| 242 | + enableProvider = enableBlinkProvider; |
| 243 | + enableDefault = enableBlinkDefault; |
| 244 | + enableCmdline = enableBlinkCmdline; |
| 245 | + enabledFiletypes = enabledBlinkFiletypes; |
| 246 | + usePluginSettings = usePluginSettingsForBlink; |
| 247 | + }) |
| 248 | + { |
| 249 | + options = lib.setAttrByPath loc { |
| 250 | + blink.settings.name = internal; |
| 251 | + }; |
| 252 | + config = lib.mkIf (pluginCfg.enable && blinkCfg.enable) { |
| 253 | + # Enable blink-compat if the plugin has `blink.enable = true` |
| 254 | + plugins.blink-compat.enable = true; |
| 255 | + # This warning will show if someone overrides `plugins.blink-compat.enable = mkForce false` |
| 256 | + warnings = lib.nixvim.mkWarnings (lib.showOption loc) { |
| 257 | + when = !config.plugins.blink-compat.enable; |
| 258 | + message = '' |
| 259 | + `${blinkOpt.enable}` is enabled, but `${options.plugins.blink-compat.enable}` is not. |
| 260 | + This plugin is a nvim-cmp source, so it requires blink.compat when used with blink.cmp. |
| 261 | + ''; |
| 262 | + }; |
| 263 | + }; |
| 264 | + } |
| 265 | + ]; |
| 266 | + options = lib.setAttrByPath loc { |
| 267 | + cmp = lib.mkOption { |
| 268 | + # TODO: this option will replace the current autoEnableCmpSources system |
| 269 | + type = lib.types.submodule { |
| 270 | + options = { |
| 271 | + enable = lib.mkOption { |
| 272 | + type = lib.types.bool; |
| 273 | + # FIXME: this should default to true, but it is incompatible with autoEnableCmpSources |
| 274 | + default = false; |
| 275 | + example = true; |
| 276 | + description = '' |
| 277 | + Whether to integrate this plugin with nvim-cmp. |
| 278 | + ''; |
| 279 | + }; |
| 280 | + name = lib.mkOption { |
| 281 | + type = lib.types.str; |
| 282 | + default = sourceName; |
| 283 | + description = "${pluginName}'s nvim-cmp source name."; |
| 284 | + internal = true; |
| 285 | + }; |
| 286 | + default = lib.mkOption { |
| 287 | + type = with lib.types; either bool (attrsOf anything); |
| 288 | + default = enableDefault; |
| 289 | + example = !enableDefault; |
| 290 | + description = '' |
| 291 | + Whether to include this plugin in the `default` completion source list. |
| 292 | +
|
| 293 | + Can be defined as attrs to pass additional config to the source. |
| 294 | + ''; |
| 295 | + }; |
| 296 | + cmdline = lib.mkOption { |
| 297 | + type = with lib.types; attrsOf (either bool (attrsOf anything)); |
| 298 | + # Remove false attrs in the final value |
| 299 | + apply = lib.filterAttrs (_: v: v != false); |
| 300 | + default = enableCmdline; |
| 301 | + example = !enableCmdline; |
| 302 | + description = '' |
| 303 | + Whether to include this plugin in the specific `cmdline` completion source lists. |
| 304 | +
|
| 305 | + Elements can be defined as attrs to pass additional config to the source. |
| 306 | + ''; |
| 307 | + }; |
| 308 | + filetypes = lib.mkOption { |
| 309 | + type = with lib.types; attrsOf (either bool (attrsOf anything)); |
| 310 | + # Remove false attrs in the final value |
| 311 | + apply = lib.filterAttrs (_: v: v != false); |
| 312 | + default = enabledFiletypes; |
| 313 | + # TODO: example |
| 314 | + description = '' |
| 315 | + Whether to include this plugin in the specific `per_filetype` completion source lists. |
| 316 | +
|
| 317 | + Elements can be defined as attrs to pass additional config to the source. |
| 318 | + ''; |
| 319 | + }; |
| 320 | + }; |
| 321 | + }; |
| 322 | + }; |
| 323 | + }; |
| 324 | + config = lib.mkMerge [ |
| 325 | + { |
| 326 | + # Backwards compatibility with autoEnableCmpSources |
| 327 | + cmpSourcePlugins.${sourceName} = |
| 328 | + assert lib.assertMsg (builtins.length loc == 2 && builtins.head loc == "plugins") |
| 329 | + "autoEnableCmpSources assumes all cmp source plugins are in the `plugins` namespace. Unsupported plugin `${lib.showOption loc}`."; |
| 330 | + lib.last loc; |
| 331 | + } |
| 332 | + (lib.mkIf (pluginCfg.enable && cfg.enable) { |
| 333 | + plugins.cmp = { |
| 334 | + settings = lib.mkIf (cfg.default != false) (toSources cfg.default); |
| 335 | + cmdline = lib.mkIf (cfg.cmdline != { }) (builtins.mapAttrs (_: toSources) cfg.cmdline); |
| 336 | + filetype = lib.mkIf (cfg.filetypes != { }) (builtins.mapAttrs (_: toSources) cfg.filetypes); |
| 337 | + }; |
| 338 | + }) |
| 339 | + ]; |
| 340 | + }; |
55 | 341 | }
|
56 | 342 | // lib.mapAttrs (
|
57 | 343 | name: msg:
|
|
0 commit comments