IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发工具 -> [neovim/nvim] LSP 与代码补全配置笔记 -> 正文阅读

[开发工具][neovim/nvim] LSP 与代码补全配置笔记

简述

记录配置nvim LSP过程。nvim版本:v0.7.2。所需插件:neovim/nvim-lspconfigwilliamboman/nvim-lsp-installer

目录结构:

目录结构

与LSP相关的配置全部置于~/.config/nvim/lua/lsp文件夹中。

使用lua配置nvim,可将配置内容依据喜好放置在不同文件,只需要在~/.config/nvim/init.lua中指明有哪些配置文件即可。

安装LSP插件

packer

  use "williamboman/nvim-lsp-installer"
  use 'neovim/nvim-lspconfig'
  • nvim-lspconfig: 配置LSP服务器
  • nvim-lsp-installer: 下载对应语言所需要的LSP服务器

配置文件

~/.config/nvim/init.lua中导入自定义的lsp模块

require("lsp")

当一个文件夹中存在init.lua文件时,可在~/.config/nvim/init.lua中直接导入该文件夹。~/.config/nvim/lua文件夹是属于自动检索路径。

文件:~/.config/nvim/lua/lsp/init.lua

require("nvim-lsp-installer").setup{}

-- Mappings.
-- See `:help vim.diagnostic.*` for documentation on any of the below functions
local opts = { noremap=true, silent=true }
vim.keymap.set('n', '<space>e', vim.diagnostic.open_float, opts)
vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, opts)
vim.keymap.set('n', ']d', vim.diagnostic.goto_next, opts)
vim.keymap.set('n', '<space>q', vim.diagnostic.setloclist, opts)

local lspconfig = require("lspconfig")
local function on_attach(client, bufnr) -- set up buffer keymaps, etc.
  -- Mappings.
  -- See `:help vim.lsp.*` for documentation on any of the below functions
  local bufopts = { noremap=true, silent=true, buffer=bufnr }
  vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, bufopts)
  vim.keymap.set('n', 'gd', vim.lsp.buf.definition, bufopts)
  vim.keymap.set('n', 'K', vim.lsp.buf.hover, bufopts)
  vim.keymap.set('n', '<space>D', vim.lsp.buf.type_definition, bufopts)
  vim.keymap.set('n', '<space>rn', vim.lsp.buf.rename, bufopts)
  vim.keymap.set('n', 'gr', vim.lsp.buf.references, bufopts)
end

local lsp_flags = {
  debounce_text_changes = 100,
}

-- Setup lspconfig.
local capabilities = require('cmp_nvim_lsp').update_capabilities(vim.lsp.protocol.make_client_capabilities())

该部分主要是设置LSP信息提示时间,按键映射。来自nvim-config插件主页中的Suggested configuration部分。

安装LSP服务器

输入命令:LspInstallInfo调出插件nvim-lsp-installer界面。

lsp-installer

i可安装当前光标下的LSP服务器。服务器是以zip文件形式下载的,需要确保本地环境有zip,unzip两个命令。 默认下载/安装路径为:~/.local/share/nvim/lsp_servers

启动LSP服务

~/.config/nvim/lua/lsp/init.lua文件尾添加启动配置。

-- after local capabilities = ....
-- start server
lspconfig.sumneko_lua.setup {
  on_attach = on_attach,
  flags = lsp_flags,
  capabilities = capabilities,
  settings = {
    Lua = {
      runtime = {
        version = 'LuaJIT',
      },
      diagnostics = {
        globals = {"vim", "packer_bootstrap"},
      },
      workspace = {
        library = vim.api.nvim_get_runtime_file("", true),
      },
      telemetry = {
        enable = false,
      },
    },
  },
}

lspconfig.pyright.setup {
  on_attach = on_attach,
  flags = lsp_flags,
  capabilities = capabilities,
  settings = {
    python = {
      analysis = {
        autoSearchPaths = true,
        diagnosticMode = "workspace",
        useLibraryCodeForTypes = true,
        typeCheckingMode = "off",
      }
    }
  },
}

这里可以查看所有nvim支持的LSP服务器默认设置。前三个参数是启动所有LSP服务器都需要填写的,就是将前面配置的内容传递给LSP服务器。后面的setting部分不一定需要修改。上面的配置启动了lua与python语言的LSP服务器。

