nixos-config/dotfiles/nvim-init.lua

461 lines
12 KiB
Lua

-- https://github.com/neovim/neovim/issues/23725#issuecomment-1561364086
local ok, wf = pcall(require, "vim.lsp._watchfiles")
if ok then
-- disable lsp watcher. Too slow on linux
wf._watchfunc = function()
return function() end
end
end
local rt = require("rust-tools")
local lint = require('lint')
local lspconfig = require('lspconfig')
tb = require("telescope.builtin")
require('telescope').setup({
defaults = {
sorting_strategy = "ascending",
},
})
require("nvim-treesitter.configs").setup {
auto_install = false,
highlight = {
enable = true,
disable = function(lang, buf)
local max_filesize = 100 * 1024 * 1024 -- 100 MB
local ok, stats = pcall(vim.loop.fs_stat, vim.api.nvim_buf_get_name(buf))
if ok and stats and stats.size > max_filesize then
return true
end
end,
},
indent = {
enable = true
}
}
-- completion
local cmp = require('cmp')
-- Global setup.
cmp.setup({
snippet = {
expand = function(args)
end,
},
window = {
-- completion = cmp.config.window.bordered(),
-- documentation = cmp.config.window.bordered(),
},
mapping = cmp.mapping.preset.insert({
['<PageUp>'] = cmp.mapping.scroll_docs(-4),
['<PageDown>'] = cmp.mapping.scroll_docs(4),
['<C-Space>'] = cmp.mapping.complete(),
['<CR>'] = cmp.mapping.confirm({ select = true }),
}),
sources = cmp.config.sources({
{ name = 'nvim_lsp' },
--{ name = 'vsnip' }, -- For vsnip users.
-- { name = 'luasnip' }, -- For luasnip users.
-- { name = 'snippy' }, -- For snippy users.
-- { name = 'ultisnips' }, -- For ultisnips users.
}, {
{ name = 'buffer' },
}),
completion = {
autocomplete = false,
keyword_length = 1,
},
})
-- Setup lspconfig.
--local capabilities = require('cmp_nvim_lsp').default_capabilities()
local lsp_status = require('lsp-status')
local function nilfunc()
return nil
end
--capabilities = vim.tbl_extend('keep', capabilities, lsp_status.capabilities)
_last_picker = nil
_last_ctx = nil
-- NOTE: this is currently unused because it so sucks. use gr instead!
local function telescope_middleware(func, ctxfunc)
local function inner()
if ctxfunc == nil then
ctx = nil
else
ctx = ctxfunc()
end
if func == _last_picker and vim.deep_equal(ctx, _last_ctx) then
tb.resume()
else
_last_picker = func
_last_ctx = ctx
func()
end
end
return inner
end
local function tokenctx()
cursor0 = vim.api.nvim_win_get_cursor(0)
vim.cmd.normal("lb")
cursor = vim.api.nvim_win_get_cursor(0)
word = vim.call('expand','<cword>')
vim.api.nvim_win_set_cursor(0, cursor0)
return {cursor, word}
end
local function lsp_keybinds(client, bufnr)
local bufopts = { noremap=true, silent=true, buffer=bufnr }
vim.keymap.set("n", "gd", tb.lsp_definitions, bufopts)
vim.keymap.set("n", "gD", tb.lsp_implementations, bufopts)
vim.keymap.set("n", "gt", tb.lsp_type_definitions, bufopts)
vim.keymap.set("n", "K", vim.lsp.buf.hover, bufopts)
vim.keymap.set('n', 'gu', tb.lsp_references, bufopts) -- "usages"
vim.keymap.set('n', 'ge', telescope_line_diagnostics, bufopts) -- "errors"
vim.keymap.set('n', 'gE', function() tb.diagnostics({ severity_limit=vim.diagnostic.severity.WARN }) end, bufopts) -- "errors"
vim.keymap.set('n', 'gaE', tb.diagnostics, bufopts) -- "errors"
--vim.api.nvim_command('inoremap <C-space> <C-x><C-o>')
--vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc')
vim.keymap.set('i', '<C-Space>', vim.lsp.buf.completion, bufopts)
vim.keymap.set('i', '<A-CR>', vim.lsp.buf.code_action, bufopts)
vim.keymap.set('n', '<A-CR>', vim.lsp.buf.code_action, bufopts)
lsp_status.on_attach(client)
end
vim.keymap.set('n', '[e', function() vim.diagnostic.goto_prev{float=false, severity={min=vim.diagnostic.severity.WARN}} end, nil)
vim.keymap.set('n', ']e', function() vim.diagnostic.goto_next{float=false, severity={min=vim.diagnostic.severity.WARN}} end, nil)
vim.keymap.set('n', 'gf', tb.live_grep, nil)
vim.keymap.set('n', 'gn', tb.find_files, nil)
vim.keymap.set('n', 'gr', tb.resume, nil)
local pickers = require("telescope.pickers")
local finders = require("telescope.finders")
local previewers = require("telescope.previewers")
local conf = require("telescope.config").values
local actions = require("telescope.actions")
local action_state = require("telescope.actions.state")
local make_entry = require("telescope.make_entry")
lsp_status.config {
indicator_errors = 'E',
indicator_warnings = 'W',
indicator_info = 'i',
indicator_hint = '?',
indicator_ok = 'Ok',
diagnostics = false,
}
lsp_status.register_progress()
function telescope_line_diagnostics(opts)
opts = opts or {}
local diags = vim.diagnostic.get(0, {
lnum = opts.lnum or vim.api.nvim_win_get_cursor(0)[1] - 1,
severity = {min = opts.severity_limit or vim.diagnostic.severity.HINT},
})
if diags[1] == nil then
print("No issues under cursor")
return
end
if diags[2] == nil then
show_full_diagnostic(diags[1])
return
end
pickers.new(opts, {
prompt_title = "Line Issues",
finder = finders.new_table {
results = diags,
entry_maker = function(diag)
return make_entry.set_default_entry_mt({
value = diag,
text = diag.message,
display = diag.message:gsub("\n", " - "),
ordinal = diag.message,
}, opts)
end
},
sorter = conf.generic_sorter(opts),
previewer = previewers.new_buffer_previewer {
define_preview = function(self, entry, status)
local text = vim.split(render_full_diagnostic_and_debug(entry.value), '\n')
vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, true, text)
end
},
attach_mappings = function(prompt_bufnr, map)
actions.select_default:replace(function()
actions.close(prompt_bufnr)
local entry = action_state.get_selected_entry()
show_full_diagnostic(entry.value)
end)
return true
end,
}):find()
end
function render_full_diagnostic(diag)
if diag.user_data and diag.user_data.lsp and diag.user_data.lsp.data and diag.user_data.lsp.data.rendered then
return diag.user_data.lsp.data.rendered
end
if diag.message then
return diag.message
end
error("Bad diagnostic value")
end
function render_full_diagnostic_and_debug(diag)
return render_full_diagnostic(diag) .. '\n\n' .. vim.inspect(diag)
end
function show_full_diagnostic(diag)
local buf = nil;
local win = nil;
for _, win2 in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
if string.match(vim.api.nvim_buf_get_name(vim.api.nvim_win_get_buf(win2)), "<diagnostic>$") then
win = win2
buf = vim.api.nvim_win_get_buf(win)
vim.api.nvim_set_current_win(win)
break
end
end
if buf == nil then
vim.cmd('bel split')
win = vim.api.nvim_get_current_win()
buf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_win_set_buf(win, buf)
vim.api.nvim_buf_set_option(buf, "bufhidden", "delete")
vim.api.nvim_buf_set_name(buf, "<diagnostic>")
end
local text = vim.split(render_full_diagnostic_and_debug(diag), '\n')
vim.api.nvim_buf_set_lines(buf, 0, -1, true, text)
vim.api.nvim_win_set_cursor(win, { 1, 0 })
end
function show_preview_diagnostic(diag)
local width = vim.api.nvim_get_option('columns') - 15
local lines = vim.split(diag.message, "\n")
local message = lines[1]
if #lines > 1 and #message <= 20 then
message = message .. ' ' .. lines[2]
end
--while true do
-- local m = message:match("^[Ee]rror")
-- if m == nil then m = message:match("^[Ww]arning") end
-- if m == nil then m = message:match("^%d+:") end
-- if m == nil then m = message:match("^[: ]+") end
-- if m == nil then
-- break
-- else
-- message = message.sub(#m + 1, #message)
-- end
--end
if width > 0 and #message >= width then
message = message:sub(1, width) .. '...'
end
vim.api.nvim_echo({{message}}, false, {})
end
rust_root_dir = function(fname)
local primary = lspconfig.util.root_pattern('rust-toolchain')(fname)
local fallback = lspconfig.util.root_pattern('Cargo.toml')(fname)
return primary or fallback
end
local pipe = io.popen('rustup which rust-analyzer --toolchain nightly 2>/dev/null')
local rust_analyzer = pipe:read()
if rust_analyzer == nil then
pipe = io.popen('which rust-analyzer')
rust_analyzer = pipe:read()
end
pipe = io.popen('which clangd')
clangd = pipe:read()
if clangd == nil then
pipe = io.popen('which clangd15')
clangd = pipe:read()
end
pipe = io.popen('which bash-language-server')
bashls = pipe:read()
pipe = io.popen('which pyright-langserver')
pyright = pipe:read()
pipe.close()
if rust_analyzer ~= nil then
rt.setup({
server = {
on_attach = lsp_keybinds,
capabilities = capabilities,
root_dir = rust_root_dir,
cmd = {rust_analyzer},
},
})
end
if pyright ~= nil then
lspconfig.pyright.setup{
on_attach = lsp_keybinds,
capabilities = capabilities,
cmd = {pyright, '--stdio'},
settings = {
python = {
analysis = {
autoSearchPaths = false,
diagnosticMode = "openFilesOnly",
useLibraryCodeForTypes = false,
},
},
},
}
end
if clangd ~= nil then
lspconfig.clangd.setup{
on_attach = lsp_keybinds,
capabilities = capabilities,
cmd = {clangd, "--limit-references=1000000" },
handlers = lsp_status.extensions.clangd.setup(),
init_options = {
clangdFileStatus = true
},
single_file_support = false,
}
end
lspconfig.nil_ls.setup{
on_attach = lsp_keybinds,
capabilities = capabilities,
}
lspconfig.csharp_ls.setup{
on_attach = lsp_keybinds,
capabilities = capabilities,
}
if bashls ~= nil then
lspconfig.bashls.setup{
on_attach = lsp_keybinds,
capabilities = capabilities,
cmd = {bashls, "start" },
}
end
lspconfig.gopls.setup{
on_attach = lsp_keybinds,
capabilities = capabilities,
}
lspconfig.ts_ls.setup{
on_attach = lsp_keybinds,
capabilities = capabilities,
}
lspconfig.lua_ls.setup{
on_attach = lsp_keybinds,
capabilities = capabilities,
settings = {
Lua = {
workspace = {
library = {"/home/audrey/loenn_stubs.lua"},
},
},
},
}
--lspconfig.ocamllsp.setup{
-- on_attach = lsp_keybinds,
-- capabilities = capabilities,
--}
--vim.api.nvim_create_autocmd({ "BufWritePost", "BufReadPost" }, {
-- callback = function()
-- lint.try_lint()
-- end
--})
--lint.linters_by_ft = {
-- python = {'ruff'},
-- rust = {},
--}
-- LSP Diagnostics Options Setup
local sign = function(opts)
vim.fn.sign_define(opts.name, {
texthl = opts.name,
text = opts.text,
numhl = ''
})
end
sign({name = 'DiagnosticSignError', text = '!'})
sign({name = 'DiagnosticSignWarn', text = '-'})
--sign({name = 'DiagnosticSignHint', text = '.'})
--sign({name = 'DiagnosticSignInfo', text = '+'})
vim.diagnostic.config({
virtual_text = false,
signs = {
severity = {min = vim.diagnostic.severity.WARN},
},
update_in_insert = true,
underline = true,
severity_sort = true,
float = {
border = 'rounded',
source = 'always',
header = '',
prefix = '',
},
})
vim.api.nvim_create_autocmd({ 'DiagnosticChanged' }, {
callback = function(args)
local diags = args.data.diagnostics
for _, diag in pairs(diags) do
if diag.severity == vim.diagnostic.severity.ERROR then
show_preview_diagnostic(diag)
return
end
end
vim.api.nvim_echo({{''}}, false, {})
end,
})
vim.api.nvim_create_autocmd({ 'CursorMoved' }, {
callback = function()
local diags = vim.diagnostic.get(0, {
lnum = vim.api.nvim_win_get_cursor(0)[1] - 1,
severity = {min = vim.diagnostic.severity.WARN},
})
for _, diag in pairs(diags) do
show_preview_diagnostic(diag)
break
end
end
})
vim.api.nvim_create_user_command('Fmt', function() vim.lsp.buf.format({}) end, {})
show = function(x)
vim.notify(vim.inspect(x))
end
vim.g.sweetie = {
palette = {
dark = {
bg_alt = "#151523"
}
},
overrides = {
StatusLineNC = { fg = "#eeffee", bg = "#151523" },
StatusLine = {fg = "#ffffff", bg = "#151523", bold = true },
MatchParen = { fg = '#ae920a', reverse = false },
Search = { fg = '#ae920a', bg = "#0b658e" },
}
}
if vim.env.TERM == "tmux" or vim.env.TERM == "xterm" then
vim.cmd.colorscheme("default")
else
vim.cmd.colorscheme("sweetie")
end