initial commit

This commit is contained in:
Dmitriy Pleshevskiy 2024-04-26 02:08:23 +03:00
commit 13177e2c36
Signed by: pleshevskiy
GPG key ID: 17041163DA10A9A2
11 changed files with 554 additions and 0 deletions

11
.gitignore vendored Normal file
View file

@ -0,0 +1,11 @@
# editors
.idea/
.vscode/
*.swp
# direnv
.direnv
.envrc
# nix
/result
# custom
test-cfg

31
default.nix Normal file
View file

@ -0,0 +1,31 @@
{ config ? { }
, pkgs ? import <nixpkgs> { }
, nix2lua ? import <nix2lua>
}:
let
inherit (pkgs.lib) evalModules filter concatMapStringsSep showWarnings;
allModules = import ./module-list.nix { inherit pkgs; };
rawModule = evalModules {
modules = [ config ] ++ allModules;
specialArgs = {
inherit pkgs;
nix2lua = nix2lua.lib;
};
};
failedAssertions = map (x: x.message) (filter (x: !x.assertion) rawModule.config.assertions);
module =
if failedAssertions != [ ]
then throw "\nFailed assertions:\n${concatMapStringsSep "\n" (x: "- ${x}") failedAssertions}"
else showWarnings rawModule.config.warnings rawModule;
in
{
inherit (module.config.build) neovim;
inherit (module) config options;
inherit pkgs;
}

18
module-list.nix Normal file
View file

@ -0,0 +1,18 @@
{ pkgs }:
[
./modules/build/neovim.nix
./modules/vim/opts.nix
./modules/vim/keymap.nix
./modules/filetype.nix
./modules/input.nix
./modules/plugin.nix
./modules/plugins/theme/catppuccin.nix
./modules/plugins/navigation/telescope.nix
##################################################
(pkgs.path + "/nixos/modules/misc/assertions.nix")
]

70
modules/build/neovim.nix Normal file
View file

@ -0,0 +1,70 @@
{ config, lib, pkgs, nix2lua, ... }:
let
inherit (builtins) filter attrValues;
cfg = config.build.neovim;
in
{
options.build.neovim = with lib; with types; {
luaConfig = mkOption {
type = lines;
readOnly = true;
internal = true;
description = ''
Neovim editor lua configuration.
'';
};
plugins = mkOption {
type = listOf package;
readOnly = true;
internal = true;
};
package = mkOption {
type = types.package;
readOnly = true;
internal = true;
description = ''
Neovim editor derivation with plugins and configurations.
'';
};
};
config.build.neovim = {
luaConfig = with nix2lua; toLua (spaceBetween (lib.flatten [
# Global Opts
(lib.flip lib.mapAttrsToList config.vim.g (k: set "vim.g.${k}"))
# Opts
(lib.flip lib.mapAttrsToList config.vim.opt (k: set "vim.opt.${k}"))
# Keymaps
(lib.flip map config.vim.keymap.set ({ mode, lhs, rhs, ... } @ vars:
call "vim.keymap.set" [ mode lhs rhs (removeAttrs vars [ "mode" "lhs" "rhs" ]) ]
))
# Plugins
(map (v: v.genConfig) (filter (v: !v.isDependency) (attrValues config.plugin)))
# Cmd
(lib.optional (config.vim.cmd != "") (call "vim.cmd" config.vim.cmd))
]));
plugins = lib.mapAttrsToList (k: v: v.package) config.plugin;
package = pkgs.wrapNeovim pkgs.neovim-unwrapped {
viAlias = false;
vimAlias = false;
withPython3 = false;
withNodeJs = false;
withRuby = false;
configure = {
customRC = ''
lua << EOF
${cfg.luaConfig}
EOF
'';
packages.myVimPackages = { start = cfg.plugins; };
};
};
};
}

67
modules/filetype.nix Normal file
View file

@ -0,0 +1,67 @@
{ config, lib, ... }:
let cfg = config.filetype; in
{
options.filetype = with lib; with types; {
enable = mkOption {
type = bool;
default = true;
description = ''
Vim can detect the type of file that is edited. This is done by checking the
file name and sometimes by inspecting the contents of the file for specific
text.
`:help filetypes`
`:help filetype-off`
`:help filetype-overview`
'';
};
plugin = mkOption {
type = bool;
default = true;
description = ''
Enable loading the plugin files for specific file types
`:help :filetype-plugin-on`
`:help :filetype-plugin-off`
'';
};
indent = mkOption {
type = bool;
default = true;
description = ''
Enable loading the indent file for specific file types
`:help :filetype-indent-on`
`:help :filetype-indent-off`
'';
};
ignore = mkOption {
type = uniq (listOf str);
default = [ "Z" "gz" "bz2" "zip" "tgz" ];
description = ''
To avoid that certain files are being inspected, the g:ft_ignore_pat variable
is used. The default value is set like this:
`:help filetype-ignore`
'';
};
extraIgnore = mkOption {
type = uniq (listOf str);
default = [ ];
};
};
config = {
vim.namedCmd.filetype = lib.concatLines
(lib.flip lib.mapAttrsToList { inherit (cfg) enable plugin indent; }
(k: v: ''filetype ${if k == "enable" then "" else k} ${if v then "on" else "off"}'')
);
vim.g.ft_ignore_pat = "\\\\.(${lib.concatStringsSep "|" (cfg.ignore ++ cfg.extraIgnore)})$";
};
}

