Neovim 配置全面解析(下)

Neovim 配置全面解析(下)

原文:Neovim 配置全面解析(下) - 知乎 (zhihu.com)

环境:Ubuntu 20.04

宿主机:windows (windows terminal)WSL 2

NVIM:v 0.10.0-dev

配置 Neovim 需要保证流畅的 github 环境(以便于快速拉取插件),可以使用代理或是配置 Github SSH key

本篇博客是学习掘金小册的学习笔记,有兴趣的朋友可以直接点击下文链接了解详情

小册链接: https://s.juejin.cn/ds/iFGpuLW6/

因为文章字数超出平台限制,所以教程分上下两章节

Neovim 配置全面解析(上) - 知乎 (zhihu.com)

Neovim 配置全面解析(下) - 知乎 (zhihu.com)

基于 LSP 代码补全及自定义代码段

相关插件:hrsh7th/nvim-cmp: A completion plugin for neovim coded in Lua. (github.com)

相关概念:

  1. 补全引擎

    补全引擎就是为 Neovim 提供代码补全核心功能的插件,比如 nvim-cmp

  2. 补全源

    补全源就是补全引擎需要的数据来源,最常见的来源是来自 Language Server 提供的数据,它会知道某个类有哪些属性和方法等。

  3. snippet 引擎

    snippet 引擎就是自定义代码段的引擎,常见的有 vsnipluasnip

添加插件

    -- 补全引擎
    use ("hrsh 7 th/nvim-cmp")
    -- snippet 引擎
    use ("hrsh 7 th/vim-vsnip")
    -- 补全源
    use ("hrsh 7 th/cmp-vsnip")
    use ("hrsh 7 th/cmp-nvim-lsp") -- { name = nvim_lsp }
    use ("hrsh 7 th/cmp-buffer") -- { name = 'buffer' },
    use ("hrsh 7 th/cmp-path") -- { name = 'path' }
    use ("hrsh 7 th/cmp-cmdline") -- { name = 'cmdline' }

    -- 常见编程语言代码段
    use ("rafamadriz/friendly-snippets")

注意:只有 hrsh 7 th/nvim-cmp 是补全引擎插件本身,其他 cmp-xxx 基本都是插件补全来源,也就是说当你输入一个变量的时候,可以从多个来源显示补全的内容。

像 hrsh 7 th/cmp-nvim-lsp 就是 Neovim 内置 LSP 提供的补全内容,hrsh 7 th/cmp-buffer 补全当前 buffer 的内容, hrsh 7 th/cmp-cmdline 是命令行的补全,hrsh 7 th/cmp-path 则是用来补全路径,如果配置了这个,当输入一个路径的时候会补全路径

创建lua/lsp/cmp. lua

local cmp = require ("cmp")

cmp.setup ({
  -- 指定 snippet 引擎
  snippet = {
    expand = function (args)
      -- For `vsnip` users.
      vim. fn ["vsnip#anonymous"](args.body)

      -- For `luasnip` users.
      -- require ('luasnip'). lsp_expand (args. body)

      -- For `ultisnips` users.
      -- vim. fn ["UltiSnips#Anon"](args.body)

      -- For `snippy` users.
      -- require'snippy'. expand_snippet (args. body)
    end,
  },
  -- 补全源
  sources = cmp.config.sources ({
    { name = "nvim_lsp" },
    -- For vsnip users.
    { name = "vsnip" },

    -- For luasnip users.
    -- { name = 'luasnip' },

    --For ultisnips users.
    -- { name = 'ultisnips' },

    -- -- For snippy users.
    -- { name = 'snippy' },
  }, { { name = "buffer" }, { name = "path" } }),

  -- 快捷键设置
  mapping = require ("keybindings"). cmp (cmp),
})

-- / 查找模式使用 buffer 源
cmp.setup.cmdline ("/", {
  mapping = cmp.mapping.preset.cmdline (),
  sources = {
    { name = "buffer" },
  },
})

-- : 命令行模式中使用 path 和 cmdline 源.
cmp.setup.cmdline (": ", {
  mapping = cmp.mapping.preset.cmdline (),
  sources = cmp.config.sources ({
    { name = "path" },
  }, {
    { name = "cmdline" },
  }),
})

lua/keybindings. lua添加

-- nvim-cmp 自动补全
pluginKeys. cmp = function (cmp)
    return {
        -- 出现补全
        ["<A-.>"] = cmp.mapping (cmp.mapping.complete (), {"i", "c"}),
        -- 取消补全
        ["<A-,>"] = cmp.mapping ({
            i = cmp.mapping.abort (),
            c = cmp.mapping.close ()
        }),
        -- 上一个
        ["<C-k>"] = cmp. mapping. select_prev_item (),
        -- 下一个
        ["<C-j>"] = cmp. mapping. select_next_item (),
        -- 确认
        ["<CR>"] = cmp.mapping.confirm ({
            select = true,
            behavior = cmp. ConfirmBehavior. Replace
        }),
        -- 如果窗口内容太多,可以滚动
        ["<C-u>"] = cmp.mapping (cmp. mapping. scroll_docs (-4), {"i", "c"}),
        ["<C-d>"] = cmp.mapping (cmp. mapping. scroll_docs (4), {"i", "c"}),
    }
end

init. lua

require ("lsp. cmp") --  (新增)

LSP 功能增强

UI 插件,同时 lspage 还可以自定义快捷键,对于我自己而言我认为有些地方文字更加直观,如果有些朋友需要美化可自行查找

弹窗显示错误

当一行代码很长的时候,右侧的提示文字就会显示不全

之前配置过 gp 快捷键使用弹窗显示错误,可以有效解决

功能增强

相关插件:kkharji/lspsaga.nvim: The neovim language-server-client UI (github.com)

添加插件

    use ("tami 5/lspsaga. nvim" )

创建lua/lsp/ui. lua

local lspsaga = require 'lspsaga'
lspsaga. setup { -- defaults ...
  debug = false,
  use_saga_diagnostic_sign = true,
  -- diagnostic sign
  error_sign = "",
  warn_sign = "",
  hint_sign = "",
  infor_sign = "",
  diagnostic_header_icon = "   ",
  -- code action title icon
  code_action_icon = " ",
  code_action_prompt = {
    enable = true,
    sign = true,
    sign_priority = 40,
    virtual_text = true,
  },
  finder_definition_icon = "  ",
  finder_reference_icon = "  ",
  max_preview_lines = 10,
  finder_action_keys = {
    -- open = "o",
    open = "<CR>",
    vsplit = "s",
    split = "i",
    -- quit = "q",
    quit = "<ESC>",
    scroll_down = "<C-f>",
    scroll_up = "<C-b>",
  },
  code_action_keys = {
    -- quit = "q",
    quit = "<ESC>",
    exec = "<CR>",
  },
  rename_action_keys = {
    -- quit = "<C-c>",
    quit = "<ESC>",
    exec = "<CR>",
  },
  definition_preview_icon = "  ",
  border_style = "single",
  rename_prompt_prefix = "➤",
  rename_output_qflist = {
    enable = false,
    auto_open_qflist = false,
  },
  server_filetype_map = {},
  diagnostic_prefix_format = "%d. ",
  diagnostic_message_format = "%m %c",
  highlight_prefix = false,
}

lua/keybindings. lua中的 mapLSP 函数替换为

-- lsp 回调函数快捷键设置
pluginKeys. mapLSP = function (mapbuf)
  -- rename
  --[[
  Lspsaga 替换 rn
  mapbuf ("n", "<leader>rn", "<cmd>lua vim.lsp.buf.rename ()<CR>", opt)
  --]]
  mapbuf ("n", "<leader>rn", "<cmd>Lspsaga rename<CR>", opt)
  -- code action
  --[[
  Lspsaga 替换 ca
  mapbuf ("n", "<leader>ca", "<cmd>lua vim. lsp. buf. code_action ()<CR>", opt)
  --]]
  mapbuf ("n", "<leader>ca", "<cmd>Lspsaga code_action<CR>", opt)
  -- go xx
  --[[
    mapbuf ('n', 'gd', '<cmd>Lspsaga preview_definition<CR>', opt)
  --]]
  mapbuf ("n", "gd", "<cmd>lua vim.lsp.buf.definition ()<CR>", opt)
  --[[
  Lspsaga 替换 gh
  mapbuf ("n", "gh", "<cmd>lua vim.lsp.buf.hover ()<CR>", opt)
  --]]
  mapbuf ("n", "gh", "<cmd>Lspsaga hover_doc<cr>", opt)
  --[[
  Lspsaga 替换 gr
  mapbuf ("n", "gr", "<cmd>lua vim.lsp.buf.references ()<CR>", opt)
  --]]
  mapbuf ("n", "gr", "<cmd>Lspsaga lsp_finder<CR>", opt)
  --[[
  Lspsaga 替换 gp, gj, gk
  mapbuf ("n", "gp", "<cmd>lua vim. diagnostic. open_float ()<CR>", opt)
  mapbuf ("n", "gj", "<cmd>lua vim. diagnostic. goto_next ()<CR>", opt)
  mapbuf ("n", "gk", "<cmd>lua vim. diagnostic. goto_prev ()<CR>", opt)
  --]]
  -- diagnostic
  mapbuf ("n", "gp", "<cmd>Lspsaga show_line_diagnostics<CR>", opt)
  mapbuf ("n", "gj", "<cmd>Lspsaga diagnostic_jump_next<cr>", opt)
  mapbuf ("n", "gk", "<cmd>Lspsaga diagnostic_jump_prev<cr>", opt)
  mapbuf ("n", "<leader>f", "<cmd>lua vim.lsp.buf.format ({ bufnr = bufnr })<CR>", opt)
  -- 未用
  -- mapbuf ("n", "gD", "<cmd>lua vim.lsp.buf.declaration ()<CR>", opt)
  -- mapbuf ("n", "gi", "<cmd>lua vim.lsp.buf.implementation ()<CR>", opt)
  -- mapbuf ('n', '<leader>q', '<cmd>lua vim.diagnostic.setloclist ()<CR>', opt)
  -- mapbuf ("n", "<C-k>", "<cmd>lua vim. lsp. buf. signature_help ()<CR>", opt)
  -- mapbuf ('n', '<space>wa', '<cmd>lua vim. lsp. buf. add_workspace_folder ()<CR>', opt)
  -- mapbuf ('n', '<space>wr', '<cmd>lua vim. lsp. buf. remove_workspace_folder ()<CR>', opt)
  -- mapbuf ('n', '<space>wl', '<cmd>lua print (vim.inspect (vim. lsp. buf. list_workspace_folders ()))<CR>', opt)
  -- mapbuf ('n', '<space>D', '<cmd>lua vim. lsp. buf. type_definition ()<CR>', opt)
end

init. lua

require ("lsp. ui")

代码格式化

之前lua/keybindings. lua定义过格式化快捷键

mapbuf ("n", "<leader>f", "<cmd>lua vim.lsp.buf.format ({ bufnr = bufnr })<CR>", opt)

但是你会发现格式化不起作用,这是因为使用的 Lua Language Server 并没有实现格式化功能。

格式化方案有如下两种:

  • 第一种是使用专门的格式化插件;

  • 第二种是给 Language Server 注入格式化功能。

这里只讲解第二种

相关插件:jose-elias-alvarez/null-ls.nvim: Use Neovim as a language server to inject LSP diagnostics, code actions, and more via Lua. (github.com)

添加插件

    -- 代码格式化
    use ({ "jose-elias-alvarez/null-ls. nvim", requires = "nvim-lua/plenary. nvim" })

添加配置文件 lua/lsp/null-ls. lua

local status, null_ls = pcall (require, "null-ls")
if not status then
  vim.notify ("没有找到 null-ls")
  return
end

       local formatting = null_ls. builtins. formatting


null_ls.setup ({
  debug = false,
  sources = {
    -- Formatting ---------------------
    --  brew install shfmt
    formatting. shfmt,
    -- StyLua
    formatting. stylua,
    -- frontend
    formatting.prettier.with ({ -- 只比默认配置少了 markdown
      filetypes = {
        "javascript",
        "javascriptreact",
        "typescript",
        "typescriptreact",
        "vue",
        "css",
        "scss",
        "less",
        "html",
        "json",
        "yaml",
        "graphql",
      },
      prefer_local = "node_modules/. bin",
    }),
    -- formatting. fixjson,
    -- formatting.black.with ({ extra_args = { "--fast" } }),
  },
  -- 保存自动格式化
    on_attach = function (client, bufnr)
        if client. supports_method ("textDocument/formatting") then
            vim. api. nvim_clear_autocmds ({ group = augroup, buffer = bufnr })
            vim. api. nvim_create_autocmd ("BufWritePre", {
                group = augroup,
                buffer = bufnr,
                callback = function ()
                    -- on 0.8, you should use vim.lsp.buf.format ({ bufnr = bufnr }) instead
                    vim.lsp.buf.format ({ bufnr = bufnr })
                    -- vim. lsp. buf. formatting_sync ()
                end,
            })
        end
    end,
})

init. lua

require ("lsp. null-ls")

安装之后可以运行:LspInfo查看绑定的 Language Server

然后我们可以看到有两个 LSP 了,null-ls 作为通用 LSP,可以在任何 filetypes 中运行。

然后执行:NullLsInfo查看源的激活情况

之后的话即可使用: lua vim.lsp.buf.format ()命令或是直接使用快捷键<leader>f进行格式化

但是我们会发现包如下错误,这是因为相应语言应该配置相应的 Code Formatter,显示报错就是缺少 Lua 语言的 StyLua,其它语言可以自行配置相应的 Formatter

下面展示如何配置 stylua

配置环境

stylua 需要配置 rust 环境,rust 官网:安装 Rust - Rust 程序设计语言 (rust-lang.org)

因为我是使用 WSL,因此直接执行如下命令即可

curl --proto '=https' --tlsv 1.2 -sSf https://sh.rustup.rs | sh

执行source "$HOME/. cargo/env"

执行rustc --version看是否成功,失败则看是否添加~/. cargo/bin路径到环境变量中

安装步骤

执行

cargo install stylua

输出stylua -V看是否成功

出现问题

格式化之后里面的空格就都变成了"^I", 原本应该是"·"的

直接将basic. lua文件中设置vim. o. listchars = "space:·, tab:··"或是设置vim. o. list = false

前端开发必要配置

配置语法高亮

执行: TSInstall css scss json html vue javascript typescript

执行:TSInstallInfo查看安装情况

配置 LSP

lua/lsp/setup. lua

mason_config.setup ({
    ensure_installed = {"lua_ls", "html", "cssls"}
})
...
local servers = {
    lua_ls = require ("lsp. config. lua"),
    -- 新增
    html = require ("lsp. config. html"),
    cssls = require ("lsp. config. css")
}

创建lsp/common-config. lua

local M = {}

M.keyAttach = function (bufnr)
  local function buf_set_keymap (mode, lhs, rhs)
    vim.keymap.set (mode, lhs, rhs, { noremap = true, silent = true, buffer = bufnr })
  end
  -- 绑定快捷键
  require ("keybindings"). mapLSP (buf_set_keymap)
end

-- 禁用格式化功能,交给专门插件插件处理
M.disableFormat = function (client)
  if vim.fn.has ("nvim-0.8") == 1 then
    client. server_capabilities. documentFormattingProvider = false
    client. server_capabilities. documentRangeFormattingProvider = false
  else
    client. resolved_capabilities. document_formatting = false
    client. resolved_capabilities. document_range_formatting = false
  end
end

-- M.capabilities = require ("cmp_nvim_lsp"). update_capabilities (vim. lsp. protocol. make_client_capabilities ())
M.capabilities = require ("cmp_nvim_lsp"). default_capabilities ()

M.flags = {
  debounce_text_changes = 150,
}

return M

创建lsp/config/html. lua

