dev: rebase on a less personalized neovim flake

This commit is contained in:
NotAShelf 2023-02-01 22:11:37 +03:00
commit 9c00808863
No known key found for this signature in database
GPG key ID: 5B5C8895F28445F1
70 changed files with 4910 additions and 0 deletions

View file

@ -0,0 +1,43 @@
{
pkgs,
lib,
config,
...
}:
with lib;
with builtins; let
cfg = config.vim.autopairs;
in {
options.vim = {
autopairs = {
enable = mkOption {
type = types.bool;
default = false;
description = "enable autopairs";
};
type = mkOption {
type = types.enum ["nvim-autopairs"];
default = "nvim-autopairs";
description = "Set the autopairs type. Options: nvim-autopairs [nvim-autopairs]";
};
};
};
config =
mkIf cfg.enable
{
vim.startPlugins = ["nvim-autopairs"];
vim.luaConfigRC.autopairs = nvim.dag.entryAnywhere ''
require("nvim-autopairs").setup{}
${optionalString (config.vim.autocomplete.type == "nvim-compe") ''
require('nvim-autopairs.completion.compe').setup({
map_cr = true,
map_complete = true,
auto_select = false,
})
''}
'';
};
}

225
modules/basic/default.nix Normal file
View file

@ -0,0 +1,225 @@
{
pkgs,
lib,
config,
...
}:
with lib;
with builtins; let
cfg = config.vim;
in {
options.vim = {
colourTerm = mkOption {
type = types.bool;
default = true;
description = "Set terminal up for 256 colours";
};
disableArrows = mkOption {
type = types.bool;
default = false;
description = "Set to prevent arrow keys from moving cursor";
};
hideSearchHighlight = mkOption {
type = types.bool;
default = false;
description = "Hide search highlight so it doesn't stay highlighted";
};
scrollOffset = mkOption {
type = types.int;
default = 8;
description = "Start scrolling this number of lines from the top or bottom of the page.";
};
wordWrap = mkOption {
type = types.bool;
default = true;
description = "Enable word wrapping.";
};
syntaxHighlighting = mkOption {
type = types.bool;
default = true;
description = "Enable syntax highlighting";
};
mapLeaderSpace = mkOption {
type = types.bool;
default = true;
description = "Map the space key to leader key";
};
useSystemClipboard = mkOption {
type = types.bool;
default = true;
description = "Make use of the clipboard for default yank and paste operations. Don't use * and +";
};
mouseSupport = mkOption {
type = with types; enum ["a" "n" "v" "i" "c"];
default = "a";
description = "Set modes for mouse support. a - all, n - normal, v - visual, i - insert, c - command";
};
lineNumberMode = mkOption {
type = with types; enum ["relative" "number" "relNumber" "none"];
default = "relNumber";
description = "How line numbers are displayed. none, relative, number, relNumber";
};
preventJunkFiles = mkOption {
type = types.bool;
default = false;
description = "Prevent swapfile, backupfile from being created";
};
tabWidth = mkOption {
type = types.int;
default = 4;
description = "Set the width of tabs";
};
autoIndent = mkOption {
type = types.bool;
default = true;
description = "Enable auto indent";
};
cmdHeight = mkOption {
type = types.int;
default = 1;
description = "Height of the command pane";
};
updateTime = mkOption {
type = types.int;
default = 300;
description = "The number of milliseconds till Cursor Hold event is fired";
};
showSignColumn = mkOption {
type = types.bool;
default = true;
description = "Show the sign column";
};
bell = mkOption {
type = types.enum ["none" "visual" "on"];
default = "none";
description = "Set how bells are handled. Options: on, visual or none";
};
mapTimeout = mkOption {
type = types.int;
default = 500;
description = "Timeout in ms that neovim will wait for mapped action to complete";
};
splitBelow = mkOption {
type = types.bool;
default = true;
description = "New splits will open below instead of on top";
};
splitRight = mkOption {
type = types.bool;
default = true;
description = "New splits will open to the right";
};
};
config = {
vim.startPlugins = ["plenary-nvim"];
vim.nmap = mkIf cfg.disableArrows {
"<up>" = "<nop>";
"<down>" = "<nop>";
"<left>" = "<nop>";
"<right>" = "<nop>";
};
vim.imap = mkIf cfg.disableArrows {
"<up>" = "<nop>";
"<down>" = "<nop>";
"<left>" = "<nop>";
"<right>" = "<nop>";
};
vim.nnoremap = mkIf cfg.mapLeaderSpace {"<space>" = "<nop>";};
vim.configRC.basic = nvim.dag.entryAfter ["globalsScript"] ''
" Settings that are set for everything
set encoding=utf-8
set mouse=${cfg.mouseSupport}
set tabstop=${toString cfg.tabWidth}
set shiftwidth=${toString cfg.tabWidth}
set softtabstop=${toString cfg.tabWidth}
set expandtab
set cmdheight=${toString cfg.cmdHeight}
set updatetime=${toString cfg.updateTime}
set shortmess+=c
set tm=${toString cfg.mapTimeout}
set hidden
${optionalString cfg.splitBelow ''
set splitbelow
''}
${optionalString cfg.splitRight ''
set splitright
''}
${optionalString cfg.showSignColumn ''
set signcolumn=yes
''}
${optionalString cfg.autoIndent ''
set autoindent
''}
${optionalString cfg.preventJunkFiles ''
set noswapfile
set nobackup
set nowritebackup
''}
${optionalString (cfg.bell == "none") ''
set noerrorbells
set novisualbell
''}
${optionalString (cfg.bell == "on") ''
set novisualbell
''}
${optionalString (cfg.bell == "visual") ''
set noerrorbells
''}
${optionalString (cfg.lineNumberMode == "relative") ''
set relativenumber
''}
${optionalString (cfg.lineNumberMode == "number") ''
set number
''}
${optionalString (cfg.lineNumberMode == "relNumber") ''
set number relativenumber
''}
${optionalString cfg.useSystemClipboard ''
set clipboard+=unnamedplus
''}
${optionalString cfg.mapLeaderSpace ''
let mapleader=" "
let maplocalleader=" "
''}
${optionalString cfg.syntaxHighlighting ''
syntax on
''}
${optionalString (!cfg.wordWrap) ''
set nowrap
''}
${optionalString cfg.hideSearchHighlight ''
set nohlsearch
set incsearch
''}
${optionalString cfg.colourTerm ''
set termguicolors
set t_Co=256
''}
'';
};
}

View file

@ -0,0 +1,126 @@
{
pkgs,
lib,
config,
...
}:
with lib;
with builtins; let
cfg = config.vim.autocomplete;
in {
options.vim = {
autocomplete = {
enable = mkOption {
type = types.bool;
default = false;
description = "enable autocomplete";
};
type = mkOption {
type = types.enum ["nvim-cmp"];
default = "nvim-cmp";
description = "Set the autocomplete plugin. Options: [nvim-cmp]";
};
};
};
config = mkIf cfg.enable {
vim.startPlugins = [
"nvim-cmp"
"cmp-buffer"
"cmp-vsnip"
"cmp-path"
"cmp-treesitter"
];
vim.luaConfigRC.completion = mkIf (cfg.type == "nvim-cmp") (nvim.dag.entryAnywhere ''
local has_words_before = function()
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
end
local feedkey = function(key, mode)
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), mode, true)
end
local cmp = require'cmp'
cmp.setup({
snippet = {
expand = function(args)
vim.fn["vsnip#anonymous"](args.body)
end,
},
sources = {
${optionalString (config.vim.lsp.enable) "{ name = 'nvim_lsp' },"}
${optionalString (config.vim.lsp.rust.enable) "{ name = 'crates' },"}
{ name = 'vsnip' },
{ name = 'treesitter' },
{ name = 'path' },
{ name = 'buffer' },
},
mapping = {
['<C-d>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }),
['<C-f>'] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c'}),
['<C-Space>'] = cmp.mapping(cmp.mapping.complete(), { 'i', 'c'}),
['<C-y>'] = cmp.config.disable,
['<C-e>'] = cmp.mapping({
i = cmp.mapping.abort(),
c = cmp.mapping.close(),
}),
['<CR>'] = cmp.mapping.confirm({
select = true,
}),
['<Tab>'] = cmp.mapping(function (fallback)
if cmp.visible() then
cmp.select_next_item()
elseif vim.fn['vsnip#available'](1) == 1 then
feedkey("<Plug>(vsnip-expand-or-jump)", "")
elseif has_words_before() then
cmp.complete()
else
fallback()
end
end, { 'i', 's' }),
['<S-Tab>'] = cmp.mapping(function (fallback)
if cmp.visible() then
cmp.select_prev_item()
elseif vim.fn['vsnip#available'](-1) == 1 then
feedkeys("<Plug>(vsnip-jump-prev)", "")
end
end, { 'i', 's' })
},
completion = {
completeopt = 'menu,menuone,noinsert',
},
formatting = {
format = function(entry, vim_item)
-- type of kind
vim_item.kind = ${
optionalString (config.vim.visuals.lspkind.enable)
"require('lspkind').presets.default[vim_item.kind] .. ' ' .."
} vim_item.kind
-- name for each source
vim_item.menu = ({
buffer = "[Buffer]",
nvim_lsp = "[LSP]",
vsnip = "[VSnip]",
crates = "[Crates]",
path = "[Path]",
})[entry.source.name]
return vim_item
end,
}
})
${optionalString (config.vim.autopairs.enable && config.vim.autopairs.type == "nvim-autopairs") ''
local cmp_autopairs = require('nvim-autopairs.completion.cmp')
cmp.event:on('confirm_done', cmp_autopairs.on_confirm_done({ map_char = { text = ""} }))
''}
'');
vim.snippets.vsnip.enable =
if (cfg.type == "nvim-cmp")
then true
else config.vim.snippets.vsnip.enable;
};
}

