Skip to content

Instantly share code, notes, and snippets.

@shivamashtikar
Last active April 25, 2024 22:18
Show Gist options
  • Save shivamashtikar/16a4d7b83b743c9619e29b47a66138e0 to your computer and use it in GitHub Desktop.
Save shivamashtikar/16a4d7b83b743c9619e29b47a66138e0 to your computer and use it in GitHub Desktop.
" Function to quickly open/hide terminal window inside vim
" Terminal operation when
" 1. terminal is open in split window, it closes the window (terminal still
" running)
" 2. terminal open in buffer, it moves window into split window
" 3. no termial instance running then it opens new terminal instance in split
" window
function Term() abort
let bufNum = bufnr('term://')
let termNum = bufwinnr('term://')
if termNum > 0 && winnr('$') > 1
execute termNum . 'wincmd c'
elseif bufNum > 0 && bufNum != bufnr(@%)
execute 'sb ' . bufNum . ' | wincmd p'
elseif bufNum == bufnr(@%)
execute 'bprevious | sb ' . bufNum . ' | wincmd p'
else
execute 'sp term://zsh'
endif
endfunction
command! -bang -nargs=* Term call Term()
nmap <leader><space> :Term<CR>
" Maps Escape button in terminal window
autocmd BufEnter * if !empty(matchstr(@%, "term",0)) | tnoremap <buffer> <Esc> <C-\><C-n> | endif
@janwvjaarsveld
Copy link

janwvjaarsveld commented Dec 30, 2022

-- Function to quickly open/hide terminal window inside vim
-- Terminal operation  when
-- 1. terminal is open in split window, it closes the window (terminal still
--    running)
-- 2. terminal open in buffer, it moves window into split window
-- 3. no termial instance running then it opens new terminal instance in split
--    window
local function Term()
  local terminal_buffer_number = vim.fn.bufnr("term://")
  local terminal_window_number = vim.fn.bufwinnr("term://")
  local window_count = vim.fn.winnr("$")

  if terminal_window_number > 0 and window_count > 1 then
    vim.fn.execute(terminal_window_number .. "wincmd c")
  elseif terminal_buffer_number > 0 and terminal_buffer_number ~= vim.fn.bufnr("%") then
    vim.fn.execute("sb " .. terminal_buffer_number)  
  elseif terminal_buffer_number == vim.fn.bufnr("%") then
    vim.fn.execute("bprevious | sb " .. terminal_buffer_number .. " | wincmd p")
  else
    vim.fn.execute("sp term://zsh")
  end
end

vim.api.nvim_create_user_command("Term", Term, {
  desc = "Open terminal window",
})

vim.keymap.set("n", "<leader><space>", vim.cmd.Term, { noremap = true, silent = true })
vim.keymap.set("t", "jj", "<C-\\><C-n>", { noremap = true, silent = true })

@zyriab
Copy link

zyriab commented Feb 21, 2024

I found this gist through an old Reddit post, thought I'd share my implementation which I think is simple and works well.
The TermKill command is used by my session manager to make sure that no terminal is opened when I restore a session.

vim.api.nvim_create_user_command("TermToggle", function()
    local is_open = vim.g.term_win_id ~= nil and vim.api.nvim_win_is_valid(vim.g.term_win_id)

    if is_open then
        vim.api.nvim_win_hide(vim.g.term_win_id)
        vim.g.term_win_id = nil
        return
    end

    -- Open new window 25 lines tall at the bottom of the screen
    vim.cmd("botright 25 new")
    vim.g.term_win_id = vim.api.nvim_get_current_win()

    local has_term_buf = vim.g.term_buf_id ~= nil and vim.api.nvim_buf_is_valid(vim.g.term_buf_id)

    if has_term_buf then
        vim.api.nvim_win_set_buf(vim.g.term_win_id, vim.g.term_buf_id)
    else
        vim.cmd.term()
        vim.g.term_buf_id = vim.api.nvim_get_current_buf()
    end

    vim.cmd.startinsert()
end, {})

-- For session manager usage
vim.api.nvim_create_user_command("TermKill", function()
    if vim.g.term_win_id ~= nil then
        vim.api.nvim_win_close(vim.g.term_win_id, true)
        vim.g.term_win_id = nil
    end
    if vim.g.term_buf_id ~= nil then
        vim.api.nvim_buf_delete(vim.g.term_buf_id, { force = true })
        vim.g.term_buf_id = nil
    end
end, {})

vim.keymap.set("n", "<leader>t", vim.cmd.TermToggle, { desc = "Toggle [T]erminal", silent = true })
vim.keymap.set("t", "<C-t>", vim.cmd.TermToggle, { desc = "Toggle [^][T]erminal", silent = true })

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment