2021-11-03 14:10:54 +01:00
|
|
|
-- Aliases
|
|
|
|
local cmd = vim.cmd
|
|
|
|
local fn = vim.fn
|
|
|
|
local g = vim.g
|
|
|
|
local opt = vim.opt
|
|
|
|
local map = vim.api.nvim_set_keymap
|
|
|
|
|
|
|
|
-- Helpers
|
|
|
|
local function noremap(mode, lhs, rhs, opts)
|
|
|
|
local options = { noremap = true }
|
|
|
|
if opts then options = vim.tbl_extend('force', options, opts) end
|
|
|
|
vim.api.nvim_set_keymap(mode, lhs, rhs, options)
|
|
|
|
end
|
|
|
|
|
|
|
|
local function associate_filetype(glob, ft)
|
|
|
|
cmd('autocmd BufRead,BufNewFile ' .. glob .. ' set filetype=' .. ft)
|
|
|
|
end
|
|
|
|
local function setup_filetype(ft, tab, expandtab, opts)
|
|
|
|
local cmdline = 'autocmd Filetype ' .. ft .. ' setlocal'
|
|
|
|
if tab then cmdline = cmdline .. ' ts=' .. tab .. ' sw=' .. tab .. ' sts=' .. tab end
|
|
|
|
if opts then cmdline = cmdline .. ' ' .. opts end -- FIXME: opts should be a table
|
|
|
|
cmd(cmdline)
|
|
|
|
end
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
-- Display
|
|
|
|
opt.number = true -- line numbers
|
|
|
|
opt.colorcolumn = { '80' } -- line at 80 characters
|
|
|
|
opt.scrolloff = 5 -- context at top/bottom
|
|
|
|
opt.sidescrolloff = 8 -- context on the left/right side
|
|
|
|
opt.conceallevel = 1 -- conceal inactive lines
|
|
|
|
|
|
|
|
opt.termguicolors = true
|
|
|
|
cmd('colorscheme solarized')
|
|
|
|
|
|
|
|
-- Undo
|
|
|
|
opt.undofile = true
|
|
|
|
opt.undolevels = 4096
|
|
|
|
opt.undoreload = 16384
|
2022-06-12 21:03:32 +02:00
|
|
|
cmd('autocmd BufWritePre /dev/shm/* setlocal noundofile') -- exclude pass
|
|
|
|
cmd('autocmd BufWritePre /tmp/* setlocal noundofile') -- exclude sops
|
2021-11-03 14:10:54 +01:00
|
|
|
|
|
|
|
-- Behaviour
|
|
|
|
opt.hidden = true -- background buffers
|
|
|
|
opt.expandtab = true -- spaces instead of tabs by default
|
|
|
|
opt.smartindent = true -- automatic indentation
|
|
|
|
opt.tabstop = 2 -- tabs have width of 2 by default
|
|
|
|
opt.shiftwidth = 0 -- shift width = tab width
|
|
|
|
opt.joinspaces = false -- no double spaces when joining
|
|
|
|
opt.clipboard = 'unnamedplus' -- use system clipboard
|
|
|
|
opt.modeline = true
|
|
|
|
|
|
|
|
cmd([[
|
|
|
|
autocmd BufReadPost * if line("'\"") >= 1 && line("'\"") <= line("$") && &ft !~# 'commit' | exe "normal! g`\"" | endif
|
|
|
|
]]) -- see :h last-position-jump
|
|
|
|
|
|
|
|
-- Search
|
|
|
|
opt.ignorecase = true -- ignore case
|
2022-04-12 17:58:52 +02:00
|
|
|
opt.inccommand = 'nosplit' -- live preview of substitution
|
2021-11-03 14:10:54 +01:00
|
|
|
opt.smartcase = true -- but only with all-lowercase searches
|
|
|
|
|
|
|
|
-- Highlight trailing spaces
|
|
|
|
cmd([[autocmd BufWinEnter * match errorMsg /\s\+$\| \+\ze\t/]])
|
|
|
|
|
|
|
|
-- Mappings
|
|
|
|
g.mapleader = ','
|
|
|
|
|
|
|
|
noremap('n', '<CR>', ':nohlsearch<CR>', { silent = true }) -- hide highlights on enter
|
|
|
|
noremap('v', '<Leader>s', ':sort<CR>') -- sort in visual mode
|
|
|
|
noremap('t', '<Esc><Esc>', [[<C-\><C-n>]])
|
|
|
|
|
|
|
|
-- Filetypes
|
|
|
|
associate_filetype('*.vpy', 'python') -- vapoursynth scripts
|
|
|
|
|
|
|
|
setup_filetype('bib', 1)
|
|
|
|
setup_filetype('c', 4)
|
|
|
|
setup_filetype('cpp', 4)
|
|
|
|
setup_filetype('dockerfile', 4)
|
|
|
|
setup_filetype('gitcommit', nil, 'colorcolumn=72')
|
|
|
|
setup_filetype('go', 4, 'noexpandtab')
|
|
|
|
setup_filetype('haskell', 4)
|
|
|
|
setup_filetype('lua', 4)
|
|
|
|
setup_filetype('python', 4)
|
|
|
|
setup_filetype('sh', 4, 'noexpandtab')
|
|
|
|
setup_filetype('tex', 1)
|
|
|
|
setup_filetype('zsh', 4)
|
|
|
|
|
|
|
|
-- Plugins
|
|
|
|
|
|
|
|
-- Status line
|
|
|
|
local custom_solarized_lualine = require('lualine.themes.solarized')
|
|
|
|
-- default colours are very hard to read
|
|
|
|
custom_solarized_lualine.normal.b = { fg = '#eee8d5', bg = '#586e75' }
|
|
|
|
require('lualine').setup {
|
|
|
|
options = {
|
|
|
|
theme = custom_solarized_lualine,
|
|
|
|
},
|
|
|
|
sections = {
|
|
|
|
lualine_c = {
|
|
|
|
'filename',
|
|
|
|
'lsp_progress',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
-- Tagbar
|
|
|
|
noremap('n', '<F8>', ':TagbarToggle<CR>')
|
|
|
|
|
|
|
|
-- Keymap popup
|
|
|
|
require('which-key').setup {}
|
|
|
|
|
|
|
|
-- Icons
|
|
|
|
require('nvim-web-devicons').setup { default = true }
|
|
|
|
|
|
|
|
-- Git
|
|
|
|
require('plenary') -- otherwise neogit SIGABRTs
|
|
|
|
require('neogit').setup {
|
|
|
|
disable_commit_confirmation = true,
|
|
|
|
integrations = {
|
|
|
|
diffview = true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
cmd([[
|
|
|
|
hi NeogitNotificationInfo guifg=#268bd2
|
|
|
|
hi NeogitNotificationWarning guifg=#cb4b16
|
|
|
|
hi NeogitNotificationError guifg=#dc322f
|
|
|
|
]])
|
2022-06-12 21:12:50 +02:00
|
|
|
require('gitsigns').setup {
|
|
|
|
-- copied from upstream readme
|
|
|
|
on_attach = function(bufnr)
|
|
|
|
local gs = package.loaded.gitsigns
|
|
|
|
|
|
|
|
local function map(mode, l, r, opts)
|
|
|
|
opts = opts or {}
|
|
|
|
opts.buffer = bufnr
|
|
|
|
vim.keymap.set(mode, l, r, opts)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Navigation
|
|
|
|
map('n', ']c', function()
|
|
|
|
if vim.wo.diff then return ']c' end
|
|
|
|
vim.schedule(function() gs.next_hunk() end)
|
|
|
|
return '<Ignore>'
|
|
|
|
end, {expr=true})
|
|
|
|
|
|
|
|
map('n', '[c', function()
|
|
|
|
if vim.wo.diff then return '[c' end
|
|
|
|
vim.schedule(function() gs.prev_hunk() end)
|
|
|
|
return '<Ignore>'
|
|
|
|
end, {expr=true})
|
|
|
|
|
|
|
|
-- Actions
|
|
|
|
map({'n', 'v'}, '<leader>hs', ':Gitsigns stage_hunk<CR>')
|
|
|
|
map({'n', 'v'}, '<leader>hr', ':Gitsigns reset_hunk<CR>')
|
|
|
|
map('n', '<leader>hS', gs.stage_buffer)
|
|
|
|
map('n', '<leader>hu', gs.undo_stage_hunk)
|
|
|
|
map('n', '<leader>hR', gs.reset_buffer)
|
|
|
|
map('n', '<leader>hp', gs.preview_hunk)
|
|
|
|
map('n', '<leader>hb', function() gs.blame_line{full=true} end)
|
|
|
|
map('n', '<leader>tb', gs.toggle_current_line_blame)
|
|
|
|
map('n', '<leader>hd', gs.diffthis)
|
|
|
|
map('n', '<leader>hD', function() gs.diffthis('~') end)
|
|
|
|
map('n', '<leader>td', gs.toggle_deleted)
|
|
|
|
|
|
|
|
-- Text object
|
|
|
|
map({'o', 'x'}, 'ih', ':<C-U>Gitsigns select_hunk<CR>')
|
|
|
|
end
|
|
|
|
}
|
2021-11-03 14:10:54 +01:00
|
|
|
require('diffview').setup {}
|
|
|
|
|
|
|
|
-- Fuzzy finder/option picker
|
|
|
|
require('telescope').setup {}
|
|
|
|
|
|
|
|
-- Completion/Snippets
|
|
|
|
local cmp = require('cmp')
|
|
|
|
local lspkind = require('lspkind')
|
|
|
|
local luasnip = require('luasnip')
|
|
|
|
luasnip.config.set_config {
|
|
|
|
enable_autosnippets = true,
|
|
|
|
}
|
|
|
|
|
|
|
|
require('snippets')
|
|
|
|
|
|
|
|
cmp.setup {
|
|
|
|
snippet = {
|
|
|
|
expand = function(args) luasnip.lsp_expand(args.body) end,
|
|
|
|
},
|
2022-05-31 14:40:18 +02:00
|
|
|
mapping = cmp.mapping.preset.insert({
|
2021-11-03 14:10:54 +01:00
|
|
|
['<C-d>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }),
|
|
|
|
['<C-f>'] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c' }),
|
|
|
|
['<C-e>'] = cmp.mapping({ i = cmp.mapping.abort(), c = cmp.mapping.close() }),
|
|
|
|
['<CR>'] = cmp.mapping.confirm({ select = false }),
|
|
|
|
|
|
|
|
['<Tab>'] = cmp.mapping(function(fallback)
|
|
|
|
if luasnip.expand_or_jumpable() then
|
|
|
|
luasnip.expand_or_jump()
|
|
|
|
elseif cmp.visible() then
|
|
|
|
cmp.select_next_item()
|
|
|
|
elseif has_words_before() then
|
|
|
|
cmp.complete()
|
|
|
|
else
|
|
|
|
fallback()
|
|
|
|
end
|
|
|
|
end, { 'i', 's' }),
|
|
|
|
|
|
|
|
['<S-Tab>'] = cmp.mapping(function(fallback)
|
|
|
|
if luasnip.jumpable(-1) then
|
|
|
|
luasnip.jump(-1)
|
|
|
|
elseif cmp.visible() then
|
|
|
|
cmp.select_prev_item()
|
|
|
|
else
|
|
|
|
fallback()
|
|
|
|
end
|
|
|
|
end, { 'i', 's' }),
|
2022-05-31 14:40:18 +02:00
|
|
|
}),
|
2021-11-03 14:10:54 +01:00
|
|
|
sources = cmp.config.sources({
|
|
|
|
{ name = 'nvim_lsp' },
|
|
|
|
{ name = 'luasnip' },
|
|
|
|
{ name = 'path' }
|
|
|
|
}, {
|
|
|
|
{
|
|
|
|
name = 'buffer',
|
2022-05-31 14:40:18 +02:00
|
|
|
option = {
|
2021-11-03 14:10:54 +01:00
|
|
|
keyword_pattern = [[\k\+]], -- allow unicode multibyte characters
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
formatting = {
|
|
|
|
format = lspkind.cmp_format({
|
|
|
|
with_text = false,
|
|
|
|
maxwidth = 50,
|
|
|
|
})
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
-- LSP
|
|
|
|
local lsp = require('lspconfig')
|
|
|
|
|
|
|
|
vim.lsp.handlers['textDocument/publishDiagnostics'] = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
|
|
|
|
update_in_insert = true, -- update suggestions in insert mode
|
|
|
|
})
|
|
|
|
|
2022-05-31 14:40:18 +02:00
|
|
|
for type, icon in pairs({ Error = ' ', Warn = ' ', Hint = ' ', Info = ' ' }) do
|
|
|
|
fn.sign_define("DiagnosticSign" .. type, { text = icon, texthl = "Diagnostic" .. type })
|
2021-11-03 14:10:54 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
local on_attach = function(client, bufnr)
|
|
|
|
local function buf_set_keymap(...) vim.api.nvim_buf_set_keymap(bufnr, ...) end
|
|
|
|
local function buf_set_option(...) vim.api.nvim_buf_set_option(bufnr, ...) end
|
|
|
|
|
|
|
|
buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')
|
|
|
|
|
|
|
|
local opts = { noremap = true, silent = true }
|
|
|
|
|
|
|
|
buf_set_keymap('n', 'gD', '<cmd>lua vim.lsp.buf.declaration()<CR>', opts)
|
|
|
|
buf_set_keymap('n', 'gd', '<cmd>lua require("telescope.builtin").lsp_definitions()<CR>', opts)
|
|
|
|
buf_set_keymap('n', 'K', '<cmd>lua vim.lsp.buf.hover()<CR>', opts)
|
|
|
|
buf_set_keymap('n', 'gi', '<cmd>lua require("telescope.builtin").lsp_implementations()<CR>', opts)
|
|
|
|
buf_set_keymap('n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
|
|
|
|
buf_set_keymap('n', '<Leader>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
|
|
|
|
buf_set_keymap('n', '<Leader>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
|
|
|
|
buf_set_keymap('n', '<Leader>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
|
|
|
|
buf_set_keymap('n', '<Leader>D', '<cmd>lua require("telescope.builtin").lsp_type_definitions()<CR>', opts)
|
|
|
|
buf_set_keymap('n', '<Leader>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
|
|
|
|
buf_set_keymap('n', '<Leader>ca', '<cmd>lua require("telescope.builtin").lsp_code_actions()<CR>', opts)
|
|
|
|
buf_set_keymap('n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
|
|
|
|
buf_set_keymap('n', '<Leader>d', '<cmd>lua vim.lsp.diagnostic.show_line_diagnostics()<CR>', opts)
|
|
|
|
buf_set_keymap('n', '[d', '<cmd>lua vim.lsp.diagnostic.goto_prev()<CR>', opts)
|
|
|
|
buf_set_keymap('n', ']d', '<cmd>lua vim.lsp.diagnostic.goto_next()<CR>', opts)
|
|
|
|
buf_set_keymap('n', '<Leader>q', '<cmd>lua vim.lsp.diagnostic.set_loclist()<CR>', opts)
|
|
|
|
buf_set_keymap('n', '<Leader>f', '<cmd>lua vim.lsp.buf.formatting()<CR>', opts)
|
2022-06-12 22:34:27 +02:00
|
|
|
|
|
|
|
require('illuminate').on_attach(client)
|
|
|
|
buf_set_keymap('n', '<a-n>', '<cmd>lua require("illuminate").next_reference{wrap=true}<CR>', { noremap = true })
|
|
|
|
buf_set_keymap('n', '<a-p>', '<cmd>lua require("illuminate").next_reference{reverse=true,wrap=true}<CR>', { noremap = true })
|
2021-11-03 14:10:54 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
lsp.gopls.setup {
|
|
|
|
on_attach = on_attach,
|
|
|
|
}
|
|
|
|
lsp.hls.setup {
|
|
|
|
on_attach = on_attach,
|
|
|
|
root_dir = lsp.util.root_pattern('*.cabal', 'stack.yaml', 'cabal.project', 'package.yaml', 'hie.yaml', '.git'),
|
|
|
|
}
|
|
|
|
lsp.pylsp.setup {
|
|
|
|
on_attach = on_attach,
|
|
|
|
}
|
|
|
|
lsp.rnix.setup {
|
|
|
|
on_attach = on_attach,
|
|
|
|
}
|
|
|
|
lsp.rust_analyzer.setup {
|
|
|
|
on_attach = on_attach,
|
|
|
|
settings = {
|
|
|
|
['rust-analyzer'] = {
|
|
|
|
checkOnSave = {
|
|
|
|
command = 'clippy',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
require('trouble').setup {}
|
|
|
|
|
2022-06-12 22:44:55 +02:00
|
|
|
-- Tree Sitter
|
|
|
|
require('nvim-treesitter.configs').setup {
|
|
|
|
highlight = {
|
|
|
|
enable = true,
|
|
|
|
additional_vim_regex_highlighting = false,
|
|
|
|
},
|
|
|
|
indent = {
|
|
|
|
enable = true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2021-11-03 14:10:54 +01:00
|
|
|
-- VimTeX
|
|
|
|
g.tex_flavor = 'latex'
|
|
|
|
g.vimtex_view_method = 'zathura'
|
|
|
|
g.tex_conceal = 'abdmg'
|
|
|
|
|
|
|
|
-- this disables some helful warnings that often have a reason why I ignore them
|
|
|
|
g.vimtex_quickfix_ignore_filters = {
|
|
|
|
[[Underfull \\hbox (badness [0-9]*) in ]],
|
|
|
|
[[Overfull \\hbox ([0-9]*.[0-9]*pt too wide) in ]],
|
|
|
|
[[Overfull \\vbox ([0-9]*.[0-9]*pt too high) detected ]],
|
|
|
|
[[Package hyperref Warning: Token not allowed in a PDF string]],
|
|
|
|
[[Package typearea Warning: Bad type area settings!]],
|
|
|
|
}
|
|
|
|
|
|
|
|
-- When using math environments vim does not know if if it currently is in one or outside of one
|
|
|
|
-- unless it parses the file from the start.
|
|
|
|
-- Parsing the file from the start each time fixes this
|
|
|
|
-- but leads to a performance drop (depending on the number of lines).
|
|
|
|
-- Also, somehow using FileType tex does not work, so this will enable slow syntax highlighting
|
|
|
|
-- everywhere once a *.tex file is opened.
|
|
|
|
cmd([[autocmd BufEnter *.tex syntax sync fromstart]])
|
|
|
|
|
|
|
|
-- rust.vim
|
|
|
|
g.rustfmt_autosave_if_config_present = 1
|
|
|
|
g.rust_fold = 1
|
|
|
|
noremap('n', '<Leader>rt', ':RustTest<CR>')
|
|
|
|
|
|
|
|
-- Markdown
|
|
|
|
g.vim_markdown_folding_disabled = 1
|