34
modules/input.nix Normal file
View file

@ -0,0 +1,34 @@
{ config, lib, ... }:
let
cfg = config.input;
disableKeymaps = mode: lhss: lib.flip map lhss (lhs: { inherit mode lhs; rhs = "<nop>"; });
in
{
options.input = with lib; with types; {
exMode.enable = (mkEnableOption "Ex mode") // { default = true; };
arrowKeys = {
disableInMode = mkOption {
type = oneOf [ str (uniq (listOf str)) ];
default = [ "n" "v" ];
};
};
pageButtons = {
disableInMode = mkOption {
type = oneOf [ str (uniq (listOf str)) ];
default = [ "n" "v" "i" ];
};
};
};
config.vim.keymap.set =
# Disable the annoying and useless ex-mode
lib.optionals (!cfg.exMode.enable) (disableKeymaps "n" [ "Q" "gQ" ])
# Disable arrow keys
++ lib.optionals (cfg.arrowKeys.disableInMode != [ ])
(disableKeymaps cfg.arrowKeys.disableInMode [ "<Up>" "<Down>" "<Left>" "<Right>" ])
# Disable PageUp / PageDown
++ lib.optionals (cfg.pageButtons.disableInMode != [ ])
(disableKeymaps cfg.pageButtons.disableInMode [ "<PageUp>" "<PageDown>" ]);
}

80
modules/plugin.nix Normal file
View file

@ -0,0 +1,80 @@
{ lib, pkgs, nix2lua, ... }:
let
pluginOpts = ({ name, config, ... }: {
options = with lib; with types; {
name = mkOption {
type = str;
};
varName = mkOption {
type = str;
# TODO: add validation
};
package = mkPackageOption pkgs.vimPlugins name { };
isDependency = mkOption {
type = bool;
default = false;
};
beforeSetup = mkOption {
type = listOf attrs;
default = [ ];
};
setupFnName = mkOption {
type = str;
default = "setup";
};
setupSettings = mkOption {
type = nullOr attrs;
default = null;
};
afterSetup = mkOption {
type = listOf attrs;
default = [ ];
};
extra = mkOption {
type = listOf attrs;
default = [ ];
};
genConfig = mkOption {
type = listOf attrs;
readOnly = true;
internal = true;
};
luaConfig = mkOption {
type = str;
readOnly = true;
internal = true;
};
};
config = {
name = lib.mkDefault name;
varName = lib.mkDefault (builtins.replaceStrings [ "-" "/" ] [ "_" "_" ] config.name);
genConfig = with nix2lua; lib.mkIf (!config.isDependency) (lib.flatten [
(local (set config.varName (require config.name)))
config.beforeSetup
(lib.optional (config.setupSettings != null)
(pipe1 (var config.varName) (call config.setupFnName config.setupSettings))
)
config.afterSetup
config.extra
]);
luaConfig = with nix2lua; toLua (spaceBetween config.genConfig);
};
});
in
{
options.plugin = with lib; with types; mkOption {
type = attrsOf (submodule pluginOpts);
default = { };
};
}

View file

@ -0,0 +1,35 @@
{ config, lib, pkgs, ... }:
let cfg = config.plugins.navigation.telescope; in
{
options.plugins.navigation.telescope = with lib; {
enable = mkEnableOption "telescope";
package = mkPackageOption pkgs.vimPlugins "telescope-nvim" { };
settings = mkOption {
type = types.attrs;
default = { };
description = ''
See: https://github.com/nvim-telescope/telescope.nvim?tab=readme-ov-file#customization
'';
example = {
pickers = {
find_files = {
theme = "dropdown";
};
};
};
};
};
config = lib.mkIf cfg.enable {
plugin.plenary-nvim = lib.mkDefault { isDependency = true; };
plugin.telescope-nvim = {
name = "telescope";
package = cfg.package;
setupSettings = cfg.settings;
};
};
}

View file

@ -0,0 +1,34 @@
{ config, lib, pkgs, ... }:
let cfg = config.plugins.theme.catppuccin; in
{
options.plugins.theme.catppuccin = with lib; {
enable = mkEnableOption "catppuccin";
package = mkPackageOption pkgs.vimPlugins "catppuccin-nvim" { };
settings = mkOption {
type = types.attrs;
default = { };
description = ''
See: https://github.com/catppuccin/nvim/?tab=readme-ov-file#configuration
'';
example = {
flavour = "frappe";
};
};
};
config = lib.mkIf cfg.enable {
plugin.catppuccin-nvim = {
name = "catppuccin";
package = cfg.package;
setupSettings = cfg.settings;
};
vim.namedCmd.colorscheme = ''
colorscheme catppuccin
'';
};
}

141
modules/vim/keymap.nix Normal file
View file

@ -0,0 +1,141 @@
{ lib, ... }:
let
modeType = lib.types.enum [ "" "n" "!" "i" "c" "v" "x" "s" "o" "t" "l" ];
# TODO: maybe add more options and add descriptions from
# :help vim.keymap.set
# :help nvim_set_keymap
setKeymapType = with lib; with types; submodule {
options = {
lhs = mkOption {
type = str;
description = ''
Left-hand side |{lhs}| of the mapping.
'';
};
rhs = mkOption {
type = oneOf [ str attrs ];
description = ''
Right-hand side |{rhs}| of the mapping, can be a Lua function.
'';
};
mode = mkOption {
type = oneOf [
modeType
(uniq (listOf modeType))
];
default = "";
description = ''
Mode | Norm | Ins | Cmd | Vis | Sel | Opr | Term | Lang |
Command +------+-----+-----+-----+-----+-----+------+------+
"" | yes | - | - | yes | yes | yes | - | - |
"n" | yes | - | - | - | - | - | - | - |
"!" | - | yes | yes | - | - | - | - | - |
"i" | - | yes | - | - | - | - | - | - |
"c" | - | - | yes | - | - | - | - | - |
"v" | - | - | - | yes | yes | - | - | - |
"x" | - | - | - | yes | - | - | - | - |
"s" | - | - | - | - | yes | - | - | - |
"o" | - | - | - | - | - | yes | - | - |
"t" | - | - | - | - | - | - | yes | - |
"l" | - | yes | yes | - | - | - | - | yes |
`:help map-overview`
'';
};
buffer = mkOption {
type = nullOr str;
default = null;
description = ''
The mapping will be effective in the current buffer only.
`:help :map-buffer`
'';
};
nowait = mkOption {
type = bool;
default = false;
description = ''
When defining a buffer-local mapping for "," there may be a global mapping
that starts with ",". Then you need to type another character for Vim to know
whether to use the "," mapping or the longer one. To avoid this add the
<nowait> argument. Then the mapping will be used when it matches, Vim does
not wait for more characters to be typed.
`:help :map-nowait`
'';
};
silent = mkOption {
type = bool;
default = false;
description = ''
To define a mapping which will not be echoed on the command line.
`:help :map-silent`
'';
};
script = mkOption {
type = bool;
default = false;
description = ''
If the first argument to one of these commands is "<script>" and it is used to
define a new mapping or abbreviation, the mapping will only remap characters
in the {rhs} using mappings that were defined local to a script, starting with
"<SID>". This can be used to avoid that mappings from outside a script
interfere (e.g., when CTRL-V is remapped in mswin.vim), but do use other
mappings defined in the script.
`:help :map-script`
'';
};
expr = mkOption {
type = bool;
default = false;
description = ''
If the first argument to one of these commands is "<expr>" and it is used to
define a new mapping or abbreviation, the argument is an expression. The
expression is evaluated to obtain the {rhs} that is used.
`:help :map-expression`
'';
};
unique = mkOption {
type = bool;
default = false;
description = ''
It is used to define a new mapping or abbreviation, the command will fail if
the mapping or abbreviation already exists.
When defining a local mapping, there will also be a check if a global map
already exists which is equal.
`:help :map-unique`
'';
};
remap = mkOption {
type = bool;
default = false;
description = ''
Make the mapping recursive.
'';
};
desc = mkOption {
type = nullOr str;
default = null;
description = ''
Human-readable description.
'';
};
};
};
in
{
options.vim.keymap = with lib; with types; {
set = mkOption {
type = listOf setKeymapType;
default = [ ];
};
};
}

33
modules/vim/opts.nix Normal file
View file

@ -0,0 +1,33 @@
{ config, lib, ... }:
{
options.vim = with lib; with types; {
g = mkOption {
type = attrsOf (oneOf [ str bool number ]);
};
opt = mkOption {
type = attrsOf anything;
description = ''
A special interface |vim.opt| exists for conveniently interacting with list-
and map-style option from Lua: It allows accessing them as Lua tables and
offers object-oriented method for adding and removing entries.
`:help vim.opt`
'';
};
# TODO: think more about vim.cmd
namedCmd = mkOption {
type = attrsOf str;
default = { };
};
cmd = mkOption {
type = str;
readOnly = true;
};
};
config = {
vim.cmd = lib.concatLines (lib.flip lib.mapAttrsToList config.vim.namedCmd (k: v: "\" ${k}\n${v}"));
};
}