225
modules/core/default.nix Normal file
View file

@ -0,0 +1,225 @@
{
config,
lib,
pkgs,
...
}:
with lib;
with builtins; let
cfg = config.vim;
wrapLuaConfig = luaConfig: ''
lua << EOF
${luaConfig}
EOF
'';
mkMappingOption = it:
mkOption ({
default = {};
type = with types; attrsOf (nullOr str);
}
// it);
in {
options.vim = {
viAlias = mkOption {
description = "Enable vi alias";
type = types.bool;
default = true;
};
vimAlias = mkOption {
description = "Enable vim alias";
type = types.bool;
default = true;
};
configRC = mkOption {
description = "vimrc contents";
type = nvim.types.dagOf types.lines;
default = {};
};
luaConfigRC = mkOption {
description = "vim lua config";
type = nvim.types.dagOf types.lines;
default = {};
};
builtConfigRC = mkOption {
internal = true;
type = types.lines;
description = "The built config for neovim after resolving the DAG";
};
startPlugins = nvim.types.pluginsOpt {
default = [];
description = "List of plugins to startup.";
};
optPlugins = nvim.types.pluginsOpt {
default = [];
description = "List of plugins to optionally load";
};
globals = mkOption {
default = {};
description = "Set containing global variable values";
type = types.attrs;
};
nnoremap =
mkMappingOption {description = "Defines 'Normal mode' mappings";};
inoremap = mkMappingOption {
description = "Defines 'Insert and Replace mode' mappings";
};
vnoremap = mkMappingOption {
description = "Defines 'Visual and Select mode' mappings";
};
xnoremap =
mkMappingOption {description = "Defines 'Visual mode' mappings";};
snoremap =
mkMappingOption {description = "Defines 'Select mode' mappings";};
cnoremap =
mkMappingOption {description = "Defines 'Command-line mode' mappings";};
onoremap = mkMappingOption {
description = "Defines 'Operator pending mode' mappings";
};
tnoremap =
mkMappingOption {description = "Defines 'Terminal mode' mappings";};
nmap = mkMappingOption {description = "Defines 'Normal mode' mappings";};
imap = mkMappingOption {
description = "Defines 'Insert and Replace mode' mappings";
};
vmap = mkMappingOption {
description = "Defines 'Visual and Select mode' mappings";
};
xmap = mkMappingOption {description = "Defines 'Visual mode' mappings";};
smap = mkMappingOption {description = "Defines 'Select mode' mappings";};
cmap =
mkMappingOption {description = "Defines 'Command-line mode' mappings";};
omap = mkMappingOption {
description = "Defines 'Operator pending mode' mappings";
};
tmap =
mkMappingOption {description = "Defines 'Terminal mode' mappings";};
};
config = let
mkVimBool = val:
if val
then "1"
else "0";
valToVim = val:
if (isInt val)
then (builtins.toString val)
else
(
if (isBool val)
then (mkVimBool val)
else (toJSON val)
);
filterNonNull = mappings: filterAttrs (name: value: value != null) mappings;
globalsScript =
mapAttrsFlatten (name: value: "let g:${name}=${valToVim value}")
(filterNonNull cfg.globals);
matchCtrl = it: match "Ctrl-(.)(.*)" it;
mapKeyBinding = it: let
groups = matchCtrl it;
in
if groups == null
then it
else "<C-${toUpper (head groups)}>${head (tail groups)}";
mapVimBinding = prefix: mappings:
mapAttrsFlatten (name: value: "${prefix} ${mapKeyBinding name} ${value}")
(filterNonNull mappings);
nmap = mapVimBinding "nmap" config.vim.nmap;
imap = mapVimBinding "imap" config.vim.imap;
vmap = mapVimBinding "vmap" config.vim.vmap;
xmap = mapVimBinding "xmap" config.vim.xmap;
smap = mapVimBinding "smap" config.vim.smap;
cmap = mapVimBinding "cmap" config.vim.cmap;
omap = mapVimBinding "omap" config.vim.omap;
tmap = mapVimBinding "tmap" config.vim.tmap;
nnoremap = mapVimBinding "nnoremap" config.vim.nnoremap;
inoremap = mapVimBinding "inoremap" config.vim.inoremap;
vnoremap = mapVimBinding "vnoremap" config.vim.vnoremap;
xnoremap = mapVimBinding "xnoremap" config.vim.xnoremap;
snoremap = mapVimBinding "snoremap" config.vim.snoremap;
cnoremap = mapVimBinding "cnoremap" config.vim.cnoremap;
onoremap = mapVimBinding "onoremap" config.vim.onoremap;
tnoremap = mapVimBinding "tnoremap" config.vim.tnoremap;
resolveDag = {
name,
dag,
mapResult,
}: let
sortedDag = nvim.dag.topoSort dag;
result =
if sortedDag ? result
then mapResult sortedDag.result
else abort ("Dependency cycle in ${name}: " + toJSON sortedConfig);
in
result;
in {
vim = {
configRC = {
globalsScript = nvim.dag.entryAnywhere (concatStringsSep "\n" globalsScript);
luaScript = let
mkSection = r: ''
-- SECTION: ${r.name}
${r.data}
'';
mapResult = r: (wrapLuaConfig (concatStringsSep "\n" (map mkSection r)));
luaConfig = resolveDag {
name = "lua config script";
dag = cfg.luaConfigRC;
inherit mapResult;
};
in
nvim.dag.entryAfter ["globalsScript"] luaConfig;
mappings = let
maps = [nmap imap vmap xmap smap cmap omap tmap nnoremap inoremap vnoremap xnoremap snoremap cnoremap onoremap tnoremap];
mapConfig = concatStringsSep "\n" (map (v: concatStringsSep "\n" v) maps);
in
nvim.dag.entryAfter ["globalsScript"] mapConfig;
};
builtConfigRC = let
mkSection = r: ''
" SECTION: ${r.name}
${r.data}
'';
mapResult = r: (concatStringsSep "\n" (map mkSection r));
vimConfig = resolveDag {
name = "vim config script";
dag = cfg.configRC;
inherit mapResult;
};
in
vimConfig;
};
};
}

72
modules/default.nix Normal file
View file

@ -0,0 +1,72 @@
{inputs}: {
configuration,
pkgs,
lib ? pkgs.lib,
check ? true,
extraSpecialArgs ? {},
}: let
inherit (pkgs) neovim-unwrapped wrapNeovim vimPlugins;
inherit (builtins) map filter isString toString getAttr hasAttr attrNames;
inherit (pkgs.vimUtils) buildVimPluginFrom2Nix;
extendedLib = import ./lib/stdlib-extended.nix lib;
nvimModules = import ./modules.nix {
inherit check pkgs;
lib = extendedLib;
};
module = extendedLib.evalModules {
modules = [configuration] ++ nvimModules;
specialArgs =
{
modulesPath = toString ./.;
}
// extraSpecialArgs;
};
buildPlug = name:
buildVimPluginFrom2Nix rec {
pname = name;
version = "master";
src = assert lib.asserts.assertMsg (name != "nvim-treesitter") "Use buildTreesitterPlug for building nvim-treesitter.";
getAttr pname inputs;
};
buildTreesitterPlug = grammars: vimPlugins.nvim-treesitter.withPlugins (_: grammars);
vimOptions = module.config.vim;
buildConfigPlugins = plugins:
map
(plug: (
if (isString plug)
then
(
if (plug == "nvim-treesitter")
then (buildTreesitterPlug vimOptions.treesitter.grammars)
else (buildPlug plug)
)
else plug
))
(filter
(f: f != null)
plugins);
neovim = wrapNeovim neovim-unwrapped {
viAlias = vimOptions.viAlias;
vimAlias = vimOptions.vimAlias;
configure = {
customRC = vimOptions.builtConfigRC;
packages.myVimPackage = {
start = buildConfigPlugins vimOptions.startPlugins;
opt = buildConfigPlugins vimOptions.optPlugins;
};
};
};
in {
inherit (module) options config;
inherit (module._module.args) pkgs;
inherit neovim;
}

View file

@ -0,0 +1,10 @@
{
pkgs,
lib,
config,
...
}: {
imports = [
./nvimtreelua.nix
];
}

View file

@ -0,0 +1,186 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.filetree.nvimTreeLua;
in {
options.vim.filetree.nvimTreeLua = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable nvim-tree-lua";
};
treeSide = mkOption {
default = "left";
description = "Side the tree will appear on left or right";
type = types.enum ["left" "right"];
};
treeWidth = mkOption {
default = 25;
description = "Width of the tree in charecters";
type = types.int;
};
hideFiles = mkOption {
default = [".git" "node_modules" ".cache"];
description = "Files to hide in the file view by default.";
type = with types; listOf str;
};
hideIgnoredGitFiles = mkOption {
default = false;
description = "Hide files ignored by git";
type = types.bool;
};
openOnSetup = mkOption {
default = true;
description = "Open when vim is started on a directory";
type = types.bool;
};
closeOnLastWindow = mkOption {
default = true;
description = "Close when tree is last window open";
type = types.bool;
};
ignoreFileTypes = mkOption {
default = [];
description = "Ignore file types";
type = with types; listOf str;
};
closeOnFileOpen = mkOption {
default = false;
description = "Closes the tree when a file is opened.";
type = types.bool;
};
resizeOnFileOpen = mkOption {
default = false;
description = "Resizes the tree when opening a file.";
type = types.bool;
};
followBufferFile = mkOption {
default = true;
description = "Follow file that is in current buffer on tree";
type = types.bool;
};
indentMarkers = mkOption {
default = true;
description = "Show indent markers";
type = types.bool;
};
hideDotFiles = mkOption {
default = false;
description = "Hide dotfiles";
type = types.bool;
};
openTreeOnNewTab = mkOption {
default = false;
description = "Opens the tree view when opening a new tab";
type = types.bool;
};
disableNetRW = mkOption {
default = false;
description = "Disables netrw and replaces it with tree";
type = types.bool;
};
hijackNetRW = mkOption {
default = true;
description = "Prevents netrw from automatically opening when opening directories";
type = types.bool;
};
trailingSlash = mkOption {
default = true;
description = "Add a trailing slash to all folders";
type = types.bool;
};
groupEmptyFolders = mkOption {
default = true;
description = "Compact empty folders trees into a single item";
type = types.bool;
};
lspDiagnostics = mkOption {
default = true;
description = "Shows lsp diagnostics in the tree";
type = types.bool;
};
systemOpenCmd = mkOption {
default = "${pkgs.xdg-utils}/bin/xdg-open";
description = "The command used to open a file with the associated default program";
type = types.str;
};
};
config = mkIf cfg.enable {
vim.startPlugins = ["nvim-tree-lua"];
vim.nnoremap = {
"<C-n>" = ":NvimTreeToggle<CR>";
"<leader>tr" = ":NvimTreeRefresh<CR>";
"<leader>tg" = ":NvimTreeFindFile<CR>";
"<leader>tf" = ":NvimTreeFocus<CR>";
};
vim.luaConfigRC.nvimtreelua = nvim.dag.entryAnywhere ''
require'nvim-tree'.setup({
disable_netrw = ${boolToString cfg.disableNetRW},
hijack_netrw = ${boolToString cfg.hijackNetRW},
open_on_tab = ${boolToString cfg.openTreeOnNewTab},
open_on_setup = ${boolToString cfg.openOnSetup},
open_on_setup_file = ${boolToString cfg.openOnSetup},
system_open = {
cmd = ${"'" + cfg.systemOpenCmd + "'"},
},
diagnostics = {
enable = ${boolToString cfg.lspDiagnostics},
},
view = {
width = ${toString cfg.treeWidth},
side = ${"'" + cfg.treeSide + "'"},
},
renderer = {
indent_markers = {
enable = ${boolToString cfg.indentMarkers},
},
add_trailing = ${boolToString cfg.trailingSlash},
group_empty = ${boolToString cfg.groupEmptyFolders},
},
actions = {
open_file = {
quit_on_open = ${boolToString cfg.closeOnFileOpen},
resize_window = ${boolToString cfg.resizeOnFileOpen},
},
},
git = {
enable = true,
ignore = ${boolToString cfg.hideIgnoredGitFiles},
},
filters = {
dotfiles = ${boolToString cfg.hideDotFiles},
custom = {
${builtins.concatStringsSep "\n" (builtins.map (s: "\"" + s + "\",") cfg.hideFiles)}
},
},
})
'';
};
}

