expose helpers to config.nixvim.helpers (#51)

This commit is contained in:
Pedro Alves 2022-10-18 14:21:09 +01:00
commit 928e7f2673
11 changed files with 244 additions and 405 deletions

View file

@ -6,7 +6,6 @@
inputs.nmdSrc.url = "gitlab:rycee/nmd"; inputs.nmdSrc.url = "gitlab:rycee/nmd";
inputs.nmdSrc.flake = false; inputs.nmdSrc.flake = false;
# TODO: Use flake-utils to support all architectures
outputs = { self, nixpkgs, nmdSrc, flake-utils, ... }@inputs: outputs = { self, nixpkgs, nmdSrc, flake-utils, ... }@inputs:
with nixpkgs.lib; with nixpkgs.lib;
with builtins; with builtins;
@ -30,66 +29,25 @@
./plugins/default.nix ./plugins/default.nix
]; ];
nixvimOption = pkgs: mkOption {
type = types.submodule ((modules pkgs) ++ [{
options.enable = mkEnableOption "Enable nixvim";
}]);
};
helperOption = pkgs: mkOption {
type = mkOptionType {
name = "helpers";
description = "Helpers that can be used when writing nixvim configs";
check = builtins.isAttrs;
};
description = "Use this option to access the helpers";
default = import ./plugins/helpers.nix { inherit (pkgs) lib; };
};
build = pkgs:
configuration:
let
eval = evalModules {
modules = modules pkgs ++ [{ config = configuration; }];
};
in
eval.config.output;
flakeOutput = flakeOutput =
flake-utils.lib.eachDefaultSystem flake-utils.lib.eachDefaultSystem
(system: rec { (system:
let
pkgs = import nixpkgs { inherit system; };
in
{
packages.docs = import ./docs { packages.docs = import ./docs {
pkgs = import nixpkgs { inherit system; }; pkgs = import nixpkgs { inherit system; };
lib = nixpkgs.lib; lib = nixpkgs.lib;
nixvimModules = nixvimModules; nixvimModules = nixvimModules;
inherit nmdSrc; inherit nmdSrc;
}; };
legacyPackages.makeNixvim = import ./wrappers/standalone.nix pkgs (modules pkgs);
}); });
in in
flakeOutput // rec { flakeOutput // {
inherit build; nixosModules.nixvim = import ./wrappers/nixos.nix modules;
homeManagerModules.nixvim = import ./wrappers/hm.nix modules;
nixosModules.nixvim = { pkgs, config, lib, ... }: {
options = {
programs.nixvim = nixvimOption pkgs;
nixvim.helpers = helperOption pkgs;
};
config = mkIf config.programs.nixvim.enable {
environment.systemPackages = [
config.programs.nixvim.output
];
};
};
homeManagerModules.nixvim = { pkgs, config, lib, ... }: {
options = {
programs.nixvim = nixvimOption pkgs;
nixvim.helpers = helperOption pkgs;
};
config = mkIf config.programs.nixvim.enable {
home.packages = [
config.programs.nixvim.output
];
};
};
}; };
} }

View file

@ -65,9 +65,21 @@ in
description = "Extra contents for init.vim"; description = "Extra contents for init.vim";
}; };
output = mkOption { wrapRc = mkOption {
type = types.bool;
description = "Should the config be included in the wrapper script";
default = false;
};
finalPackage = mkOption {
type = types.package; type = types.package;
description = "Final package built by nixvim"; description = "Wrapped neovim";
readOnly = true;
};
initContent = mkOption {
type = types.str;
description = "The content of the init.vim file";
readOnly = true; readOnly = true;
visible = false; visible = false;
}; };
@ -75,9 +87,14 @@ in
config = config =
let let
customRC = config.extraConfigVim + (optionalString (config.extraConfigLua != "" || config.extraConfigLuaPre != "" || config.extraConfigLuaPost != "") '' customRC =
(optionalString (config.extraConfigLuaPre != "") ''
lua <<EOF lua <<EOF
${config.extraConfigLuaPre} ${config.extraConfigLuaPre}
EOF
'') +
config.extraConfigVim + (optionalString (config.extraConfigLuaPre != "" || config.extraConfigLuaPost != "") ''
lua <<EOF
${config.extraConfigLua} ${config.extraConfigLua}
${config.extraConfigLuaPost} ${config.extraConfigLuaPost}
EOF EOF
@ -100,7 +117,7 @@ in
# cda1f8ae468 - neovim: pass packpath via the wrapper # cda1f8ae468 - neovim: pass packpath via the wrapper
// optionalAttrs (functionArgs pkgs.neovimUtils.makeNeovimConfig ? configure) { // optionalAttrs (functionArgs pkgs.neovimUtils.makeNeovimConfig ? configure) {
configure.packages = configure.packages =
{ nixvim = { start = map (x: x.plugin) normalizedPlugins; opt = []; }; }; { nixvim = { start = map (x: x.plugin) normalizedPlugins; opt = [ ]; }; };
}); });
extraWrapperArgs = optionalString (config.extraPackages != [ ]) extraWrapperArgs = optionalString (config.extraPackages != [ ])
@ -108,9 +125,10 @@ in
wrappedNeovim = pkgs.wrapNeovimUnstable config.package (neovimConfig // { wrappedNeovim = pkgs.wrapNeovimUnstable config.package (neovimConfig // {
wrapperArgs = lib.escapeShellArgs neovimConfig.wrapperArgs + " " + extraWrapperArgs; wrapperArgs = lib.escapeShellArgs neovimConfig.wrapperArgs + " " + extraWrapperArgs;
inherit (config) wrapRc;
}); });
in in {
{ finalPackage = wrappedNeovim;
output = wrappedNeovim; initContent = neovimConfig.neovimRcContent;
}; };
} }

