Neovim的常见快捷键和命令

14,955 阅读8分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

以下内容参考掘金小册子Neovim 配置实战:从0到1打造自己的IDE
个别快捷键会有些不一样请根据自身情况更改(以Mac为例,与Win下差别不大)

normal模式下

移动/编辑相关

快捷键作用
h
j
k
l
ctrl + j/k上下跳4行
ctrl + u/d上下9行
i在光标前插入
a在光标后插入
A到末尾插入
I到首插入
s删当前字符并进入插入模式
zc折叠代码
zo打开折叠
u撤销上一次代码修改/undo
ctrl + r与u相反/redo

tab/buffer/标签相关(按vim的用法来说应该叫buffer)

快捷键作用
ctrl + h/l左右切换tab
ctrl + w关闭当前tab
<leader>bl关闭右边所有tab
<leader>bh关闭左边所有tab
<leader>bc选择关闭tab

窗口相关

快捷键作用
option + h/j/k/l左下上右切换窗口
sv左右分屏
sh上下分屏
sc关闭当前窗口
<leader> + t底部打开terminal
<leader> + vt侧边打开terminal
s,当前窗口左右比例缩小
s.当前窗口左右比例放大
sj当前窗口上下比例放大
sk当前窗口上下比例缩小

tree(侧边栏)相关

快捷键作用
ctrl + m隐藏与显示tree
Enter打开tree中选中的文件
v左右分屏打开
h上下分屏
i忽略node_modules
.显示与隐藏隐藏文件
F5refresh file
acreate file
dremove file
rrename file
xcut file
ccopy file
ppaste file
ssystem_open file
oopen file

telescope搜索相关

快捷键作用
ctrl + p搜索文件
ctrl + f全局搜索
# 以下命令是在👆的命令后使用
ctrl + j向下移动选择文件
ctrl + k向上移动选择文件
ctrl + n历史搜索下一个
ctrl + p历史搜索上一个
ctrl + c关闭搜索页面
ctrl + u预览上滚
ctrl + d预览下滚

LSP相关

快捷键作用
gd跳到变量的定义处
gh悬浮显示当前变量的信息
gp显示当前文件的错误的代码信息
gj跳到下一个错误代码的地方
gk跳到上一个错误代码的地方
<leader> + f格式化代码
ctrl + j/n选择下一个提示
ctrl + k/p选择上一个提示
Enter确认选择
<leader> + rn重命名变量名

退出

快捷键作用
q:q
qq:q!
Q:qa!

Inser模式下

移动/编辑相关

快捷键作用
option + h/j/k/l左下上右移动
ctrl + b到末尾
ctrl + e到首
ctrl + j开辟新行

Visual模式下

移动相关

快捷键作用
j向下移动代码
k向上移动选中的代码
<左缩进代码
右缩进代码
=选中代码后格式化代码

常用命令