local common = require ("lsp. common-config")
local opts = {
  capabilities = common. capabilities,
  flags = common. flags,
  on_attach = function (client, bufnr)
      -- 禁用本身语言格式化
    common.disableFormat (client)
    common.keyAttach (bufnr)
  end,
}
return {
  on_setup = function (server)
    server.setup (opts)
  end,
}

创建lsp/config/css. lua

local common = require ("lsp. common-config")
local opts = {
  capabilities = common. capabilities,
  flags = common. flags,
  on_attach = function (client, bufnr)
    common.disableFormat (client)
    common.keyAttach (bufnr)
  end,
  settings = {
    css = {
      validate = true,
      -- tailwindcss
      lint = {
        unknownAtRules = "ignore",
      },
    },
    less = {
      validate = true,
      lint = {
        unknownAtRules = "ignore",
      },
    },
    scss = {
      validate = true,
      lint = {
        unknownAtRules = "ignore",
      },
    },
  },
}

return {
  on_setup = function (server)
    server.setup (opts)
  end,
}

上面不禁用的话也是可以的,只不过会和默认的 null-ls 中的 prettier 格式化冲突,每次格式化都需要选择

注意 html、css 文件均是需要项目根目录有package. json文件和 prettier 依赖

# 创建 package. json 并安装 prettier 依赖,顺便把 eslint 也配置上
npm init -y && npm i -D prettier eslint

Emmet LSP 配置

使用 emmet 可是使用简单的语法可以快速打出 HTML 结构标签

创建lua/lsp/config/emmet. lua

local opts = {
  filetypes = { "html", "typescriptreact", "javascriptreact", "css", "sass", "scss", "less" },
}
return {
  on_setup = function (server)
    server.setup (opts)
  end,
}

lua/lsp/setup. lua修改

mason_config.setup ({
    ensure_installed = {"lua_ls", "html", "cssls", "emmet_ls"}
})
...
local servers = {
    lua_ls = require ("lsp. config. lua"),
    html = require ("lsp. config. html"),
    cssls = require ("lsp. config. css"),
    -- 新增
    emmet_ls = require ("lsp. config. emmet")
}

配置 jsonls

JSON Schema Store 插件,即 JSON 增强包

plugins. lua添加插件

-- JSON 增强
use ("b 0 o/schemastore. nvim")

新建lua/lsp/config/json. lua

local common = require ("lsp. common-config")
local opts = {
  capabilities = common. capabilities,
  flags = common. flags,
  on_attach = function (client, bufnr)
    -- use fixjson to format
    -- https://github.com/rhysd/fixjson
    common.disableFormat (client)
    common.keyAttach (bufnr)
  end,
  settings = {
    json = {
      schemas = require ("schemastore"). json.schemas (),
    },
  },
}

return {
  on_setup = function (server)
    server.setup (opts)
  end,
}

lsp/config/setup. lua修改

mason_config.setup ({
    ensure_installed = {"lua_ls", "html", "cssls", "emmet_ls","jsonls"}
})

local servers = {
    lua_ls = require ("lsp. config. lua"),
    html = require ("lsp. config. html"),
    cssls = require ("lsp. config. css"),
    emmet_ls = require ("lsp. config. emmet"),
    -- 新增
    jsonls = require ("lsp. config. json")
}

配置 tssserver

添加 TS 增强包插件

use ({ "jose-elias-alvarez/nvim-lsp-ts-utils", requires = "nvim-lua/plenary. nvim" })

创建lsp/config/ts. lua

local common = require ("lsp. common-config")
local keybindings = require ("keybindings")
local ts_utils = require ("nvim-lsp-ts-utils")
local opts = {
  flags = common. flags,
  capabilities = common. capabilities,

  -- https://github.com/jose-elias-alvarez/nvim-lsp-ts-utils/blob/main/lua/nvim-lsp-ts-utils/utils.lua
  -- 传入 tsserver 初始化参数
  -- make inlay hints work
  init_options = {
    hostInfo = "neovim",
    preferences = {
      includeInlayParameterNameHints = "all",
      includeInlayParameterNameHintsWhenArgumentMatchesName = true,
      includeInlayFunctionParameterTypeHints = true,
      includeInlayVariableTypeHints = true,
      includeInlayPropertyDeclarationTypeHints = true,
      includeInlayFunctionLikeReturnTypeHints = true,
      includeInlayEnumMemberValueHints = true,
    },
  },

  on_attach = function (client, bufnr)
    common.disableFormat (client)
    common.keyAttach (bufnr)
    -- defaults
    ts_utils.setup ({
      debug = false,
      disable_commands = false,
      enable_import_on_completion = false,
      -- import all
      import_all_timeout = 5000, -- ms
      -- lower numbers = higher priority
      import_all_priorities = {
        same_file = 1, -- add to existing import statement
        local_files = 2, -- git files or files with relative path markers
        buffer_content = 3, -- loaded buffer content
        buffers = 4, -- loaded buffer names
      },
      import_all_scan_buffers = 100,
      import_all_select_source = false,
      -- if false will avoid organizing imports
      always_organize_imports = true,

      -- filter diagnostics
      filter_out_diagnostics_by_severity = {},
      -- https://github.com/microsoft/TypeScript/blob/main/src/compiler/diagnosticMessages.json
      filter_out_diagnostics_by_code = {
        80001,
      },

      -- inlay hints
      auto_inlay_hints = true,
      inlay_hints_highlight = "Comment",
      inlay_hints_priority = 200, -- priority of the hint extmarks
      inlay_hints_throttle = 150, -- throttle the inlay hint request
      inlay_hints_format = { -- format options for individual hint kind
        Type = {},
        Parameter = {},
        Enum = {},
        -- Example format customization for `Type` kind:
        -- Type = {
        --     highlight = "Comment",
        --     text = function (text)
        --         return "->" .. text: sub (2)
        --     end,
        -- },
      },

      -- update imports on file move
      update_imports_on_move = false,
      require_confirmation_on_move = false,
      watch_dir = nil,
    })
    -- required to fix code action ranges and filter diagnostics
    ts_utils. setup_client (client)
    -- no default maps, so you may want to define some here
    keybindings.mapTsLSP (bufnr)
  end,
}