14
modules/git/config.nix Normal file
View file

@ -0,0 +1,14 @@
{
pkgs,
config,
lib,
...
}:
with lib; {
config = {
vim.git = {
enable = mkDefault false;
gitsigns.enable = mkDefault false;
};
};
}

11
modules/git/default.nix Normal file
View file

@ -0,0 +1,11 @@
{
pkgs,
config,
lib,
...
}: {
imports = [
./config.nix
./git.nix
];
}

69
modules/git/git.nix Normal file
View file

@ -0,0 +1,69 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.git;
in {
options.vim.git = {
enable = mkOption {
type = types.bool;
description = "Enable git plugins";
};
gitsigns.enable = mkOption {
type = types.bool;
description = "Enable git options";
};
};
config =
mkIf cfg.enable
(
let
mkVimBool = val:
if val
then "1"
else "0";
in {
vim.startPlugins =
if (cfg.gitsigns.enable)
then ["gitsigns-nvim"]
else [];
vim.luaConfigRC.gitsigns = mkIf (cfg.gitsigns.enable) (nvim.dag.entryAnywhere ''
-- GitSigns setup
require('gitsigns').setup {
keymaps = {
noremap = true,
['n <leader>gn'] = { expr = true, "&diff ? \'\' : '<cmd>Gitsigns next_hunk<CR>'"},
['n <leader>gp'] = { expr = true, "&diff ? \'\' : '<cmd>Gitsigns prev_hunk<CR>'"},
['n <leader>gs'] = '<cmd>Gitsigns stage_hunk<CR>',
['v <leader>gs'] = ':Gitsigns stage_hunk<CR>',
['n <leader>gu'] = '<cmd>Gitsigns undo_stage_hunk<CR>',
['n <leader>gr'] = '<cmd>Gitsigns reset_hunk<CR>',
['v <leader>gr'] = ':Gitsigns reset_hunk<CR>',
['n <leader>gR'] = '<cmd>Gitsigns reset_buffer<CR>',
['n <leader>gp'] = '<cmd>Gitsigns preview_hunk<CR>',
['n <leader>gb'] = '<cmd>lua require"gitsigns".blame_line{full=true}<CR>',
['n <leader>gS'] = '<cmd>Gitsigns stage_buffer<CR>',
['n <leader>gU'] = '<cmd>Gitsigns reset_buffer_index<CR>',
['n <leader>gts'] = ':Gitsigns toggle_signs<CR>',
['n <leader>gtn'] = ':Gitsigns toggle_numhl<CR>',
['n <leader>gtl'] = ':Gitsigns toggle_linehl<CR>',
['n <leader>gtw'] = ':Gitsigns toggle_word_diff<CR>',
-- Text objects
['o ih'] = ':<C-U>Gitsigns select_hunk<CR>',
['x ih'] = ':<C-U>Gitsigns select_hunk<CR>'
},
}
'');
}
);
}

6
modules/keys/default.nix Normal file
View file

@ -0,0 +1,6 @@
{
config,
lib,
pkgs,
...
}: {imports = [./which-key.nix];}

View file

@ -0,0 +1,24 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.keys;
in {
options.vim.keys = {
enable = mkEnableOption "key binding plugins";
whichKey = {
enable = mkEnableOption "which-key menu";
};
};
config = mkIf (cfg.enable && cfg.whichKey.enable) {
vim.startPlugins = ["which-key"];
vim.luaConfigRC.whichkey = nvim.dag.entryAnywhere ''local wk = require("which-key").setup {}'';
};
}

9
modules/lib/booleans.nix Normal file
View file

@ -0,0 +1,9 @@
# From home-manager: https://github.com/nix-community/home-manager/blob/master/modules/lib/booleans.nix
{lib}: {
# Converts a boolean to a yes/no string. This is used in lots of
# configuration formats.
yesNo = value:
if value
then "yes"
else "no";
}

105
modules/lib/dag.nix Normal file
View file