命令作用
:q退出
:q!强制退出
:w保存
:qa退出并关闭
:qa!强制退出并关闭
:wq保存并退出
:PackerCompile每次改变插件配置时,必须运行此命令或 PackerSync, 重新生成编译的加载文件
:PackerClean清除所有不用的插件
:PackerInstall清除,然后安装缺失的插件
:PackerUpdate清除,然后更新并安装插件
:PackerSync(最常使用)执行 PackerUpdate 后,再执行 PackerCompile
:h base-directories查看详细文档
:echo stdpath("data")查看你系统下Neovim的数据存储在标准数据目录的实际路径
:colorscheme Tab键查看内置主题色
:echo $VIMRUNTIME查看$VIMRUNTIME` 具体的路径
:h nvim-tree.setup查看nvim-tree的帮助文档
:NvimTreeToggle再按Enter即可打开或关闭侧边栏
:checkhealth telescope检查telescope依赖情况
:Telescope find_files打开搜索文件窗口,快速打开文件
:Telescope live_grep可以打开搜索窗口,输入内容后,结果会实时显示
:Telescope buffers命令可以列出打开的 buffers
:Telescope git_files列出 git 文件
:Telescope man_pages列出帮助
:Telescope env打开环境变量列表
Telescope colorscheme换肤功能
:TSInstallInfo命令查看 language parsers 列表与安装状态
:TSInstall <language_to_install>安装指定的 Language parser 例如:TSInstall javascript
:TSModuleInfo查看你的模块是否开启成功
LSP相关命令
:h lsp查看 LSP 文档
:LspInstallInfo安装 LSP Servers的图形化界面
j/k移动光标到你要安装的 server
i安装server
X卸载该 server
u更新 server
U更新所有 servers
c检查 server 新版本
C检查所有 servers 的新版本
Esc关闭窗口
?显示其他帮助信息
:LspInfo查看绑定的 Language Server 信息
:NullLsInfo查看源的激活情况
:lua vim.lsp.buf.formatting_sync()格式化代码
:lua vim.lsp.buf.formatting_sync(nil, 9999)不加参数可能会报Time out
echo executable('xxx')查看某个命令是否可用 例如echo executable('rubocop')查看rubocop是否可用,一般用来排查格式化代码时需要的命令是否已安装

我的相关配置文件

lua/keybindings.lua

vim.g.mapleader = ","
vim.g.maplocalleader = ","
local map = vim.api.nvim_set_keymap
-- 复用 opt 参数
local opt = { noremap = true, silent = true }
-- Ctrl + [ 映射到Esc
map("n", "<C-[>", "Esc", opt)

-- windows 分屏快捷键
map("n", "sv", ":vsp<CR>", opt)
map("n", "sh", ":sp<CR>", opt)

-- 关闭当前
map("n", "sc", "<C-w>c", opt)
-- 关闭其他
map("n", "so", "<C-w>o", opt)
-- Mac 下option + hjkl  窗口之间跳转
map("n", "∑", "<C-w>w", opt)
map("n", "˙", "<C-w>h", opt)
map("n", "∆", "<C-w>j", opt)
map("n", "˚", "<C-w>k", opt)
map("n", "¬", "<C-w>l", opt)
-- Mac 下option + hjkl  左右移动
map("i", "˙", "<Left>", opt)
map("i", "∆", "<Down>", opt)
map("i", "˚", "<Up>", opt)
map("i", "¬", "<Right>", opt)

-- 左右比例控制
-- map("n", "<C-Left>", ":vertical resize -2<CR>", opt)
-- map("n", "<C-Right>", ":vertical resize +2<CR>", opt)
map("n", "s,", ":vertical resize -20<CR>", opt)
map("n", "s.", ":vertical resize +20<CR>", opt)
-- 上下比例
map("n", "sj", ":resize +10<CR>", opt)
map("n", "sk", ":resize -10<CR>", opt)
-- map("n", "<C-Down>", ":resize +2<CR>", opt)
-- map("n", "<C-Up>", ":resize -2<CR>", opt)
-- 等比例
map("n", "s=", "<C-w>=", opt)

-- Terminal相关
map("n", "<leader>t", ":sp | terminal<CR>", opt)
map("n", "<leader>vt", ":vsp | terminal<CR>", opt)
map("t", "<Esc>", "<C-\\><C-n>", opt)
-- map("t", "<A-h>", [[ <C-\><C-N><C-w>h ]], opt)
-- map("t", "<A-j>", [[ <C-\><C-N><C-w>j ]], opt)
-- map("t", "<A-k>", [[ <C-\><C-N><C-w>k ]], opt)
-- map("t", "<A-l>", [[ <C-\><C-N><C-w>l ]], opt)

-- visual模式下缩进代码
map("v", "<", "<gv", opt)
map("v", ">", ">gv", opt)
-- 上下移动选中文本
map("v", "J", ":move '>+1<CR>gv-gv", opt)
map("v", "K", ":move '<-2<CR>gv-gv", opt)

-- 上下滚动浏览
map("n", "<C-j>", "4j", opt)
map("n", "<C-k>", "4k", opt)
-- ctrl u / ctrl + d  只移动9行,默认移动半屏
map("n", "<C-u>", "9k", opt)
map("n", "<C-d>", "9j", opt)

-- 在visual 模式里粘贴不要复制
map("v", "p", '"_dP', opt)

-- 退出
map("n", "q", ":qa<CR>", opt)
map("n", "qq", ":q!<CR>", opt)
map("n", "ww", ":w<CR>", opt)
map("n", "Q", ":qa!<CR>", opt)

-- insert 模式下,跳到行首行尾
map("i", "<C-b>", "<ESC>I", opt)
map("i", "<C-e>", "<ESC>A", opt)
-- map("i", "<C-o>", "<ESC>:w<CR>", opt)

-- bufferline
-- 左右Tab切换
map("n", "<C-h>", ":BufferLineCyclePrev<CR>", opt)
map("n", "<C-l>", ":BufferLineCycleNext<CR>", opt)
-- 关闭
--"moll/vim-bbye"
map("n", "<C-w>", ":Bdelete!<CR>", opt)
map("n", "<leader>bl", ":BufferLineCloseRight<CR>", opt)
map("n", "<leader>bh", ":BufferLineCloseLeft<CR>", opt)
map("n", "<leader>bc", ":BufferLinePickClose<CR>", opt)

-- Telescope
-- 查找文件
map("n", "<C-p>", ":Telescope find_files<CR>", opt)
-- 全局搜索
map("n", "<C-f>", ":Telescope live_grep<CR>", opt)

-- 全文格式化代码
map("n", "<leadner>fm", "gg=G<C-o>", opt)
-- 插件快捷键
local pluginKeys = {}
-- nvim-tree
-- alt + m 键打开关闭tree
map("n", "<C-m>", ":NvimTreeToggle<CR>", opt)
-- 列表快捷键
pluginKeys.nvimTreeList = {
	-- 打开文件或文件夹
	{ key = { "<CR>", "o", "<2-LeftMouse>" }, action = "edit" },
	-- 分屏打开文件
	{ key = "v", action = "vsplit" },
	{ key = "h", action = "split" },
	-- 显示隐藏文件
	{ key = "i", action = "toggle_ignored" }, -- Ignore (node_modules)
	{ key = ".", action = "toggle_dotfiles" }, -- Hide (dotfiles)
	-- 文件操作
	{ key = "<F5>", action = "refresh" },
	{ key = "a", action = "create" },
	{ key = "d", action = "remove" },
	{ key = "r", action = "rename" },
	{ key = "x", action = "cut" },
	{ key = "c", action = "copy" },
	{ key = "p", action = "paste" },
	{ key = "s", action = "system_open" },
}

-- Telescope 列表中 插入模式快捷键
pluginKeys.telescopeList = {
	i = {
		-- 上下移动
		["<C-j>"] = "move_selection_next",
		["<C-k>"] = "move_selection_previous",
		["<Down>"] = "move_selection_next",
		["<Up>"] = "move_selection_previous",
		-- 历史记录
		["<C-n>"] = "cycle_history_next",
		["<C-p>"] = "cycle_history_prev",
		-- 关闭窗口
		["<C-c>"] = "close",
		-- 预览窗口上下滚动
		["<C-u>"] = "preview_scrolling_up",
		["<C-d>"] = "preview_scrolling_down",
	},
}

-- 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.formatting_sync(nil, 9999)<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

-- nvim-cmp 自动补全
pluginKeys.cmp = function(cmp)
	local feedkey = function(key, mode)
		vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), mode, true)
	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
	return {
		-- 出现补全
		["<C-.>"] = cmp.mapping(cmp.mapping.complete(), { "i", "c" }),
		-- 取消
		["<C-,>"] = 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" }),
		-- 自定义代码段跳转到下一个参数
		["<C-l>"] = cmp.mapping(function(_)
			if vim.fn["vsnip#available"](1) == 1 then
				feedkey("<Plug>(vsnip-expand-or-jump)", "")
			end
		end, { "i", "s" }),

		-- 自定义代码段跳转到上一个参数
		["<C-h>"] = cmp.mapping(function()
			if vim.fn["vsnip#jumpable"](-1) == 1 then
				feedkey("<Plug>(vsnip-jump-prev)", "")
			end
		end, { "i", "s" }),

		-- Super Tab
		["<Tab>"] = cmp.mapping(function(fallback)
			if cmp.visible() then
				cmp.select_next_item()
			elseif vim.fn["vsnip#available"](1) == 1 then
				feedkey("<Plug>(vsnip-expand-or-jump)", "")
			elseif has_words_before() then
				cmp.complete()
			else
				fallback() -- The fallback function sends a already mapped key. In this case, it's probably `<Tab>`.
			end
		end, { "i", "s" }),

		["<S-Tab>"] = cmp.mapping(function()
			if cmp.visible() then
				cmp.select_prev_item()
			elseif vim.fn["vsnip#jumpable"](-1) == 1 then
				feedkey("<Plug>(vsnip-jump-prev)", "")
			end
		end, { "i", "s" }),
		-- end of super Tab
	}
end

return pluginKeys

lua/plugins.lua

local packer = require("packer")
packer.startup({
  function(use)
    -- Packer 可以管理自己本身
    use 'wbthomason/packer.nvim'
    -- use 'tomasr/molokai'
    use 'tamelion/neovim-molokai'
    -- tokyonight
    use("folke/tokyonight.nvim")
    -- 你的插件列表...
    -- nvim-tree (新增)
    use({ "kyazdani42/nvim-tree.lua", requires = "kyazdani42/nvim-web-devicons" })
     -- bufferline (新增)
    use({ "akinsho/bufferline.nvim", requires = { "kyazdani42/nvim-web-devicons", "moll/vim-bbye" }})
    -- lualine (新增)
    use({ "nvim-lualine/lualine.nvim", requires = { "kyazdani42/nvim-web-devicons" } })
    use("arkav/lualine-lsp-progress")
    -- telescope (新增)
    use { 'nvim-telescope/telescope.nvim', requires = { "nvim-lua/plenary.nvim" } }
    -- telescope extensions
    use "LinArcX/telescope-env.nvim"
     -- dashboard-nvim (新增)
    use("glepnir/dashboard-nvim")
    -- project
    use("ahmedkhalf/project.nvim")
    -- treesitter (新增)
    use({ "nvim-treesitter/nvim-treesitter", run = ":TSUpdate" })
     --------------------- LSP --------------------
    -- lspconfig
    use({ "neovim/nvim-lspconfig", "williamboman/nvim-lsp-installer" })
    -- 补全引擎
    use("hrsh7th/nvim-cmp")
    -- snippet 引擎
    use("hrsh7th/vim-vsnip")
    use("rafamadriz/friendly-snippets")
    -- 补全源
    use("hrsh7th/cmp-vsnip")
    use("hrsh7th/cmp-nvim-lsp") -- { name = nvim_lsp }
    use("hrsh7th/cmp-buffer") -- { name = 'buffer' },
    use("hrsh7th/cmp-path") -- { name = 'path' }
    use("hrsh7th/cmp-cmdline") -- { name = 'cmdline' }

    -- 常见编程语言代码段
    use("rafamadriz/friendly-snippets")
    -- ui (新增)
    use("onsails/lspkind-nvim")
    use("tami5/lspsaga.nvim" ) -- 新增
    -- indent-blankline
    use("lukas-reineke/indent-blankline.nvim")
     -- 代码格式化
    -- use("mhartington/formatter.nvim")
    use({ "jose-elias-alvarez/null-ls.nvim", requires = "nvim-lua/plenary.nvim" })
  end,
  config = {
     display = {
        open_fn = function()
            return require("packer.util").float({ border = "single" })
        end,
    },
    -- 并发数限制
    max_jobs = 16,
    -- 自定义源
    git = {
      -- default_url_format = "https://hub.fastgit.xyz/%s",
      -- default_url_format = "https://mirror.ghproxy.com/https://github.com/%s",
      -- default_url_format = "https://gitcode.net/mirrors/%s",
      -- default_url_format = "https://gitclone.com/github.com/%s",
    },
  },
})
-- 每次保存 plugins.lua 自动安装插件
pcall(
  vim.cmd,
  [[
    augroup packer_user_config
    autocmd!
    autocmd BufWritePost plugins.lua source <afile> | PackerSync
    augroup end
  ]]
)

可能用到的资源

网址
Neovim官网
掘金小册子:Neovim 配置实战:从0到1打造自己的IDE
掘金小册子作者的Neovim完整配置的github
WSL2安装的官方指南
Nerd fonts字体
vim-plug
packer.nvim
neovim-colorscheme
telescope.nvim
自定义顶部显示的 ascii 图片官方 wiki
ascii 图片生成器patorjk.com
图标nerdfonts.com/cheat-sheet
编程语言的formatting