summaryrefslogtreecommitdiff
path: root/lua/config/05-lsp.lua
blob: 64328a999c0c491c38f0614dc286a46f290f59b5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
-- Native LSP and automatic completion for Neovim 0.12/0.13.
-- Requires nvim-lspconfig only for its server presets in runtimepath.
-- No nvim-cmp, cmp-nvim-lsp, lspkind, or vsnip required.

vim.opt.autocomplete = true
vim.opt.complete = 'o'
vim.opt.completeopt = { 'menu', 'menuone', 'noselect', 'popup' }
vim.opt.shortmess:append('c')

-- Keep the old LSP bindings; all are buffer-local.
local function map(buf, lhs, rhs, desc)
  vim.keymap.set('n', lhs, rhs, { buffer = buf, silent = true, desc = desc })
end

local group = vim.api.nvim_create_augroup('UserNativeLsp', { clear = true })

vim.api.nvim_create_autocmd('LspAttach', {
  group = group,
  callback = function(args)
    local bufnr = args.buf
    local client = vim.lsp.get_client_by_id(args.data.client_id)
    if not client then return end

    -- Completion requests are sent automatically while typing, without cmp.
    -- C-n/C-p move through suggestions; C-y accepts one; C-e dismisses.
    if client:supports_method('textDocument/completion') then
      vim.lsp.completion.enable(true, client.id, bufnr, { autotrigger = true })
    end

    map(bufnr, '<leader>rn', vim.lsp.buf.rename, 'LSP rename')
    map(bufnr, '<leader>ca', vim.lsp.buf.code_action, 'LSP code action')
    map(bufnr, '<M-k>', vim.lsp.buf.hover, 'LSP hover')
    map(bufnr, 'g0', vim.lsp.buf.document_symbol, 'Document symbols')
    map(bufnr, 'gW', vim.lsp.buf.workspace_symbol, 'Workspace symbols')
    map(bufnr, 'gd', vim.lsp.buf.definition, 'Go to definition')
    map(bufnr, 'gD', vim.lsp.buf.declaration, 'Go to declaration')
    map(bufnr, 'gi', vim.lsp.buf.implementation, 'Go to implementation')
    map(bufnr, 'gr', vim.lsp.buf.references, 'Find references')
    map(bufnr, '<C-k>', vim.lsp.buf.signature_help, 'Signature help')
    map(bufnr, 'g<Space>', vim.lsp.buf.type_definition, 'Type definition')
    map(bufnr, '[d', function() vim.diagnostic.jump({ count = -1 }) end, 'Previous diagnostic')
    map(bufnr, ']d', function() vim.diagnostic.jump({ count = 1 }) end, 'Next diagnostic')

    vim.bo[bufnr].omnifunc = 'v:lua.vim.lsp.omnifunc'
    vim.opt_local.signcolumn = 'yes'

    if client:supports_method('textDocument/documentHighlight') then
      -- Per-buffer autocommands, shared across clients to avoid duplicates.
      local hlgroup = vim.api.nvim_create_augroup('UserLspHighlight' .. bufnr, { clear = true })
      vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, {
        group = hlgroup, buffer = bufnr, callback = vim.lsp.buf.document_highlight,
      })
      vim.api.nvim_create_autocmd({ 'CursorMoved', 'InsertLeave' }, {
        group = hlgroup, buffer = bufnr, callback = vim.lsp.buf.clear_references,
      })
    end
  end,
})

vim.diagnostic.config({
  signs = {
    text = {
      [vim.diagnostic.severity.ERROR] = '✘',
      [vim.diagnostic.severity.WARN] = '▲',
      [vim.diagnostic.severity.INFO] = '●',
      [vim.diagnostic.severity.HINT] = '◆'
    }
  },
  underline = true,
  severity_sort = true,
})

-- nvim-lspconfig's modern lsp/*.lua presets supply cmd, filetypes and root detection.
-- Only list your desired servers and their overrides here.
local servers = {
  bashls = { filetypes = { 'bash', 'sh' } },
  clangd = { filetypes = { 'c', 'cpp', 'objc', 'objcpp', 'cuda' } },
  mlir = {},
  jqls = {},
  lua_ls = {
    settings = {
      Lua = {
        runtime = { version = 'LuaJIT' },
        workspace = { checkThirdParty = false, library = { vim.env.VIMRUNTIME } },
      },
    },
  },
  ocamllsp = {},
  perlpls = {},
  rust_analyzer = {},
  verible = {},
  vimls = {},
  zls = {},
  texlab = {},
  hls = { settings = { haskell = { plugin = { semanticTokens = { globalOn = true } } } } },
  pylsp = { settings = { pylsp = { plugins = { pycodestyle = { enabled = false } } } } },
}

for name, overrides in pairs(servers) do
  vim.lsp.config(name, overrides)
  vim.lsp.enable(name)
end

vim.keymap.set('i', '<Tab>', function()
  if vim.fn.pumvisible() == 1 then
    return '<C-y>'
  end
  return '<Tab>'
end, { expr = true, desc = 'Accept completion or insert Tab' })

local fallbacks = {
  Pmenu         = 'NormalFloat',
  PmenuSel      = 'Visual',
  PmenuKind     = 'Type',
  PmenuKindSel  = 'Type',
  PmenuExtra    = 'Comment',
  PmenuExtraSel = 'Comment',
  PmenuMatch    = 'Identifier',
  PmenuMatchSel = 'Identifier',
  PmenuBorder   = 'FloatBorder',
}

local function apply_fallbacks()
  for group, target in pairs(fallbacks) do
    local hl = vim.api.nvim_get_hl(0, { name = group, link = true })

    if vim.tbl_isempty(hl) or hl.link == 'Pmenu' then
      vim.api.nvim_set_hl(0, group, { link = target })
    end
  end
end

vim.api.nvim_create_autocmd('ColorScheme', {
  callback = apply_fallbacks,
})

apply_fallbacks()

vim.opt.pumheight = 12
vim.opt.pummaxwidth = 70
vim.opt.pumblend = 0