return {
  on_setup = function (server)
    server.setup (opts)
  end,
}

同样setup. lua修改

mason_config.setup ({
    ensure_installed = {"lua_ls", "html", "cssls", "emmet_ls", "jsonls", "tsserver"}
})

-- 安装列表
-- { key: 服务器名, value: 配置文件 }
-- key 必须为下列网址列出的 server name,不可以随便写
-- https://github.com/williamboman/nvim-lsp-installer#available-lsps
local servers = {
    lua_ls = require ("lsp. config. lua"),
    html = require ("lsp. config. html"),
    cssls = require ("lsp. config. css"),
    emmet_ls = require ("lsp. config. emmet"),
    jsonls = require ("lsp. config. json"),
    -- 新增
    tsserver = require ("lsp. config. ts")
}

添加快捷键lua/keybindings. lua

-- typescript 快捷键
pluginKeys. mapTsLSP = function (mapbuf)
  mapbuf ("n", "gs", ":TSLspOrganize<CR>", opt)
  mapbuf ("n", "gr", ":TSLspRenameFile<CR>", opt)
  mapbuf ("n", "gi", ":TSLspImportAll<CR>", opt)
end
  • gs 删除不用的 import 语句并重新排序。

  • gr 用于改变文件名,同时其他文件中引用该文件的文件名也会被修改。

  • gi 导入当前文件的所有依赖,并且会自动排序

ESLint 和 Prettier 配置

null-ls 中除了格式化 Formatting,还有 Diagnostics(红字错误提示) 和 Code Actions(代码触发的行为)

lsp/null-ls. lua修改为

local status, null_ls = pcall (require, "null-ls")
if not status then
    vim.notify ("没有找到 null-ls")
    return
end

local formatting = null_ls. builtins. formatting
local diagnostics = null_ls. builtins. diagnostics
local code_actions = null_ls. builtins. code_actions

null_ls.setup ({
    debug = false,
    sources = { -- Formatting ---------------------
    --  brew install shfmt
    formatting. shfmt, -- StyLua
    formatting. stylua, -- frontend
    formatting.prettier.with ({ -- 只比默认配置少了 markdown
        filetypes = {"javascript", "javascriptreact", "typescript", "typescriptreact", "vue", "css", "scss", "less",
                     "html", "json", "yaml", "graphql"},
        prefer_local = "node_modules/. bin"
    }), -- Diagnostics  ---------------------
    diagnostics.eslint.with ({
        prefer_local = "node_modules/. bin"
    }), -- code actions ---------------------
    code_actions. gitsigns, code_actions.eslint.with ({
        prefer_local = "node_modules/. bin"
    })},
    -- #{m}: message
    -- #{s}: source name (defaults to null-ls if not specified)
    -- #{c}: code (if available)
    diagnostics_format = "[#{s}] #{m}",
    -- 保存自动格式化
    on_attach = function (client, bufnr)
        if client. supports_method ("textDocument/formatting") then
            vim. api. nvim_clear_autocmds ({
                group = augroup,
                buffer = bufnr
            })
            vim. api. nvim_create_autocmd ("BufWritePre", {
                group = augroup,
                buffer = bufnr,
                callback = function ()
                    -- on 0.8, you should use vim.lsp.buf.format ({ bufnr = bufnr }) instead
                    vim.lsp.buf.format ({
                        bufnr = bufnr
                    })
                    -- vim. lsp. buf. formatting_sync ()
                end
            })
        end
    end
})

code_actions. gitsigns 没有安装可以注释掉

使用<leader>ca调用 Code Action 自动修复快捷键

Rust 开发配置

前文已安装 rust 环境,此处不赘述

语法高亮

plugin-config/nvim-treesitter. lua中的 ensure_installed 中添加"rust"

或是执行: TSInstall rust

代码提示

lsp/setup. lua

mason_config.setup ({
    ensure_installed = {"lua_ls", "html", "cssls", "emmet_ls", "jsonls", "rust_analyzer"}
})
...
local servers = {
  -- 新增
  rust_analyzer = require ("lsp. config. rust"),
}

lsp/config/rust. lua

local common = require ("lsp. common-config")
local opts = {
        capabilities = common. capabilities,
        flags = common. flags,
        on_attach = function (client, bufnr)
                common.disableFormat (client)
                common.keyAttach (bufnr)
        end,
        settings = {
                -- to enable rust-analyzer settings visit:
                -- https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/generated_config.adoc
                ["rust-analyzer"] = {
                        -- enable clippy on save
                        checkOnSave = {
                                command = "clippy",
                        },
                },
        },
}