到这里LSP已经配置完成,能够显示语法检查的错误信息等。

修改LSP提示信息风格

文件: ~/.config/nvim/lua/lsp/handlers.lua

-- Configure lsp information display style
local M = {}

M.setup = function()
  -- replace the lsp info symbol
  local signs = {
    { name = "DiagnosticSignError", text = "?" },
    { name = "DiagnosticSignWarn", text = "?" },
    { name = "DiagnosticSignHint", text = "?" },
    { name = "DiagnosticSignInfo", text = "?" },
  }

  for _, sign in ipairs(signs) do
    vim.fn.sign_define(sign.name, { texthl = sign.name, text = sign.text, numhl = "" })
  end

  -- set the style of lsp info
  local config = {
    -- disable virtual text
    -- the message show after the current line.
    virtual_text = false,
    -- show signs
    signs = {
      active = signs,
    },
    update_in_insert = true,
    underline = true,
    severity_sort = true,
    float = {
      focusable = false,
      style = "minimal",
      border = "rounded",
      source = "always",
      header = "",
      prefix = "",
    },
  }

  vim.diagnostic.config(config)

  -- set the popup window border
  vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, {
    border = "rounded",
  })

  vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with(vim.lsp.handlers.signature_help, {
    border = "rounded",
  })
end

return M

主要是将提示标志修改成nerd font字体符号,修改文档信息等呼出窗口为有边框模式等。其中virtual_text这一设置控制是否在有语法错误的那一行末显示错误信息的精简内容。

~/.config/nvim/lua/lsp/init.lua文件末导入该文件,使配置生效。

-- after start lsp server config....
-- change info style of lsp
require("lsp.handlers").setup()

效果

效果图

红色框中的内容便是最终LSP显示的信息样式。

LSP 是不怎么提供补全内容的,在nvim-lspconfig插件页面有启动默认补全的设置,这里没有使用,后续通过nvim-cmp插件来提过更加完善的补全效果。错误信息内容需要通过前面配置快捷键<space>+e呼出。

代码补全

所需插件

补全

这里使用的是nvim-cmp搭配ultisnips进行补全与代码片段实现。所用到的插件都是nvim-cmp页面中Recommended Configuration部分所罗列的设置。核心插件是nvim-cmp, cmp-nvim-lsp提供LSP的语法补全,其他插件只是完善作用。

配置nvim-cmp

文件:~/.config/nvim/lua/lsp/cmp.lua

-- ? ? ?? ? ? ? some other good icons
local kind_icons = {
  Text = "?",
  Method = "m",
  Function = "?",
  Constructor = "?",
  Field = "",
  Variable = "?",
  Class = "?",
  Interface = "?",
  Module = "?",
  Property = "?",
  Unit = "",
  Value = "?",
  Enum = "?",
  Keyword = "?",
  Snippet = "?",
  Color = "?",
  File = "?",
  Reference = "?",
  Folder = "?",
  EnumMember = "?",
  Constant = "?",
  Struct = "?",
  Event = "?",
  Operator = "?",
  TypeParameter = "?",
}
-- find more here: https://www.nerdfonts.com/cheat-sheet

local t = function(str)
  return vim.api.nvim_replace_termcodes(str, true, true, true)
end
local cmp = require('cmp')

