diff --git a/nix/programs/neovim/default.nix b/nix/programs/neovim/default.nix index ffb4388..f13bb1a 100644 --- a/nix/programs/neovim/default.nix +++ b/nix/programs/neovim/default.nix @@ -1,84 +1,530 @@ { config, lib, pkgs, ... }: -let +with lib; - colorschemeLua = '' - -- [[ COLORSCHEME ]] -- - - local colorscheme = require('base16-colorscheme') - colorscheme.setup({ - base00 = '#${config.theme.colors.base00}', - base01 = '#${config.theme.colors.base01}', - base02 = '#${config.theme.colors.base02}', - base03 = '#${config.theme.colors.base03}', - base04 = '#${config.theme.colors.base04}', - base05 = '#${config.theme.colors.base05}', - base06 = '#${config.theme.colors.base06}', - base07 = '#${config.theme.colors.base07}', - base08 = '#${config.theme.colors.base08}', - base09 = '#${config.theme.colors.base09}', - base0A = '#${config.theme.colors.base0A}', - base0B = '#${config.theme.colors.base0B}', - base0C = '#${config.theme.colors.base0C}', - base0D = '#${config.theme.colors.base0D}', - base0E = '#${config.theme.colors.base0E}', - base0F = '#${config.theme.colors.base0F}', - }) - -''; - - initLua = lib.fileContents ./init.lua; - luaConfig = colorschemeLua + initLua; - -in { - environment.variables.EDITOR = "nvim"; + options = { + neovim = { - home-manager.users.${config.user} = { - programs.neovim = { + tabWidth = mkOption { + type = types.int; + description = "Width of tabes in the editor."; + default = 4; + }; + expandTab = mkOption { + type = types.bool; + description = "If tabs should be expanded to spaces."; + default = false; + }; - enable = true; - viAlias = true; - vimAlias = true; - extraLuaConfig = luaConfig; + keys = { + leader = mkOption { + type = types.str; + description = "NeoVIM leader key"; + default = " "; + }; + noh = mkOption { + type = types.str; + description = "Keybind to remove active hilighted content."; + default = "<leader>h"; + }; - plugins = with pkgs.vimPlugins; [ - # Deoendencies - vim-devicons - nvim-web-devicons - # Lua functions - plenary-nvim - # Lines - lualine-nvim # mode line - bufferline-nvim # buffer line - # Menus - nvim-tree-lua # file browser - undotree # undo menu - trouble-nvim # error menu - telescope-nvim # grep/find menus - # Snippets - vim-vsnip - vim-vsnip-integ - friendly-snippets - # Completion - nvim-cmp - cmp-buffer - cmp-nvim-lsp - cmp-vsnip - nvim-surround # delimiter - # Lsp - base16-nvim # colorscheme - nerdcommenter # comment functions - nvim-treesitter.withAllGrammars # hilighting - vim-illuminate # hilighting - todo-comments-nvim # todo comments - nvim-lspconfig # lsp server - fidget-nvim # notifications - indent-o-matic # auto indentation - hologram-nvim # images - virt-column-nvim # 80 col line - ]; + menus = { + # file browser + browser = mkOption { + type = types.str; + description = "Keybind to open file browser."; + default = "<leader>e"; + }; + # active buffers + buffers = mkOption { + type = types.str; + description = "Keybind to show active buffers."; + default = "<leader>fb"; + }; + # error list + error = mkOption { + type = types.str; + description = "Keybind to show LSP errors."; + default = "<leader>t"; + }; + # find files + find = mkOption { + type = types.str; + description = "Keybind to search files in working directory."; + default = "<leader>ff"; + }; + # grep files + grep = mkOption { + type = types.str; + description = "Keybind to grep files in working directory."; + default = "<leader>fg"; + }; + # help menu + help = mkOption { + type = types.str; + description = "Keybind to search help menus."; + default = "<leader>fh"; + }; + # undo tree + undo = mkOption { + type = types.str; + description = "Keybind to view undo tree."; + default = "<leader>u"; + }; + }; + + # lsp actions + lsp = { + hover = mkOption { + type = types.str; + description = "Keybind to open LSP hover menu on a value."; + default = "K"; + }; + action = mkOption { + type = types.str; + description = "Keybind to perform an LSP action on a value."; + default = "<leader>la"; + }; + references = mkOption { + type = types.str; + description = "Keybind to view all references of a value."; + default = "<leader>lr"; + }; + rename = mkOption { + type = types.str; + description = "Keybind to rename currrent and all references of a value."; + default = "<leader>ln"; + }; + }; + + # completion + cmp = { + prev = mkOption { + type = types.str; + description = "Keybind to select previous value in completion engine."; + default = "<C-p>"; + }; + next = mkOption { + type = types.str; + description = "Keybind to select next value in completion engine."; + default = "<C-n>"; + }; + confirm = mkOption { + type = types.str; + description = "Keybind to confirm current value in completion engine."; + default = "<CR>"; + }; + complete = mkOption { + type = types.str; + description = "Keybind to auto complete using completion engine."; + default = "<C-space>"; + }; + }; + }; + + # active lsp servers + lsps = mkOption { + type = with types; listOf str; + description = "List of lsp servers to load"; + default = ["clangd" "rust_analyzer"]; + }; }; }; + + config = { + environment.variables.EDITOR = "nvim"; + + home-manager.users.${config.user} = { + programs.neovim = { + + enable = true; + viAlias = true; + vimAlias = true; + extraLuaConfig = '' + + --[[ VIM ]]-- + + vim.opt.tabstop = ${toString config.neovim.tabWidth} + vim.opt.softtabstop = ${toString config.neovim.tabWidth} + vim.opt.shiftwidth = ${toString config.neovim.tabWidth} + vim.opt.expandtab = ${boolToString config.neovim.expandTab} + vim.opt.mouse = "a" + vim.opt.clipboard = "unnamedplus" + vim.opt.hlsearch = true + vim.opt.autoindent = true + vim.opt.ttyfast = true + vim.opt.number = true + vim.opt.relativenumber = true + vim.opt.rnu = true + vim.opt.swapfile = false + + + --[[ BUF ]]-- + + -- remove trailing whitespace on save + vim.api.nvim_create_autocmd({ "BufWritePre" }, { + pattern = { "*" }, + command = [[%s/\s\+$//e]], + }) + + --[[ KEYBINDS ]]-- + + -- leader + + vim.g.mapleader = "${config.neovim.keys.leader}" + vim.g.maplocalleader = "${config.neovim.keys.leader}" + vim.keymap.set("", '<leader>', '<Nop>', { noremap = true, silent = true }) + + -- bind helper function + + local function bind(key, action, opts) + opts = opts or {} + vim.keymap.set('n', key, action, opts) + end + + -- lsp + + bind("${config.neovim.keys.noh}", vim.cmd.noh) + + vim.api.nvim_create_autocmd('LspAttach', { + desc = 'LSP actions', + callback = function(event) + local opts = {buffer = event.buf} + bind("${config.neovim.keys.lsp.hover}", function() vim.lsp.buf.hover() end, opts) + bind("${config.neovim.keys.lsp.action}", function() vim.lsp.buf.code_action() end, opts) + bind("${config.neovim.keys.lsp.references}", function() vim.lsp.buf.references() end, opts) + bind("${config.neovim.keys.lsp.rename}", function() vim.lsp.buf.rename() end, opts) + end + }) + + ''; + + plugins = with pkgs.vimPlugins; [ + # Deoendencies + vim-devicons + nvim-web-devicons + plenary-nvim + # Colorscheme + { + plugin = base16-nvim; + type = "lua"; + config = '' + vim.opt.termguicolors = true + vim.g.base16_transparent_background = 1 + + local colorscheme = require('base16-colorscheme') + colorscheme.setup({ + base00 = '#${config.theme.colors.base00}', + base01 = '#${config.theme.colors.base01}', + base02 = '#${config.theme.colors.base02}', + base03 = '#${config.theme.colors.base03}', + base04 = '#${config.theme.colors.base04}', + base05 = '#${config.theme.colors.base05}', + base06 = '#${config.theme.colors.base06}', + base07 = '#${config.theme.colors.base07}', + base08 = '#${config.theme.colors.base08}', + base09 = '#${config.theme.colors.base09}', + base0A = '#${config.theme.colors.base0A}', + base0B = '#${config.theme.colors.base0B}', + base0C = '#${config.theme.colors.base0C}', + base0D = '#${config.theme.colors.base0D}', + base0E = '#${config.theme.colors.base0E}', + base0F = '#${config.theme.colors.base0F}', + }) + + -- make transparent background + vim.api.nvim_set_hl(0, "Normal", { bg = "none" }) + vim.api.nvim_set_hl(0, "NormalFloat", { bg = "none" }) + vim.api.nvim_set_hl(0, 'EndOfBuffer', { bg = "none" }) + -- identifiers should not be colored + vim.api.nvim_set_hl(0, "Identifier", { fg = "#${config.theme.colors.base05}" }) + vim.api.nvim_set_hl(0, "TSVariable", { fg = "#${config.theme.colors.base05}" }) + -- macro should be colored as a keyword + vim.api.nvim_set_hl(0, "TSFuncMacro", { fg = "#${config.theme.colors.base0E}" }) + -- comments are too dark + vim.api.nvim_set_hl(0, "Comment", { fg = "#${config.theme.colors.base07}" }) + vim.api.nvim_set_hl(0, "@comment", { link = "Comment" }) + ''; + } + # Mode line + { + plugin = lualine-nvim; + type = "lua"; + config = '' + require('lualine').setup { + options = { + theme = 'base16', + icons_enabled = true, + globalstatus = true, + }, + }; + ''; + } + # Buffer line + { + plugin = bufferline-nvim; + type = "lua"; + config = '' + require('bufferline').setup {} + ''; + } + # File browser + { + plugin = nvim-tree-lua; + type = "lua"; + config = '' + vim.g.loaded_netrw = 1 + vim.g.loaded_netrwPlugin = 1 + + require('nvim-tree').setup { + sort = { + sorter = "case_sensitive", + }, + view = { + centralize_selection = true, + signcolumn = "yes", + float = { + enable = true, + quit_on_focus_loss = true, + open_win_config = { + relative = "editor", + border = "rounded", + width = 60, + height = 20, + row = 1, + col = 1, + }, + }; + }, + renderer = { + group_empty = true, + }, + actions = { + use_system_clipboard = true, + change_dir = { + enable = true, + global = false, + restrict_above_cwd = false, + }, + expand_all = { + max_folder_discovery = 300, + exclude = {}, + }, + file_popup = { + open_win_config = { + col = 1, + row = 1, + relative = "cursor", + border = "shadow", + style = "minimal", + }, + }, + open_file = { + quit_on_open = true, + window_picker = { + enable = false, + picker = "default", + chars = "abcdefghijklmnopqrstuvwxyz1234567890", + exclude = { + filetype = { "notify", "lazy", "qf", "diff", "fugitive", "fugitiveblame" }, + buftype = { "nofile", "terminal", "help" }, + }, + } + }, + remove_file = { + close_window = true, + }, + }, + filters = { + dotfiles = false, + }, + tab = { + sync = { + open = false, + close = false, + ignore = {}, + }, + }, + git = { + enable = false, + }, + update_cwd = true, + respect_buf_cwd = true, + update_focused_file = { + enable = true, + update_cwd = true + }, + }; + + bind("${config.neovim.keys.menus.browser}", vim.cmd.NvimTreeToggle) + ''; + } + # Undo tree + { + plugin = undotree; + type = "lua"; + config = '' + bind("${config.neovim.keys.menus.undo}", vim.cmd.UndotreeToggle) + ''; + } + # Trouble (error menu) + { + plugin = trouble-nvim; + type = "lua"; + config = '' + bind("${config.neovim.keys.menus.error}", function() require('trouble').toggle() end) + ''; + } + # Telescope (buffers/find/grep/help) + { + plugin = telescope-nvim; + type = "lua"; + config = '' + local telescope = require('telescope.builtin') + bind("${config.neovim.keys.menus.buffers}", telescope.buffers) + bind("${config.neovim.keys.menus.find}", telescope.find_files) + bind("${config.neovim.keys.menus.grep}", telescope.live_grep) + bind("${config.neovim.keys.menus.help}", telescope.help_tags) + vim.api.nvim_set_hl(0, 'TelescopeNormal', { bg = "none" }) + vim.api.nvim_set_hl(0, 'TelescopeBorder', { bg = "none" }) + vim.api.nvim_set_hl(0, 'TelescopeResultsTitle', { bg = "none" }) + vim.api.nvim_set_hl(0, 'TelescopePromptTitle', { bg = "none" }) + vim.api.nvim_set_hl(0, 'TelescopePreviewTitle', { bg = "none" }) + vim.api.nvim_set_hl(0, 'TelescopePromptNormal', { bg = "none" }) + vim.api.nvim_set_hl(0, 'TelescopePromptBorder', { bg = "none" }) + ''; + } + # Snippets + vim-vsnip + vim-vsnip-integ + friendly-snippets + # Completion + cmp-buffer + cmp-nvim-lsp + cmp-vsnip + { + plugin = nvim-cmp; + type = "lua"; + config = '' + local cmp = require('cmp'); + local cmp_select = {behavior = cmp.SelectBehavior.select} + local cmp_mappings = cmp.mapping.preset.insert({ + ["${config.neovim.keys.cmp.prev}"] = cmp.mapping.select_prev_item(cmp_select), + ["${config.neovim.keys.cmp.next}"] = cmp.mapping.select_next_item(cmp_select), + ["${config.neovim.keys.cmp.confirm}"] = cmp.mapping.confirm({ select = true }), + ["${config.neovim.keys.cmp.complete}"] = cmp.mapping.complete(), + }) + + cmp_mappings['<Tab>'] = nil + cmp_mappings['<S-Tab>'] = nil + + cmp.setup { + snippet = { + expand = function(args) + vim.fn["vsnip#anonymous"](args.body) + end, + }, + sources = cmp.config.sources { + { name = 'nvim_lsp' }, + { name = 'vsnip' }, + { name = 'buffer' }, + }, + mapping = cmp_mappings, + } + ''; + } + # Sourround delimiters + { + plugin = nvim-surround; + type = "lua"; + config = '' + require('nvim-surround').setup {} + ''; + } + # Comment functions + nerdcommenter + # Treesitter + nvim-treesitter.withAllGrammars + # Syntax hilighting + { + plugin = vim-illuminate; + type = "lua"; + config = '' + require('illuminate').configure { + providers = { + 'lsp', + 'treesitter', + 'regex', + }, + } + ''; + } + # Todo comments + { + plugin = todo-comments-nvim; + type = "lua"; + config = '' + require('todo-comments').setup() + ''; + } + # Lsp server + { + plugin = nvim-lspconfig; + type = "lua"; + config = let + lspConfigs = map (server: '' + lspconfig["${server}"].setup({ + capabilities = capabilities + }) + '') config.neovim.lsps; + in '' + local lspconfig = require('lspconfig') + local capabilities = require'cmp_nvim_lsp'.default_capabilities() + ${lib.concatStrings lspConfigs} + ''; + } + # Notifications + { + plugin = fidget-nvim; + type = "lua"; + config = '' + require("fidget").setup { + notification = { + window = { + winblend = 0, + }, + }, + } + ''; + } + # Auto indentation + { + plugin = indent-o-matic; + type = "lua"; + config = '' + require('indent-o-matic').setup { + max_lines = 2048, + standard_widths = { 2, 4, 8 }, + skip_multiline = true, + }; + ''; + } + # 80 column width + { + plugin = virt-column-nvim; + type = "lua"; + config = '' + require('virt-column').setup { + enabled = true, + virtcolumn = "80" + } + ''; + } + ]; + + }; + }; + }; } diff --git a/nix/programs/neovim/init.lua b/nix/programs/neovim/init.lua deleted file mode 100644 index 50d50c8..0000000 --- a/nix/programs/neovim/init.lua +++ /dev/null @@ -1,246 +0,0 @@ ---[[ CONFIG ]]-- - --- global config for iris configuration -config = { - -- colorscheme for nvim - flavour = "mocha", - -- indentation - tab_width = 4, - expand_tab = false, - -- keybinds to be set to actions - keybinds = { - -- leader key - leader = ' ', - -- toggle menus - menus = { - -- file browser - browser = '<leader>e', - -- active buffers - buffers = '<leader>fb', - -- error list - error = '<leader>t', - -- find files - find = '<leader>ff', - -- grep files - grep = '<leader>fg', - -- help browser - help = '<leader>fh', - -- undo tree - undo = '<leader>u', - }, - -- lsp actions - lsp = { - hover = 'K', - action = '<leader>la', - references = '<leader>lr', - rename = '<leader>ln', - }, - -- completion - cmp = { - -- prev item - prev = '<C-p>', - -- next item - next = '<C-n>', - -- confirm - confirm = '<CR>', - -- complete - complete = '<C-Space>', - }, - -- disable active selection - noh = '<leader>h', - }, - -- lsp servers - lsps = { - -- rust - rust_analyzer = {}, - -- c / c++ - clangd = {}, - -- java - jdtls = {}, - }, -}; - ---[[ VIM ]]-- - -vim.opt.tabstop = config.tab_width -vim.opt.softtabstop = config.tab_width -vim.opt.shiftwidth = config.tab_width -vim.opt.expandtab = config.expand_tab -vim.opt.mouse = "a" -vim.opt.clipboard = "unnamedplus" -vim.opt.hlsearch = true -vim.opt.autoindent = true -vim.opt.ttyfast = true -vim.opt.number = true -vim.opt.relativenumber = true -vim.opt.rnu = true -vim.opt.swapfile = false -vim.opt.termguicolors = true - --- remove trailing whitespace on save -vim.api.nvim_create_autocmd({ "BufWritePre" }, { - pattern = { "*" }, - command = [[%s/\s\+$//e]], -}) - ---[[ THEME ]]-- - -vim.api.nvim_set_hl(0, "Normal", { bg = "none" }) -vim.api.nvim_set_hl(0, "NormalFloat", { bg = "none" }) -vim.api.nvim_set_hl(0, "NvimTreeNormal", { bg = "none" }) -vim.api.nvim_set_hl(0, "Comment", { fg = colorscheme.colors.base04 }) -vim.api.nvim_set_hl(0, "@comment", { link = "Comment" }) - ---[[ LINES ]]-- - --- mode line -require('lualine').setup { - options = { - theme = config.colorscheme, - icons_enabled = true, - globalstatus = true, - }, -} - --- buffer line -require("bufferline").setup {} - ---[[ MENUS ]]-- - --- file browser -vim.g.loaded_netrw = 1 -vim.g.loaded_netrwPlugin = 1 -vim.opt.termguicolors = true - -require("nvim-tree").setup { - sort = { - sorter = "case_sensitive", - }, - view = { - width = 30, - }, - renderer = { - group_empty = true, - }, - actions = { - open_file = { - quit_on_open = true, - }, - }, - filters = { - dotfiles = false, - }, -} - ---[[ COMPLETION ]]-- - --- completion engine ---local cmp = require('cmp') --- ---local cmp_select = {behavior = cmp.SelectBehavior.Select} ---local cmp_mappings = cmp.mapping.preset.insert({ --- [config.keybinds.cmp.prev] = cmp.mapping.select_prev_item(cmp_select), --- [config.keybinds.cmp.next] = cmp.mapping.select_next_item(cmp_select), --- [config.keybinds.cmp.confirm] = cmp.mapping.confirm({ select = true }), --- [config.keybinds.cmp.complete] = cmp.mapping.complete(), ---}) --- ---cmp_mappings['<Tab>'] = nil ---cmp_mappings['<S-Tab>'] = nil --- ---cmp.setup { --- snippet = { --- expand = function(args) --- vim.fn["vsnip#anonymous"](args.body) --- end, --- }, --- sources = cmp.config.sources({ --- { name = 'nvim_lsp' }, --- { name = 'vsnip' }, --- { name = 'buffer' }, --- }), --- mapping = cmp_mappings, ---} --- --- delimiter completion -require'nvim-surround'.setup {} - ---[[ LSP ]]-- - -local capabilities = require'cmp_nvim_lsp'.default_capabilities() -for lsp,config in pairs(config.lsps) do - config.capabilities = capabilities - require'lspconfig'[lsp].setup(config) -end - --- illuminate -require'illuminate'.configure { - providers = { - 'lsp', - 'treesitter', - 'regex', - }, -} - --- todo comments -require('todo-comments').setup() - --- auto indentation -require('indent-o-matic').setup { - max_lines = 2048, - standard_widths = { 2, 4, 8 }, - skip_multiline = true, -} - --- image viewer ---require'hologram'.setup { --- auto_display = true ---} - --- 80 col bar -require'virt-column'.setup { - enabled = true, - virtcolumn = "80" -} - --- notifications -require("fidget").setup { - notification = { - window = { - winblend = 0, - }, - }, -} - ---[[ KEYBINDS ]]-- - -vim.g.mapleader = config.keybinds.leader -vim.g.maplocalleader = config.keybinds.leader -vim.keymap.set('', '<leader>', '<Nop>', { noremap = true, silent = true }) - -local function bind(key, action, opts) - opts = opts or {} - vim.keymap.set('n', key, action, opts) -end - -bind(config.keybinds.noh, vim.cmd.noh) -bind(config.keybinds.menus.browser, vim.cmd.NvimTreeToggle) -bind(config.keybinds.menus.undo, vim.cmd.UndotreeToggle) -bind(config.keybinds.menus.error, function() require'trouble'.toggle() end) - -local telescope = require'telescope.builtin' -bind(config.keybinds.menus.buffers, telescope.buffers) -bind(config.keybinds.menus.find, telescope.find_files) -bind(config.keybinds.menus.grep, telescope.live_grep) -bind(config.keybinds.menus.help, telescope.help_tags) - -vim.api.nvim_create_autocmd('LspAttach', { - desc = 'LSP actions', - callback = function(event) - local opts = {buffer = event.buf} - bind(config.keybinds.lsp.hover, function() vim.lsp.buf.hover() end, opts) - bind(config.keybinds.lsp.action, function() vim.lsp.buf.code_action() end, opts) - bind(config.keybinds.lsp.references, function() vim.lsp.buf.references() end, opts) - bind(config.keybinds.lsp.rename, function() vim.lsp.buf.rename() end, opts) - end -})