View file

@ -1,306 +0,0 @@
{ nixos ? false, nixOnDroid ? false, homeManager ? false }:
{ pkgs, lib, config, ... }:
with lib;
let
cfg = config.programs.nixvim;
pluginWithConfigType = types.submodule {
options = {
config = mkOption {
type = types.lines;
description = "vimscript for this plugin to be placed in init.vim";
default = "";
};
optional = mkEnableOption "optional" // {
description = "Don't load by default (load with :packadd)";
};
plugin = mkOption {
type = types.package;
description = "vim plugin";
};
};
};
mapOption = types.oneOf [
types.str
(types.submodule {
options = {
silent = mkOption {
type = types.bool;
description = "Whether this mapping should be silent. Equivalent to adding <silent> to a map.";
default = false;
};
nowait = mkOption {
type = types.bool;
description = "Whether to wait for extra input on ambiguous mappings. Equivalent to adding <nowait> to a map.";
default = false;
};
script = mkOption {
type = types.bool;
description = "Equivalent to adding <script> to a map.";
default = false;
};
expr = mkOption {
type = types.bool;
description = "Means that the action is actually an expression. Equivalent to adding <expr> to a map.";
default = false;
};
unique = mkOption {
type = types.bool;
description = "Whether to fail if the map is already defined. Equivalent to adding <unique> to a map.";
default = false;
};
noremap = mkOption {
type = types.bool;
description = "Whether to use the 'noremap' variant of the command, ignoring any custom mappings on the defined action. It is highly advised to keep this on, which is the default.";
default = true;
};
action = mkOption {
type = types.str;
description = "The action to execute.";
};
description = mkOption {
type = types.nullOr types.str;
description = "A textual description of this keybind, to be shown in which-key, if you have it.";
default = null;
};
};
})
];
mapOptions = mode: mkOption {
description = "Mappings for ${mode} mode";
type = types.attrsOf mapOption;
default = { };
};
helpers = import ./plugins/helpers.nix { lib = lib; };
in
{
options = {
programs.nixvim = {
enable = mkEnableOption "enable NixVim";
package = mkOption {
type = types.nullOr types.package;
default = null;
description = "The package to use for neovim.";
};
extraPlugins = mkOption {
type = with types; listOf (either package pluginWithConfigType);
default = [ ];
description = "List of vim plugins to install.";
};
colorscheme = mkOption {
type = types.nullOr types.str;
description = "The name of the colorscheme";
default = null;
};
extraConfigLua = mkOption {
type = types.lines;
default = "";
description = "Extra contents for init.lua";
};
extraLuaPreConfig = mkOption {
type = types.lines;
default = "";
description = "Extra contents for init.lua before everything else";
};
extraLuaPostConfig = mkOption {
type = types.lines;
default = "";
description = "Extra contents for init.lua after everything else";
};
extraConfigVim = mkOption {
type = types.lines;
default = "";
description = "Extra contents for init.vim";
};
extraPackages = mkOption {
type = types.listOf types.package;
default = [ ];
example = "[ pkgs.shfmt ]";
description = "Extra packages to be made available to neovim";
};
configure = mkOption {
type = types.attrsOf types.anything;
default = { };
description = "Internal option";
};
options = mkOption {
type = types.attrsOf types.anything;
default = { };
description = "The configuration options, e.g. line numbers";
};
globals = mkOption {
type = types.attrsOf types.anything;
default = { };
description = "Global variables";
};
maps = mkOption {
type = types.submodule {
options = {
normal = mapOptions "normal";
insert = mapOptions "insert";
select = mapOptions "select";
visual = mapOptions "visual and select";
terminal = mapOptions "terminal";
normalVisualOp = mapOptions "normal, visual, select and operator-pending (same as plain 'map')";
visualOnly = mapOptions "visual only";
operator = mapOptions "operator-pending";
insertCommand = mapOptions "insert and command-line";
lang = mapOptions "insert, command-line and lang-arg";
command = mapOptions "command-line";
};
};
default = { };
description = ''
Custom keybindings for any mode.
For plain maps (e.g. just 'map' or 'remap') use maps.normalVisualOp.
'';
example = ''
maps = {
normalVisualOp.";" = ":"; # Same as noremap ; :
normal."<leader>m" = {
silent = true;
action = "<cmd>make<CR>";
}; # Same as nnoremap <leader>m <silent> <cmd>make<CR>
};
'';
};
};
};
imports = [
./plugins
];
config =
let
neovimConfig = pkgs.neovimUtils.makeNeovimConfig {
configure = cfg.configure;
plugins = cfg.extraPlugins;
};
extraWrapperArgs = optionalString (cfg.extraPackages != [ ])
''--prefix PATH : "${makeBinPath cfg.extraPackages}"'';
package = if (cfg.package != null) then cfg.package else pkgs.neovim;
wrappedNeovim = pkgs.wrapNeovimUnstable package (neovimConfig // {
wrapperArgs = lib.escapeShellArgs neovimConfig.wrapperArgs + " "
+ extraWrapperArgs;
});
luaGlobals = optionalString (cfg.globals != { }) ''
-- Set up globals {{{
local __nixvim_globals = ${helpers.toLuaObject cfg.globals}
for k,v in pairs(__nixvim_globals) do
vim.g[k] = v
end
-- }}}
'' + optionalString (cfg.options != { }) ''
-- Set up options {{{
local __nixvim_options = ${helpers.toLuaObject cfg.options}
for k,v in pairs(__nixvim_options) do
vim.o[k] = v
end
-- }}}
'' + optionalString (mappings != [ ]) ''
-- Set up keybinds {{{
local __nixvim_binds = ${helpers.toLuaObject mappings}
for i, map in ipairs(__nixvim_binds) do
vim.api.nvim_set_keymap(map.mode, map.key, map.action, map.config)
end
-- }}}
'';
configure = {
# Make sure that globals are set before plugins are setup.
# This is becuase you might want to define variables or global functions
# that the plugin configuration depend upon.
customRC = cfg.extraConfigVim + ''
lua <<EOF
${cfg.extraLuaPreConfig}
${luaGlobals}
${cfg.extraConfigLua}
'' +
# Set colorscheme after setting globals.
# Some colorschemes depends on variables being set before setting the colorscheme.
(optionalString (cfg.colorscheme != "" && cfg.colorscheme != null) ''
vim.cmd([[colorscheme ${cfg.colorscheme}]])
'') +
''
${cfg.extraLuaPostConfig}
EOF
'';
packages.nixvim = {
start = filter (f: f != null) (map
(x:
if x ? plugin && x.optional == true then null else (x.plugin or x))
cfg.extraPlugins);
opt = filter (f: f != null)
(map (x: if x ? plugin && x.optional == true then x.plugin else null)
cfg.extraPlugins);
};
};
mappings =
(helpers.genMaps "" cfg.maps.normalVisualOp) ++
(helpers.genMaps "n" cfg.maps.normal) ++
(helpers.genMaps "i" cfg.maps.insert) ++
(helpers.genMaps "v" cfg.maps.visual) ++
(helpers.genMaps "x" cfg.maps.visualOnly) ++
(helpers.genMaps "s" cfg.maps.select) ++
(helpers.genMaps "t" cfg.maps.terminal) ++
(helpers.genMaps "o" cfg.maps.operator) ++
(helpers.genMaps "l" cfg.maps.lang) ++
(helpers.genMaps "!" cfg.maps.insertCommand) ++
(helpers.genMaps "c" cfg.maps.command);
in
mkIf cfg.enable (if nixos then {
environment.systemPackages = [ wrappedNeovim ];
programs.neovim = {
configure = configure;
};
environment.etc."xdg/nvim/sysinit.vim".text = neovimConfig.neovimRcContent;
} else
(if homeManager then {
programs.neovim = {
enable = true;
package = mkIf (cfg.package != null) cfg.package;
extraPackages = cfg.extraPackages;
extraConfig = configure.customRC;
plugins = cfg.extraPlugins;
};
} else { }));
}

