Skip to content

Commit 1b663b2

Browse files
committed
lib/modules: init mkBlinkPluginModule & mkCmpPluginModule
1 parent 2ecc535 commit 1b663b2

File tree

4 files changed

+285
-2
lines changed

4 files changed

+285
-2
lines changed

lib/modules.nix

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

plugins/by-name/blink-cmp/default.nix

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ lib.nixvim.plugins.mkNeovimPlugin {
1414

1515
description = ''
1616
Performant, batteries-included completion plugin for Neovim.
17+
18+
<!-- TODO: mention `plugins.*.blink` options -->
1719
'';
1820

1921
settingsOptions = import ./settings-options.nix lib;

plugins/by-name/blink-cmp/provider-config.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ let
33
inherit (lib) types;
44
inherit (lib.nixvim) defaultNullOpts;
55
in
6-
types.submodule {
6+
{
77
freeformType = with types; attrsOf anything;
88
options = {
99
name = defaultNullOpts.mkStr' {

plugins/by-name/blink-cmp/settings-options.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ in
525525
'';
526526

527527
providers = mkNullOrOption' {
528-
type = with types; attrsOf (import ./provider-config.nix lib);
528+
type = with types; attrsOf (submodule (import ./provider-config.nix lib));
529529
description = ''
530530
Definition of completion providers.
531531
'';

0 commit comments

Comments
 (0)