17 - 终端集成
“The terminal inside Neovim is not just a terminal — it’s a first-class citizen.”
17.1 Neovim 内置终端
17.1.1 基本使用
:terminal " 水平分割打开终端
:terminal bash " 指定 shell
:vert terminal " 垂直分割终端
:terminal ++rows=10 " 指定高度
17.1.2 终端模式切换
" 从终端模式切换到 Normal 模式
<C-\><C-n> " 标准方式
" 在终端 Normal 模式中回到终端输入
i / a " 进入终端插入模式
" 终端模式中的操作
<C-\><C-n> " 回到 Normal
<C-\><C-n>:q " 关闭终端
17.1.3 终端配置
vim.api.nvim_create_autocmd("TermOpen", {
pattern = "*",
callback = function()
vim.opt_local.number = false
vim.opt_local.relativenumber = false
vim.opt_local.signcolumn = "no"
vim.cmd("startinsert")
end,
})
17.2 ToggleTerm
17.2.1 安装与配置
{ "akinsho/toggleterm.nvim",
version = "*",
keys = {
{ "<C-\\>", "<cmd>ToggleTerm<cr>", desc = "终端切换" },
{ "<leader>tf", "<cmd>ToggleTerm direction=float<cr>", desc = "浮动终端" },
{ "<leader>th", "<cmd>ToggleTerm direction=horizontal size=15<cr>", desc = "水平终端" },
{ "<leader>tv", "<cmd>ToggleTerm direction=vertical size=60<cr>", desc = "垂直终端" },
},
opts = {
size = function(term)
if term.direction == "horizontal" then
return 15
elseif term.direction == "vertical" then
return vim.o.columns * 0.4
end
end,
open_mapping = [[<C-\>]],
hide_numbers = true,
shade_terminals = true,
start_in_insert = true,
insert_mappings = true,
terminal_mappings = true,
persist_size = true,
direction = "float", -- "vertical" | "horizontal" | "tab" | "float"
close_on_exit = true,
shell = vim.o.shell,
float_opts = {
border = "curved",
winblend = 0,
},
},
}
17.2.2 多终端管理
-- 在配置中添加多个终端
local Terminal = require("toggleterm.terminal").Terminal
-- Python REPL
local python = Terminal:new({ cmd = "python3", hidden = true, direction = "float" })
vim.keymap.set("n", "<leader>tp", function() python:toggle() end, { desc = "Python REPL" })
-- Node REPL
local node = Terminal:new({ cmd = "node", hidden = true, direction = "float" })
vim.keymap.set("n", "<leader>tn", function() node:toggle() end, { desc = "Node REPL" })
-- Lazygit
local lazygit = Terminal:new({ cmd = "lazygit", hidden = true, direction = "float" })
vim.keymap.set("n", "<leader>gg", function() lazygit:toggle() end, { desc = "LazyGit" })
17.2.3 终端内快捷键
-- 终端模式中的导航
function _G.set_terminal_keymaps()
local opts = { buffer = 0 }
vim.keymap.set("t", "<Esc>", [[<C-\><C-n>]], opts)
vim.keymap.set("t", "<C-h>", [[<Cmd>wincmd h<CR>]], opts)
vim.keymap.set("t", "<C-j>", [[<Cmd>wincmd j<CR>]], opts)
vim.keymap.set("t", "<C-k>", [[<Cmd>wincmd k<CR>]], opts)
vim.keymap.set("t", "<C-l>", [[<Cmd>wincmd l<CR>]], opts)
end
vim.cmd("autocmd! TermOpen term://*toggleterm#* lua set_terminal_keymaps()")
17.3 任务运行
17.3.1 一键运行
-- 简单的代码运行函数
function RunCode()
local filetype = vim.bo.filetype
local file = vim.fn.expand("%:p")
local cmd_map = {
python = "python3 " .. file,
javascript = "node " .. file,
typescript = "npx ts-node " .. file,
go = "go run " .. file,
rust = "cargo run",
lua = "lua " .. file,
sh = "bash " .. file,
}
local cmd = cmd_map[filetype]
if cmd then
require("toggleterm.terminal").Terminal
:new({ cmd = cmd, direction = "float" })
:toggle()
else
print("No runner for filetype: " .. filetype)
end
end
vim.keymap.set("n", "<leader>r", RunCode, { desc = "运行代码" })
17.3.2 overseer.nvim(任务运行器)
{ "stevearc/overseer.nvim",
cmd = { "OverseerRun", "OverseerToggle" },
keys = {
{ "<leader>or", "<cmd>OverseerRun<cr>", desc = "运行任务" },
{ "<leader>ot", "<cmd>OverseerToggle<cr>", desc = "任务面板" },
},
opts = {
templates = { "builtin", "user.run_script" },
},
}
17.4 浮动终端布局
-- 自定义浮动终端样式
local float_opts = {
border = "double", -- "single" | "double" | "rounded" | "solid" | "shadow"
winblend = 3, -- 透明度
width = function() return math.floor(vim.o.columns * 0.8) end,
height = function() return math.floor(vim.o.lines * 0.8) end,
}
17.5 终端中的 Neovim
17.5.1 嵌套 Neovim
# 在终端模式中使用 Neovim
nvim --remote-ui # 远程 UI 模式
17.5.2 终端中的颜色
-- 确保终端颜色正确
vim.opt.termguicolors = true
-- 设置终端颜色
vim.g.terminal_color_0 = "#1e1e2e" -- black
vim.g.terminal_color_1 = "#f38ba8" -- red
vim.g.terminal_color_2 = "#a6e3a1" -- green
vim.g.terminal_color_3 = "#f9e2af" -- yellow
vim.g.terminal_color_4 = "#89b4fa" -- blue
vim.g.terminal_color_5 = "#f5c2e7" -- magenta
vim.g.terminal_color_6 = "#94e2d5" -- cyan
vim.g.terminal_color_7 = "#bac2de" -- white
17.6 业务场景
| 场景 | 方案 |
|---|---|
| 运行脚本 | ToggleTerm + 一键运行 |
| Git 操作 | LazyGit(浮动终端) |
| REPL 交互 | Python/Node 浮动终端 |
| 构建任务 | overseer.nvim |
| 服务器管理 | 多终端标签页 |
| 测试运行 | 终端 + make/test 命令 |
17.7 总结
| 功能 | 命令/插件 |
|---|---|
| 内置终端 | :terminal |
| 终端切换 | <C-\><C-n> |
| ToggleTerm | 浮动/水平/垂直终端 |
| 多终端 | Terminal:new() |
| 任务运行 | 自定义函数 / overseer.nvim |
下一步:第 18 章 - Docker 远程开发 → 在容器中编辑代码、远程开发配置。
扩展阅读
- ToggleTerm 文档
- Overseer 文档
:h terminal— Neovim 终端参考