return {
        on_setup = function (server)
                local ok_rt, rust_tools = pcall (require, "rust-tools")
                if not ok_rt then
                        print ("Failed to load rust tools, will set up `rust_analyzer` without `rust-tools`.")
                        server.setup (opts)
                else
                        -- We don't want to call lspconfig. rust_analyzer.setup () when using rust-tools
                        rust_tools.setup ({
                                server = opts,
                                -- dap = require ("dap. nvim-dap. config. rust"),
                        })
                end
        end,
}

添加 Rust 增强包插件

-- Rust 增强
use ("simrat 39/rust-tools. nvim")

代码格式化

安装相应 Formtter

rustup component add rustfmt

null-ls. lua

source 中添加

-- rustfmt
formatting. rustfmt,

filetypes 中添加"rust"

配置 C/C++开发环境

熟悉上面的流程,这个就简单讲了

相关插件:p00f/clangd_extensions.nvim: Clangd's off-spec features for neovim's LSP client. Use https://sr.ht/~p00f/clangd_extensions.nvim instead (github.com)

setup. lua

servers 添加 "c"和"cpp"

安装格式化插件:apt-get install -y clang-format

plugin-config/nvim-treesitter. lua

ensure_installed 添加 "cpp" "c"

null-ls. lua

                formatting.prettier.with ({
                        filetypes = {
                                "c",
                                "cpp"
                        }
                }),
                -- clang-format
                formatting. clang_format,

lsp/config/clangd. lua

local common = require ("lsp. common-config")
local opts = {
        capabilities = common. capabilities,
        flags = common. flags,
        on_attach = function (client, bufnr)
                common.disableFormat (client)
                common.keyAttach (bufnr)
        end,
}