@ -0,0 +1,105 @@
# From home-manager: https://github.com/nix-community/home-manager/blob/master/modules/lib/dag.nix
# A generalization of Nixpkgs's `strings-with-deps.nix`.
#
# The main differences from the Nixpkgs version are
#
# - not specific to strings, i.e., any payload is OK,
#
# - the addition of the function `entryBefore` indicating a "wanted
# by" relationship.
{lib}: let
inherit (lib) all filterAttrs nvim mapAttrs toposort;
in {
empty = {};
isEntry = e: e ? data && e ? after && e ? before;
isDag = dag:
builtins.isAttrs dag && all nvim.dag.isEntry (builtins.attrValues dag);
# Takes an attribute set containing entries built by entryAnywhere,
# entryAfter, and entryBefore to a topologically sorted list of
# entries.
#
# Internally this function uses the `toposort` function in
# `<nixpkgs/lib/lists.nix>` and its value is accordingly.
#
# Specifically, the result on success is
#
# { result = [ { name = ?; data = ?; } … ] }
#
# For example
#
# nix-repl> topoSort {
# a = entryAnywhere "1";
# b = entryAfter [ "a" "c" ] "2";
# c = entryBefore [ "d" ] "3";
# d = entryBefore [ "e" ] "4";
# e = entryAnywhere "5";
# } == {
# result = [
# { data = "1"; name = "a"; }
# { data = "3"; name = "c"; }
# { data = "2"; name = "b"; }
# { data = "4"; name = "d"; }
# { data = "5"; name = "e"; }
# ];
# }
# true
#
# And the result on error is
#
# {
# cycle = [ { after = ?; name = ?; data = ? } … ];
# loops = [ { after = ?; name = ?; data = ? } … ];
# }
#
# For example
#
# nix-repl> topoSort {
# a = entryAnywhere "1";
# b = entryAfter [ "a" "c" ] "2";
# c = entryAfter [ "d" ] "3";
# d = entryAfter [ "b" ] "4";
# e = entryAnywhere "5";
# } == {
# cycle = [
# { after = [ "a" "c" ]; data = "2"; name = "b"; }
# { after = [ "d" ]; data = "3"; name = "c"; }
# { after = [ "b" ]; data = "4"; name = "d"; }
# ];
# loops = [
# { after = [ "a" "c" ]; data = "2"; name = "b"; }
# ];
# }
# true
topoSort = dag: let
dagBefore = dag: name:
builtins.attrNames
(filterAttrs (n: v: builtins.elem name v.before) dag);
normalizedDag =
mapAttrs (n: v: {
name = n;
data = v.data;
after = v.after ++ dagBefore dag n;
})
dag;
before = a: b: builtins.elem a.name b.after;
sorted = toposort before (builtins.attrValues normalizedDag);
in
if sorted ? result
then {
result = map (v: {inherit (v) name data;}) sorted.result;
}
else sorted;
# Applies a function to each element of the given DAG.
map = f: mapAttrs (n: v: v // {data = f n v.data;});
entryBetween = before: after: data: {inherit data before after;};
# Create a DAG entry with no particular dependency information.
entryAnywhere = nvim.dag.entryBetween [] [];
entryAfter = nvim.dag.entryBetween [];
entryBefore = before: nvim.dag.entryBetween before [];
}

5
modules/lib/default.nix Normal file
View file

@ -0,0 +1,5 @@
{lib}: {
dag = import ./dag.nix {inherit lib;};
booleans = import ./booleans.nix {inherit lib;};
types = import ./types.nix {inherit lib;};
}

View file

@ -0,0 +1,13 @@
# From home-manager: https://github.com/nix-community/home-manager/blob/master/modules/lib/stdlib-extended.nix
# Just a convenience function that returns the given Nixpkgs standard
# library extended with the HM library.
nixpkgsLib: let
mkNvimLib = import ./.;
in
nixpkgsLib.extend (self: super: {
nvim = mkNvimLib {lib = self;};
# For forward compatibility.
literalExpression = super.literalExpression or super.literalExample;
literalDocBook = super.literalDocBook or super.literalExample;
})

68
modules/lib/types-dag.nix Normal file
View file

@ -0,0 +1,68 @@
# From home-manager: https://github.com/nix-community/home-manager/blob/master/modules/lib/types-dag.nix
# Used for ordering config text.
{lib}: let
inherit
(lib)
defaultFunctor
nvim
mkIf
mkOrder
mkOption
mkOptionType
types
;
dagEntryOf = elemType: let
submoduleType = types.submodule ({name, ...}: {
options = {
data = mkOption {type = elemType;};
after = mkOption {type = with types; listOf str;};
before = mkOption {type = with types; listOf str;};
};
config = mkIf (elemType.name == "submodule") {
data._module.args.dagName = name;
};
});
maybeConvert = def:
if nvim.dag.isEntry def.value
then def.value
else
nvim.dag.entryAnywhere (
if def ? priority
then mkOrder def.priority def.value
else def.value
);
in
mkOptionType {
name = "dagEntryOf";
description = "DAG entry of ${elemType.description}";
# leave the checking to the submodule type
merge = loc: defs:
submoduleType.merge loc (map (def: {
inherit (def) file;
value = maybeConvert def;
})
defs);
};
in rec {
# A directed acyclic graph of some inner type.
#
# Note, if the element type is a submodule then the `name` argument
# will always be set to the string "data" since it picks up the
# internal structure of the DAG values. To give access to the
# "actual" attribute name a new submodule argument is provided with
# the name `dagName`.
dagOf = elemType: let
attrEquivalent = types.attrsOf (dagEntryOf elemType);
in
mkOptionType rec {
name = "dagOf";
description = "DAG of ${elemType.description}";
inherit (attrEquivalent) check merge emptyValue;
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name>"]);
getSubModules = elemType.getSubModules;
substSubModules = m: dagOf (elemType.substSubModules m);
functor = (defaultFunctor name) // {wrapped = elemType;};
nestedTypes.elemType = elemType;
};
}

View file

@ -0,0 +1,55 @@
{lib}:
with lib; let
# Plugin must be same as input name
availablePlugins = [
"nvim-treesitter-context"
"gitsigns-nvim"
"plenary-nvim"
"nvim-lspconfig"
"nvim-treesitter"
"lspsaga"
"lspkind"
"nvim-lightbulb"
"lsp-signature"
"nvim-tree-lua"
"nvim-bufferline-lua"
"lualine"
"nvim-compe"
"nvim-autopairs"
"nvim-ts-autotag"
"nvim-web-devicons"
"tokyonight"
"bufdelete-nvim"
"nvim-cmp"
"cmp-nvim-lsp"
"cmp-buffer"
"cmp-vsnip"
"cmp-path"
"cmp-treesitter"
"crates-nvim"
"vim-vsnip"
"nvim-code-action-menu"
"trouble"
"null-ls"
"which-key"
"indent-blankline"
"nvim-cursorline"
"sqls-nvim"
"glow-nvim"
"telescope"
"rust-tools"
"onedark"
"catppuccin"
];
pluginsType = with types; listOf (nullOr (either (enum availablePlugins) package));
in {
pluginsOpt = {
description,
default ? [],
}:
mkOption {
inherit description default;
type = pluginsType;
};
}

7
modules/lib/types.nix Normal file
View file

@ -0,0 +1,7 @@
{lib}: let
typesDag = import ./types-dag.nix {inherit lib;};
typesPlugin = import ./types-plugin.nix {inherit lib;};
in {
inherit (typesDag) dagOf;
inherit (typesPlugin) pluginsOpt;
}

15
modules/lsp/default.nix Normal file
View file

@ -0,0 +1,15 @@
{
config,
lib,
pkgs,
...
}: {
imports = [
./lsp.nix
./lspsaga.nix
./nvim-code-action-menu.nix
./trouble.nix
./lsp-signature.nix
./lightbulb.nix
];
}

29
modules/lsp/lightbulb.nix Normal file
View file

@ -0,0 +1,29 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.lsp;
in {
options.vim.lsp = {
lightbulb = {
enable = mkEnableOption "lightbulb for code actions. Requires emoji font";
};
};
config = mkIf (cfg.enable && cfg.lightbulb.enable) {
vim.startPlugins = ["nvim-lightbulb"];
vim.configRC.lightbulb = nvim.dag.entryAnywhere ''
autocmd CursorHold,CursorHoldI * lua require'nvim-lightbulb'.update_lightbulb()
'';
vim.luaConfigRC.lightbulb = nvim.dag.entryAnywhere ''
-- Enable trouble diagnostics viewer
require'nvim-lightbulb'.setup()
'';
};
}

View file

@ -0,0 +1,25 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.lsp;
in {
options.vim.lsp = {
lspSignature = {
enable = mkEnableOption "lsp signature viewer";
};
};
config = mkIf (cfg.enable && cfg.lspSignature.enable) {
vim.startPlugins = ["lsp-signature"];
vim.luaConfigRC.lsp-signature = nvim.dag.entryAnywhere ''
-- Enable lsp signature viewer
require("lsp_signature").setup()
'';
};
}

405
modules/lsp/lsp.nix Normal file
View file

@ -0,0 +1,405 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.lsp;
in {
options.vim.lsp = {
enable = mkEnableOption "neovim lsp support";
formatOnSave = mkEnableOption "Format on save";
nix = {
enable = mkEnableOption "Nix LSP";
server = mkOption {
type = with types; enum ["rnix" "nil"];
default = "nil";
description = "Which LSP to use";
};
pkg = mkOption {
type = types.package;
default =
if (cfg.nix.server == "rnix")
then pkgs.rnix-lsp
else pkgs.nil;
description = "The LSP package to use";
};
formatter = mkOption {
type = with types; enum ["nixpkgs-fmt" "alejandra"];
default = "alejandra";
description = "Which nix formatter to use";
};
};
rust = {
enable = mkEnableOption "Rust LSP";
rustAnalyzerOpts = mkOption {
type = types.str;
default = ''
["rust-analyzer"] = {
experimental = {
procAttrMacros = true,
},
},
'';
description = "options to pass to rust analyzer";
};
};
python = mkEnableOption "Python LSP";
clang = {
enable = mkEnableOption "C language LSP";
c_header = mkEnableOption "C syntax header files";
cclsOpts = mkOption {
type = types.str;
default = "";
};
};
sql = mkEnableOption "SQL Language LSP";
go = mkEnableOption "Go language LSP";
ts = mkEnableOption "TS language LSP";
zig.enable = mkEnableOption "Zig language LSP";
};
config = mkIf cfg.enable (
let
writeIf = cond: msg:
if cond
then msg
else "";
in {
vim.startPlugins =
[
"nvim-lspconfig"
"null-ls"
(
if (config.vim.autocomplete.enable && (config.vim.autocomplete.type == "nvim-cmp"))
then "cmp-nvim-lsp"
else null
)
(
if cfg.sql
then "sqls-nvim"
else null
)
]
++ (
if cfg.rust.enable
then [
"crates-nvim"
"rust-tools"
]
else []
);
vim.configRC.lsp = nvim.dag.entryAnywhere ''
${
if cfg.nix.enable
then ''
autocmd filetype nix setlocal tabstop=2 shiftwidth=2 softtabstop=2
''
else ""
}
${
if cfg.clang.c_header
then ''
" c syntax for header (otherwise breaks treesitter highlighting)
" https://www.reddit.com/r/neovim/comments/orfpcd/question_does_the_c_parser_from_nvimtreesitter/
let g:c_syntax_for_h = 1
''
else ""
}
'';
vim.luaConfigRC.lsp = nvim.dag.entryAnywhere ''
local attach_keymaps = function(client, bufnr)
local opts = { noremap=true, silent=true }
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>lgD', '<cmd>lua vim.lsp.buf.declaration()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>lgd', '<cmd>lua vim.lsp.buf.definition()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>lgt', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>lgn', '<cmd>lua vim.diagnostic.goto_next()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>lgp', '<cmd>lua vim.diagnostic.goto_prev()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>lwa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>lwr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>lwl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>lh', '<cmd>lua vim.lsp.buf.hover()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>ls', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>ln', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
end
local null_ls = require("null-ls")
local null_helpers = require("null-ls.helpers")
local null_methods = require("null-ls.methods")
local ls_sources = {
${writeIf cfg.python
''
null_ls.builtins.formatting.black.with({
command = "${pkgs.black}/bin/black",
}),
''}
-- Commented out for now
--${writeIf (config.vim.git.enable && config.vim.git.gitsigns.enable) ''
-- null_ls.builtins.code_actions.gitsigns,
--''}
${writeIf cfg.sql
''
null_helpers.make_builtin({
method = null_methods.internal.FORMATTING,
filetypes = { "sql" },
generator_opts = {
to_stdin = true,
ignore_stderr = true,
suppress_errors = true,
command = "${pkgs.sqlfluff}/bin/sqlfluff",
args = {
"fix",
"-",
},
},
factory = null_helpers.formatter_factory,
}),
null_ls.builtins.diagnostics.sqlfluff.with({
command = "${pkgs.sqlfluff}/bin/sqlfluff",
extra_args = {"--dialect", "postgres"}
}),
''}
${writeIf
(cfg.nix.enable
&& cfg.nix.server == "rnix"
&& cfg.nix.formatter == "alejandra")
''
null_ls.builtins.formatting.alejandra.with({
command = "${pkgs.alejandra}/bin/alejandra"
}),
''}
${writeIf cfg.ts
''
null_ls.builtins.diagnostics.eslint,
null_ls.builtins.formatting.prettier,
''}
}
vim.g.formatsave = ${
if cfg.formatOnSave
then "true"
else "false"
};
-- Enable formatting
format_callback = function(client, bufnr)
vim.api.nvim_create_autocmd("BufWritePre", {
group = augroup,
buffer = bufnr,
callback = function()
if vim.g.formatsave then
local params = require'vim.lsp.util'.make_formatting_params({})
client.request('textDocument/formatting', params, nil, bufnr)
end
end
})
end
default_on_attach = function(client, bufnr)
attach_keymaps(client, bufnr)
format_callback(client, bufnr)
end
-- Enable null-ls
require('null-ls').setup({
diagnostics_format = "[#{m}] #{s} (#{c})",
debounce = 250,
default_timeout = 5000,
sources = ls_sources,
on_attach=default_on_attach
})
-- Enable lspconfig
local lspconfig = require('lspconfig')
local capabilities = vim.lsp.protocol.make_client_capabilities()
${
let
cfg = config.vim.autocomplete;
in
writeIf cfg.enable (
if cfg.type == "nvim-cmp"
then ''
capabilities = require('cmp_nvim_lsp').default_capabilities()
''
else ""
)
}
${writeIf cfg.rust.enable ''
-- Rust config
local rt = require('rust-tools')
rust_on_attach = function(client, bufnr)
default_on_attach(client, bufnr)
local opts = { noremap=true, silent=true, buffer = bufnr }
vim.keymap.set("n", "<leader>ris", rt.inlay_hints.set, opts)
vim.keymap.set("n", "<leader>riu", rt.inlay_hints.unset, opts)
vim.keymap.set("n", "<leader>rr", rt.runnables.runnables, opts)
vim.keymap.set("n", "<leader>rp", rt.parent_module.parent_module, opts)
vim.keymap.set("n", "<leader>rm", rt.expand_macro.expand_macro, opts)
vim.keymap.set("n", "<leader>rc", rt.open_cargo_toml.open_cargo_toml, opts)
vim.keymap.set("n", "<leader>rg", function() rt.crate_graph.view_crate_graph("x11", nil) end, opts)
end
local rustopts = {
tools = {
autoSetHints = true,
hover_with_actions = false,
inlay_hints = {
only_current_line = false,
}
},
server = {
capabilities = capabilities,
on_attach = rust_on_attach,
cmd = {"${pkgs.rust-analyzer}/bin/rust-analyzer"},
settings = {
${cfg.rust.rustAnalyzerOpts}
}
}
}
require('crates').setup {
null_ls = {
enabled = true,
name = "crates.nvim",
}
}
rt.setup(rustopts)
''}
${optionalString cfg.zig.enable ''
-- Zig config
lspconfig.zls.setup {
capabilities = capabilities,
on_attach=default_on_attach,
cmd = {"${pkgs.zls}/bin/zls"},
settings = {
["zls"] = {
zig_exe_path = "${pkgs.zig}/bin/zig",
zig_lib_path = "${pkgs.zig}/lib/zig",
}
}
}
''}
${writeIf cfg.python ''
-- Python config
lspconfig.pyright.setup{
capabilities = capabilities;
on_attach=default_on_attach;
cmd = {"${pkgs.nodePackages.pyright}/bin/pyright-langserver", "--stdio"}
}
''}
${writeIf cfg.nix.enable (
(writeIf (cfg.nix.server == "rnix") ''
-- Nix (rnix) config
lspconfig.rnix.setup{
capabilities = capabilities,
${writeIf (cfg.nix.formatter == "alejandra")
''
on_attach = function(client, bufnr)
attach_keymaps(client, bufnr)
end,
''}
${writeIf (cfg.nix.formatter == "nixpkgs-fmt")
''
on_attach = default_on_attach,
''}
cmd = {"${cfg.nix.pkg}/bin/rnix-lsp"},
}
'')
+ (writeIf (cfg.nix.server == "nil") ''
-- Nix (nil) config
lspconfig.nil_ls.setup{
capabilities = capabilities,
on_attach=default_on_attach,
cmd = {"${cfg.nix.pkg}/bin/nil"},
settings = {
["nil"] = {
${writeIf (cfg.nix.formatter == "alejandra")
''
formatting = {
command = {"${pkgs.alejandra}/bin/alejandra", "--quiet"},
},
''}
${writeIf (cfg.nix.formatter == "nixpkgs-fmt")
''
formatting = {
command = {"${pkgs.nixpkgs-fmt}/bin/nixpkgs-fmt"},
},
''}
},
};
}
'')
)}
${writeIf cfg.clang.enable ''
-- CCLS (clang) config
lspconfig.ccls.setup{
capabilities = capabilities;
on_attach=default_on_attach;
cmd = {"${pkgs.ccls}/bin/ccls"};
${
if cfg.clang.cclsOpts == ""
then ""
else "init_options = ${cfg.clang.cclsOpts}"
}
}
''}
${writeIf cfg.sql ''
-- SQLS config
lspconfig.sqls.setup {
on_attach = function(client)
client.server_capabilities.execute_command = true
on_attach_keymaps(client, bufnr)
require'sqls'.setup{}
end,
cmd = {"${pkgs.sqls}/bin/sqls", "-config", string.format("%s/config.yml", vim.fn.getcwd()) }
}
''}
${writeIf cfg.go ''
-- Go config
lspconfig.gopls.setup {
capabilities = capabilities;
on_attach = default_on_attach;
cmd = {"${pkgs.gopls}/bin/gopls", "serve"},
}
''}
${writeIf cfg.ts ''
-- TS config
lspconfig.tsserver.setup {
capabilities = capabilities;
on_attach = function(client, bufnr)
attach_keymaps(client, bufnr)
end,
cmd = { "${pkgs.nodePackages.typescript-language-server}/bin/typescript-language-server", "--stdio" }
}
''}
'';
}
);
}

54
modules/lsp/lspsaga.nix Normal file
View file

@ -0,0 +1,54 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.lsp;
in {
options.vim.lsp = {lspsaga = {enable = mkEnableOption "LSP Saga";};};
config = mkIf (cfg.enable && cfg.lspsaga.enable) {
vim.startPlugins = ["lspsaga"];
vim.vnoremap = {
"<silent><leader>ca" = ":<C-U>lua require('lspsaga.codeaction').range_code_action()<CR>";
};
vim.nnoremap =
{
"<silent><leader>lf" = "<cmd>lua require'lspsaga.provider'.lsp_finder()<CR>";
"<silent><leader>lh" = "<cmd>lua require('lspsaga.hover').render_hover_doc()<CR>";
"<silent><C-f>" = "<cmd>lua require('lspsaga.action').smart_scroll_with_saga(1)<CR>";
"<silent><C-b>" = "<cmd>lua require('lspsaga.action').smart_scroll_with_saga(-1)<CR>";
"<silent><leader>lr" = "<cmd>lua require'lspsaga.rename'.rename()<CR>";
"<silent><leader>ld" = "<cmd>lua require'lspsaga.provider'.preview_definition()<CR>";
"<silent><leader>ll" = "<cmd>lua require'lspsaga.diagnostic'.show_line_diagnostics()<CR>";
"<silent><leader>lc" = "<cmd>lua require'lspsaga.diagnostic'.show_cursor_diagnostics()<CR>";
"<silent><leader>lp" = "<cmd>lua require'lspsaga.diagnostic'.lsp_jump_diagnostic_prev()<CR>";
"<silent><leader>ln" = "<cmd>lua require'lspsaga.diagnostic'.lsp_jump_diagnostic_next()<CR>";
}
// (
if (!cfg.nvimCodeActionMenu.enable)
then {
"<silent><leader>ca" = "<cmd>lua require('lspsaga.codeaction').code_action()<CR>";
}
else {}
)
// (
if (!cfg.lspSignature.enable)
then {
"<silent><leader>ls" = "<cmd>lua require('lspsaga.signaturehelp').signature_help()<CR>";
}
else {}
);
vim.luaConfigRC.lspsage = nvim.dag.entryAnywhere ''
-- Enable lspsaga
local saga = require 'lspsaga'
saga.init_lsp_saga()
'';
};
}

