dotfiles/.config/nvim/init.lua

487 lines
15 KiB
Lua

-- Install packer
local install_path = vim.fn.stdpath 'data' .. '/site/pack/packer/start/packer.nvim'
if vim.fn.empty(vim.fn.glob(install_path)) > 0 then
vim.fn.execute('!git clone https://github.com/wbthomason/packer.nvim ' .. install_path)
end
vim.api.nvim_exec(
[[
augroup Packer
autocmd!
autocmd BufWritePost init.lua PackerCompile
augroup end
]],
false
)
local use = require('packer').use
require('packer').startup(function()
-- Package manager
use 'wbthomason/packer.nvim'
-- UI to select things (files, grep results, open buffers...)
use {
'nvim-telescope/telescope.nvim',
requires = {
{ 'nvim-lua/popup.nvim' },
{ 'nvim-lua/plenary.nvim' },
{ 'nvim-telescope/telescope-fzf-native.nvim', run = "make" },
{ 'nvim-telescope/telescope-media-files.nvim' }
}
}
-- Add indentation guides even on blank lines
use 'lukas-reineke/indent-blankline.nvim'
-- Add git related info in the signs columns and popups
-- use {
-- 'lewis6991/gitsigns.nvim',
-- config = function()
-- require('gitsigns').setup()
-- end
-- }
-- Highlight, edit, and navigate code using a fast incremental parsing library
use 'nvim-treesitter/nvim-treesitter'
-- LSP
use 'neovim/nvim-lspconfig'
-- Autocompletion
use 'hrsh7th/nvim-compe'
-- Snippets
use 'L3MON4D3/LuaSnip'
-- Bufferline for tabs
use { 'akinsho/nvim-bufferline.lua', requires = 'kyazdani42/nvim-web-devicons'}
-- Remember last edit location in file
use 'ethanholz/nvim-lastplace'
-- File manager
use {
'kyazdani42/nvim-tree.lua',
requires = {
'kyazdani42/nvim-web-devicons',
},
config = function() require'nvim-tree'.setup{} end
}
-- lualine
use {
'nvim-lualine/lualine.nvim',
requires = { 'kyazdan42/nvim-web-devicons', opt = true }
}
-- Editorconfig
use 'editorconfig/editorconfig-vim'
-- nvim-commenter
use 'terrortylor/nvim-comment'
-- sloum/gemini-vim-syntax
use 'https://tildegit.org/sloum/gemini-vim-syntax'
-- catppuccin theme
use {
'catppuccin/nvim',
as = 'catppuccin'
}
end)
-- Local map function
local function map(mode, lhs, rhs, opts)
local options = { noremap = true, silent = true }
if opts then
options = vim.tbl_extend("force", options, opts)
end
vim.api.nvim_set_keymap(mode, lhs, rhs, options)
end
local opt = {}
--Remap space as leader key
map('', '<Space>', '<Nop>', { noremap = true, silent = true })
vim.g.mapleader = ' '
vim.g.maplocalleader = ' '
--Incremental live completion
vim.o.inccommand = 'split'
--Set highlight on search
vim.o.hlsearch = true
--Make line numbers default
vim.wo.number = true
-- Relative line numbers
vim.wo.relativenumber = true
--Do not save when switching buffers
vim.o.hidden = true
--Enable mouse mode
vim.o.mouse = 'a'
--Enable break indent
vim.o.breakindent = true
--Save undo history
vim.cmd [[set undofile]]
--Case insensitive searching UNLESS /C or capital in search
vim.o.ignorecase = true
vim.o.smartcase = true
--Decrease update time
vim.o.updatetime = 250
vim.wo.signcolumn = 'yes'
--Set colorscheme (order is important here)
vim.o.termguicolors = true
vim.g.catppuccin_flavour = "mocha"
require("catppuccin").setup()
vim.cmd("colorscheme catppuccin")
--Highlight column 88
vim.cmd("set colorcolumn=88")
--Set splits
vim.o.splitbelow = true
vim.o.splitright = true
--Clipboard
vim.o.clipboard = "unnamedplus"
-- Press ESC to turn off search highlight
map("n", "<Esc>", ":noh<CR>", opt)
--Tabs and indents
vim.o.shiftwidth = 4
vim.o.smartindent = true
vim.o.softtabstop = 4
vim.o.tabstop = 4
vim.o.autoindent = true
-- Lualine
require('lualine').setup{
options = {
theme = "catppuccin"
}
}
-- Sometimes I don't let go of the shift key in time
vim.cmd("command! WQ wq")
vim.cmd("command! Wq wq")
vim.cmd("command! Wqa wqa")
vim.cmd("command! WQa wqa")
vim.cmd("command! W w")
vim.cmd("command! Q q")
-- Sometimes I accidentally undo a change when trying to enter INSERT mode
map("n", "u", "<Nop>", opt)
-- Don't copy deleted text
map("n", "dd", [=[ "_dd ]=], opt)
map("v", "dd", [=[ "_dd ]=], opt)
map("v", "x", [=[ "_x ]=], opt)
-- Copy whole file content
map("n", "<C-a>", [[ <Cmd> %y+<CR>]], opt)
-- Commenter keybinding
require('nvim_comment').setup()
map("n", "<leader>/", ":CommentToggle<CR>", opt)
map("v", "<leader>/", ":CommentToggle<CR>", opt)
--Remap for dealing with word wrap
map('n', 'k', "v:count == 0 ? 'gk' : 'k'", { noremap = true, expr = true, silent = true })
map('n', 'j', "v:count == 0 ? 'gj' : 'j'", { noremap = true, expr = true, silent = true })
--Map blankline
vim.g.indent_blankline_char = ''
vim.g.indent_blankline_filetype_exclude = { 'help', 'packer' }
vim.g.indent_blankline_buftype_exclude = { 'terminal', 'nofile' }
vim.g.indent_blankline_char_highlight = 'LineNr'
vim.g.indent_blankline_show_trailing_blankline_indent = false
-- Ansible-flavorited YAML
vim.g.ansible_unindent_after_newline = true
-- nvim-lastplace
require'nvim-lastplace'.setup{}
-- nvim-bufferline.lua
require("bufferline").setup{
options = {
separator_style = "slant"
}
}
map("n", "<S-t>", ":enew<CR>", opt) -- new buffer
map("n", "<C-t>b", ":tabnew<CR>", opt) -- new tab
map("n", "<S-x>", ":bd!<CR>", opt) -- close tab
map("n", "<TAB>", ":BufferLineCycleNext<CR>", opt)
map("n", "<S-TAB>", ":BufferLineCyclePrev<CR>", opt)
-- Telescope
require('telescope').setup {
defaults = {
mappings = {
i = {
['<C-u>'] = false,
['<C-d>'] = false,
},
},
},
}
--Add leader shortcuts
map('n', '<leader><space>', [[<cmd>lua require('telescope.builtin').buffers()<CR>]], { noremap = true, silent = true })
map('n', '<leader>sf', [[<cmd>lua require('telescope.builtin').find_files({previewer = false})<CR>]], { noremap = true, silent = true })
map('n', '<leader>sb', [[<cmd>lua require('telescope.builtin').current_buffer_fuzzy_find()<CR>]], { noremap = true, silent = true })
map('n', '<leader>sh', [[<cmd>lua require('telescope.builtin').help_tags()<CR>]], { noremap = true, silent = true })
map('n', '<leader>st', [[<cmd>lua require('telescope.builtin').tags()<CR>]], { noremap = true, silent = true })
map('n', '<leader>sd', [[<cmd>lua require('telescope.builtin').grep_string()<CR>]], { noremap = true, silent = true })
map('n', '<leader>sp', [[<cmd>lua require('telescope.builtin').live_grep()<CR>]], { noremap = true, silent = true })
map('n', '<leader>so', [[<cmd>lua require('telescope.builtin').tags{ only_current_buffer = true }<CR>]], { noremap = true, silent = true })
map('n', '<leader>?', [[<cmd>lua require('telescope.builtin').oldfiles()<CR>]], { noremap = true, silent = true })
-- Highlight on yank
vim.api.nvim_exec(
[[
augroup YankHighlight
autocmd!
autocmd TextYankPost * silent! lua vim.highlight.on_yank()
augroup end
]],
false
)
-- Y yank until the end of line
map('n', 'Y', 'y$', { noremap = true })
-- Nvim Tree
map('n', '<C-n>', ':NvimTreeToggle<CR>', opt)
map('n', '<leader>r', ':NvimTreeRefresh<CR>', opt)
map('n', '<leader>n', ':NvimTreeFindFile<CR>', opt)
-- LSP settings
local nvim_lsp = require 'lspconfig'
local on_attach = function(_, bufnr)
vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc')
local opts = { noremap = true, silent = true }
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gD', '<Cmd>lua vim.lsp.buf.declaration()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gd', '<Cmd>lua vim.lsp.buf.definition()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'K', '<Cmd>lua vim.lsp.buf.hover()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>ca', '<cmd>lua vim.lsp.buf.code_action()<CR>', opts)
-- vim.api.nvim_buf_set_keymap(bufnr, 'v', '<leader>ca', '<cmd>lua vim.lsp.buf.range_code_action()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>e', '<cmd>lua vim.lsp.diagnostic.show_line_diagnostics()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '[d', '<cmd>lua vim.lsp.diagnostic.goto_prev()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', ']d', '<cmd>lua vim.lsp.diagnostic.goto_next()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>q', '<cmd>lua vim.lsp.diagnostic.set_loclist()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>so', [[<cmd>lua require('telescope.builtin').lsp_document_symbols()<CR>]], opts)
vim.cmd [[ command! Format execute 'lua vim.lsp.buf.formatting()' ]]
end
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities.textDocument.completion.completionItem.snippetSupport = true
-- Enable the following language servers
local servers = { 'ansiblels', 'bashls', 'dockerls', 'jsonls', 'pyright', 'yamlls' }
for _, lsp in ipairs(servers) do
nvim_lsp[lsp].setup {
on_attach = on_attach,
capabilities = capabilities,
}
end
-- Sumneko Lua Language Server
local sumneko_root_path
local sumneko_binary
sumneko_root_path = vim.fn.getenv("HOME").."/.local/share/lua-language-server"
sumneko_binary = sumneko_root_path .. "/bin/lua-language-server"
-- Make runtime files discoverable to the server
local runtime_path = vim.split(package.path, ';')
table.insert(runtime_path, 'lua/?.lua')
table.insert(runtime_path, 'lua/?/init.lua')
require('lspconfig').sumneko_lua.setup {
cmd = { sumneko_binary, '-E', sumneko_root_path .. '/main.lua' },
on_attach = on_attach,
capabilities = capabilities,
settings = {
Lua = {
runtime = {
-- Tell the language server which version of Lua you're using (most likely LuaJIT in the case of Neovim)
version = 'LuaJIT',
-- Setup your lua path
path = runtime_path,
},
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),
preloadFileSize = 1000,
checkThirdParty = false,
},
-- Do not send telemetry data containing a randomized but unique identifier
telemetry = {
enable = false,
},
},
},
}
-- Ansible LSP
require('lspconfig').ansiblels.setup{}
-- Bash LSP
require('lspconfig').bashls.setup{}
-- Docker LSP
require('lspconfig').dockerls.setup{}
-- JSON LSP
require('lspconfig').jsonls.setup{}
-- Pyright (Python) LSP
require('lspconfig').pyright.setup{}
-- Treesitter configuration
-- Parsers must be installed manually via :TSInstall
require('nvim-treesitter.configs').setup {
highlight = {
enable = true, -- false will disable the whole extension
},
incremental_selection = {
enable = true,
keymaps = {
init_selection = 'gnn',
node_incremental = 'grn',
scope_incremental = 'grc',
node_decremental = 'grm',
},
},
indent = {
enable = true,
},
textobjects = {
select = {
enable = true,
lookahead = true, -- Automatically jump forward to textobj, similar to targets.vim
keymaps = {
-- You can use the capture groups defined in textobjects.scm
['af'] = '@function.outer',
['if'] = '@function.inner',
['ac'] = '@class.outer',
['ic'] = '@class.inner',
},
},
move = {
enable = true,
set_jumps = true, -- whether to set jumps in the jumplist
goto_next_start = {
[']m'] = '@function.outer',
[']]'] = '@class.outer',
},
goto_next_end = {
[']M'] = '@function.outer',
[']['] = '@class.outer',
},
goto_previous_start = {
['[m'] = '@function.outer',
['[['] = '@class.outer',
},
goto_previous_end = {
['[M'] = '@function.outer',
['[]'] = '@class.outer',
},
},
},
}
-- Set completeopt to have a better completion experience
vim.o.completeopt = 'menuone,noinsert'
-- Compe setup
require('compe').setup {
source = {
path = true,
nvim_lsp = true,
luasnip = true,
buffer = false,
calc = false,
nvim_lua = false,
vsnip = false,
ultisnips = false,
},
}
-- Utility functions for compe and luasnip
local t = function(str)
return vim.api.nvim_replace_termcodes(str, true, true, true)
end
local check_back_space = function()
local col = vim.fn.col '.' - 1
if col == 0 or vim.fn.getline('.'):sub(col, col):match '%s' then
return true
else
return false
end
end
-- Use (s-)tab to:
--- move to prev/next item in completion menuone
--- jump to prev/next snippet's placeholder
local luasnip = require 'luasnip'
_G.tab_complete = function()
if vim.fn.pumvisible() == 1 then
return t '<C-n>'
elseif luasnip.expand_or_jumpable() then
return t '<Plug>luasnip-expand-or-jump'
elseif check_back_space() then
return t '<Tab>'
else
return vim.fn['compe#complete']()
end
end
_G.s_tab_complete = function()
if vim.fn.pumvisible() == 1 then
return t '<C-p>'
elseif luasnip.jumpable(-1) then
return t '<Plug>luasnip-jump-prev'
else
return t '<S-Tab>'
end
end
-- Map tab to the above tab complete functiones
map('i', '<Tab>', 'v:lua.tab_complete()', { expr = true })
map('s', '<Tab>', 'v:lua.tab_complete()', { expr = true })
map('i', '<S-Tab>', 'v:lua.s_tab_complete()', { expr = true })
map('s', '<S-Tab>', 'v:lua.s_tab_complete()', { expr = true })
-- Map compe confirm and complete functions
map('i', '<cr>', 'compe#confirm("<cr>")', { expr = true })
map('i', '<c-space>', 'compe#complete()', { expr = true })