diff --git a/modules/core/default.nix b/modules/core/default.nix index a43a259..af9331d 100644 --- a/modules/core/default.nix +++ b/modules/core/default.nix @@ -59,12 +59,6 @@ in { pull.rebase = true; }; }; - neovim = { - enable = true; - viAlias = true; - vimAlias = true; - defaultEditor = true; - }; }; system = { diff --git a/users/common/default.nix b/users/common/default.nix index 0abd684..9e5b98e 100644 --- a/users/common/default.nix +++ b/users/common/default.nix @@ -8,7 +8,7 @@ ./fish.nix ./git.nix ./htop.nix - #./neovim + ./neovim #./ssh.nix ./starship.nix #./tmux.nix diff --git a/users/common/neovim/default.nix b/users/common/neovim/default.nix new file mode 100644 index 0000000..7022ec1 --- /dev/null +++ b/users/common/neovim/default.nix @@ -0,0 +1,17 @@ +{ + lib, + pkgs, + ... +}: { + programs = { + neovim = { + enable = true; + viAlias = true; + vimAlias = true; + vimdiffAlias = true; + defaultEditor = true; + }; + }; + xdg.configFile."nvim/lua".source = ./lua; + xdg.configFile."nvim/init.lua".source = ./init.lua; +} diff --git a/users/common/neovim/init.lua b/users/common/neovim/init.lua new file mode 100644 index 0000000..51d73e2 --- /dev/null +++ b/users/common/neovim/init.lua @@ -0,0 +1,171 @@ +pcall(require, "impatient") +require "options" +require "keymaps" + +-- TODO: this should be in treesitter.lua, but it doesn't work there. +-- Something is overriding it. +-- Use treesitter to determine folds, and always start unfolded. +-- FIXME: disabled because extremely slow. apparently called for each line. +--vim.opt.foldlevelstart = 99 +--vim.opt.foldmethod = 'expr' +--vim.opt.foldexpr = 'nvim_treesitter#foldexpr()' + +local function conf_module(module) + return "require('plugins." .. module .. "')" +end +local function conf_setup(module) + return "require('" .. module .. "').setup(require('plugins.others')['" .. module .. "'] or {})" +end +local function conf_fn(module) + return "require('plugins.others')['" .. module .. "']()" +end +local bootstrap = require "utils.bootstrap" +local packer_bootstrap = bootstrap.ensure_packer() +local packer = require "packer" + +return packer.startup(function(use) + use "wbthomason/packer.nvim" -- Packer can manage itself + use "lewis6991/impatient.nvim" -- Lua module cache + + ---------------------------------------------------------------------------------------------------- + -- Library plugins + ---------------------------------------------------------------------------------------------------- + + -- Utility functions + use "nvim-lua/plenary.nvim" + use "nvim-lua/popup.nvim" + use "MunifTanjim/nui.nvim" + -- Notifications (should be early) + use { "rcarriga/nvim-notify", config = conf_fn "notify" } + -- Icon definitions for use in other plugins + use { "kyazdani42/nvim-web-devicons", config = conf_fn "nvim-web-devicons" } + + ---------------------------------------------------------------------------------------------------- + -- Appearance + ---------------------------------------------------------------------------------------------------- + + -- Colorscheme + use { "navarasu/onedark.nvim", config = conf_fn "onedark" } + -- Statusline + use { "nvim-lualine/lualine.nvim", config = conf_fn "lualine", after = "onedark.nvim" } + -- Colored parentheses + use "p00f/nvim-ts-rainbow" + -- Line indentation markers + use { "lukas-reineke/indent-blankline.nvim", config = conf_setup "indent_blankline" } + -- Show invalid whitespace + use { "ntpeters/vim-better-whitespace", config = conf_fn "better-whitespace" } + -- Git status in signcolumn + use { "lewis6991/gitsigns.nvim", config = conf_module "gitsigns" } + -- Replace built-in LSP prompts and windows + use { "stevearc/dressing.nvim", config = conf_setup "dressing" } + -- Status updates for LSP progress in right bottom corner. + use { "j-hui/fidget.nvim", after = "nvim-lspconfig", config = conf_setup "fidget" } + -- Show latex math equations + use { "jbyuki/nabla.nvim", config = conf_fn "nabla" } + -- Show colors + use { "norcalli/nvim-colorizer.lua", config = conf_setup "colorizer" } + + ---------------------------------------------------------------------------------------------------- + -- Language support + ---------------------------------------------------------------------------------------------------- + + -- Syntax parsing + use { "nvim-treesitter/nvim-treesitter", run = ":TSUpdate", config = conf_module "treesitter" } + use { "nvim-treesitter/playground", after = "nvim-treesitter" } + -- Rust specific tools + use { "simrat39/rust-tools.nvim", before = "nvim-lspconfig" } + -- Language server configurations + use { "neovim/nvim-lspconfig", config = conf_module "lspconfig", after = "mason-lspconfig.nvim" } + -- Neovim as an additional language server + use { "jose-elias-alvarez/null-ls.nvim", config = conf_fn "null-ls" } + + ---------------------------------------------------------------------------------------------------- + -- Editing + ---------------------------------------------------------------------------------------------------- + + -- Multicursor + use { "mg979/vim-visual-multi" } + -- Commenting + use { "numToStr/Comment.nvim", config = conf_setup "Comment" } + -- Modify Surrounding things like parenthesis and quotes + use { "machakann/vim-sandwich", config = conf_fn "sandwich" } + -- Extend vim's "%" key + use "andymass/vim-matchup" + -- Align + use "junegunn/vim-easy-align" + -- Move blocks + use { "booperlv/nvim-gomove", config = conf_setup "gomove" } + -- Case changer + use "johmsalas/text-case.nvim" + -- camelcase (and similar) word motions and textobjects + use { "chaoren/vim-wordmotion", config = conf_fn "wordmotion" } + -- Codex completion + use { "tom-doerr/vim_codex" } + + ---------------------------------------------------------------------------------------------------- + -- Functionality + ---------------------------------------------------------------------------------------------------- + + -- Startup screen + use { "goolord/alpha-nvim", config = conf_module "alpha" } + -- Language server / DAP installer + use { "williamboman/mason.nvim", config = conf_setup "mason" } + use { "williamboman/mason-lspconfig.nvim", config = conf_setup "mason-lspconfig", after = "mason.nvim" } + -- Window Picker + use { "s1n7ax/nvim-window-picker", tag = "v1.*", config = conf_setup "window-picker" } + -- Filebrowser + use { "nvim-neo-tree/neo-tree.nvim", branch = "main", config = conf_module "neo-tree" } + -- Telescope fzf native + use { "nvim-telescope/telescope-fzf-native.nvim", run = "make" } + -- Anything Picker + use { + "nvim-telescope/telescope.nvim", + config = conf_module "telescope", + after = { "telescope-fzf-native.nvim", "nvim-notify" }, + } + -- Git integration + use "tpope/vim-fugitive" + use "sindrets/diffview.nvim" + -- FIXME: still broken and unusable + --use { "TimUntersberger/neogit", config = conf_setup "neogit" } + -- Undo tree + use { "mbbill/undotree", config = conf_fn "undotree" } + -- Gpg integration + use "jamessan/vim-gnupg" + + ---------------------------------------------------------------------------------------------------- + -- Completion + ---------------------------------------------------------------------------------------------------- + + -- Completion engine + use { "hrsh7th/nvim-cmp", config = conf_module "cmp" } + -- Snippet engine + use { "L3MON4D3/LuaSnip", after = "nvim-cmp" } + -- Luasnip completion source + use { "saadparwaiz1/cmp_luasnip", after = "LuaSnip" } + -- Internal LSP completion source + use { "hrsh7th/cmp-nvim-lsp", after = "cmp_luasnip" } + -- Buffer words completion source + use { "hrsh7th/cmp-buffer", after = "cmp_luasnip" } + -- Cmdline completion source + use { "hrsh7th/cmp-cmdline", after = "cmp_luasnip" } + -- path completion source + use { "hrsh7th/cmp-path", after = "cmp_luasnip" } + -- emoji completion source + use { "hrsh7th/cmp-emoji", after = "cmp_luasnip" } + -- Shows function signatures on hover + use "ray-x/lsp_signature.nvim" + + ---------------------------------------------------------------------------------------------------- + -- Miscellaneous + ---------------------------------------------------------------------------------------------------- + + use { "folke/trouble.nvim", config = conf_setup "trouble" } + use { "folke/todo-comments.nvim", config = conf_setup "todo-comments" } + use { "liuchengxu/vista.vim", cmd = "Vista" } + + -- Automatically sync after installing for the first time + if packer_bootstrap then + packer.sync() + end +end) diff --git a/users/common/neovim/lua/keymaps.lua b/users/common/neovim/lua/keymaps.lua new file mode 100644 index 0000000..a4f4985 --- /dev/null +++ b/users/common/neovim/lua/keymaps.lua @@ -0,0 +1,125 @@ +local default_opts = { noremap = true, silent = true } +local function map(mode, lhs, rhs, opts) + for c in mode:gmatch "." do + vim.api.nvim_set_keymap(c, lhs, rhs, opts or default_opts) + end +end + +---------------------------------------------------------------------------------------------------- +-- General +---------------------------------------------------------------------------------------------------- + +-- Shift + scroll with cursor locked to position +map("", "", "") +map("", "", "") +map("i", "", "a") +map("i", "", "a") + +-- Shift + Alt + change the current window size +map("n", "", ":resize -2") +map("n", "", ":resize +2") +map("n", "", ":vertical resize -2") +map("n", "", ":vertical resize +2") + +-- Allow exiting terminal mode +map("t", "", "") +-- Allow C-w in terminal mode +map("t", "", "") + +-- Open fixed size terminal window at the bottom +map("n", "", ":belowright new | setlocal wfh | resize 10 | terminal") + +---------------------------------------------------------------------------------------------------- +-- Language server +---------------------------------------------------------------------------------------------------- + +map("n", "gD", "lua vim.lsp.buf.declaration()") +map("n", "gd", "lua require('telescope.builtin').lsp_definitions()") +map("n", "K", "lua vim.lsp.buf.hover()") +map("n", "gi", "lua require('telescope.builtin').lsp_implementations()") +map("n", "", "lua vim.lsp.buf.signature_help()") +map("n", "wa", "lua vim.lsp.buf.add_workspace_folder()") +map("n", "wr", "lua vim.lsp.buf.remove_workspace_folder()") +map("n", "wl", "lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))") +map("n", "gt", "lua require('telescope.builtin').lsp_type_definitions()") +map("n", "r", "lua vim.lsp.buf.rename()") +map("n", "a", "lua vim.lsp.buf.code_action()") +map("n", "gr", "lua require('telescope.builtin').lsp_references()") +map("n", "gl", "lua vim.diagnostic.open_float()") +map("n", "[d", "lua vim.diagnostic.goto_prev()") +map("n", "]d", "lua vim.diagnostic.goto_next()") +map("n", "q", "lua vim.diagnostic.setloclist()") +map("n", "f", "lua vim.lsp.buf.format { async = true }") + +---------------------------------------------------------------------------------------------------- +-- Plugin: Easy Align +---------------------------------------------------------------------------------------------------- + +map("n", "A", "(EasyAlign)") +map("v", "A", "(EasyAlign)") + +---------------------------------------------------------------------------------------------------- +-- Plugin: Undotree +--[[ ---------------------------------------------------------------------------------------------------- +]] +map("n", "u", ":UndotreeToggle") + +---------------------------------------------------------------------------------------------------- +-- Plugin: Better Whitespace +---------------------------------------------------------------------------------------------------- + +map("n", "$", ":StripWhitespace") + +---------------------------------------------------------------------------------------------------- +-- Plugin: Neotree +---------------------------------------------------------------------------------------------------- + +-- Mappings to open the tree / find the current file +map("n", "t", ":Neotree toggle") +map("n", "T", ":Neotree reveal") +map("n", "G", ":Neotree float git_status") +map("n", "b", ":Neotree float buffers") + +---------------------------------------------------------------------------------------------------- +-- Plugin: Sandwich +---------------------------------------------------------------------------------------------------- + +map("nv", "m", "(operator-sandwich-add)") +map("nv", "M", "(operator-sandwich-delete)") +map("nv", "C-m", "(operator-sandwich-replace)") + +---------------------------------------------------------------------------------------------------- +-- Plugin: gomove +---------------------------------------------------------------------------------------------------- + +--map("n", "", "GoNSMLeft") +--map("n", "", "GoNSMDown") +--map("n", "", "GoNSMUp") +--map("n", "", "GoNSMRight") + +map("x", "", "GoVSMLeft") +map("x", "", "GoVSMDown") +map("x", "", "GoVSMUp") +map("x", "", "GoVSMRight") + +--map("n", "", "GoNSDLeft") +--map("n", "", "GoNSDDown") +--map("n", "", "GoNSDUp") +--map("n", "", "GoNSDRight") + +map("x", "", "GoVSDLeft") +map("x", "", "GoVSDDown") +map("x", "", "GoVSDUp") +map("x", "", "GoVSDRight") + +---------------------------------------------------------------------------------------------------- +-- Plugin: wordmotion +---------------------------------------------------------------------------------------------------- + +map("xo", "ie", "WordMotion_iw") + +---------------------------------------------------------------------------------------------------- +-- Plugin: textcase +---------------------------------------------------------------------------------------------------- + +-- TODO: ... keybinds + telescope integration diff --git a/users/common/neovim/lua/options.lua b/users/common/neovim/lua/options.lua new file mode 100644 index 0000000..fe462da --- /dev/null +++ b/users/common/neovim/lua/options.lua @@ -0,0 +1,68 @@ +local opt = vim.opt +local g = vim.g + +g.python3_host_prog = vim.fn.stdpath "data" .. "/venv/bin/python3" +g.mapleader = "," + +---------------------------------------------------------------------------------------------------- +-- General +---------------------------------------------------------------------------------------------------- + +opt.undolevels = 1000000 -- Set maximum undo levels +opt.undofile = true -- Enable persistent undo which persists undo history across vim sessions +opt.updatetime = 300 -- Save swap file after 300ms +opt.mouse = "a" -- Enable full mouse support + +---------------------------------------------------------------------------------------------------- +-- Editor visuals +---------------------------------------------------------------------------------------------------- + +opt.termguicolors = true -- Enable true color in terminals + +-- FIXME: TODO: neovim after 0.8: enable this! +--opt.splitkeep = 'screen' -- Try not to move text when opening/closing splits +opt.wrap = false -- Do not wrap text longer than the window's width +opt.scrolloff = 2 -- Keep 2 lines above and below the cursor. +opt.sidescrolloff = 2 -- Keep 2 lines left and right of the cursor. + +opt.number = true -- Show line numbers +opt.cursorline = true -- Enable cursorline, colorscheme only shows this in number column +opt.wildmode = { "list", "full" } -- Only complete the longest common prefix and list all results +opt.fillchars = { stlnc = "─" } -- Show separators in inactive window statuslines + +-- FIXME: disabled because this really fucks everything up in the terminal. +opt.title = false -- Sets the window title +--opt.titlestring = "%t%( %M%)%( (%{expand(\"%:~:.:h\")})%) - nvim" -- The format for the window title + +-- Hide line numbers in terminal windows +vim.api.nvim_exec([[au BufEnter term://* setlocal nonumber]], false) + +---------------------------------------------------------------------------------------------------- +-- Editing behavior +---------------------------------------------------------------------------------------------------- + +opt.whichwrap = "" -- Never let the curser switch to the next line when reaching line end +opt.ignorecase = true -- Ignore case in search by default +opt.smartcase = true -- Be case sensitive when an upper-case character is included + +opt.expandtab = false +opt.tabstop = 4 -- Set indentation of tabs to be equal to 4 spaces. +opt.shiftwidth = 4 +opt.softtabstop = 4 +opt.shiftround = true -- Round indentation commands to next multiple of shiftwidth + +opt.formatoptions = "rqj" -- r = insert comment leader when hitting in insert mode +-- q = allow explicit formatting with gq +-- j = remove comment leaders when joining lines if it makes sense + +opt.virtualedit = "all" -- Allow the curser to be positioned on cells that have no actual character; +-- Like moving beyond EOL or on any visual 'space' of a tab character +opt.selection = "old" -- Do not include line ends in past the-line selections +opt.smartindent = true -- Use smart auto indenting for all file types + +opt.timeoutlen = 20 -- Only wait 20 milliseconds for characters to arrive (see :help timeout) +opt.ttimeoutlen = 20 +opt.timeout = false -- Disable timeout, but enable ttimeout (only timeout on keycodes) +opt.ttimeout = true + +opt.grepprg = "rg --vimgrep --smart-case --follow" -- Replace grep with ripgrep diff --git a/users/common/neovim/lua/plugins/alpha.lua b/users/common/neovim/lua/plugins/alpha.lua new file mode 100644 index 0000000..f6b634a --- /dev/null +++ b/users/common/neovim/lua/plugins/alpha.lua @@ -0,0 +1,86 @@ +local function button(shortcut, txt, keybind, keybind_opts) + local opts = { + position = "center", + shortcut = shortcut, + cursor = 5, + width = 50, + align_shortcut = "right", + hl_shortcut = "Keyword", + } + + if keybind then + keybind_opts = vim.F.if_nil(keybind_opts, { noremap = true, silent = true }) + opts.keymap = { "n", shortcut, keybind, keybind_opts } + end + + local function on_press() + local key = vim.api.nvim_replace_termcodes(shortcut .. "", true, false, true) + vim.api.nvim_feedkeys(key, "normal", false) + end + + return { + type = "button", + val = txt, + on_press = on_press, + opts = opts, + } +end + +local function buttons(xs, spacing) + return { + type = "group", + val = xs, + opts = { spacing = vim.F.if_nil(spacing, 1) }, + } +end + +local function text(value, hl) + return { + type = "text", + val = value, + opts = { + position = "center", + hl = hl, + }, + } +end + +local function pad(lines) + return { type = "padding", val = lines } +end + +local header = { + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣶⣶⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⠀⢸⣄⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⠛⠀⠀⠹⣧⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⠀⠀⠀⠀⣿⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⢠⠀⡄⠀⣿⠀⢀⣤⣤⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⢰⡏⠚⠀⠃⠀⣿⣴⠞⠉⢹⠀⠀", + "⠀⣀⡀⠀⠀⠀⠀⢀⣸⠇⠀⠀⠀⠀⠈⠀⠀⣀⡿⠀⠀", + "⢸⣟⠛⢳⣤⣤⡶⠛⠃⠀⣠⠀⠀⠀⠚⣶⡾⠟⠀⠀⠀", + "⠀⠉⢷⣤⣀⣀⣀⣀⣠⡾⠻⣧⡀⠀⠀⢘⣷⣄⣀⣤⣄", + "⠀⠀⠀⠈⠉⠉⠉⠉⠉⠀⠀⠘⠻⣦⣤⣈⣁⣀⣠⣾⠋", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠉⠉⠉⠀⠀", +} + +require("alpha").setup { + layout = { + pad(2), + text(header, "Type"), + --pad(2), text(separator, 'Number'), + pad(2), + buttons { + button("e", " New file", ":enew"), + --button("f", " Find file", ":Telescope find_files"), + --button("w", " Find word", ":Telescope grep_string"), + }, + pad(2), + buttons { + button("u", " Update plugins", ":PackerSync"), + button("h", " Check health", ":checkhealth"), + button("q", " Quit", ":qa"), + }, + --text(separator, 'Number'), + }, + opts = { margin = 5 }, +} diff --git a/users/common/neovim/lua/plugins/cmp.lua b/users/common/neovim/lua/plugins/cmp.lua new file mode 100644 index 0000000..377c94c --- /dev/null +++ b/users/common/neovim/lua/plugins/cmp.lua @@ -0,0 +1,97 @@ +-- TODO: lspconfig keymappings +-- TODO: a inserts literal tab instead of completing when in a word with characters ahead +-- TODO: some way to search fuzzy in completion window +-- TODO: completion should be repeatable with . +local cmp = require "cmp" +if cmp == nil then + return +end + +local icons = require("utils.icons").lspkind +local luasnip = require "luasnip" +local compare = cmp.config.compare + +-- Show completion menu also if only one item is available (for context) +vim.opt.completeopt = { "menu", "menuone", "preview" } + +local has_words_before = function() + local line, col = table.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 + +cmp.setup { + snippet = { + expand = function(args) + luasnip.lsp_expand(args.body) + end, + }, + formatting = { + format = function(_, vim_item) + vim_item.kind = string.format("%s %s", icons[vim_item.kind], vim_item.kind) + return vim_item + end, + }, + mapping = cmp.mapping.preset.insert { + [""] = cmp.config.disable, + [""] = cmp.mapping.scroll_docs(-4), + [""] = cmp.mapping.scroll_docs(4), + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.close(), + [""] = cmp.mapping.confirm { + behavior = cmp.ConfirmBehavior.Replace, + select = false, + }, + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_next_item() + elseif luasnip.expand_or_jumpable() then + luasnip.expand_or_jump() + elseif has_words_before() then + cmp.complete() + else + fallback() + end + end, { "i", "s", "c" }), + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif luasnip.jumpable(-1) then + luasnip.jump(-1) + else + fallback() + end + end, { "i", "s", "c" }), + }, + sorting = { + priority_weight = 2, + comparators = { + compare.locality, + compare.recently_used, + compare.offset, + compare.exact, + -- compare.scopes, + compare.score, + compare.kind, + compare.sort_text, + compare.length, + compare.order, + }, + }, + sources = cmp.config.sources({ + { name = "path", priority_weight = 105 }, + { name = "luasnip", priority_weight = 103 }, + { name = "nvim_lsp", priority_weight = 100 }, + { name = "nvim_lsp_signature_help", priority_weight = 99 }, + { name = "nvim_lua", priority_weight = 60 }, + { name = "buffer", priority_weight = 50 }, + { name = "emoji", priority_weight = 50 }, + }, { + { name = "buffer", priority_weight = 50 }, + }), +} + +cmp.setup.cmdline(":", { + sources = { + { name = "cmdline" }, + }, +}) diff --git a/users/common/neovim/lua/plugins/gitsigns.lua b/users/common/neovim/lua/plugins/gitsigns.lua new file mode 100644 index 0000000..e96e93b --- /dev/null +++ b/users/common/neovim/lua/plugins/gitsigns.lua @@ -0,0 +1 @@ +require("gitsigns").setup {} diff --git a/users/common/neovim/lua/plugins/lspconfig.lua b/users/common/neovim/lua/plugins/lspconfig.lua new file mode 100644 index 0000000..2428f07 --- /dev/null +++ b/users/common/neovim/lua/plugins/lspconfig.lua @@ -0,0 +1,78 @@ +local lsp_symbol = function(name, icon) + vim.fn.sign_define( + "DiagnosticSign" .. name, + { text = icon, numhl = "Diagnostic" .. name, texthl = "Diagnostic" .. name } + ) +end + +lsp_symbol("Error", "") +lsp_symbol("Info", "") +lsp_symbol("Hint", "") +lsp_symbol("Warn", "") + +vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, { + border = "single", +}) + +vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with(vim.lsp.handlers.signature_help, { + border = "single", + focusable = false, + relative = "cursor", +}) + +-- Borders for LspInfo winodw +local win = require "lspconfig.ui.windows" +local _default_opts = win.default_opts + +win.default_opts = function(options) + local opts = _default_opts(options) + opts.border = "single" + return opts +end + +local lspconfig = require "lspconfig" + +-- lua: https://github.com/sumneko/lua-language-server +lspconfig.sumneko_lua.setup { + settings = { + Lua = { + diagnostics = { + -- Get the language server to recognize the `vim` global + globals = { "vim" }, + }, + workspace = { + -- Make the server aware of Neovim runtime files + library = vim.api.nvim_get_runtime_file("", true), + }, + -- Do not send telemetry data containing a randomized but unique identifier + telemetry = { enable = false }, + }, + }, +} + +lspconfig.clangd.setup {} +lspconfig.bashls.setup {} +lspconfig.cmake.setup {} +lspconfig.html.setup {} +lspconfig.jdtls.setup {} +lspconfig.pyright.setup {} +lspconfig.texlab.setup {} + +local rt = require "rust-tools" +rt.setup { + server = { + on_attach = function(_, bufnr) + -- Hover actions + vim.keymap.set("n", "", rt.hover_actions.hover_actions, { buffer = bufnr }) + end, + settings = { + ["rust-analyzer"] = { + checkOnSave = { + command = "clippy", + }, + }, + }, + }, +} + +require("lsp_signature").setup() diff --git a/users/common/neovim/lua/plugins/neo-tree.lua b/users/common/neovim/lua/plugins/neo-tree.lua new file mode 100644 index 0000000..ecd1b94 --- /dev/null +++ b/users/common/neovim/lua/plugins/neo-tree.lua @@ -0,0 +1,99 @@ +vim.cmd [[let g:neo_tree_remove_legacy_commands = 1]] +local notify = function(message, level) + vim.notify(message, level, { title = "NeoTree" }) +end + +require("neo-tree").setup { + sort_case_insensitive = true, + use_popups_for_input = false, + popup_border_style = "rounded", + -- source_selector = { + -- winbar = true, + -- separator = { left = "", right= "" }, + -- }, + win_options = { + winblend = 0, + }, + default_component_configs = { + modified = { + symbol = "~ ", + }, + indent = { + with_expanders = true, + }, + name = { + trailing_slash = true, + }, + git_status = { + symbols = { + added = "+", + deleted = "✖", + modified = "", + renamed = "➜", + untracked = "?", + ignored = "", + unstaged = "", + staged = "", + conflict = "", + }, + }, + }, + window = { + width = 34, + position = "left", + mappings = { + [""] = "open_with_window_picker", + ["s"] = "split_with_window_picker", + ["v"] = "vsplit_with_window_picker", + ["t"] = "open_tabnew", + ["z"] = "close_all_nodes", + ["Z"] = "expand_all_nodes", + ["a"] = { "add", config = { show_path = "relative" } }, + ["A"] = { "add_directory", config = { show_path = "relative" } }, + ["c"] = { "copy", config = { show_path = "relative" } }, + ["m"] = { "move", config = { show_path = "relative" } }, + }, + }, + filesystem = { + window = { + mappings = { + ["gA"] = "git_add_all", + ["ga"] = "git_add_file", + ["gu"] = "git_unstage_file", + }, + }, + group_empty_dirs = true, + follow_current_file = true, + use_libuv_file_watcher = true, + filtered_items = { + hide_dotfiles = false, + hide_by_name = { ".git" }, + }, + }, + event_handlers = { + { + event = "file_added", + handler = function(arg) + notify("Added: " .. arg, "info") + end, + }, + { + event = "file_deleted", + handler = function(arg) + notify("Deleted: " .. arg, "info") + end, + }, + { + event = "file_renamed", + handler = function(args) + notify("Renamed: " .. args.source .. " -> " .. args.destination, "info") + end, + }, + { + event = "file_moved", + handler = function(args) + notify("Moved: " .. args.source .. " -> " .. args.destination, "info") + end, + }, + }, +} diff --git a/users/common/neovim/lua/plugins/others.lua b/users/common/neovim/lua/plugins/others.lua new file mode 100644 index 0000000..32c14dc --- /dev/null +++ b/users/common/neovim/lua/plugins/others.lua @@ -0,0 +1,214 @@ +local configs = { + ["dressing"] = { + input = { + prefer_width = 80, + max_width = { 140, 0.9 }, + min_width = { 80, 0.6 }, + win_options = { + winblend = 0, + }, + }, + }, + ["null-ls"] = function() + local null_ls = require "null-ls" + null_ls.setup { + sources = { + null_ls.builtins.code_actions.shellcheck, + null_ls.builtins.formatting.stylua, + null_ls.builtins.diagnostics.eslint, + null_ls.builtins.completion.spell, + }, + } + end, + ["lualine"] = function() + local c = require "onedark.colors" + local theme = { + inactive = { + a = { fg = c.fg, bg = c.bg2, gui = "bold" }, + b = { fg = c.fg, bg = c.bg2 }, + c = { fg = c.bg2, bg = c.bg0 }, + }, + normal = { + a = { fg = c.bg0, bg = c.green, gui = "bold" }, + b = { fg = c.fg, bg = c.bg2 }, + c = { fg = c.fg, bg = c.bg0 }, + }, + visual = { a = { fg = c.bg0, bg = c.purple, gui = "bold" } }, + replace = { a = { fg = c.bg0, bg = c.red, gui = "bold" } }, + insert = { a = { fg = c.bg0, bg = c.blue, gui = "bold" } }, + command = { a = { fg = c.bg0, bg = c.yellow, gui = "bold" } }, + terminal = { a = { fg = c.bg0, bg = c.cyan, gui = "bold" } }, + } + + require("lualine").setup { + options = { + theme = theme, + component_separators = "", + section_separators = { left = "", right = "" }, + }, + sections = { + lualine_a = { "mode" }, + lualine_b = { "branch", "filename" }, + lualine_c = { "diff", "diagnostics" }, + lualine_x = { "encoding", "fileformat", "filetype" }, + lualine_y = { "progress" }, + lualine_z = { "location" }, + }, + inactive_sections = { + lualine_a = { "filename" }, + lualine_b = {}, + lualine_c = { "diagnostics" }, + lualine_x = {}, + lualine_y = {}, + lualine_z = { "location" }, + }, + extensions = { "quickfix", "fugitive", "fzf", "nvim-dap-ui", "neo-tree" }, + } + end, + ["neogit"] = { + disable_builtin_notifications = true, + }, + ["window-picker"] = { + selection_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + filter_rules = { + bo = { + filetype = { "neo-tree", "neo-tree-popup", "notify", "quickfix" }, + buftype = { "terminal", "quickfix", "prompt" }, + }, + }, + other_win_hl_color = "#4493c8", + }, + ["mason"] = { + ui = { + icons = { + package_pending = " ", + package_installed = " ", + package_uninstalled = " ﮊ", + }, + }, + }, + ["gomove"] = { + map_defaults = false, + undojoin = true, + move_past_end_col = true, + }, + ["better-whitespace"] = function() + function _G.whitespace_visibility() + pcall(function() + if vim.bo.buftype == "nofile" or vim.bo.buftype == "help" then + vim.cmd "DisableWhitespace" + else + vim.cmd "EnableWhitespace" + end + end) + end + + vim.cmd [[autocmd WinEnter * lua whitespace_visibility()]] + end, + ["onedark"] = function() + local onedark = require "onedark" + onedark.setup { + toggle_style_key = "", + colors = { + fg = "#abb2bf", + black = "#181a1f", + bg0 = "#1e222a", + bg1 = "#252931", + bg2 = "#282c34", + bg3 = "#353b45", + bg_d = "#191c21", + bg_blue = "#73b8f1", + bg_yellow = "#ebd09c", + + dark_cyan = "#2b6f77", + dark_red = "#993939", + dark_yellow = "#93691d", + + grey = "#42464e", + grey_fg = "#565c64", + grey_fg2 = "#6f737b", + light_grey = "#6f737b", + baby_pink = "#de8c92", + pink = "#ff75a0", + nord_blue = "#81a1c1", + sun = "#ebcb8b", + light_purple = "#de98fd", + dark_purple = "#c882e7", + teal = "#519aba", + dark_pink = "#fca2aa", + light_blue = "#a3b8ef", + vibrant_green = "#7eca9c", + + red = "#e06c75", + orange = "#d19a66", + yellow = "#e5c07b", + green = "#98c379", + cyan = "#56b6c2", + blue = "#61afef", + purple = "#c678dd", + + diff_add = "#31392b", + diff_delete = "#382b2c", + diff_change = "#1c3448", + diff_text = "#2c5372", + }, + highlights = { + CursorLine = { bg = "$bg0" }, + FloatBorder = { fg = "$blue" }, + NeoTreeTabActive = { fg = "$fg", bg = "$bg_d" }, + NeoTreeTabInactive = { fg = "$grey", bg = "$black" }, + NeoTreeTabSeparatorActive = { fg = "$black", bg = "$black" }, + NeoTreeTabSeparatorInactive = { fg = "$black", bg = "$black" }, + NeoTreeWinSeparator = { fg = "$bg_d", bg = "$bg_d" }, + NeoTreeVertSplit = { fg = "$bg_d", bg = "$bg_d" }, + VisualMultiMono = { fg = "$purple", bg = "$diff_change" }, + VisualMultiExtend = { bg = "$diff_change" }, + VisualMultiCursor = { fg = "$purple", bg = "$diff_change" }, + VisualMultiInsert = { fg = "$blue", bg = "$diff_change" }, + }, + } + vim.g.VM_Mono_hl = "VisualMultiMono" + vim.g.VM_Extend_hl = "VisualMultiExtend" + vim.g.VM_Cursor_hl = "VisualMultiCursor" + vim.g.VM_Insert_hl = "VisualMultiInsert" + onedark.load() + end, + ["sandwich"] = function() + vim.g.operator_sandwich_no_default_key_mappings = 1 + vim.g.textobj_sandwich_no_default_key_mappings = 1 + end, + ["undotree"] = function() + vim.g.undotree_SetFocusWhenToggle = 1 + vim.g.undotree_WindowLayout = 4 + end, + ["wordmotion"] = function() + vim.g.wordmotion_nomap = 1 + end, + ["nvim-web-devicons"] = function() + local devicons = require "nvim-web-devicons" + devicons.setup { + override = require("utils.icons").devicons, + default = true, + } + end, + ["notify"] = function() + local notify = require "notify" + notify.setup { + fps = 60, + icons = { + DEBUG = "", + ERROR = "", + INFO = "", + TRACE = "✎", + WARN = "", + }, + max_width = 120, + } + vim.notify = notify + end, + ["nabla"] = function() + require("nabla").enable_virt() + end, +} + +return configs diff --git a/users/common/neovim/lua/plugins/telescope.lua b/users/common/neovim/lua/plugins/telescope.lua new file mode 100644 index 0000000..2e0f553 --- /dev/null +++ b/users/common/neovim/lua/plugins/telescope.lua @@ -0,0 +1,31 @@ +-- TODO: files and content in the searchable area should be split into two window portions, +-- TODO: Ctrl+Up in telescope fucks up spacing +-- or maybe only that the file just takes small amount of space + +local telescope = require "telescope" + +telescope.setup { + defaults = { + -- Default configuration for telescope goes here: + -- config_key = value, + mappings = { + i = { + [""] = "which_key", + [""] = require("telescope.actions").cycle_history_next, + [""] = require("telescope.actions").cycle_history_prev, + }, + }, + prompt_prefix = " ", + selection_caret = " ", + }, +} + +local function load_ext(ext) + local ok, _ = pcall(telescope.load_extension, ext) + if not ok then + vim.notify("Could not load telescope extension: " .. ext, "error") + end +end + +load_ext "fzf" +load_ext "notify" diff --git a/users/common/neovim/lua/plugins/treesitter.lua b/users/common/neovim/lua/plugins/treesitter.lua new file mode 100644 index 0000000..4a6b263 --- /dev/null +++ b/users/common/neovim/lua/plugins/treesitter.lua @@ -0,0 +1,16 @@ +require("nvim-treesitter.configs").setup { + ensure_installed = "all", + highlight = { + enable = true, + use_languagetree = true, + }, + rainbow = { + enable = true, + extended_mode = true, + -- colors = { }, + -- termcolors = { } + }, + matchup = { + enable = true, + }, +} diff --git a/users/common/neovim/lua/todo b/users/common/neovim/lua/todo new file mode 100644 index 0000000..ee639d8 --- /dev/null +++ b/users/common/neovim/lua/todo @@ -0,0 +1,57 @@ +keybinds: +- comment.nvim +- smarter keybinds for surround, e.g. "" on word --> "word", same for '', maybe others. +- lsp keybinds +- move block of lines +- m to surround +- dressing make larger + + + +- maybe install pynvim and npm neovim on update +- nice wrapping behavior g g, setlocal linebreak, setlocal wrap, setlocal showbreak=\| \ \ \ , setlocal breakindent +- when set wrap, have an alternative V and ctrlV that behave like the text was actually that way. + + +- mundo +- easyalign + +- nvim dap (some kind of debugger pls) + +- (link still applise= nvim cmp can kill nvim by completing /dev/ and going over stdin whoops. +- long opening times when opening paper.jar +- remove ZZ shortcut +- converter: number <-> hex <-> oct <-> ...; camelcase pascalcase snakecase +- gJ but delete every trailing and leading space, maybe gdJ +- button to jump to end of match under cursor NOT in visual mode +- visual mode f --> vf" should mark to next " +- v......s sometimes jumps back some characters which makes inital cursor movement strange. subst shouldnt move cursor from beginning if characters are deleted or ever like noooooop +- multi search highlight with different color. +- make ctrl-shift-cv copy/insert things from * buffer +- maybe an IDE init button like . before that only minimal plugins loaded, e.g. no completion no tabnine nothing too obstrusive and nothing that is slow on large arbitarary files. +- textobject for "current functino parameter like ciw -> cip +- multuple cursors on each line, then trigger completion, but allow two modes. either only first cursor gets completion, others get same completion, + or all cursors complete separately and take the first completion by themselves. +- key for Crtl+[] for jump back and select in help +- indent blankline error: when searching for a word, and a indentline begins in the next line such that it is under the first char of the marked word, the blankline will be visually marked too. +- automacros: always record a macro when esc is pressed until esc is pressed again. Begin recording only on first actual action i.e. movement doesnt count before recording, only after starting -> things like Js will become a repeat sequence yay. +- after nvimcmp replaced text, goto end of this text. +- search and replace "popup" or maybe just prefilled cmdline with interactive search visuals +- whitespace +- indentline +- tabline for TABS not buffer :/ +- nvim-tree: a = create new in (selected folder if cursor is hovering over one, else current folder), A = create new in current folder regardless of cursor pos +- lsp +- colored parens +- git +- whitespace marker lines also in NvoimTree +- show bad whitespace +- markdown? latex? +- highlight current line in more lighter cola +- Create a virtualenv specifically for Nvim and use `g:python3_host_prog`. This will avoid the need to install the pynvim module in each virtualenv. + + +fast: +- delete ; at end of each line +- align on = +- align function arguments diff --git a/users/common/neovim/lua/utils/bootstrap.lua b/users/common/neovim/lua/utils/bootstrap.lua new file mode 100644 index 0000000..f1c648f --- /dev/null +++ b/users/common/neovim/lua/utils/bootstrap.lua @@ -0,0 +1,14 @@ +local M = {} + +M.ensure_packer = function() + local fn = vim.fn + local install_path = fn.stdpath "data" .. "/site/pack/packer/start/packer.nvim" + if fn.empty(fn.glob(install_path)) > 0 then + fn.system { "git", "clone", "--depth", "1", "https://github.com/wbthomason/packer.nvim", install_path } + vim.cmd [[packadd packer.nvim]] + return true + end + return false +end + +return M diff --git a/users/common/neovim/lua/utils/icons.lua b/users/common/neovim/lua/utils/icons.lua new file mode 100644 index 0000000..33d24e8 --- /dev/null +++ b/users/common/neovim/lua/utils/icons.lua @@ -0,0 +1,208 @@ +local M = {} + +M.lspkind = { + Namespace = "", + Text = " ", + Method = " ", + Function = " ", + Constructor = " ", + Field = "ﰠ ", + Variable = " ", + Class = "ﴯ ", + Interface = " ", + Module = " ", + Property = "ﰠ ", + Unit = "塞 ", + Value = " ", + Enum = " ", + Keyword = " ", + Snippet = " ", + Color = " ", + File = " ", + Reference = " ", + Folder = " ", + EnumMember = " ", + Constant = " ", + Struct = "פּ ", + Event = " ", + Operator = " ", + TypeParameter = " ", + Table = "", + Object = " ", + Tag = "", + Array = "[]", + Boolean = " ", + Number = " ", + Null = "ﳠ", + String = " ", + Calendar = "", + Watch = " ", + Package = "", + Copilot = " ", +} + +M.statusline_separators = { + default = { + left = "", + right = " ", + }, + + round = { + left = "", + right = "", + }, + + block = { + left = "█", + right = "█", + }, + + arrow = { + left = "", + right = "", + }, +} + +M.devicons = { + default_icon = { + icon = "", + name = "Default", + }, + + c = { + icon = "", + name = "c", + }, + + css = { + icon = "", + name = "css", + }, + + deb = { + icon = "", + name = "deb", + }, + + Dockerfile = { + icon = "", + name = "Dockerfile", + }, + + html = { + icon = "", + name = "html", + }, + + jpeg = { + icon = "", + name = "jpeg", + }, + + jpg = { + icon = "", + name = "jpg", + }, + + js = { + icon = "", + name = "js", + }, + + kt = { + icon = "󱈙", + name = "kt", + }, + + lock = { + icon = "", + name = "lock", + }, + + lua = { + icon = "", + name = "lua", + }, + + mp3 = { + icon = "", + name = "mp3", + }, + + mp4 = { + icon = "", + name = "mp4", + }, + + out = { + icon = "", + name = "out", + }, + + png = { + icon = "", + name = "png", + }, + + py = { + icon = "", + name = "py", + }, + + ["robots.txt"] = { + icon = "ﮧ", + name = "robots", + }, + + toml = { + icon = "", + name = "toml", + }, + + ts = { + icon = "ﯤ", + name = "ts", + }, + + ttf = { + icon = "", + name = "TrueTypeFont", + }, + + rb = { + icon = "", + name = "rb", + }, + + rpm = { + icon = "", + name = "rpm", + }, + + vue = { + icon = "﵂", + name = "vue", + }, + + woff = { + icon = "", + name = "WebOpenFontFormat", + }, + + woff2 = { + icon = "", + name = "WebOpenFontFormat2", + }, + + xz = { + icon = "", + name = "xz", + }, + + zip = { + icon = "", + name = "zip", + }, +} + +return M