View file

@ -0,0 +1,24 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.lsp;
in {
options.vim.lsp = {
nvimCodeActionMenu = {
enable = mkEnableOption "nvim code action menu";
};
};
config = mkIf (cfg.enable && cfg.nvimCodeActionMenu.enable) {
vim.startPlugins = ["nvim-code-action-menu"];
vim.nnoremap = {
"<silent><leader>ca" = ":CodeActionMenu<CR>";
};
};
}

34
modules/lsp/trouble.nix Normal file
View file

@ -0,0 +1,34 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.lsp;
in {
options.vim.lsp = {
trouble = {
enable = mkEnableOption "trouble diagnostics viewer";
};
};
config = mkIf (cfg.enable && cfg.trouble.enable) {
vim.startPlugins = ["trouble"];
vim.nnoremap = {
"<leader>xx" = "<cmd>TroubleToggle<CR>";
"<leader>lwd" = "<cmd>TroubleToggle workspace_diagnostics<CR>";
"<leader>ld" = "<cmd>TroubleToggle document_diagnostics<CR>";
"<leader>lr" = "<cmd>TroubleToggle lsp_references<CR>";
"<leader>xq" = "<cmd>TroubleToggle quickfix<CR>";
"<leader>xl" = "<cmd>TroubleToggle loclist<CR>";
};
vim.luaConfigRC.trouble = nvim.dag.entryAnywhere ''
-- Enable trouble diagnostics viewer
require("trouble").setup {}
'';
};
}