cmp.setup{
  snippet = {
    expand = function(args)
      vim.fn["UltiSnips#Anon"](args.body)
    end,
  },
  window = {
    completion = cmp.config.window.bordered(),
    documentation = cmp.config.window.bordered(),
  },
  mapping = {
    ["<Tab>"] = cmp.mapping({
      c = function()
        if cmp.visible() then
          cmp.select_next_item({ behavior = cmp.SelectBehavior.Insert })
        else
          cmp.complete()
        end
      end,
      i = function(fallback)
        if cmp.visible() then
          cmp.select_next_item({ behavior = cmp.SelectBehavior.Insert })
        else
          fallback()
        end
      end
    }),
    ["<S-Tab>"] = cmp.mapping({
      c = function()
        if cmp.visible() then
          cmp.select_prev_item({ behavior = cmp.SelectBehavior.Insert })
        else
          cmp.complete()
        end
      end,
      i = function(fallback)
        if cmp.visible() then
          cmp.select_prev_item({ behavior = cmp.SelectBehavior.Insert })
        else
          fallback()
        end
      end
    }),
    ['<Down>'] = cmp.mapping(cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Select }), {'i'}),
    ['<Up>'] = cmp.mapping(cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Select }), {'i'}),
    ['<C-n>'] = cmp.mapping({
      c = function()
        if cmp.visible() then
          cmp.select_next_item({ behavior = cmp.SelectBehavior.Select })
        else
          vim.api.nvim_feedkeys(t('<Down>'), 'n', true)
        end
      end,
      i = function(fallback)
        if cmp.visible() then
          cmp.select_next_item({ behavior = cmp.SelectBehavior.Select })
        else
          fallback()
        end
      end
    }),
    ['<C-p>'] = cmp.mapping({
      c = function()
        if cmp.visible() then
          cmp.select_prev_item({ behavior = cmp.SelectBehavior.Select })
        else
          vim.api.nvim_feedkeys(t('<Up>'), 'n', true)
        end
      end,
      i = function(fallback)
        if cmp.visible() then
          cmp.select_prev_item({ behavior = cmp.SelectBehavior.Select })
        else
          fallback()
        end
      end
    }),
    ['<C-b>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), {'i', 'c'}),
    ['<C-f>'] = cmp.mapping(cmp.mapping.scroll_docs(4), {'i', 'c'}),
    --['<C-e>'] = cmp.mapping(cmp.mapping.complete(), {'i', 'c'}),
    --['<C-e>'] = cmp.mapping({ i = cmp.mapping.close(), c = cmp.mapping.close() }),
    ['<CR>'] = cmp.mapping({
      i = cmp.mapping.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = true }),
      c = function(fallback)
        if cmp.visible() then
          cmp.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = true})
        else
          fallback()
        end
      end
    }),
  },

  formatting = {
    fields = { "kind", "abbr", "menu" },
    format = function(entry, vim_item)
      -- Kind icons
      vim_item.kind = string.format("%s", kind_icons[vim_item.kind])
      vim_item.menu = ({
        nvim_lsp = "[LSP]",
        ultisnips = "[Snippet]",
        buffer = "[Buffer]",
        path = "[Path]",
      })[entry.source.name]
      return vim_item
    end,
  },

  sources = cmp.config.sources({
    { name = 'nvim_lsp' },
    { name = 'ultisnips' },
  }, {
    { name = 'buffer' },
    { name = 'path' },
  })
}

-- Set configuration for specific filetype.
cmp.setup.filetype('gitcommit', {
  sources = cmp.config.sources({
    { name = 'cmp_git' }, -- You can specify the `cmp_git` source if you were installed it.
  }, {
    { name = 'buffer' },
  })
})

-- Use buffer source foj `/` (if you enabled `native_menu`, this won't work anymore).
cmp.setup.cmdline('/', {
  completion = { autocomplete = false },
  sources = {
    { name = 'buffer' }
  }
})

-- Use cmdline & path source for ':' (if you enabled `native_menu`, this won't work anymore).
cmp.setup.cmdline(':', {
  completion = { autocomplete = false },
  sources = cmp.config.sources({
    { name = 'path' }
  }, {
    { name = 'cmdline' }
  })
})

配置内容主要来自插件nvim-cmp主页Recommended Configuration部分。只是添加了一些nerd font图标,并根据Wiki部分做了部分修改。

主页中使用的代码片段插件不是ultisnips。上面提供了多种选择。

启动补全

在文件~/.config/nvim/lua/lsp/init.lua文件末添加如下内容。

-- after require("lsp.handlers").setup()...
-- start cmp
require("lsp.cmp")

最终效果

cmp

  开发工具 最新文章
Postman接口测试之Mock快速入门
ASCII码空格替换查表_最全ASCII码对照表0-2
如何使用 ssh 建立 socks 代理
Typora配合PicGo阿里云图床配置
SoapUI、Jmeter、Postman三种接口测试工具的
github用相对路径显示图片_GitHub 中 readm
Windows编译g2o及其g2o viewer
解决jupyter notebook无法连接/ jupyter连接
Git恢复到之前版本
VScode常用快捷键
上一篇文章      下一篇文章      查看所有文章
加:2022-07-17 16:44:21  更:2022-07-17 16:48:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 2:30:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码