From 7b68372b358da90798290c49d0c0d5b0d0950e00 Mon Sep 17 00:00:00 2001 From: Danielle McLean Date: Tue, 31 Oct 2023 12:07:27 +1100 Subject: [PATCH] Introduce a separate Neovim config in Lua --- dot-config/nvim/init.lua | 29 +++++ dot-config/nvim/init.vim | 5 - dot-config/nvim/lazy-lock.json | 28 +++++ dot-config/nvim/lua/dot-vim/completion.lua | 58 ++++++++++ dot-config/nvim/lua/dot-vim/lsp.lua | 53 ++++++++++ dot-config/nvim/lua/dot-vim/plugins.lua | 111 ++++++++++++++++++++ dot-config/nvim/lua/dot-vim/tree-sitter.lua | 41 ++++++++ 7 files changed, 320 insertions(+), 5 deletions(-) create mode 100644 dot-config/nvim/init.lua delete mode 100644 dot-config/nvim/init.vim create mode 100644 dot-config/nvim/lazy-lock.json create mode 100644 dot-config/nvim/lua/dot-vim/completion.lua create mode 100644 dot-config/nvim/lua/dot-vim/lsp.lua create mode 100644 dot-config/nvim/lua/dot-vim/plugins.lua create mode 100644 dot-config/nvim/lua/dot-vim/tree-sitter.lua diff --git a/dot-config/nvim/init.lua b/dot-config/nvim/init.lua new file mode 100644 index 0000000..7bf2184 --- /dev/null +++ b/dot-config/nvim/init.lua @@ -0,0 +1,29 @@ +-- g:mapleader needs to be set before any plugins are loaded. +vim.g.mapleader = "\\" + +-- Bootstrap the lazy.nvim package manager. It will automatically manage +-- itself, but other plugins to use are defined in ./lua/plugins.lua. +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not vim.loop.fs_stat(lazypath) then + vim.fn.system({ + "git", "clone", "--filter=blob:none", + "https://github.com/folke/lazy.nvim.git", "--branch=stable", lazypath + }) +end +vim.opt.rtp:prepend(lazypath) + +require("lazy").setup "dot-vim.plugins" + +vim.o.breakindent = true +vim.o.termguicolors = true +vim.o.shiftwidth = 2 +vim.o.tabstop = 2 +vim.o.relativenumber = true + +vim.o.wildmode = 'longest,full' + +vim.keymap.set('i', 'jj', '') + +require("dot-vim.tree-sitter").setup() +require("dot-vim.completion").setup() +require("dot-vim.lsp").setup() diff --git a/dot-config/nvim/init.vim b/dot-config/nvim/init.vim deleted file mode 100644 index eb6c92f..0000000 --- a/dot-config/nvim/init.vim +++ /dev/null @@ -1,5 +0,0 @@ -set runtimepath+=$XDG_CONFIG_HOME/vim,$XDG_CACHE_HOME/vim,$XDG_CONFIG_HOME/vim/after,$XDG_CACHE_HOME/vim/after -if exists('+packpath') - set packpath^=$XDG_CONFIG_HOME/vim,$XDG_CACHE_HOME/vim -endif -source $XDG_CONFIG_HOME/vim/init.vim diff --git a/dot-config/nvim/lazy-lock.json b/dot-config/nvim/lazy-lock.json new file mode 100644 index 0000000..284bebf --- /dev/null +++ b/dot-config/nvim/lazy-lock.json @@ -0,0 +1,28 @@ +{ + "Comment.nvim": { "branch": "master", "commit": "0236521ea582747b58869cb72f70ccfa967d2e89" }, + "LuaSnip": { "branch": "master", "commit": "80a8528f084a97b624ae443a6f50ff8074ba486b" }, + "cmp-nvim-lsp": { "branch": "main", "commit": "44b16d11215dce86f253ce0c30949813c0a90765" }, + "cmp_luasnip": { "branch": "master", "commit": "05a9ab28b53f71d1aece421ef32fee2cb857a843" }, + "fidget.nvim": { "branch": "main", "commit": "0ba1e16d07627532b6cae915cc992ecac249fb97" }, + "gitsigns.nvim": { "branch": "main", "commit": "af0f583cd35286dd6f0e3ed52622728703237e50" }, + "lazy.nvim": { "branch": "main", "commit": "16603c6917435d8446f7357cb61095138a417085" }, + "lualine.nvim": { "branch": "master", "commit": "2248ef254d0a1488a72041cfb45ca9caada6d994" }, + "neodev.nvim": { "branch": "main", "commit": "f3f5d756f4043180523bb69072a104f7216b5f42" }, + "nvim-cmp": { "branch": "main", "commit": "51260c02a8ffded8e16162dcf41a23ec90cfba62" }, + "nvim-lspconfig": { "branch": "master", "commit": "d0467b9574b48429debf83f8248d8cee79562586" }, + "nvim-lua-gf": { "branch": "main", "commit": "ca712497b2bab6351518917be219e9bfd8d63e4f" }, + "nvim-surround": { "branch": "main", "commit": "4f0e1f470595af067eca9b872778d83c7f52f134" }, + "nvim-treesitter": { "branch": "master", "commit": "c36681bb496ebce2946867459ed08774cb61788c" }, + "nvim-treesitter-textsubjects": { "branch": "master", "commit": "48b3bf54e32f23e2299c59ff76fa3b0599565b39" }, + "nvim-web-devicons": { "branch": "master", "commit": "5de460ca7595806044eced31e3c36c159a493857" }, + "onedark.nvim": { "branch": "master", "commit": "b9acd92ded2ba155867ca5af9d618e933d96e3b0" }, + "penlight": { "branch": "master", "commit": "dc6d19c5c1e1b4ac55b14df17b7645af6b410140" }, + "plenary.nvim": { "branch": "master", "commit": "50012918b2fc8357b87cff2a7f7f0446e47da174" }, + "telescope-fzf-native.nvim": { "branch": "main", "commit": "6c921ca12321edaa773e324ef64ea301a1d0da62" }, + "telescope.nvim": { "branch": "0.1.x", "commit": "7011eaae0ac1afe036e30c95cf80200b8dc3f21a" }, + "unimpaired-which-key.nvim": { "branch": "main", "commit": "321a247ecbbb31a59a8580350eec044b88d82e81" }, + "vim-fugitive": { "branch": "master", "commit": "46eaf8918b347906789df296143117774e827616" }, + "vim-sleuth": { "branch": "master", "commit": "1cc4557420f215d02c4d2645a748a816c220e99b" }, + "vim-unimpaired": { "branch": "master", "commit": "6d44a6dc2ec34607c41ec78acf81657248580bf1" }, + "which-key.nvim": { "branch": "main", "commit": "4433e5ec9a507e5097571ed55c02ea9658fb268a" } +} \ No newline at end of file diff --git a/dot-config/nvim/lua/dot-vim/completion.lua b/dot-config/nvim/lua/dot-vim/completion.lua new file mode 100644 index 0000000..2958ba2 --- /dev/null +++ b/dot-config/nvim/lua/dot-vim/completion.lua @@ -0,0 +1,58 @@ +local cmp = require "cmp" +local luasnip = require "luasnip" + +local has_words_before = function() + unpack = unpack or table.unpack + 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 mapping = cmp.mapping.preset.insert{ + [''] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_next_item() + elseif luasnip.expand_or_locally_jumpable() then + luasnip.expand_or_jump() + elseif has_words_before() then + cmp.complete() + else + fallback() + end + end, {"i", "s"}), + + [''] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif luasnip.locally_jumpable(-1) then + luasnip.jump(-1) + else + fallback() + end + end, {"i", "s"}), + + [''] = cmp.mapping.confirm { + behavior = cmp.ConfirmBehavior.Replace, + select = true, + }, +} + +local config = { + snippet = { + expand = function(args) + luasnip.lsp_expand(args.body) + end, + }, + sources = cmp.config.sources{ + {name = "nvim_lsp"}, + {name = "luasnip"}, + }, + mapping = mapping, +} + +return { + setup = function() + require('luasnip.loaders.from_vscode').lazy_load() + luasnip.config.setup {} + cmp.setup(config) + end, +} diff --git a/dot-config/nvim/lua/dot-vim/lsp.lua b/dot-config/nvim/lua/dot-vim/lsp.lua new file mode 100644 index 0000000..1a03b9e --- /dev/null +++ b/dot-config/nvim/lua/dot-vim/lsp.lua @@ -0,0 +1,53 @@ +local union = require"pl.tablex".union +local neodev = require "neodev" +local lspconfig = require "lspconfig" + +local capabilities = vim.lsp.protocol.make_client_capabilities() +capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities) + +---@param _ any the vim.lsp.client object that got attached, but Neovim doesn't expose that type properly? +---@param bufnr number the number of the buffer the LSP client just attached to +local function on_attach(_, bufnr) + local telescope = require('telescope.builtin') + ---@param lhs string LHS like you'd pass to vim.keymap.set + ---@param func fun(): nil The function to be called when the mapping is invoked + ---@param desc? string Human-readable description of what this mapping does + local function nmap(lhs, func, desc) + if desc then + desc = 'LSP: ' .. desc + end + + vim.keymap.set('n', lhs, func, { buffer = bufnr, desc = desc }) + end + + nmap('gd', telescope.lsp_definitions, '[G]oto [D]efinition') + nmap('gr', telescope.lsp_references, '[G]oto [R]eferences') + nmap('K', vim.lsp.buf.hover, 'Hover Documentation') + nmap('', vim.lsp.buf.signature_help, 'Signature Documentation') +end + +local servers = { + lua_ls = {}, + jsonls = {}, + perlls = {}, + perlnavigator = {cmd = {"perlnavigator"}}, + phpactor = {}, + pylsp = {}, + solargraph = {}, + taplo = {}, + tsserver = {}, + yamlls = {}, +} + +return { + setup = function() + neodev.setup{} + + for name, opts in pairs(servers) do + lspconfig[name].setup(union({ + capabilities = capabilities, + on_attach = on_attach, + }, opts)) + end + end, +} diff --git a/dot-config/nvim/lua/dot-vim/plugins.lua b/dot-config/nvim/lua/dot-vim/plugins.lua new file mode 100644 index 0000000..1607c92 --- /dev/null +++ b/dot-config/nvim/lua/dot-vim/plugins.lua @@ -0,0 +1,111 @@ +local LspAttach = "LspAttach" +local VeryLazy = "VeryLazy" + +return { + -- Penlight is a Lua utility library. It's not Neovim-specific, but installing it like this still makes require("pl") work anywhere else in your config. :) + "lunarmodules/penlight", + + -- Familiar Vim plugins for Git integration and smart indentation. + "tpope/vim-fugitive", + "tpope/vim-sleuth", + + -- Comment toggle plugin, like tpope/vim-commentary. + {"numToStr/Comment.nvim", opts = {}}, + + -- Adds Neovim's Lua package directories to 'path' when editing a Neovim Lua file. + "sam4llis/nvim-lua-gf", + + -- Reminder popups as you type multiple-key mappings + {"folke/which-key.nvim", event = VeryLazy, init = function() + vim.o.timeout = true + vim.o.timeoutlen = 300 + end, opts = {}}, + + -- Unimpaired's handy bracket mappings, but also which-key.nvim knows about them and can remind me of them. + {"afreakk/unimpaired-which-key.nvim", dependencies = {"tpope/vim-unimpaired"}, config = function() + local wk = require "which-key" + local uwk = require "unimpaired-which-key" + wk.register(uwk.normal_mode) + wk.register(uwk.normal_and_visual_mode, {mode = {"n", "v"}}) + end}, + + -- Fuzzy finder for all sorts of things. Files, buffers, LSP references and definitions, the list goes on. + {"nvim-telescope/telescope.nvim", + branch = '0.1.x', + dependencies = { + "nvim-lua/plenary.nvim", + -- This small native binary is technically optional but is highly recommended to improve Telescope's performance. + {"nvim-telescope/telescope-fzf-native.nvim", build = "make"}, + }, + opts = { + extensions = { + fzf = {}, + }, + }, + init = function() + local telescope = require('telescope') + telescope.load_extension('fzf') + end + }, + + -- Indicate which parts of the buffer have changed according to Git in the left margin. Basically the same thing as mhinz/vim-signify. + {"lewis6991/gitsigns.nvim", opts = { + signs = { + add = {text = "+"}, + change = {text = "~"}, + delete = {text = "_"}, + topdelete = {text = "‾"}, + changedelete = {text = "~"}, + }, + }}, + + {"navarasu/onedark.nvim", + priority = 1000, + init = function() + require("onedark").load() + end, + opts = { + transparent = true, + ending_tildes = true, + } + }, + + {"nvim-lualine/lualine.nvim", + dependencies = { + {"nvim-tree/nvim-web-devicons", opts = {}}, + }, + opts = { + options = { + icons_enabled = true, + theme = "onedark", + }, + extensions = { + "fugitive", + "lazy", + "quickfix", + }, + }, + }, + + -- Basically a Neovim clone of tpope's vim-surround. The original tpope plugin does work in Neovim, but this one integrates better with other Neovim plugins like which-key.nvim. + {"kylechui/nvim-surround", event = VeryLazy, opts = {}}, + + {"neovim/nvim-lspconfig", dependencies = { + -- UI for feedback on running language servers. + {"j-hui/fidget.nvim", tag = "legacy", event = LspAttach, opts = {}}, + -- Better support for using lua_ls with Neovim itself. + "folke/neodev.nvim", + }}, + + {"hrsh7th/nvim-cmp", dependencies = { + -- nvim-cmp *requires* a snippet engine to work. We'll use LuaSnip. + "L3MON4D3/LuaSnip", + "saadparwaiz1/cmp_luasnip", + + "hrsh7th/cmp-nvim-lsp", + }}, + + {"nvim-treesitter/nvim-treesitter", dependencies = { + "RRethy/nvim-treesitter-textsubjects", + }, build = ":TSUpdate"}, +} diff --git a/dot-config/nvim/lua/dot-vim/tree-sitter.lua b/dot-config/nvim/lua/dot-vim/tree-sitter.lua new file mode 100644 index 0000000..3d288f1 --- /dev/null +++ b/dot-config/nvim/lua/dot-vim/tree-sitter.lua @@ -0,0 +1,41 @@ +local setup = function() + local config = { + ensure_installed = { + "c", "cpp", "make", + "css", "html", "http", "javascript", "typescript", + "elixir", "erlang", + "csv", "json", "jq", "toml", "yaml", + "git_config", "gitattributes", "gitignore", + "lua", "luadoc", + "perl", "php", "python", "ruby", + }, + auto_install = false, + sync_install = false, + ignore_install = {}, + highlight = { + enable = true, + additional_vim_regex_highlighting = false, + }, + indent = {enable = true}, + textsubjects = { + enable = true, + prev_selection = ",", + keymaps = { + ["."] = {"textsubjects-smart", desc = "textsubjects subject"}, + ["a;"] = {"textsubjects-container-outer", desc = "container (class, function, etc.)"}, + ["i;"] = {"textsubjects-container-inner", desc = "container (class, function, etc.)"}, + }, + }, + } + + require("nvim-treesitter.configs").setup(config) +end + +local defer_setup = function() + vim.defer_fn(setup, 0) +end + +return { + setup = setup, + defer_setup = defer_setup, +}