View file

@ -0,0 +1,14 @@
{
pkgs,
config,
lib,
...
}:
with lib; {
config = {
vim.markdown = {
enable = mkDefault false;
glow.enable = mkDefault false;
};
};
}

View file

@ -0,0 +1,11 @@
{
config,
lib,
pkgs,
...
}: {
imports = [
./config.nix
./glow.nix
];
}

38
modules/markdown/glow.nix Normal file
View file

@ -0,0 +1,38 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.markdown;
in {
options.vim.markdown = {
enable = mkEnableOption "markdown tools and plugins";
glow.enable = mkOption {
type = types.bool;
default = true;
description = "Enable markdown preview in neovim with glow";
};
};
config = mkIf (cfg.enable) {
vim.startPlugins = [
(
if cfg.glow.enable
then "glow-nvim"
else null
)
];
vim.globals = mkIf (cfg.glow.enable) {
"glow_binary_path" = "${pkgs.glow}/bin";
};
vim.configRC.glow = mkIf (cfg.glow.enable) (nvim.dag.entryAnywhere ''
autocmd FileType markdown noremap <leader>p :Glow<CR>
'');
};
}

35
modules/modules.nix Normal file
View file

@ -0,0 +1,35 @@
{
pkgs,
lib,
check ? true,
}: let
modules = [
./completion
./theme
./core
./basic
./statusline
./tabline
./filetree
./visuals
./lsp
./treesitter
./tidal
./autopairs
./snippets
./keys
./markdown
./telescope
./git
];
pkgsModule = {config, ...}: {
config = {
_module.args.baseModules = modules;
_module.args.pkgsPath = lib.mkDefault pkgs.path;
_module.args.pkgs = lib.mkDefault pkgs;
_module.check = check;
};
};
in
modules ++ [pkgsModule]

View file

@ -0,0 +1,10 @@
{
pkgs,
lib,
config,
...
}: {
imports = [
./vsnip.nix
];
}

View file

@ -0,0 +1,18 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.snippets.vsnip;
in {
options.vim.snippets.vsnip = {
enable = mkEnableOption "Enable vim-vsnip";
};
config = mkIf cfg.enable {
vim.startPlugins = ["vim-vsnip"];
};
}

View file

@ -0,0 +1,65 @@
{
pkgs,
config,
lib,
...
}:
with lib; {
config = {
vim.statusline.lualine = {
enable = mkDefault false;
icons = mkDefault true;
theme = mkDefault "auto";
sectionSeparator = {
left = mkDefault "";
right = mkDefault "";
};
componentSeparator = {
left = mkDefault "";
right = mkDefault "";
};
activeSection = {
a = mkDefault "{'mode'}";
b = ''
{
{
"branch",
separator = '',
},
"diff",
}
'';
c = mkDefault "{'filename'}";
x = mkDefault ''
{
{
"diagnostics",
sources = {'nvim_lsp'},
separator = '',
symbols = {error = '', warn = '', info = '', hint = ''},
},
{
"filetype",
},
"fileformat",
"encoding",
}
'';
y = mkDefault "{'progress'}";
z = mkDefault "{'location'}";
};
inactiveSection = {
a = mkDefault "{}";
b = mkDefault "{}";
c = mkDefault "{'filename'}";
x = mkDefault "{'location'}";
y = mkDefault "{}";
z = mkDefault "{}";
};
};
};
}

View file

@ -0,0 +1,11 @@
{
pkgs,
config,
lib,
...
}: {
imports = [
./lualine.nix
./config.nix
];
}

View file

@ -0,0 +1,205 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.statusline.lualine;
supported_themes = import ./supported_lualine_themes.nix;
in {
options.vim.statusline.lualine = {
enable = mkOption {
type = types.bool;
description = "Enable lualine";
};
icons = mkOption {
type = types.bool;
description = "Enable icons for lualine";
};
theme = mkOption {
type = types.enum (
[
"auto"
"16color"
"gruvbox"
"ayu_dark"
"ayu_light"
"ayu_mirage"
"codedark"
"dracula"
"everforest"
"gruvbox"
"gruvbox_light"
"gruvbox_material"
"horizon"
"iceberg_dark"
"iceberg_light"
"jellybeans"
"material"
"modus_vivendi"
"molokai"
"nightfly"
"nord"
"oceanicnext"
"onelight"
"palenight"
"papercolor_dark"
"papercolor_light"
"powerline"
"seoul256"
"solarized_dark"
"tomorrow"
"wombat"
]
++ (
if elem config.vim.theme.name supported_themes
then [config.vim.theme.name]
else []
)
);
description = "Theme for lualine";
};
sectionSeparator = {
left = mkOption {
type = types.str;
description = "Section separator for left side";
};
right = mkOption {
type = types.str;
description = "Section separator for right side";
};
};
componentSeparator = {
left = mkOption {
type = types.str;
description = "Component separator for left side";
};
right = mkOption {
type = types.str;
description = "Component separator for right side";
};
};
activeSection = {
a = mkOption {
type = types.str;
description = "active config for: | (A) | B | C X | Y | Z |";
};
b = mkOption {
type = types.str;
description = "active config for: | A | (B) | C X | Y | Z |";
};
c = mkOption {
type = types.str;
description = "active config for: | A | B | (C) X | Y | Z |";
};
x = mkOption {
type = types.str;
description = "active config for: | A | B | C (X) | Y | Z |";
};
y = mkOption {
type = types.str;
description = "active config for: | A | B | C X | (Y) | Z |";
};
z = mkOption {
type = types.str;
description = "active config for: | A | B | C X | Y | (Z) |";
};
};
inactiveSection = {
a = mkOption {
type = types.str;
description = "inactive config for: | (A) | B | C X | Y | Z |";
};
b = mkOption {
type = types.str;
description = "inactive config for: | A | (B) | C X | Y | Z |";
};
c = mkOption {
type = types.str;
description = "inactive config for: | A | B | (C) X | Y | Z |";
};
x = mkOption {
type = types.str;
description = "inactive config for: | A | B | C (X) | Y | Z |";
};
y = mkOption {
type = types.str;
description = "inactive config for: | A | B | C X | (Y) | Z |";
};
z = mkOption {
type = types.str;
description = "inactive config for: | A | B | C X | Y | (Z) |";
};
};
};
config =
mkIf cfg.enable
{
#assertions = [
# ({
# assertion = if cfg.icons then (config.vim.visuals.enable && config.vim.visuals.nvimWebDevicons.enable) else true;
# message = "Must enable config.vim.visual.nvimWebDevicons if using config.vim.visuals.lualine.icons";
# })
#];
vim.startPlugins = ["lualine"];
vim.luaConfigRC.lualine = nvim.dag.entryAnywhere ''
require'lualine'.setup {
options = {
icons_enabled = ${
if cfg.icons
then "true"
else "false"
},
theme = "${cfg.theme}",
component_separators = {"${cfg.componentSeparator.left}","${cfg.componentSeparator.right}"},
section_separators = {"${cfg.sectionSeparator.left}","${cfg.sectionSeparator.right}"},
disabled_filetypes = {},
},
sections = {
lualine_a = ${cfg.activeSection.a},
lualine_b = ${cfg.activeSection.b},
lualine_c = ${cfg.activeSection.c},
lualine_x = ${cfg.activeSection.x},
lualine_y = ${cfg.activeSection.y},
lualine_z = ${cfg.activeSection.z},
},
inactive_sections = {
lualine_a = ${cfg.inactiveSection.a},
lualine_b = ${cfg.inactiveSection.b},
lualine_c = ${cfg.inactiveSection.c},
lualine_x = ${cfg.inactiveSection.x},
lualine_y = ${cfg.inactiveSection.y},
lualine_z = ${cfg.inactiveSection.z},
},
tabline = {},
extensions = {${
if config.vim.filetree.nvimTreeLua.enable
then "\"nvim-tree\""
else ""
}},
}
'';
};
}

View file

@ -0,0 +1,5 @@
[
"tokyonight"
"onedark"
"catppuccin"
]

View file

@ -0,0 +1,10 @@
{
pkgs,
lib,
config,
...
}: {
imports = [
./nvim-bufferline.nix
];
}

View file

@ -0,0 +1,100 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.tabline.nvimBufferline;
in {
options.vim.tabline.nvimBufferline = {
enable = mkEnableOption "nvim-bufferline-lua";
};
config = mkIf cfg.enable (
let
mouse = {
right = "'vertical sbuffer %d'";
close = ''
function(bufnum)
require("bufdelete").bufdelete(bufnum, false)
end
'';
};
in {
vim.startPlugins = [
(assert config.vim.visuals.nvimWebDevicons.enable == true; "nvim-bufferline-lua")
"bufdelete-nvim"
];
vim.nnoremap = {
"<silent><leader>bn" = ":BufferLineCycleNext<CR>";
"<silent><leader>bp" = ":BufferLineCyclePrev<CR>";
"<silent><leader>bc" = ":BufferLinePick<CR>";
"<silent><leader>bse" = ":BufferLineSortByExtension<CR>";
"<silent><leader>bsd" = ":BufferLineSortByDirectory<CR>";
"<silent><leader>bsi" = ":lua require'bufferline'.sort_buffers_by(function (buf_a, buf_b) return buf_a.id < buf_b.id end)<CR>";
"<silent><leader>bmn" = ":BufferLineMoveNext<CR>";
"<silent><leader>bmp" = ":BufferLineMovePrev<CR>";
"<silent><leader>b1" = "<Cmd>BufferLineGoToBuffer 1<CR>";
"<silent><leader>b2" = "<Cmd>BufferLineGoToBuffer 2<CR>";
"<silent><leader>b3" = "<Cmd>BufferLineGoToBuffer 3<CR>";
"<silent><leader>b4" = "<Cmd>BufferLineGoToBuffer 4<CR>";
"<silent><leader>b5" = "<Cmd>BufferLineGoToBuffer 5<CR>";
"<silent><leader>b6" = "<Cmd>BufferLineGoToBuffer 6<CR>";
"<silent><leader>b7" = "<Cmd>BufferLineGoToBuffer 7<CR>";
"<silent><leader>b8" = "<Cmd>BufferLineGoToBuffer 8<CR>";
"<silent><leader>b9" = "<Cmd>BufferLineGoToBuffer 9<CR>";
};
vim.luaConfigRC.nvimBufferline = nvim.dag.entryAnywhere ''
require("bufferline").setup{
options = {
numbers = "both",
close_command = ${mouse.close},
right_mouse_command = ${mouse.right},
indicator = {
indicator_icon = '',
style = 'icon',
},
buffer_close_icon = '',
modified_icon = '',
close_icon = '',
left_trunc_marker = '',
right_trunc_marker = '',
separator_style = "thin",
max_name_length = 18,
max_prefix_length = 15,
tab_size = 18,
show_buffer_icons = true,
show_buffer_close_icons = true,
show_close_icon = true,
show_tab_indicators = true,
persist_buffer_sort = true,
enforce_regular_tabs = false,
always_show_bufferline = true,
offsets = {{filetype = "NvimTree", text = "File Explorer", text_align = "left"}},
sort_by = 'extension',
diagnostics = "nvim_lsp",
diagnostics_update_in_insert = true,
diagnostics_indicator = function(count, level, diagnostics_dict, context)
local s = ""
for e, n in pairs(diagnostics_dict) do
local sym = e == "error" and ""
or (e == "warning" and "" or "" )
if(sym ~= "") then
s = s .. " " .. n .. sym
end
end
return s
end,
numbers = function(opts)
return string.format('%s·%s', opts.raise(opts.id), opts.lower(opts.ordinal))
end,
}
}
'';
}
);
}

View file

@ -0,0 +1,77 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.telescope;
in {
options.vim.telescope = {
enable = mkEnableOption "enable telescope";
};
config = mkIf (cfg.enable) {
vim.startPlugins = [
"telescope"
];
vim.nnoremap =
{
"<leader>ff" = "<cmd> Telescope find_files<CR>";
"<leader>fg" = "<cmd> Telescope live_grep<CR>";
"<leader>fb" = "<cmd> Telescope buffers<CR>";
"<leader>fh" = "<cmd> Telescope help_tags<CR>";
"<leader>ft" = "<cmd> Telescope<CR>";
"<leader>fvcw" = "<cmd> Telescope git_commits<CR>";
"<leader>fvcb" = "<cmd> Telescope git_bcommits<CR>";
"<leader>fvb" = "<cmd> Telescope git_branches<CR>";
"<leader>fvs" = "<cmd> Telescope git_status<CR>";
"<leader>fvx" = "<cmd> Telescope git_stash<CR>";
}
// (
if config.vim.lsp.enable
then {
"<leader>flsb" = "<cmd> Telescope lsp_document_symbols<CR>";
"<leader>flsw" = "<cmd> Telescope lsp_workspace_symbols<CR>";
"<leader>flr" = "<cmd> Telescope lsp_references<CR>";
"<leader>fli" = "<cmd> Telescope lsp_implementations<CR>";
"<leader>flD" = "<cmd> Telescope lsp_definitions<CR>";
"<leader>flt" = "<cmd> Telescope lsp_type_definitions<CR>";
"<leader>fld" = "<cmd> Telescope diagnostics<CR>";
}
else {}
)
// (
if config.vim.treesitter.enable
then {
"<leader>fs" = "<cmd> Telescope treesitter<CR>";
}
else {}
);
vim.luaConfigRC.telescope = nvim.dag.entryAnywhere ''
require("telescope").setup {
defaults = {
vimgrep_arguments = {
"${pkgs.ripgrep}/bin/rg",
"--color=never",
"--no-heading",
"--with-filename",
"--line-number",
"--column",
"--smart-case"
},
pickers = {
find_command = {
"${pkgs.fd}/bin/fd",
},
},
}
}
'';
};
}

11
modules/theme/config.nix Normal file
View file

@ -0,0 +1,11 @@
{ pkgs, config, lib, ... }:
with lib; {
config = {
vim.theme = {
enable = mkDefault false;
name = mkDefault "onedark";
style = mkDefault "darker";
extraConfig = mkDefault "";
};
};
}