View file

@ -0,0 +1,36 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.plugins.copilot;
in
{
options = {
plugins.copilot = {
enable = mkEnableOption "Enable copilot";
filetypes = mkOption {
type = types.attrsOf types.bool;
description = "A dictionary mapping file types to their enabled status";
default = { };
example = literalExpression ''{
"*": false,
python: true
}'';
};
proxy = mkOption {
type = types.nullOr types.str;
description = "Tell Copilot what proxy server to use.";
default = null;
example = "localhost:3128";
};
};
};
config =
mkIf cfg.enable {
extraPlugins = [ pkgs.vimPlugins.copilot-vim ];
globals = {
copilot_node_command = "${pkgs.nodejs-16_x}/bin/node";
copilot_filetypes = cfg.filetypes;
} // (if cfg.proxy != null then { copilot_proxy = cfg.proxy; } else { });
};
}

View file

@ -11,6 +11,7 @@
./colorschemes/tokyonight.nix ./colorschemes/tokyonight.nix
./completion/coq.nix ./completion/coq.nix
./completion/copilot.nix
./completion/nvim-cmp ./completion/nvim-cmp
./completion/nvim-cmp/sources ./completion/nvim-cmp/sources

View file

@ -20,13 +20,16 @@ let
}); });
default = null; default = null;
}; };
component_options = mode: component_options = defaultName:
mkOption { mkOption {
type = types.nullOr (types.submodule { type = types.nullOr (types.listOf (types.oneOf [
types.str
(types.submodule {
options = { options = {
mode = mkOption { name = mkOption {
type = types.str; type = types.str;
default = "${mode}"; description = "component name";
default = defaultName;
}; };
icons_enabled = mkOption { icons_enabled = mkOption {
type = types.enum [ "True" "False" ]; type = types.enum [ "True" "False" ];
@ -39,8 +42,14 @@ let
description = "displays icon in front of the component"; description = "displays icon in front of the component";
}; };
separator = separators; separator = separators;
extraConfig = mkOption {
type = types.attrs;
default = { };
description = "extra options for the component";
}; };
}); };
})
]));
default = null; default = null;
}; };
in in
@ -112,6 +121,14 @@ in
}; };
config = config =
let let
processComponent = x: (if isAttrs x then processTableComponent else id) x;
processTableComponent = { name, icons_enabled, icon, separator, extraConfig }: mergeAttrs
{
"@" = name;
inherit icons_enabled icon separator;
}
extraConfig;
processSections = sections: mapAttrs (_: mapNullable (map processComponent)) sections;
setupOptions = { setupOptions = {
options = { options = {
theme = cfg.theme; theme = cfg.theme;
@ -121,8 +138,8 @@ in
always_divide_middle = cfg.alwaysDivideMiddle; always_divide_middle = cfg.alwaysDivideMiddle;
}; };
sections = cfg.sections; sections = mapNullable processSections cfg.sections;
tabline = cfg.tabline; tabline = mapNullable processSections cfg.tabline;
extensions = cfg.extensions; extensions = cfg.extensions;
}; };
in in

59
tests/flake.lock generated
View file

@ -30,6 +30,21 @@
"type": "github" "type": "github"
} }
}, },
"flake-utils_3": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1663491030, "lastModified": 1663491030,
@ -82,12 +97,31 @@
}, },
"locked": { "locked": {
"lastModified": 0, "lastModified": 0,
"narHash": "sha256-NTQaGxll4rko4eOOxtCODb2mnkwVMNyJNqwsRCc89h4=", "narHash": "sha256-51K3gjUQAgBuXJMUCxloBqJeRiB5nwix0kMSbffDxak=",
"path": "/nix/store/a1ngrmrp1wbv12682s0c2dp60b7gljm8-source", "path": "/nix/store/y78h7ccdy3jdy4mwyw8dyg3prhwqx61f-source",
"type": "path" "type": "path"
}, },
"original": { "original": {
"path": "/nix/store/a1ngrmrp1wbv12682s0c2dp60b7gljm8-source", "path": "/nix/store/y78h7ccdy3jdy4mwyw8dyg3prhwqx61f-source",
"type": "path"
}
},
"nixvim-stable": {
"inputs": {
"flake-utils": "flake-utils_3",
"nixpkgs": [
"nixpkgs-stable"
],
"nmdSrc": "nmdSrc_2"
},
"locked": {
"lastModified": 0,
"narHash": "sha256-51K3gjUQAgBuXJMUCxloBqJeRiB5nwix0kMSbffDxak=",
"path": "/nix/store/y78h7ccdy3jdy4mwyw8dyg3prhwqx61f-source",
"type": "path"
},
"original": {
"path": "/nix/store/y78h7ccdy3jdy4mwyw8dyg3prhwqx61f-source",
"type": "path" "type": "path"
} }
}, },
@ -107,12 +141,29 @@
"type": "gitlab" "type": "gitlab"
} }
}, },
"nmdSrc_2": {
"flake": false,
"locked": {
"lastModified": 1654807200,
"narHash": "sha256-RNLq09vfj21TyYuUCeD6BNTNC6Ew8bLhQULZytN4Xx8=",
"owner": "rycee",
"repo": "nmd",
"rev": "91dee681dd1c478d6040a00835d73c0f4a4c5c29",
"type": "gitlab"
},
"original": {
"owner": "rycee",
"repo": "nmd",
"type": "gitlab"
}
},
"root": { "root": {
"inputs": { "inputs": {
"flake-utils": "flake-utils", "flake-utils": "flake-utils",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"nixpkgs-stable": "nixpkgs-stable", "nixpkgs-stable": "nixpkgs-stable",
"nixvim": "nixvim" "nixvim": "nixvim",
"nixvim-stable": "nixvim-stable"
} }
} }
}, },

View file

@ -5,15 +5,19 @@
inputs.nixvim.url = "./.."; inputs.nixvim.url = "./..";
inputs.nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-22.05"; inputs.nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-22.05";
inputs.nixvim-stable = {
url = "./..";
inputs.nixpkgs.follows = "nixpkgs-stable";
};
outputs = { self, nixvim, nixpkgs, flake-utils, nixpkgs-stable, ... }: outputs = { self, nixvim, nixvim-stable, nixpkgs, flake-utils, nixpkgs-stable, ... }:
(flake-utils.lib.eachDefaultSystem (flake-utils.lib.eachDefaultSystem
(system: (system:
let let
pkgs = import nixpkgs { inherit system; }; pkgs = import nixpkgs { inherit system; };
pkgs-stable = import nixpkgs-stable { inherit system; }; pkgs-stable = import nixpkgs-stable { inherit system; };
build = nixvim.build pkgs; build = nixvim.legacyPackages.${system}.makeNixvim;
build-stable = nixvim.build pkgs-stable; build-stable = nixvim-stable.legacyPackages.${system}.makeNixvim;
in in
rec { rec {
# A plain nixvim configuration # A plain nixvim configuration

23
wrappers/hm.nix Normal file
View file

@ -0,0 +1,23 @@
modules:
{ pkgs, config, lib, ... }:
let
inherit (lib) mkEnableOption mkOption mkIf mkMerge types;
cfg = config.programs.nixvim;
in {
options = {
programs.nixvim = lib.mkOption {
type = types.submodule ((modules pkgs) ++ [{
options.enable = mkEnableOption "nixvim";
}]);
};
};
config = mkIf cfg.enable
(mkMerge [
{ home.packages = [ cfg.finalPackage ]; }
(mkIf (!cfg.wrapRc) {
xdg.configFile."nvim/init.vim".text = cfg.initContent;
})
]);
}

24
wrappers/nixos.nix Normal file
View file

@ -0,0 +1,24 @@
modules:
{ pkgs, config, lib, ... }:
let
inherit (lib) mkEnableOption mkOption mkMerge mkIf types;
cfg = config.programs.nixvim;
in {
options = {
programs.nixvim = lib.mkOption {
type = types.submodule ((modules pkgs) ++ [{
options.enable = mkEnableOption "nixvim";
}]);
};
};
config = mkIf cfg.enable
(mkMerge [
{ environment.systemPackages = [ cfg.finalPackage ]; }
(mkIf (!cfg.wrapRc) {
environment.etc."nvim/sysinit.vim".text = cfg.initContent;
environment.variables."VIM" = "/etc/nvim";
})
]);
}

13
wrappers/standalone.nix Normal file
View file

@ -0,0 +1,13 @@
pkgs: modules: configuration:
let
inherit (pkgs) lib;
wrap = { wrapRc = true; };
eval = lib.evalModules {
modules = modules ++ [ { config = configuration; } wrap ];
};
in eval.config.finalPackage