return {
        on_setup = function (server)
                local ok_rt, clangd_extensions = pcall (require, "clangd_extensions")
                if not ok_rt then
                        server.setup (opts)
                else
                        clangd_extensions.setup ({
                                server = opts,
                                extensions = {
                                        -- defaults:
                                        -- Automatically set inlay hints (type hints)
                                        autoSetHints = true,
                                        -- These apply to the default ClangdSetInlayHints command
                                        inlay_hints = {
                                                -- Only show inlay hints for the current line
                                                only_current_line = false,
                                                -- Event which triggers a refersh of the inlay hints.
                                                -- You can make this "CursorMoved" or "CursorMoved, CursorMovedI" but
                                                -- not that this may cause  higher CPU usage.
                                                -- This option is only respected when only_current_line and
                                                -- autoSetHints both are true.
                                                only_current_line_autocmd = "CursorHold",
                                                -- whether to show parameter hints with the inlay hints or not
                                                show_parameter_hints = true,
                                                -- prefix for parameter hints
                                                parameter_hints_prefix = "<- ",
                                                -- prefix for all the other hints (type, chaining)
                                                other_hints_prefix = "=> ",
                                                -- whether to align to the length of the longest line in the file
                                                max_len_align = false,
                                                -- padding from the left if max_len_align is true
                                                max_len_align_padding = 1,
                                                -- whether to align to the extreme right or not
                                                right_align = false,
                                                -- padding from the right if right_align is true
                                                right_align_padding = 7,
                                                -- The color of the hints
                                                highlight = "Comment",
                                                -- The highlight group priority for extmark
                                                priority = 100,
                                        },
                                        ast = {
                                                -- These are unicode, should be available in any font
                                                role_icons = {
                                                        type = " ",
                                                        declaration = " ",
                                                        expression = " ",
                                                        statement = ";",
                                                        specifier = " ",
                                                        ["template argument"] = " ",
                                                },
                                                kind_icons = {
                                                        Compound = " ",
                                                        Recovery = " ",
                                                        TranslationUnit = " ",
                                                        PackExpansion = " ",
                                                        TemplateTypeParm = " ",
                                                        TemplateTemplateParm = " ",
                                                        TemplateParamObject = " ",
                                                },
                                                --[[ These require codicons ( https://github.com/microsoft/vscode-codicons )
            role_icons = {
                type = "",
                declaration = "",
                expression = "",
                specifier = "",
                statement = "",
                ["template argument"] = "",
            },

            kind_icons = {
                Compound = "",
                Recovery = "",
                TranslationUnit = "",
                PackExpansion = "",
                TemplateTypeParm = "",
                TemplateTemplateParm = "",
                TemplateParamObject = "",
            }, ]]

                                                highlights = {
                                                        detail = "Comment",
                                                },
                                        },
                                        memory_usage = {
                                                border = "none",
                                        },
                                        symbol_info = {
                                                border = "none",
                                        },
                                },
                        })
                end
        end,
}

代码运行器

相关插件:CRAG666/code_runner.nvim: Neovim plugin.The best code runner you could have, it is like the one in vscode but with super powers, it manages projects like in intellij but without being slow (github.com)

添加插件:

use 'CRAG 666/code_runner. nvim'

配置插件plugin-config/code-runner. lua

local status, code_runner = pcall (require, "code_runner")
if not status then
    vim.notify ("没有找到 code_runner")
    return
end

code_runner.setup ({
    -- choose default mode (valid term, tab, float, toggle)
    mode = "term",
    -- Focus on runner window (only works on toggle, term and tab mode)
    focus = true,
    -- startinsert (see ': h inserting-ex')
    startinsert = false,
    term = {
        --  Position to open the terminal, this option is ignored if mode is tab
        position = "bot",
        -- window size, this option is ignored if tab is true
        size = 8,
    },
    float = {
        -- Key that close the code_runner floating window
        close_key = "<ESC>",
        -- Window border (see ': h nvim_open_win')
        border = "none",

        -- Num from `0 - 1` for measurements
        height = 0.8,
        width = 0.8,
        x = 0.5,
        y = 0.5,

        -- Highlight group for floating window/border (see ': h winhl')
        border_hl = "FloatBorder",
        float_hl = "Normal",

        -- Transparency (see ': h winblend')
        blend = 0,
    },
    filetype_path = "", -- No default path defined
    before_run_filetype = function ()
        vim.cmd (": w")
    end,
    filetype = {
        javascript = "node",
        java = {
            "cd $dir &&",
            "javac $fileName &&",
            "java $fileNameWithoutExt",
        },
        c = {
            "cd $dir &&",
            "gcc $fileName",
            "-o $fileNameWithoutExt &&",
            "$dir/$fileNameWithoutExt",
        },
        cpp = {
            "cd $dir &&",
            "g++ $fileName",
            "-o $fileNameWithoutExt &&",
            "$dir/$fileNameWithoutExt",
        },
        python = "python -u",
        sh = "bash",
        rust = {
            "cd $dir &&",
            "rustc $fileName &&",
            "$dir/$fileNameWithoutExt",
        },
    },
    project_path = "", -- No default path defined
    project = {},
})

之后 init. lua 中添加插件,最后添加快捷键,使用空格加r即可运行代码

-- 代码运行器
map ('n', '<leader>r', ':RunCode<CR>', { noremap = true, silent = false })

其他配置

自动补全括号

插件仓库:windwp/nvim-autopairs: autopairs for neovim written by lua (github.com)

引入插件

use ("windwp/nvim-autopairs")

创建lua/plugin-config/nvim-autopairs. lua

-- https://github.com/windwp/nvim-autopairs
local status, autopairs = pcall (require, "nvim-autopairs")
if not status then
  vim.notify ("没有找到 nvim-autopairs")
  return
end
autopairs.setup ({
  check_ts = true,
  ts_config = {
    lua = { "string" }, -- it will not add a pair on that treesitter node
    javascript = { "template_string" },
    java = false, -- don't check treesitter on java
  },
})
-- If you want insert `(` after select function or method item
local cmp_autopairs = require ("nvim-autopairs. completion. cmp")
local cmp = require ("cmp")
cmp.event: on ("confirm_done", cmp_autopairs. on_confirm_done ({ map_char = { tex = "" } }))

init. lua

快速注释插件

插件仓库:numToStr/Comment.nvim: // Smart and powerful comment plugin for neovim. Supports treesitter, dot repeat, left-right/up-down motions, hooks, and more (github.com)

添加插件

use ("numToStr/Comment. nvim")

创建lua/plugin-config/comment. lua

local status, comment = pcall (require, "Comment")
if not status then
  vim.notify ("没有找到 Comment")
  return
end

local default_opts = {
  ---Add a space b/w comment and the line
  ---@type boolean|fun ():boolean
  padding = true,

  ---Whether the cursor should stay at its position
  ---NOTE: This only affects NORMAL mode mappings and doesn't work with dot-repeat
  ---@type boolean
  sticky = true,

  ---Lines to be ignored while comment/uncomment.
  ---Could be a regex string or a function that returns a regex string.
  ---Example: Use '^$' to ignore empty lines
  ---@type string|fun ():string
  ignore = nil,

  ---LHS of toggle mappings in NORMAL + VISUAL mode
  ---@type table
  toggler = {
    ---Line-comment toggle keymap
    line = "gcc",
    ---Block-comment toggle keymap
    block = "gbc",
  },

  ---LHS of operator-pending mappings in NORMAL + VISUAL mode
  ---@type table
  opleader = {
    ---Line-comment keymap
    line = "gc",
    ---Block-comment keymap
    block = "gb",
  },

  ---LHS of extra mappings
  ---@type table
  extra = {
    ---Add comment on the line above
    above = "gcO",
    ---Add comment on the line below
    below = "gco",
    ---Add comment at the end of line
    eol = "gcA",
  },

  ---Create basic (operator-pending) and extended mappings for NORMAL + VISUAL mode
  ---NOTE: If `mappings = false` then the plugin won't create any mappings
  ---@type boolean|table
  mappings = {
    ---Operator-pending mapping
    ---Includes `gcc`, `gbc`, `gc[count]{motion}` and `gb[count]{motion}`
    ---NOTE: These mappings can be changed individually by `opleader` and `toggler` config
    basic = true,
    ---Extra mapping
    ---Includes `gco`, `gcO`, `gcA`
    extra = false,
    ---Extended mapping
    ---Includes `g>`, `g<`, `g>[count]{motion}` and `g<[count]{motion}`
    extended = false,
  },

  ---Pre-hook, called before commenting the line
  ---@type fun (ctx: Ctx):string
  pre_hook = nil,

  ---Post-hook, called after commenting is done
  ---@type fun (ctx: Ctx)
  post_hook = nil,
}

-- 关闭了 extra 快捷键,只用 keybindings 里定义的基础快捷键
comment.setup (vim. tbl_deep_extend ("force", default_opts, require ("keybindings"). comment))

定义快捷键 keybindings. lua gcc 快捷键作为行注释,gbc 快捷键作为块注释

-- 代码注释插件
-- see ./lua/plugin-config/comment. lua
pluginKeys. comment = {
  -- Normal 模式快捷键
  toggler = {
    line = "gcc", -- 行注释
    block = "gbc", -- 块注释
  },
  -- Visual 模式
  opleader = {
    line = "gc",
    bock = "gb",
  },
}

init. lua中引入

require ("plugin-config. comment")

Surround 配置

引入插件

    -- surround
    use ("ur 4 ltz/surround. nvim")

lua/plugin-config/surround. lua

local status, surround = pcall (require, "surround")
if not status then
  vim.notify ("没有找到 surround")
  return
end

surround.setup ({
  mappings_style = "surround",
})

init. lua

surround 官方快捷键如下

Normal Mode - Sandwich Mode
Provides key mapping to add surrounding characters. ( visually select then press s<char> or press sa{motion}{char})
Provides key mapping to replace surrounding characters. ( sr<from><to> )
Provides key mapping to delete surrounding characters. ( sd<char> )
ss repeats last surround command.
Normal Mode - Surround Mode
Provides key mapping to add surrounding characters. ( visually select then press s<char> or press ys{motion}{char})
Provides key mapping to replace surrounding characters. ( cs<from><to> )
Provides key mapping to delete surrounding characters. ( ds<char> )
Insert Mode
<c-s><char> will insert both pairs in insert mode.
<c-s><char><space> will insert both pairs in insert mode with surrounding whitespace.
<c-s><char><c-s> will insert both pairs on newlines insert mode.

常用快捷键

  • ds<char>

  • cs<from><to>

  • ys{motion}{char}

其他问题

我在推送仓库时频繁遇到GnuTLS recv error (-110)

解决链接:git - GnuTLS recv error (-110)

#!/bin/bash
set -e
sudo apt-get install build-essential fakeroot dpkg-dev -y
sudo apt-get build-dep git -y
sudo apt-get install libcurl 4-openssl-dev -y
cd ~
mkdir source-git
cd source-git/
apt-get source git
cd git-2.*.*/
sed -i -- 's/libcurl 4-gnutls-dev/libcurl 4-openssl-dev/' ./debian/control
sed -i -- '/TEST\s*=\s*test/d' ./debian/rules
dpkg-buildpackage -rfakeroot -b -uc -us
sudo dpkg -i ../git_*ubuntu*. deb

直接运行这个脚本即可

之后推送遇到remote: Support for password authentication was removed on August 13, 2021问题,虽然我不太清楚我配了 SSH key,为什么还是走的密码验证,但是我还是按照他的提示来做获取token,直接 github 首页中 Setting->Developer settings->Personal access tokens 生成 token

执行

git remote set-url origin https://<your_token>@github. com/<USERNAME>/<REPO>.git

最后即可免密推送

备忘记录

学习 vim 快捷键网站:Vim Cheat Sheet (rtorr.com)

使用: h clipboard查看复制粘贴命令

文档推荐使用set clipboard=unnamedplus,或是执行set clipboard^=unnamed, unnamedplus就可以连通 vim 剪切板和系统剪切板,但是这个命令只是暂时性的,只能当前页面生效,为了永久生效,可以在basic. lua中添加

-- 复制粘贴联通系统粘贴板
vim. o. clipboard = "unnamedplus"

全选复制文件:%y或是ggyG

只是删除而不将删除的部分复制到剪切板中"_dd(本质上是将剪切的内容放到_寄存器中,以便于和+寄存器区分)

结语

对我自己而言,配置的这些功能虽然少,但是暂时够用,如果追求更多的功能,可以直接用小册作者的仓库,或是其他优秀仓库

其实我觉得其实作为个人使用来说,没有特殊需求的情况下不是很推荐自己配置,只需要看懂本篇博客,然后可以做到更改别人写好的配置即可

还有就是切忌盲目复制粘贴,一定要看官方文档

本篇博客示例配置仓库:ReturnTmp/rettmp-nvim

掘金小册作者仓库: https://github.com/nshen/learn-neovim-lua

注意:v 2 分支是 neovim 8.0+适用

或是直接使用作者的新仓库:nshen/InsisVim: An out-of-the-box Neovim IDE solution that setup development environment in an incredibly simple way. (github.com)

除了小册作者的配置仓库,这里再推荐一个优秀 Neovim 配置仓库: ayamir/nvimdots: A well configured and structured Neovim. (github.com)

至此 Neovim 配置学习就结束了:smile:

相关推荐
西邮彭于晏2 分钟前
差分进化算法
windows·python·算法
取名真难.4 分钟前
人脸检测(Python)
python·opencv·计算机视觉
五月阳光暖洋洋7 分钟前
SpringBoot2.2.6使用spring-boot-validation读取不到自定义配置文件中的属性
java·开发语言·spring boot
中云DDoS CC防护蔡蔡21 分钟前
爬虫爬数据犯法吗
运维·服务器·爬虫·python·http
小悟空GK1 小时前
Http介绍
开发语言
JH_vision1 小时前
Python OpenCV与霍夫变换:检测符合特定斜率范围的直线
python·目标检测
502胶水2051 小时前
腾讯地图异步调用
开发语言·ios·swift
森龙安1 小时前
指针 || 引用 || const || 智能指针 || 动态内存
c++
SwBack1 小时前
【pearcmd】通过pearcmd.php 进行GetShell
android·开发语言·php
Lingoesforstudy1 小时前
c#中的超时终止
开发语言·笔记·c#