11
modules/theme/default.nix Normal file
View file

@ -0,0 +1,11 @@
{
pkgs,
config,
lib,
...
}: {
imports = [
./theme.nix
./config.nix
];
}

View file

@ -0,0 +1,33 @@
{
onedark = {
setup = { style ? "dark" }: ''
-- OneDark theme
require('onedark').setup {
style = "${style}"
}
require('onedark').load()
'';
styles = [ "dark" "darker" "cool" "deep" "warm" "warmer" ];
};
tokyonight = {
setup = { style ? "night" }: ''
-- need to set style before colorscheme to apply
vim.g.tokyonight_style = '${style}'
vim.cmd[[colorscheme tokyonight]]
'';
styles = [ "day" "night" "storm" ];
};
catppuccin = {
setup = { style ? "mocha" }: ''
-- Catppuccin theme
require('catppuccin').setup {
flavour = "${style}"
}
-- setup must be called before loading
vim.cmd.colorscheme "catppuccin"
'';
styles = [ "latte" "frappe" "macchiato" "mocha" ];
};
}

40
modules/theme/theme.nix Normal file
View file

@ -0,0 +1,40 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with lib.attrsets;
with builtins; let
cfg = config.vim.theme;
supported_themes = import ./supported_themes.nix;
in {
options.vim.theme = {
enable = mkOption {
type = types.bool;
description = "Enable Theme";
};
name = mkOption {
type = types.enum (attrNames supported_themes);
description = "Supported themes can be found in `supported_themes.nix`";
};
style = mkOption {
type = with types; enum supported_themes.${cfg.name}.styles;
description = "Specific style for theme if it supports it";
};
extraConfig = mkOption {
type = with types; lines;
description = "Additional lua configuration to add before setup";
};
};
config = mkIf cfg.enable {
vim.startPlugins = [cfg.name];
vim.luaConfigRC.themeSetup = nvim.dag.entryBefore ["theme"] cfg.extraConfig;
vim.luaConfigRC.theme = supported_themes.${cfg.name}.setup {style = cfg.style;};
};
}

View file

@ -0,0 +1,6 @@
{
config,
lib,
pkgs,
...
}: {imports = [./tidal.nix];}

39
modules/tidal/tidal.nix Normal file
View file

@ -0,0 +1,39 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.tidal;
in {
options.vim.tidal = {
enable = mkEnableOption "tidal tools and plugins";
flash = mkOption {
description = ''When sending a paragraph or a single line, vim-tidal will "flash" the selection for some milliseconds'';
type = types.int;
default = 150;
};
openSC = mkOption {
description = "Automatically run the supercollider CLI, sclang, alongside the Tidal GHCI terminal.";
type = types.bool;
default = true;
};
};
config = mkIf (cfg.enable) {
vim.startPlugins = [
# From tidalcycles flake
pkgs.vimPlugins.vim-tidal
];
vim.globals = {
"tidal_target" = "terminal";
"tidal_flash_duration" = 150;
"tidal_sc_enable" = cfg.openSC;
};
};
}

View file

@ -0,0 +1,31 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.treesitter;
in {
options.vim.treesitter.context.enable = mkOption {
type = types.bool;
default = false;
description = "enable function context [nvim-treesitter-context]";
};
config = mkIf (cfg.enable && cfg.context.enable) {
vim.startPlugins = [
"nvim-treesitter-context"
];
vim.luaConfigRC.treesitter-context = nvim.dag.entryAnywhere ''
-- Treesitter Context config
require'treesitter-context'.setup {
enable = true,
throttle = true,
max_lines = 0
}
'';
};
}

View file

@ -0,0 +1,11 @@
{
config,
lib,
pkgs,
...
}: {
imports = [
./treesitter.nix
./context.nix
];
}

View file

@ -0,0 +1,111 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.treesitter;
in {
options.vim.treesitter = {
enable = mkOption {
default = false;
type = types.bool;
description = "enable tree-sitter [nvim-treesitter]";
};
fold = mkOption {
default = false;
type = types.bool;
description = "enable fold with tree-sitter";
};
autotagHtml = mkOption {
default = false;
type = types.bool;
description = "enable autoclose and rename html tag [nvim-ts-autotag]";
};
grammars = mkOption {
type = with types; listOf package;
default = with (pkgs.vimPlugins.nvim-treesitter.builtGrammars); [
c
cpp
nix
python
rust
markdown
comment
toml
make
tsx
html
javascript
css
graphql
json
zig
];
description = ''
List of treesitter grammars to install.
When enabling a language, its treesitter grammar is added for you.
'';
};
};
config = mkIf cfg.enable (
let
writeIf = cond: msg:
if cond
then msg
else "";
in {
vim.startPlugins = [
"nvim-treesitter"
(
if cfg.autotagHtml
then "nvim-ts-autotag"
else null
)
];
# For some reason treesitter highlighting does not work on start if this is set before syntax on
vim.configRC.treesitter = writeIf cfg.fold (nvim.dag.entryBefore ["basic"] ''
" Tree-sitter based folding
set foldmethod=expr
set foldexpr=nvim_treesitter#foldexpr()
set nofoldenable
'');
vim.luaConfigRC.treesitter = nvim.dag.entryAnywhere ''
-- Treesitter config
require'nvim-treesitter.configs'.setup {
highlight = {
enable = true,
disable = {},
},
auto_install = false,
ensure_installed = {},
incremental_selection = {
enable = true,
keymaps = {
init_selection = "gnn",
node_incremental = "grn",
scope_incremental = "grc",
node_decremental = "grm",
},
},
${writeIf cfg.autotagHtml ''
autotag = {
enable = true,
},
''}
}
'';
}
);
}

View file

@ -0,0 +1,28 @@
{ pkgs
, config
, lib
, ...
}:
with lib; {
config = {
vim.visuals = {
enable = mkDefault false;
nvimWebDevicons.enable = mkDefault false;
lspkind.enable = mkDefault false;
cursorWordline = {
enable = mkDefault false;
lineTimeout = mkDefault 500;
};
indentBlankline = {
enable = mkDefault false;
listChar = mkDefault "";
fillChar = mkDefault "";
eolChar = mkDefault "";
showCurrContext = mkDefault true;
};
};
};
}

View file

@ -0,0 +1,11 @@
{
pkgs,
config,
lib,
...
}: {
imports = [
./config.nix
./visuals.nix
];
}

135
modules/visuals/visuals.nix Normal file
View file

@ -0,0 +1,135 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.visuals;
in {
options.vim.visuals = {
enable = mkOption {
type = types.bool;
description = "visual enhancements";
};
nvimWebDevicons.enable = mkOption {
type = types.bool;
description = "enable dev icons. required for certain plugins [nvim-web-devicons]";
};
lspkind.enable = mkOption {
type = types.bool;
description = "enable vscode-like pictograms for lsp [lspkind]";
};
cursorWordline = {
enable = mkOption {
type = types.bool;
description = "enable word and delayed line highlight [nvim-cursorline]";
};
lineTimeout = mkOption {
type = types.int;
description = "time in milliseconds for cursorline to appear";
};
};
indentBlankline = {
enable = mkOption {
type = types.bool;
description = "enable indentation guides [indent-blankline]";
};
listChar = mkOption {
type = types.str;
description = "Character for indentation line";
};
fillChar = mkOption {
type = types.str;
description = "Character to fill indents";
};
eolChar = mkOption {
type = types.str;
description = "Character at end of line";
};
showCurrContext = mkOption {
type = types.bool;
description = "Highlight current context from treesitter";
};
};
};
config =
mkIf cfg.enable
{
vim.startPlugins = [
(
if cfg.nvimWebDevicons.enable
then "nvim-web-devicons"
else null
)
(
if cfg.lspkind.enable
then "lspkind"
else null
)
(
if cfg.cursorWordline.enable
then "nvim-cursorline"
else null
)
(
if cfg.indentBlankline.enable
then "indent-blankline"
else null
)
];
vim.luaConfigRC.visuals = nvim.dag.entryAnywhere ''
${
if cfg.lspkind.enable
then "require'lspkind'.init()"
else ""
}
${
if cfg.indentBlankline.enable
then ''
-- highlight error: https://github.com/lukas-reineke/indent-blankline.nvim/issues/59
vim.wo.colorcolumn = "99999"
vim.opt.list = true
${
if cfg.indentBlankline.eolChar == ""
then ""
else ''vim.opt.listchars:append({ eol = "${cfg.indentBlankline.eolChar}" })''
}
${
if cfg.indentBlankline.fillChar == ""
then ""
else ''vim.opt.listchars:append({ space = "${cfg.indentBlankline.fillChar}"})''
}
require("indent_blankline").setup {
char = "${cfg.indentBlankline.listChar}",
show_current_context = ${boolToString cfg.indentBlankline.showCurrContext},
show_end_of_line = true,
}
''
else ""
}
${
if cfg.cursorWordline.enable
then "vim.g.cursorline_timeout = ${toString cfg.cursorWordline.lineTimeout}"
else ""
}
'';
};
}