Created
April 6, 2026 16:50
-
-
Save swarn/7b30ce77332051127290c2737a4ba6a7 to your computer and use it in GitHub Desktop.
My neovim terminal config
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| local group = vim.api.nvim_create_augroup("my_terminal", { clear = true }) | |
| ------------------------------------------------------------------------------ | |
| -- TERMINAL EXIT | |
| ------------------------------------------------------------------------------ | |
| -- Remove the built-in autocommand to delete the buffer on shell exit, which | |
| -- deletes the scrollback history and alters window layout. | |
| pcall(function() vim.cmd [[au! nvim.terminal TermClose]] end) | |
| -- Instead, scrape the scrollback and copy it to a scratch buffer, then swap | |
| -- the scratch buffer in for the terminal buffer in all windows. | |
| vim.api.nvim_create_autocmd("TermClose", { | |
| group = group, | |
| callback = function(args) | |
| local lines = vim.api.nvim_buf_get_lines(args.buf, 0, -1, false) | |
| local scrollback_buf = vim.api.nvim_create_buf(true, true) | |
| vim.api.nvim_buf_set_lines(scrollback_buf, 0, -1, false, lines) | |
| vim.api.nvim_buf_set_name(scrollback_buf, "term-log-" .. args.buf) | |
| vim.bo[scrollback_buf].buftype = 'nowrite' | |
| for _, win in ipairs(vim.fn.win_findbuf(args.buf)) do | |
| vim.api.nvim_win_set_buf(win, scrollback_buf) | |
| end | |
| vim.api.nvim_buf_delete(args.buf, { force = true }) | |
| end, | |
| }) | |
| ------------------------------------------------------------------------------ | |
| -- TERMINAL MODE MANAGEMENT | |
| ------------------------------------------------------------------------------ | |
| -- Enter terminal mode in new terminals. | |
| vim.api.nvim_create_autocmd("TermOpen", { | |
| group = group, | |
| callback = function(args) | |
| if args.buf == vim.api.nvim_get_current_buf() then vim.cmd.startinsert() end | |
| vim.b[args.buf].restore_term_mode = true | |
| end, | |
| }) | |
| -- Save terminal mode status when leaving a terminal buffer. | |
| vim.api.nvim_create_autocmd("BufLeave", { | |
| group = group, | |
| pattern = "term://*", | |
| callback = function(args) | |
| local mode = vim.api.nvim_get_mode().mode | |
| vim.b[args.buf].restore_term_mode = (mode == "t") | |
| end, | |
| }) | |
| -- Restore terminal mode status when returning to a terminal buffer. | |
| vim.api.nvim_create_autocmd("BufEnter", { | |
| group = group, | |
| pattern = "term://*", | |
| callback = function(args) | |
| if vim.b[args.buf].restore_term_mode then vim.cmd.startinsert() end | |
| end, | |
| }) | |
| ------------------------------------------------------------------------------ | |
| -- TERMINAL MAPPINGS | |
| ------------------------------------------------------------------------------ | |
| local set = vim.keymap.set | |
| set("t", "<c-w>n", "<C-\\><C-n>", { desc = "Normal mode" }) | |
| set("t", "<c-w><c-n>", "<C-\\><C-n>", { desc = "Normal mode" }) | |
| set("t", "<c-w>:", "<c-\\><c-o>:", { desc = "Do a command" }) | |
| set("t", "<c-w>.", "<c-w>", { desc = "Send ctrl-w to terminal" }) | |
| set("t", '<c-w>"', function() | |
| local char = vim.fn.getcharstr() | |
| local valid_register, _ = pcall(vim.fn.getregtype, char) | |
| if not valid_register then return "" end | |
| return '<C-\\><C-n>"' .. char .. "pi" | |
| end, { desc = "Paste from register", expr = true }) | |
| set("t", "<c-w>gt", "<C-\\><C-n>gt", { desc = "go to next tabpage" }) | |
| set("t", "<c-w>gT", "<C-\\><C-n>gT", { desc = "go to previous tabpage" }) | |
| -- Standard window navigation and management works in terminal mode. | |
| for c in ("hjklptbxrwsvqco="):gmatch "." do | |
| local rhs = string.format("<cmd>wincmd %s<cr>", c) | |
| set("t", string.format("<c-w><c-%s>", c), rhs) | |
| set("t", string.format("<c-w>%s", c), rhs) | |
| end | |
| for c in ("KJHLT"):gmatch "." do | |
| local rhs = string.format("<cmd>wincmd %s<cr>", c) | |
| set("t", string.format("<c-w>%s", c), rhs) | |
| end | |
| ------------------------------------------------------------------------------ | |
| -- FLOATING TERMINAL | |
| ------------------------------------------------------------------------------ | |
| -- A floating window that you can toggle. It starts a terminal, but is | |
| -- otherwise a normal window: you can change its layout, view the terminal | |
| -- buffer in other windows, open a new terminal with :term, etc. | |
| local float_buf = -1 | |
| local terminal_win = -1 | |
| local function toggle_term_window() | |
| local exists = vim.api.nvim_win_is_valid(terminal_win) | |
| local floating = exists and vim.api.nvim_win_get_config(terminal_win).relative ~= "" | |
| local current = vim.api.nvim_get_current_win() == terminal_win | |
| if exists and floating then | |
| if current then | |
| float_buf = vim.api.nvim_win_get_buf(terminal_win) | |
| vim.api.nvim_win_close(terminal_win, true) | |
| else | |
| vim.api.nvim_set_current_win(terminal_win) | |
| end | |
| return | |
| end | |
| local make_new_term = not vim.api.nvim_buf_is_valid(float_buf) | |
| if make_new_term then float_buf = vim.api.nvim_create_buf(true, false) end | |
| terminal_win = vim.api.nvim_open_win(float_buf, true, { | |
| relative = "editor", | |
| row = math.floor(vim.o.lines * 0.1), | |
| col = math.floor(vim.o.columns * 0.1), | |
| height = math.floor(vim.o.lines * 0.8), | |
| width = math.floor(vim.o.columns * 0.8), | |
| border = "solid", | |
| }) | |
| if make_new_term then vim.fn.jobstart(vim.o.shell, { term = true }) end | |
| end | |
| set({ "n", "t" }, "<C-/>", toggle_term_window) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment