Repository files navigation

toggleterm.nvim

A neovim plugin to persist and toggle multiple terminals during an editing session

toggleterm in action

Multiple orientations

  • Float

floating window

  • Vertical

vertical-terms

  • Tab

tab orientation

Send commands to different terminals

exec

Winbar (Experimental/Nightly ONLY)

image

Requirements

This plugin only works in Neovim 0.7 or newer.

Installation

Using packer in lua

use {"akinsho/toggleterm.nvim", tag='*', config=function()
require("toggleterm").setup()
end}

Using lazy.nvim in lua

{
-- amongst your other plugins
{'akinsho/toggleterm.nvim', version="*", config=true}
-- or
{'akinsho/toggleterm.nvim', version="*", opts= {--[[ things you want to change go here]]}}
}

Using vim-plug in vimscript

Plug 'akinsho/toggleterm.nvim', {'tag' : '*'}
luarequire("toggleterm").setup()

You can/should specify a tag for the current major version of the plugin, to avoid breaking changes as this plugin evolves. To use a version of this plugin compatible with nvim versions less than 0.7 please use the tag v1.*.

Notices

  • 28/07/1990 — If using persist_mode terminal mappings should be changed to use wincmd instead otherwise persist mode will not work correctly. See here for details.

Why?

Neovim's terminal is a very cool, but not super ergonomic tool to use. I find that I often want to set a process going and leave it to continue to run in the background. I don't need to see it all the time. I just need to be able to refer back to it at intervals. I also sometimes want to create a new terminal and run a few commands.

Sometimes I want these side by side, and I really want these terminals to be easy to access. I also want my terminal to look different from non-terminal buffers, so I use winhighlight to darken them based on the Normal background colour.

This is the exact use case this was designed for. If that's your use case this might work for you.

Roadmap

All I really want this plugin to be is what I described above. A wrapper around the terminal functionality.

It basically (almost) does all that I need it to.

I won't be turning this into a REPL plugin or doing a bunch of complex stuff. If you find any issues, please consider a pull request not an issue. I'm also going to be pretty conservative about what I add.

Setup

This plugin must be explicitly enabled by using require("toggleterm").setup{}

Setting the open_mapping key to use for toggling the terminal(s) will set up mappings for normal mode. The open_mapping can be a key string or an array of key strings. If you prefix the mapping with a number that particular terminal will be opened. Otherwise if a prefix is not set, then the last toggled terminal will be opened. In case there are multiple terminals opened they'll all be closed, and on the next mapping key they'll be restored.

If you set the insert_mappings key to true, the mapping will also take effect in insert mode; similarly setting terminal_mappings to true will have the mappings take effect in the opened terminal.

However you will not be able to use a count with the open mapping in terminal and insert modes. You can create buffer specific mappings to exit terminal mode and then use a count with the open mapping. Check Terminal window mappings for an example of how to do this.

alternatively you can do this manually (not recommended but, your prerogative)

" setautocmd TermEnter term://*toggleterm#*\ tnoremap<silent><c-t><Cmd>exe v:count1 . "ToggleTerm"<CR>" By applying the mappings this way you can pass a count to your" mapping to open a specific window." For example: 2<C-t> will open terminal 2nnoremap<silent><c-t><Cmd>exe v:count1 . "ToggleTerm"<CR>inoremap<silent><c-t><Esc><Cmd>exe v:count1 . "ToggleTerm"<CR>

NOTE: Please ensure you have set hidden in your neovim config, otherwise the terminals will be discarded when closed.

WARNING: Please do not copy and paste this configuration! It is here to show what options are available. It is not written to be used as is.

require("toggleterm").setup{
-- size can be a number or function which is passed the current terminalsize=20 | function(term)
ifterm.direction=="horizontal" thenreturn15elseifterm.direction=="vertical" thenreturnvim.o.columns*0.4endend,
open_mapping=[[<c-\>]], -- or { [[<c-\>]], [[<c-¥>]] } if you also use a Japanese keyboard.on_create=fun(t: Terminal), -- function to run when the terminal is first createdon_open=fun(t: Terminal), -- function to run when the terminal openson_close=fun(t: Terminal), -- function to run when the terminal closeson_stdout=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stdouton_stderr=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stderron_exit=fun(t: Terminal, job: number, exit_code: number, name: string) -- function to run when terminal process exitshide_numbers=true, -- hide the number column in toggleterm buffersshade_filetypes= {},
autochdir=false, -- when neovim changes it current directory the terminal will change it's own when next it's openedhighlights= {
-- highlights which map to a highlight group name and a table of it's values-- NOTE: this is only a subset of values, any group placed here will be set for the terminal window splitNormal= {
guibg="<VALUE-HERE>",
},
NormalFloat= {
link='Normal'
},
FloatBorder= {
guifg="<VALUE-HERE>",
guibg="<VALUE-HERE>",
},
},
shade_terminals=true, -- NOTE: this option takes priority over highlights specified so if you specify Normal highlights you should set this to falseshading_factor='<number>', -- the percentage by which to lighten dark terminal background, default: -30shading_ratio='<number>', -- the ratio of shading factor for light/dark terminal background, default: -3start_in_insert=true,
insert_mappings=true, -- whether or not the open mapping applies in insert modeterminal_mappings=true, -- whether or not the open mapping applies in the opened terminalspersist_size=true,
persist_mode=true, -- if set to true (default) the previous terminal mode will be remembereddirection='vertical' | 'horizontal' | 'tab' | 'float',
close_on_exit=true, -- close the terminal window when the process exitsclear_env=false, -- use only environmental variables from `env`, passed to jobstart()-- Change the default shell. Can be a string or a function returning a stringshell=vim.o.shell,
auto_scroll=true, -- automatically scroll to the bottom on terminal output-- This field is only relevant if direction is set to 'float'float_opts= {
-- The border key is *almost* the same as 'nvim_open_win'-- see :h nvim_open_win for details on borders however-- the 'curved' border is a custom border type-- not natively supported but implemented in this plugin.border='single' | 'double' | 'shadow' | 'curved' | ...otheroptionssupportedbywinopen-- like `size`, width, height, row, and col can be a number or function which is passed the current terminalwidth=<value>,
height=<value>,
row=<value>,
col=<value>,
winblend=3,
zindex=<value>,
title_pos='left' | 'center' | 'right', positionofthetitleofthefloatingwindow
},
winbar= {
enabled=false,
name_formatter=function(term) -- term: Terminalreturnterm.nameend
},
responsiveness= {
-- breakpoint in terms of `vim.o.columns` at which terminals will start to stack on top of each other-- instead of next to each other-- default = 0 which means the feature is turned offhorizontal_breakpoint=135,
}
}

Usage

ToggleTerm

This is the command the mappings call under the hood. You can use it directly and prefix it with a count to target a specific terminal. This function also takes arguments size, dir, direction and name. e.g.

:ToggleTerm size=40dir=~/Desktop direction=horizontal name=desktop

If dir is specified on creation toggle term will open at the specified directory. If the terminal has already been opened at a particular directory it will remain in that directory.

The directory can also be specified as git_dir which toggleterm will then use to try and derive the git repo directory. NOTE: This will not work for git-worktrees or other more complex setups.

If size is specified, and the command opens a split (horizontal/vertical) terminal, the height/width of all terminals in the same direction will be changed to size.

If direction is specified, and the command opens a terminal, the terminal will be changed to the specified direction.

If name is specified, the display name is set for the toggled terminal. This name will be visible when using TermSelect command to indicate the specific terminal.

size and direction are ignored if the command closes a terminal.

Caveats

  • Having multiple terminals with different directions open at the same time is unsupported.

ToggleTermToggleAll

This command allows you to open all the previously toggled terminal in one go or close all the open terminals at once.

TermExec

This command allows you to open a terminal with a specific action. e.g. 2TermExec cmd="git status" dir=~/<my-repo-path> will run git status in terminal 2. note that the cmd argument must be quoted.

NOTE: the dir argument can also be optionally quoted if it contains spaces.

The cmd and dir arguments can also expand the same special keywords as :h expand e.g. TermExec cmd="echo %" will be expanded to TermExec cmd="echo /file/example"

These special keywords can be escaped using the \ character, if you want to print character as is.

The size, direction and name arguments are like the size, direction and name arguments of ToggleTerm.

By default, focus is returned to the original window after executing the command (except for floating terminals). Use argument go_back=0 to disable this behaviour.

You can send commands to a terminal without opening its window by using the open=0 argument.

see :h expand() for more details

TermNew

This command allows you to open a new terminal at the next available count. It's helpful in combination with TermSelect (see below) to work with terminals without needing to remember numbers. The size, dir, direction and name arguments work the same as in ToggleTerm.

TermSelect

This command uses vim.ui.select to allow a user to select a terminal to open or to focus it if it's already open. This can be useful if you have a lot of terminals and want to open a specific one.

Sending lines to the terminal

You can "send lines" to the toggled terminals with the following commands:

  • :ToggleTermSendCurrentLine <T_ID>: sends the whole line where you are standing with your cursor
  • :ToggleTermSendVisualLines <T_ID>: sends all the (whole) lines in your visual selection
  • :ToggleTermSendVisualSelection <T_ID>: sends only the visually selected text (this can be a block of text or a selection in a single line)

(<T_ID is an optional terminal ID parameter, which defines where should we send the lines. If the parameter is not provided, then the default is the first terminal)

Alternatively, for more fine-grained control and use in mappings, in lua:

localtrim_spaces=truevim.keymap.set("v", "<space>s", function()
require("toggleterm").send_lines_to_terminal("single_line", trim_spaces, { args=vim.v.count })
end)
-- Replace with these for the other two options-- require("toggleterm").send_lines_to_terminal("visual_lines", trim_spaces, { args = vim.v.count })-- require("toggleterm").send_lines_to_terminal("visual_selection", trim_spaces, { args = vim.v.count })-- For use as an operator map:-- Send motion to terminalvim.keymap.set("n", [[<leader><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("g@", "n", false)
end)
-- Double the command to send line to terminalvim.keymap.set("n", [[<leader><c-\><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("g@_", "n", false)
end)
-- Send whole filevim.keymap.set("n", [[<leader><leader><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("ggg@G''", "n", false)
end)

Set trim_spaces=false for sending to REPLs for whitespace-sensitive languages like python. (For python, you probably want to start ipython with ipython --no-autoindent.)

Example:

send_lines_example.mov

ToggleTermSetName

This function allows setting a display name for a terminal. This name is primarily used inside the winbar, and can be a more descriptive way to remember, which terminal is for what.

You can map this to a key and call it with a count, which will then prompt you a name for the terminal with the matching ID. Alternatively you can call it with just the name e.g. :ToggleTermSetName work<CR> this will the prompt you for which terminal it should apply to. Lastly you can call it without any arguments, and it will prompt you for which terminal it should apply to then prompt you for the name to use.

Set terminal shading

This plugin automatically shades terminal filetypes to be darker than other window you can disable this by setting shade_terminals = false in the setup object

require'toggleterm'.setup {
shade_terminals=false
}

alternatively you can set, which filetypes should be shaded by setting

-- fzf is just an examplerequire'toggleterm'.setup {
shade_filetypes= { "none", "fzf" }
}

setting "none" will allow normal terminal buffers to be highlighted.

Set persistent size

By default, this plugin will persist the size of horizontal and vertical terminals. Split terminals in the same direction always have the same size. You can disable this behaviour by setting persist_size = false in the setup object. Disabling this behaviour forces the opening terminal size to the size defined in the setup object.

require'toggleterm'.setup{
persist_size=false
}

Terminal window mappings

It can be helpful to add mappings to make moving in and out of a terminal easier once toggled, whilst still keeping it open.

function_G.set_terminal_keymaps()
localopts= {buffer=0}
vim.keymap.set('t', '<esc>', [[<C-\><C-n>]], opts)
vim.keymap.set('t', 'jk', [[<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)
vim.keymap.set('t', '<C-w>', [[<C-\><C-n><C-w>]], opts)
end-- if you only want these mappings for toggle term use term://*toggleterm#* insteadvim.cmd('autocmd! TermOpen term://* lua set_terminal_keymaps()')

Custom Terminals

lazy gitusing lazygit

Toggleterm also exposes the Terminal class so that this can be used to create custom terminals for showing terminal UIs like lazygit, htop etc.

Each terminal can take the following arguments:

Terminal:new {
cmd=string-- command to execute when creating the terminal e.g. 'top'display_name=string-- the name of the terminaldirection=string-- the layout for the terminal, same as the main config optionsdir=string-- the directory for the terminalclose_on_exit=bool-- close the terminal window when the process exitshighlights=table-- a table with highlightsenv=table-- key:value table with environmental variables passed to jobstart()clear_env=bool-- use only environmental variables from `env`, passed to jobstart()on_open=fun(t: Terminal) -- function to run when the terminal openson_close=fun(t: Terminal) -- function to run when the terminal closesauto_scroll=boolean-- automatically scroll to the bottom on terminal output-- callbacks for processing the outputon_stdout=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stdouton_stderr=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stderron_exit=fun(t: Terminal, job: number, exit_code: number, name: string) -- function to run when terminal process exits
}

If you want to spawn a custom terminal without running any command, you can omit the cmd option.

Custom terminal usage

localTerminal=require('toggleterm.terminal').Terminallocallazygit=Terminal:new({ cmd="lazygit", hidden=true })
function_lazygit_toggle()
lazygit:toggle()
endvim.api.nvim_set_keymap("n", "<leader>g", "<cmd>lua _lazygit_toggle()<CR>", {noremap=true, silent=true})

This will create a new terminal, but the specified command is not being run immediately. The command will run once the terminal is opened. Alternatively term:spawn() can be used to start the command in a background buffer without opening a terminal window yet. If the hidden key is set to true, this terminal will not be toggled by normal toggleterm commands such as :ToggleTerm or the open mapping. It will only open and close by using the returned terminal object. A mapping for toggling the terminal can be set as in the example above.

Alternatively the terminal can be specified with a count, which is the number that can be used to trigger this specific terminal. This can then be triggered using the current count e.g. :5ToggleTerm<CR>

locallazygit=Terminal:new({ cmd="lazygit", count=5 })

You can also set a custom layout for a terminal.

locallazygit=Terminal:new({
cmd="lazygit",
dir="git_dir",
direction="float",
float_opts= {
border="double",
},
-- function to run on opening the terminalon_open=function(term)
vim.cmd("startinsert!")
vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "<cmd>close<CR>", {noremap=true, silent=true})
end,
-- function to run on closing the terminalon_close=function(term)
vim.cmd("startinsert!")
end,
})
function_lazygit_toggle()
lazygit:toggle()
endvim.api.nvim_set_keymap("n", "<leader>g", "<cmd>lua _lazygit_toggle()<CR>", {noremap=true, silent=true})

WARNING: do not use any of the private functionality of the terminal or other non-public parts of the API as these can change in the future.

Statusline

To tell each terminal apart you can use the terminal buffer variable b:toggle_number in your statusline

" this is pseudo codeletstatusline.='%{&ft == "toggleterm" ? "terminal (".b:toggle_number.")" : ""}'

Custom commands

You can create your own commands by using the lua functions this plugin provides directly

command! -count=1 TermGitPush lua require'toggleterm'.exec("git push", <count>, 12)
command! -count=1 TermGitPushF lua require'toggleterm'.exec("git push -f", <count>, 12)

Open multiple terminals side-by-side

DirectionSupported
vertical✔️
horizontal✔️
tab✖️
float✖️

In your first terminal, you need to leave the TERMINAL mode using C-\C-N which can be remapped to Esc for ease of use. image

Then you type on: 2<C-\>, and the result: image

Explain:

  • 2: this is the terminal's number (or ID), your first terminal is 1 (e.g. your 3rd terminal will be 3<C-\>, so on).
  • C-\: this is the combined key mapping to the command :ToggleTerm.

FAQ

How do I get this plugin to work with Powershell?

Please check out the Wiki section on this topic.

About

A neovim lua plugin to help easily manage multiple terminal windows

Topics

Resources

Stars

5.6k stars

Watchers

21 watching

Forks

Sponsor this project

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

toggleterm.nvim

A neovim plugin to persist and toggle multiple terminals during an editing session

toggleterm in action

Multiple orientations

  • Float

floating window

  • Vertical

vertical-terms

  • Tab

tab orientation

Send commands to different terminals

exec

Winbar (Experimental/Nightly ONLY)

image

Requirements

This plugin only works in Neovim 0.7 or newer.

Installation

Using packer in lua

use {"akinsho/toggleterm.nvim", tag='*', config=function()
require("toggleterm").setup()
end}

Using lazy.nvim in lua

{
-- amongst your other plugins
{'akinsho/toggleterm.nvim', version="*", config=true}
-- or
{'akinsho/toggleterm.nvim', version="*", opts= {--[[ things you want to change go here]]}}
}

Using vim-plug in vimscript

Plug 'akinsho/toggleterm.nvim', {'tag' : '*'}
luarequire("toggleterm").setup()

You can/should specify a tag for the current major version of the plugin, to avoid breaking changes as this plugin evolves. To use a version of this plugin compatible with nvim versions less than 0.7 please use the tag v1.*.

Notices

  • 28/07/1990 — If using persist_mode terminal mappings should be changed to use wincmd instead otherwise persist mode will not work correctly. See here for details.

Why?

Neovim's terminal is a very cool, but not super ergonomic tool to use. I find that I often want to set a process going and leave it to continue to run in the background. I don't need to see it all the time. I just need to be able to refer back to it at intervals. I also sometimes want to create a new terminal and run a few commands.

Sometimes I want these side by side, and I really want these terminals to be easy to access. I also want my terminal to look different from non-terminal buffers, so I use winhighlight to darken them based on the Normal background colour.

This is the exact use case this was designed for. If that's your use case this might work for you.

Roadmap

All I really want this plugin to be is what I described above. A wrapper around the terminal functionality.

It basically (almost) does all that I need it to.

I won't be turning this into a REPL plugin or doing a bunch of complex stuff. If you find any issues, please consider a pull request not an issue. I'm also going to be pretty conservative about what I add.

Setup

This plugin must be explicitly enabled by using require("toggleterm").setup{}

Setting the open_mapping key to use for toggling the terminal(s) will set up mappings for normal mode. The open_mapping can be a key string or an array of key strings. If you prefix the mapping with a number that particular terminal will be opened. Otherwise if a prefix is not set, then the last toggled terminal will be opened. In case there are multiple terminals opened they'll all be closed, and on the next mapping key they'll be restored.

If you set the insert_mappings key to true, the mapping will also take effect in insert mode; similarly setting terminal_mappings to true will have the mappings take effect in the opened terminal.

However you will not be able to use a count with the open mapping in terminal and insert modes. You can create buffer specific mappings to exit terminal mode and then use a count with the open mapping. Check Terminal window mappings for an example of how to do this.

alternatively you can do this manually (not recommended but, your prerogative)

" setautocmd TermEnter term://*toggleterm#*\ tnoremap<silent><c-t><Cmd>exe v:count1 . "ToggleTerm"<CR>" By applying the mappings this way you can pass a count to your" mapping to open a specific window." For example: 2<C-t> will open terminal 2nnoremap<silent><c-t><Cmd>exe v:count1 . "ToggleTerm"<CR>inoremap<silent><c-t><Esc><Cmd>exe v:count1 . "ToggleTerm"<CR>

NOTE: Please ensure you have set hidden in your neovim config, otherwise the terminals will be discarded when closed.

WARNING: Please do not copy and paste this configuration! It is here to show what options are available. It is not written to be used as is.

require("toggleterm").setup{
-- size can be a number or function which is passed the current terminalsize=20 | function(term)
ifterm.direction=="horizontal" thenreturn15elseifterm.direction=="vertical" thenreturnvim.o.columns*0.4endend,
open_mapping=[[<c-\>]], -- or { [[<c-\>]], [[<c-¥>]] } if you also use a Japanese keyboard.on_create=fun(t: Terminal), -- function to run when the terminal is first createdon_open=fun(t: Terminal), -- function to run when the terminal openson_close=fun(t: Terminal), -- function to run when the terminal closeson_stdout=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stdouton_stderr=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stderron_exit=fun(t: Terminal, job: number, exit_code: number, name: string) -- function to run when terminal process exitshide_numbers=true, -- hide the number column in toggleterm buffersshade_filetypes= {},
autochdir=false, -- when neovim changes it current directory the terminal will change it's own when next it's openedhighlights= {
-- highlights which map to a highlight group name and a table of it's values-- NOTE: this is only a subset of values, any group placed here will be set for the terminal window splitNormal= {
guibg="<VALUE-HERE>",
},
NormalFloat= {
link='Normal'
},
FloatBorder= {
guifg="<VALUE-HERE>",
guibg="<VALUE-HERE>",
},
},
shade_terminals=true, -- NOTE: this option takes priority over highlights specified so if you specify Normal highlights you should set this to falseshading_factor='<number>', -- the percentage by which to lighten dark terminal background, default: -30shading_ratio='<number>', -- the ratio of shading factor for light/dark terminal background, default: -3start_in_insert=true,
insert_mappings=true, -- whether or not the open mapping applies in insert modeterminal_mappings=true, -- whether or not the open mapping applies in the opened terminalspersist_size=true,
persist_mode=true, -- if set to true (default) the previous terminal mode will be remembereddirection='vertical' | 'horizontal' | 'tab' | 'float',
close_on_exit=true, -- close the terminal window when the process exitsclear_env=false, -- use only environmental variables from `env`, passed to jobstart()-- Change the default shell. Can be a string or a function returning a stringshell=vim.o.shell,
auto_scroll=true, -- automatically scroll to the bottom on terminal output-- This field is only relevant if direction is set to 'float'float_opts= {
-- The border key is *almost* the same as 'nvim_open_win'-- see :h nvim_open_win for details on borders however-- the 'curved' border is a custom border type-- not natively supported but implemented in this plugin.border='single' | 'double' | 'shadow' | 'curved' | ...otheroptionssupportedbywinopen-- like `size`, width, height, row, and col can be a number or function which is passed the current terminalwidth=<value>,
height=<value>,
row=<value>,
col=<value>,
winblend=3,
zindex=<value>,
title_pos='left' | 'center' | 'right', positionofthetitleofthefloatingwindow
},
winbar= {
enabled=false,
name_formatter=function(term) -- term: Terminalreturnterm.nameend
},
responsiveness= {
-- breakpoint in terms of `vim.o.columns` at which terminals will start to stack on top of each other-- instead of next to each other-- default = 0 which means the feature is turned offhorizontal_breakpoint=135,
}
}

Usage

ToggleTerm

This is the command the mappings call under the hood. You can use it directly and prefix it with a count to target a specific terminal. This function also takes arguments size, dir, direction and name. e.g.

:ToggleTerm size=40dir=~/Desktop direction=horizontal name=desktop

If dir is specified on creation toggle term will open at the specified directory. If the terminal has already been opened at a particular directory it will remain in that directory.

The directory can also be specified as git_dir which toggleterm will then use to try and derive the git repo directory. NOTE: This will not work for git-worktrees or other more complex setups.

If size is specified, and the command opens a split (horizontal/vertical) terminal, the height/width of all terminals in the same direction will be changed to size.

If direction is specified, and the command opens a terminal, the terminal will be changed to the specified direction.

If name is specified, the display name is set for the toggled terminal. This name will be visible when using TermSelect command to indicate the specific terminal.

size and direction are ignored if the command closes a terminal.

Caveats

  • Having multiple terminals with different directions open at the same time is unsupported.

ToggleTermToggleAll

This command allows you to open all the previously toggled terminal in one go or close all the open terminals at once.

TermExec

This command allows you to open a terminal with a specific action. e.g. 2TermExec cmd="git status" dir=~/<my-repo-path> will run git status in terminal 2. note that the cmd argument must be quoted.

NOTE: the dir argument can also be optionally quoted if it contains spaces.

The cmd and dir arguments can also expand the same special keywords as :h expand e.g. TermExec cmd="echo %" will be expanded to TermExec cmd="echo /file/example"

These special keywords can be escaped using the \ character, if you want to print character as is.

The size, direction and name arguments are like the size, direction and name arguments of ToggleTerm.

By default, focus is returned to the original window after executing the command (except for floating terminals). Use argument go_back=0 to disable this behaviour.

You can send commands to a terminal without opening its window by using the open=0 argument.

see :h expand() for more details

TermNew

This command allows you to open a new terminal at the next available count. It's helpful in combination with TermSelect (see below) to work with terminals without needing to remember numbers. The size, dir, direction and name arguments work the same as in ToggleTerm.

TermSelect

This command uses vim.ui.select to allow a user to select a terminal to open or to focus it if it's already open. This can be useful if you have a lot of terminals and want to open a specific one.

Sending lines to the terminal

You can "send lines" to the toggled terminals with the following commands:

  • :ToggleTermSendCurrentLine <T_ID>: sends the whole line where you are standing with your cursor
  • :ToggleTermSendVisualLines <T_ID>: sends all the (whole) lines in your visual selection
  • :ToggleTermSendVisualSelection <T_ID>: sends only the visually selected text (this can be a block of text or a selection in a single line)

(<T_ID is an optional terminal ID parameter, which defines where should we send the lines. If the parameter is not provided, then the default is the first terminal)

Alternatively, for more fine-grained control and use in mappings, in lua:

localtrim_spaces=truevim.keymap.set("v", "<space>s", function()
require("toggleterm").send_lines_to_terminal("single_line", trim_spaces, { args=vim.v.count })
end)
-- Replace with these for the other two options-- require("toggleterm").send_lines_to_terminal("visual_lines", trim_spaces, { args = vim.v.count })-- require("toggleterm").send_lines_to_terminal("visual_selection", trim_spaces, { args = vim.v.count })-- For use as an operator map:-- Send motion to terminalvim.keymap.set("n", [[<leader><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("g@", "n", false)
end)
-- Double the command to send line to terminalvim.keymap.set("n", [[<leader><c-\><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("g@_", "n", false)
end)
-- Send whole filevim.keymap.set("n", [[<leader><leader><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("ggg@G''", "n", false)
end)

Set trim_spaces=false for sending to REPLs for whitespace-sensitive languages like python. (For python, you probably want to start ipython with ipython --no-autoindent.)

Example:

send_lines_example.mov

ToggleTermSetName

This function allows setting a display name for a terminal. This name is primarily used inside the winbar, and can be a more descriptive way to remember, which terminal is for what.

You can map this to a key and call it with a count, which will then prompt you a name for the terminal with the matching ID. Alternatively you can call it with just the name e.g. :ToggleTermSetName work<CR> this will the prompt you for which terminal it should apply to. Lastly you can call it without any arguments, and it will prompt you for which terminal it should apply to then prompt you for the name to use.

Set terminal shading

This plugin automatically shades terminal filetypes to be darker than other window you can disable this by setting shade_terminals = false in the setup object

require'toggleterm'.setup {
shade_terminals=false
}

alternatively you can set, which filetypes should be shaded by setting

-- fzf is just an examplerequire'toggleterm'.setup {
shade_filetypes= { "none", "fzf" }
}

setting "none" will allow normal terminal buffers to be highlighted.

Set persistent size

By default, this plugin will persist the size of horizontal and vertical terminals. Split terminals in the same direction always have the same size. You can disable this behaviour by setting persist_size = false in the setup object. Disabling this behaviour forces the opening terminal size to the size defined in the setup object.

require'toggleterm'.setup{
persist_size=false
}

Terminal window mappings

It can be helpful to add mappings to make moving in and out of a terminal easier once toggled, whilst still keeping it open.

function_G.set_terminal_keymaps()
localopts= {buffer=0}
vim.keymap.set('t', '<esc>', [[<C-\><C-n>]], opts)
vim.keymap.set('t', 'jk', [[<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)
vim.keymap.set('t', '<C-w>', [[<C-\><C-n><C-w>]], opts)
end-- if you only want these mappings for toggle term use term://*toggleterm#* insteadvim.cmd('autocmd! TermOpen term://* lua set_terminal_keymaps()')

Custom Terminals

lazy gitusing lazygit

Toggleterm also exposes the Terminal class so that this can be used to create custom terminals for showing terminal UIs like lazygit, htop etc.

Each terminal can take the following arguments:

Terminal:new {
cmd=string-- command to execute when creating the terminal e.g. 'top'display_name=string-- the name of the terminaldirection=string-- the layout for the terminal, same as the main config optionsdir=string-- the directory for the terminalclose_on_exit=bool-- close the terminal window when the process exitshighlights=table-- a table with highlightsenv=table-- key:value table with environmental variables passed to jobstart()clear_env=bool-- use only environmental variables from `env`, passed to jobstart()on_open=fun(t: Terminal) -- function to run when the terminal openson_close=fun(t: Terminal) -- function to run when the terminal closesauto_scroll=boolean-- automatically scroll to the bottom on terminal output-- callbacks for processing the outputon_stdout=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stdouton_stderr=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stderron_exit=fun(t: Terminal, job: number, exit_code: number, name: string) -- function to run when terminal process exits
}

If you want to spawn a custom terminal without running any command, you can omit the cmd option.

Custom terminal usage

localTerminal=require('toggleterm.terminal').Terminallocallazygit=Terminal:new({ cmd="lazygit", hidden=true })
function_lazygit_toggle()
lazygit:toggle()
endvim.api.nvim_set_keymap("n", "<leader>g", "<cmd>lua _lazygit_toggle()<CR>", {noremap=true, silent=true})

This will create a new terminal, but the specified command is not being run immediately. The command will run once the terminal is opened. Alternatively term:spawn() can be used to start the command in a background buffer without opening a terminal window yet. If the hidden key is set to true, this terminal will not be toggled by normal toggleterm commands such as :ToggleTerm or the open mapping. It will only open and close by using the returned terminal object. A mapping for toggling the terminal can be set as in the example above.

Alternatively the terminal can be specified with a count, which is the number that can be used to trigger this specific terminal. This can then be triggered using the current count e.g. :5ToggleTerm<CR>

locallazygit=Terminal:new({ cmd="lazygit", count=5 })

You can also set a custom layout for a terminal.

locallazygit=Terminal:new({
cmd="lazygit",
dir="git_dir",
direction="float",
float_opts= {
border="double",
},
-- function to run on opening the terminalon_open=function(term)
vim.cmd("startinsert!")
vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "<cmd>close<CR>", {noremap=true, silent=true})
end,
-- function to run on closing the terminalon_close=function(term)
vim.cmd("startinsert!")
end,
})
function_lazygit_toggle()
lazygit:toggle()
endvim.api.nvim_set_keymap("n", "<leader>g", "<cmd>lua _lazygit_toggle()<CR>", {noremap=true, silent=true})

WARNING: do not use any of the private functionality of the terminal or other non-public parts of the API as these can change in the future.

Statusline

To tell each terminal apart you can use the terminal buffer variable b:toggle_number in your statusline

" this is pseudo codeletstatusline.='%{&ft == "toggleterm" ? "terminal (".b:toggle_number.")" : ""}'

Custom commands

You can create your own commands by using the lua functions this plugin provides directly

command! -count=1 TermGitPush lua require'toggleterm'.exec("git push", <count>, 12)
command! -count=1 TermGitPushF lua require'toggleterm'.exec("git push -f", <count>, 12)

Open multiple terminals side-by-side

DirectionSupported
vertical✔️
horizontal✔️
tab✖️
float✖️

In your first terminal, you need to leave the TERMINAL mode using C-\C-N which can be remapped to Esc for ease of use. image

Then you type on: 2<C-\>, and the result: image

Explain:

  • 2: this is the terminal's number (or ID), your first terminal is 1 (e.g. your 3rd terminal will be 3<C-\>, so on).
  • C-\: this is the combined key mapping to the command :ToggleTerm.

FAQ

How do I get this plugin to work with Powershell?

Please check out the Wiki section on this topic.

About

A neovim lua plugin to help easily manage multiple terminal windows

Topics

Resources

Stars

5.6k stars

Watchers

21 watching

Forks

Sponsor this project

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

toggleterm.nvim

A neovim plugin to persist and toggle multiple terminals during an editing session

toggleterm in action

Multiple orientations

  • Float

floating window

  • Vertical

vertical-terms

  • Tab

tab orientation

Send commands to different terminals

exec

Winbar (Experimental/Nightly ONLY)

image

Requirements

This plugin only works in Neovim 0.7 or newer.

Installation

Using packer in lua

use {"akinsho/toggleterm.nvim", tag='*', config=function()
require("toggleterm").setup()
end}

Using lazy.nvim in lua

{
-- amongst your other plugins
{'akinsho/toggleterm.nvim', version="*", config=true}
-- or
{'akinsho/toggleterm.nvim', version="*", opts= {--[[ things you want to change go here]]}}
}

Using vim-plug in vimscript

Plug 'akinsho/toggleterm.nvim', {'tag' : '*'}
luarequire("toggleterm").setup()

You can/should specify a tag for the current major version of the plugin, to avoid breaking changes as this plugin evolves. To use a version of this plugin compatible with nvim versions less than 0.7 please use the tag v1.*.

Notices

  • 28/07/1990 — If using persist_mode terminal mappings should be changed to use wincmd instead otherwise persist mode will not work correctly. See here for details.

Why?

Neovim's terminal is a very cool, but not super ergonomic tool to use. I find that I often want to set a process going and leave it to continue to run in the background. I don't need to see it all the time. I just need to be able to refer back to it at intervals. I also sometimes want to create a new terminal and run a few commands.

Sometimes I want these side by side, and I really want these terminals to be easy to access. I also want my terminal to look different from non-terminal buffers, so I use winhighlight to darken them based on the Normal background colour.

This is the exact use case this was designed for. If that's your use case this might work for you.

Roadmap

All I really want this plugin to be is what I described above. A wrapper around the terminal functionality.

It basically (almost) does all that I need it to.

I won't be turning this into a REPL plugin or doing a bunch of complex stuff. If you find any issues, please consider a pull request not an issue. I'm also going to be pretty conservative about what I add.

Setup

This plugin must be explicitly enabled by using require("toggleterm").setup{}

Setting the open_mapping key to use for toggling the terminal(s) will set up mappings for normal mode. The open_mapping can be a key string or an array of key strings. If you prefix the mapping with a number that particular terminal will be opened. Otherwise if a prefix is not set, then the last toggled terminal will be opened. In case there are multiple terminals opened they'll all be closed, and on the next mapping key they'll be restored.

If you set the insert_mappings key to true, the mapping will also take effect in insert mode; similarly setting terminal_mappings to true will have the mappings take effect in the opened terminal.

However you will not be able to use a count with the open mapping in terminal and insert modes. You can create buffer specific mappings to exit terminal mode and then use a count with the open mapping. Check Terminal window mappings for an example of how to do this.

alternatively you can do this manually (not recommended but, your prerogative)

" setautocmd TermEnter term://*toggleterm#*\ tnoremap<silent><c-t><Cmd>exe v:count1 . "ToggleTerm"<CR>" By applying the mappings this way you can pass a count to your" mapping to open a specific window." For example: 2<C-t> will open terminal 2nnoremap<silent><c-t><Cmd>exe v:count1 . "ToggleTerm"<CR>inoremap<silent><c-t><Esc><Cmd>exe v:count1 . "ToggleTerm"<CR>

NOTE: Please ensure you have set hidden in your neovim config, otherwise the terminals will be discarded when closed.

WARNING: Please do not copy and paste this configuration! It is here to show what options are available. It is not written to be used as is.

require("toggleterm").setup{
-- size can be a number or function which is passed the current terminalsize=20 | function(term)
ifterm.direction=="horizontal" thenreturn15elseifterm.direction=="vertical" thenreturnvim.o.columns*0.4endend,
open_mapping=[[<c-\>]], -- or { [[<c-\>]], [[<c-¥>]] } if you also use a Japanese keyboard.on_create=fun(t: Terminal), -- function to run when the terminal is first createdon_open=fun(t: Terminal), -- function to run when the terminal openson_close=fun(t: Terminal), -- function to run when the terminal closeson_stdout=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stdouton_stderr=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stderron_exit=fun(t: Terminal, job: number, exit_code: number, name: string) -- function to run when terminal process exitshide_numbers=true, -- hide the number column in toggleterm buffersshade_filetypes= {},
autochdir=false, -- when neovim changes it current directory the terminal will change it's own when next it's openedhighlights= {
-- highlights which map to a highlight group name and a table of it's values-- NOTE: this is only a subset of values, any group placed here will be set for the terminal window splitNormal= {
guibg="<VALUE-HERE>",
},
NormalFloat= {
link='Normal'
},
FloatBorder= {
guifg="<VALUE-HERE>",
guibg="<VALUE-HERE>",
},
},
shade_terminals=true, -- NOTE: this option takes priority over highlights specified so if you specify Normal highlights you should set this to falseshading_factor='<number>', -- the percentage by which to lighten dark terminal background, default: -30shading_ratio='<number>', -- the ratio of shading factor for light/dark terminal background, default: -3start_in_insert=true,
insert_mappings=true, -- whether or not the open mapping applies in insert modeterminal_mappings=true, -- whether or not the open mapping applies in the opened terminalspersist_size=true,
persist_mode=true, -- if set to true (default) the previous terminal mode will be remembereddirection='vertical' | 'horizontal' | 'tab' | 'float',
close_on_exit=true, -- close the terminal window when the process exitsclear_env=false, -- use only environmental variables from `env`, passed to jobstart()-- Change the default shell. Can be a string or a function returning a stringshell=vim.o.shell,
auto_scroll=true, -- automatically scroll to the bottom on terminal output-- This field is only relevant if direction is set to 'float'float_opts= {
-- The border key is *almost* the same as 'nvim_open_win'-- see :h nvim_open_win for details on borders however-- the 'curved' border is a custom border type-- not natively supported but implemented in this plugin.border='single' | 'double' | 'shadow' | 'curved' | ...otheroptionssupportedbywinopen-- like `size`, width, height, row, and col can be a number or function which is passed the current terminalwidth=<value>,
height=<value>,
row=<value>,
col=<value>,
winblend=3,
zindex=<value>,
title_pos='left' | 'center' | 'right', positionofthetitleofthefloatingwindow
},
winbar= {
enabled=false,
name_formatter=function(term) -- term: Terminalreturnterm.nameend
},
responsiveness= {
-- breakpoint in terms of `vim.o.columns` at which terminals will start to stack on top of each other-- instead of next to each other-- default = 0 which means the feature is turned offhorizontal_breakpoint=135,
}
}

Usage

ToggleTerm

This is the command the mappings call under the hood. You can use it directly and prefix it with a count to target a specific terminal. This function also takes arguments size, dir, direction and name. e.g.

:ToggleTerm size=40dir=~/Desktop direction=horizontal name=desktop

If dir is specified on creation toggle term will open at the specified directory. If the terminal has already been opened at a particular directory it will remain in that directory.

The directory can also be specified as git_dir which toggleterm will then use to try and derive the git repo directory. NOTE: This will not work for git-worktrees or other more complex setups.

If size is specified, and the command opens a split (horizontal/vertical) terminal, the height/width of all terminals in the same direction will be changed to size.

If direction is specified, and the command opens a terminal, the terminal will be changed to the specified direction.

If name is specified, the display name is set for the toggled terminal. This name will be visible when using TermSelect command to indicate the specific terminal.

size and direction are ignored if the command closes a terminal.

Caveats

  • Having multiple terminals with different directions open at the same time is unsupported.

ToggleTermToggleAll

This command allows you to open all the previously toggled terminal in one go or close all the open terminals at once.

TermExec

This command allows you to open a terminal with a specific action. e.g. 2TermExec cmd="git status" dir=~/<my-repo-path> will run git status in terminal 2. note that the cmd argument must be quoted.

NOTE: the dir argument can also be optionally quoted if it contains spaces.

The cmd and dir arguments can also expand the same special keywords as :h expand e.g. TermExec cmd="echo %" will be expanded to TermExec cmd="echo /file/example"

These special keywords can be escaped using the \ character, if you want to print character as is.

The size, direction and name arguments are like the size, direction and name arguments of ToggleTerm.

By default, focus is returned to the original window after executing the command (except for floating terminals). Use argument go_back=0 to disable this behaviour.

You can send commands to a terminal without opening its window by using the open=0 argument.

see :h expand() for more details

TermNew

This command allows you to open a new terminal at the next available count. It's helpful in combination with TermSelect (see below) to work with terminals without needing to remember numbers. The size, dir, direction and name arguments work the same as in ToggleTerm.

TermSelect

This command uses vim.ui.select to allow a user to select a terminal to open or to focus it if it's already open. This can be useful if you have a lot of terminals and want to open a specific one.

Sending lines to the terminal

You can "send lines" to the toggled terminals with the following commands:

  • :ToggleTermSendCurrentLine <T_ID>: sends the whole line where you are standing with your cursor
  • :ToggleTermSendVisualLines <T_ID>: sends all the (whole) lines in your visual selection
  • :ToggleTermSendVisualSelection <T_ID>: sends only the visually selected text (this can be a block of text or a selection in a single line)

(<T_ID is an optional terminal ID parameter, which defines where should we send the lines. If the parameter is not provided, then the default is the first terminal)

Alternatively, for more fine-grained control and use in mappings, in lua:

localtrim_spaces=truevim.keymap.set("v", "<space>s", function()
require("toggleterm").send_lines_to_terminal("single_line", trim_spaces, { args=vim.v.count })
end)
-- Replace with these for the other two options-- require("toggleterm").send_lines_to_terminal("visual_lines", trim_spaces, { args = vim.v.count })-- require("toggleterm").send_lines_to_terminal("visual_selection", trim_spaces, { args = vim.v.count })-- For use as an operator map:-- Send motion to terminalvim.keymap.set("n", [[<leader><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("g@", "n", false)
end)
-- Double the command to send line to terminalvim.keymap.set("n", [[<leader><c-\><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("g@_", "n", false)
end)
-- Send whole filevim.keymap.set("n", [[<leader><leader><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("ggg@G''", "n", false)
end)

Set trim_spaces=false for sending to REPLs for whitespace-sensitive languages like python. (For python, you probably want to start ipython with ipython --no-autoindent.)

Example:

send_lines_example.mov

ToggleTermSetName

This function allows setting a display name for a terminal. This name is primarily used inside the winbar, and can be a more descriptive way to remember, which terminal is for what.

You can map this to a key and call it with a count, which will then prompt you a name for the terminal with the matching ID. Alternatively you can call it with just the name e.g. :ToggleTermSetName work<CR> this will the prompt you for which terminal it should apply to. Lastly you can call it without any arguments, and it will prompt you for which terminal it should apply to then prompt you for the name to use.

Set terminal shading

This plugin automatically shades terminal filetypes to be darker than other window you can disable this by setting shade_terminals = false in the setup object

require'toggleterm'.setup {
shade_terminals=false
}

alternatively you can set, which filetypes should be shaded by setting

-- fzf is just an examplerequire'toggleterm'.setup {
shade_filetypes= { "none", "fzf" }
}

setting "none" will allow normal terminal buffers to be highlighted.

Set persistent size

By default, this plugin will persist the size of horizontal and vertical terminals. Split terminals in the same direction always have the same size. You can disable this behaviour by setting persist_size = false in the setup object. Disabling this behaviour forces the opening terminal size to the size defined in the setup object.

require'toggleterm'.setup{
persist_size=false
}

Terminal window mappings

It can be helpful to add mappings to make moving in and out of a terminal easier once toggled, whilst still keeping it open.

function_G.set_terminal_keymaps()
localopts= {buffer=0}
vim.keymap.set('t', '<esc>', [[<C-\><C-n>]], opts)
vim.keymap.set('t', 'jk', [[<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)
vim.keymap.set('t', '<C-w>', [[<C-\><C-n><C-w>]], opts)
end-- if you only want these mappings for toggle term use term://*toggleterm#* insteadvim.cmd('autocmd! TermOpen term://* lua set_terminal_keymaps()')

Custom Terminals

lazy gitusing lazygit

Toggleterm also exposes the Terminal class so that this can be used to create custom terminals for showing terminal UIs like lazygit, htop etc.

Each terminal can take the following arguments:

Terminal:new {
cmd=string-- command to execute when creating the terminal e.g. 'top'display_name=string-- the name of the terminaldirection=string-- the layout for the terminal, same as the main config optionsdir=string-- the directory for the terminalclose_on_exit=bool-- close the terminal window when the process exitshighlights=table-- a table with highlightsenv=table-- key:value table with environmental variables passed to jobstart()clear_env=bool-- use only environmental variables from `env`, passed to jobstart()on_open=fun(t: Terminal) -- function to run when the terminal openson_close=fun(t: Terminal) -- function to run when the terminal closesauto_scroll=boolean-- automatically scroll to the bottom on terminal output-- callbacks for processing the outputon_stdout=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stdouton_stderr=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stderron_exit=fun(t: Terminal, job: number, exit_code: number, name: string) -- function to run when terminal process exits
}

If you want to spawn a custom terminal without running any command, you can omit the cmd option.

Custom terminal usage

localTerminal=require('toggleterm.terminal').Terminallocallazygit=Terminal:new({ cmd="lazygit", hidden=true })
function_lazygit_toggle()
lazygit:toggle()
endvim.api.nvim_set_keymap("n", "<leader>g", "<cmd>lua _lazygit_toggle()<CR>", {noremap=true, silent=true})

This will create a new terminal, but the specified command is not being run immediately. The command will run once the terminal is opened. Alternatively term:spawn() can be used to start the command in a background buffer without opening a terminal window yet. If the hidden key is set to true, this terminal will not be toggled by normal toggleterm commands such as :ToggleTerm or the open mapping. It will only open and close by using the returned terminal object. A mapping for toggling the terminal can be set as in the example above.

Alternatively the terminal can be specified with a count, which is the number that can be used to trigger this specific terminal. This can then be triggered using the current count e.g. :5ToggleTerm<CR>

locallazygit=Terminal:new({ cmd="lazygit", count=5 })

You can also set a custom layout for a terminal.

locallazygit=Terminal:new({
cmd="lazygit",
dir="git_dir",
direction="float",
float_opts= {
border="double",
},
-- function to run on opening the terminalon_open=function(term)
vim.cmd("startinsert!")
vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "<cmd>close<CR>", {noremap=true, silent=true})
end,
-- function to run on closing the terminalon_close=function(term)
vim.cmd("startinsert!")
end,
})
function_lazygit_toggle()
lazygit:toggle()
endvim.api.nvim_set_keymap("n", "<leader>g", "<cmd>lua _lazygit_toggle()<CR>", {noremap=true, silent=true})

WARNING: do not use any of the private functionality of the terminal or other non-public parts of the API as these can change in the future.

Statusline

To tell each terminal apart you can use the terminal buffer variable b:toggle_number in your statusline

" this is pseudo codeletstatusline.='%{&ft == "toggleterm" ? "terminal (".b:toggle_number.")" : ""}'

Custom commands

You can create your own commands by using the lua functions this plugin provides directly

command! -count=1 TermGitPush lua require'toggleterm'.exec("git push", <count>, 12)
command! -count=1 TermGitPushF lua require'toggleterm'.exec("git push -f", <count>, 12)

Open multiple terminals side-by-side

DirectionSupported
vertical✔️
horizontal✔️
tab✖️
float✖️

In your first terminal, you need to leave the TERMINAL mode using C-\C-N which can be remapped to Esc for ease of use. image

Then you type on: 2<C-\>, and the result: image

Explain:

  • 2: this is the terminal's number (or ID), your first terminal is 1 (e.g. your 3rd terminal will be 3<C-\>, so on).
  • C-\: this is the combined key mapping to the command :ToggleTerm.

FAQ

How do I get this plugin to work with Powershell?

Please check out the Wiki section on this topic.

About

A neovim lua plugin to help easily manage multiple terminal windows

Topics

Resources

Stars

5.6k stars

Watchers

21 watching

Forks

Sponsor this project

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

toggleterm.nvim

A neovim plugin to persist and toggle multiple terminals during an editing session

toggleterm in action

Multiple orientations

  • Float

floating window

  • Vertical

vertical-terms

  • Tab

tab orientation

Send commands to different terminals

exec

Winbar (Experimental/Nightly ONLY)

image

Requirements

This plugin only works in Neovim 0.7 or newer.

Installation

Using packer in lua

use {"akinsho/toggleterm.nvim", tag='*', config=function()
require("toggleterm").setup()
end}

Using lazy.nvim in lua

{
-- amongst your other plugins
{'akinsho/toggleterm.nvim', version="*", config=true}
-- or
{'akinsho/toggleterm.nvim', version="*", opts= {--[[ things you want to change go here]]}}
}

Using vim-plug in vimscript

Plug 'akinsho/toggleterm.nvim', {'tag' : '*'}
luarequire("toggleterm").setup()

You can/should specify a tag for the current major version of the plugin, to avoid breaking changes as this plugin evolves. To use a version of this plugin compatible with nvim versions less than 0.7 please use the tag v1.*.

Notices

  • 28/07/1990 — If using persist_mode terminal mappings should be changed to use wincmd instead otherwise persist mode will not work correctly. See here for details.

Why?

Neovim's terminal is a very cool, but not super ergonomic tool to use. I find that I often want to set a process going and leave it to continue to run in the background. I don't need to see it all the time. I just need to be able to refer back to it at intervals. I also sometimes want to create a new terminal and run a few commands.

Sometimes I want these side by side, and I really want these terminals to be easy to access. I also want my terminal to look different from non-terminal buffers, so I use winhighlight to darken them based on the Normal background colour.

This is the exact use case this was designed for. If that's your use case this might work for you.

Roadmap

All I really want this plugin to be is what I described above. A wrapper around the terminal functionality.

It basically (almost) does all that I need it to.

I won't be turning this into a REPL plugin or doing a bunch of complex stuff. If you find any issues, please consider a pull request not an issue. I'm also going to be pretty conservative about what I add.

Setup

This plugin must be explicitly enabled by using require("toggleterm").setup{}

Setting the open_mapping key to use for toggling the terminal(s) will set up mappings for normal mode. The open_mapping can be a key string or an array of key strings. If you prefix the mapping with a number that particular terminal will be opened. Otherwise if a prefix is not set, then the last toggled terminal will be opened. In case there are multiple terminals opened they'll all be closed, and on the next mapping key they'll be restored.

If you set the insert_mappings key to true, the mapping will also take effect in insert mode; similarly setting terminal_mappings to true will have the mappings take effect in the opened terminal.

However you will not be able to use a count with the open mapping in terminal and insert modes. You can create buffer specific mappings to exit terminal mode and then use a count with the open mapping. Check Terminal window mappings for an example of how to do this.

alternatively you can do this manually (not recommended but, your prerogative)

" setautocmd TermEnter term://*toggleterm#*\ tnoremap<silent><c-t><Cmd>exe v:count1 . "ToggleTerm"<CR>" By applying the mappings this way you can pass a count to your" mapping to open a specific window." For example: 2<C-t> will open terminal 2nnoremap<silent><c-t><Cmd>exe v:count1 . "ToggleTerm"<CR>inoremap<silent><c-t><Esc><Cmd>exe v:count1 . "ToggleTerm"<CR>

NOTE: Please ensure you have set hidden in your neovim config, otherwise the terminals will be discarded when closed.

WARNING: Please do not copy and paste this configuration! It is here to show what options are available. It is not written to be used as is.

require("toggleterm").setup{
-- size can be a number or function which is passed the current terminalsize=20 | function(term)
ifterm.direction=="horizontal" thenreturn15elseifterm.direction=="vertical" thenreturnvim.o.columns*0.4endend,
open_mapping=[[<c-\>]], -- or { [[<c-\>]], [[<c-¥>]] } if you also use a Japanese keyboard.on_create=fun(t: Terminal), -- function to run when the terminal is first createdon_open=fun(t: Terminal), -- function to run when the terminal openson_close=fun(t: Terminal), -- function to run when the terminal closeson_stdout=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stdouton_stderr=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stderron_exit=fun(t: Terminal, job: number, exit_code: number, name: string) -- function to run when terminal process exitshide_numbers=true, -- hide the number column in toggleterm buffersshade_filetypes= {},
autochdir=false, -- when neovim changes it current directory the terminal will change it's own when next it's openedhighlights= {
-- highlights which map to a highlight group name and a table of it's values-- NOTE: this is only a subset of values, any group placed here will be set for the terminal window splitNormal= {
guibg="<VALUE-HERE>",
},
NormalFloat= {
link='Normal'
},
FloatBorder= {
guifg="<VALUE-HERE>",
guibg="<VALUE-HERE>",
},
},
shade_terminals=true, -- NOTE: this option takes priority over highlights specified so if you specify Normal highlights you should set this to falseshading_factor='<number>', -- the percentage by which to lighten dark terminal background, default: -30shading_ratio='<number>', -- the ratio of shading factor for light/dark terminal background, default: -3start_in_insert=true,
insert_mappings=true, -- whether or not the open mapping applies in insert modeterminal_mappings=true, -- whether or not the open mapping applies in the opened terminalspersist_size=true,
persist_mode=true, -- if set to true (default) the previous terminal mode will be remembereddirection='vertical' | 'horizontal' | 'tab' | 'float',
close_on_exit=true, -- close the terminal window when the process exitsclear_env=false, -- use only environmental variables from `env`, passed to jobstart()-- Change the default shell. Can be a string or a function returning a stringshell=vim.o.shell,
auto_scroll=true, -- automatically scroll to the bottom on terminal output-- This field is only relevant if direction is set to 'float'float_opts= {
-- The border key is *almost* the same as 'nvim_open_win'-- see :h nvim_open_win for details on borders however-- the 'curved' border is a custom border type-- not natively supported but implemented in this plugin.border='single' | 'double' | 'shadow' | 'curved' | ...otheroptionssupportedbywinopen-- like `size`, width, height, row, and col can be a number or function which is passed the current terminalwidth=<value>,
height=<value>,
row=<value>,
col=<value>,
winblend=3,
zindex=<value>,
title_pos='left' | 'center' | 'right', positionofthetitleofthefloatingwindow
},
winbar= {
enabled=false,
name_formatter=function(term) -- term: Terminalreturnterm.nameend
},
responsiveness= {
-- breakpoint in terms of `vim.o.columns` at which terminals will start to stack on top of each other-- instead of next to each other-- default = 0 which means the feature is turned offhorizontal_breakpoint=135,
}
}

Usage

ToggleTerm

This is the command the mappings call under the hood. You can use it directly and prefix it with a count to target a specific terminal. This function also takes arguments size, dir, direction and name. e.g.

:ToggleTerm size=40dir=~/Desktop direction=horizontal name=desktop

If dir is specified on creation toggle term will open at the specified directory. If the terminal has already been opened at a particular directory it will remain in that directory.

The directory can also be specified as git_dir which toggleterm will then use to try and derive the git repo directory. NOTE: This will not work for git-worktrees or other more complex setups.

If size is specified, and the command opens a split (horizontal/vertical) terminal, the height/width of all terminals in the same direction will be changed to size.

If direction is specified, and the command opens a terminal, the terminal will be changed to the specified direction.

If name is specified, the display name is set for the toggled terminal. This name will be visible when using TermSelect command to indicate the specific terminal.

size and direction are ignored if the command closes a terminal.

Caveats

  • Having multiple terminals with different directions open at the same time is unsupported.

ToggleTermToggleAll

This command allows you to open all the previously toggled terminal in one go or close all the open terminals at once.

TermExec

This command allows you to open a terminal with a specific action. e.g. 2TermExec cmd="git status" dir=~/<my-repo-path> will run git status in terminal 2. note that the cmd argument must be quoted.

NOTE: the dir argument can also be optionally quoted if it contains spaces.

The cmd and dir arguments can also expand the same special keywords as :h expand e.g. TermExec cmd="echo %" will be expanded to TermExec cmd="echo /file/example"

These special keywords can be escaped using the \ character, if you want to print character as is.

The size, direction and name arguments are like the size, direction and name arguments of ToggleTerm.

By default, focus is returned to the original window after executing the command (except for floating terminals). Use argument go_back=0 to disable this behaviour.

You can send commands to a terminal without opening its window by using the open=0 argument.

see :h expand() for more details

TermNew

This command allows you to open a new terminal at the next available count. It's helpful in combination with TermSelect (see below) to work with terminals without needing to remember numbers. The size, dir, direction and name arguments work the same as in ToggleTerm.

TermSelect

This command uses vim.ui.select to allow a user to select a terminal to open or to focus it if it's already open. This can be useful if you have a lot of terminals and want to open a specific one.

Sending lines to the terminal

You can "send lines" to the toggled terminals with the following commands:

  • :ToggleTermSendCurrentLine <T_ID>: sends the whole line where you are standing with your cursor
  • :ToggleTermSendVisualLines <T_ID>: sends all the (whole) lines in your visual selection
  • :ToggleTermSendVisualSelection <T_ID>: sends only the visually selected text (this can be a block of text or a selection in a single line)

(<T_ID is an optional terminal ID parameter, which defines where should we send the lines. If the parameter is not provided, then the default is the first terminal)

Alternatively, for more fine-grained control and use in mappings, in lua:

localtrim_spaces=truevim.keymap.set("v", "<space>s", function()
require("toggleterm").send_lines_to_terminal("single_line", trim_spaces, { args=vim.v.count })
end)
-- Replace with these for the other two options-- require("toggleterm").send_lines_to_terminal("visual_lines", trim_spaces, { args = vim.v.count })-- require("toggleterm").send_lines_to_terminal("visual_selection", trim_spaces, { args = vim.v.count })-- For use as an operator map:-- Send motion to terminalvim.keymap.set("n", [[<leader><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("g@", "n", false)
end)
-- Double the command to send line to terminalvim.keymap.set("n", [[<leader><c-\><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("g@_", "n", false)
end)
-- Send whole filevim.keymap.set("n", [[<leader><leader><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("ggg@G''", "n", false)
end)

Set trim_spaces=false for sending to REPLs for whitespace-sensitive languages like python. (For python, you probably want to start ipython with ipython --no-autoindent.)

Example:

send_lines_example.mov

ToggleTermSetName

This function allows setting a display name for a terminal. This name is primarily used inside the winbar, and can be a more descriptive way to remember, which terminal is for what.

You can map this to a key and call it with a count, which will then prompt you a name for the terminal with the matching ID. Alternatively you can call it with just the name e.g. :ToggleTermSetName work<CR> this will the prompt you for which terminal it should apply to. Lastly you can call it without any arguments, and it will prompt you for which terminal it should apply to then prompt you for the name to use.

Set terminal shading

This plugin automatically shades terminal filetypes to be darker than other window you can disable this by setting shade_terminals = false in the setup object

require'toggleterm'.setup {
shade_terminals=false
}

alternatively you can set, which filetypes should be shaded by setting

-- fzf is just an examplerequire'toggleterm'.setup {
shade_filetypes= { "none", "fzf" }
}

setting "none" will allow normal terminal buffers to be highlighted.

Set persistent size

By default, this plugin will persist the size of horizontal and vertical terminals. Split terminals in the same direction always have the same size. You can disable this behaviour by setting persist_size = false in the setup object. Disabling this behaviour forces the opening terminal size to the size defined in the setup object.

require'toggleterm'.setup{
persist_size=false
}

Terminal window mappings

It can be helpful to add mappings to make moving in and out of a terminal easier once toggled, whilst still keeping it open.

function_G.set_terminal_keymaps()
localopts= {buffer=0}
vim.keymap.set('t', '<esc>', [[<C-\><C-n>]], opts)
vim.keymap.set('t', 'jk', [[<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)
vim.keymap.set('t', '<C-w>', [[<C-\><C-n><C-w>]], opts)
end-- if you only want these mappings for toggle term use term://*toggleterm#* insteadvim.cmd('autocmd! TermOpen term://* lua set_terminal_keymaps()')

Custom Terminals

lazy gitusing lazygit

Toggleterm also exposes the Terminal class so that this can be used to create custom terminals for showing terminal UIs like lazygit, htop etc.

Each terminal can take the following arguments:

Terminal:new {
cmd=string-- command to execute when creating the terminal e.g. 'top'display_name=string-- the name of the terminaldirection=string-- the layout for the terminal, same as the main config optionsdir=string-- the directory for the terminalclose_on_exit=bool-- close the terminal window when the process exitshighlights=table-- a table with highlightsenv=table-- key:value table with environmental variables passed to jobstart()clear_env=bool-- use only environmental variables from `env`, passed to jobstart()on_open=fun(t: Terminal) -- function to run when the terminal openson_close=fun(t: Terminal) -- function to run when the terminal closesauto_scroll=boolean-- automatically scroll to the bottom on terminal output-- callbacks for processing the outputon_stdout=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stdouton_stderr=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stderron_exit=fun(t: Terminal, job: number, exit_code: number, name: string) -- function to run when terminal process exits
}

If you want to spawn a custom terminal without running any command, you can omit the cmd option.

Custom terminal usage

localTerminal=require('toggleterm.terminal').Terminallocallazygit=Terminal:new({ cmd="lazygit", hidden=true })
function_lazygit_toggle()
lazygit:toggle()
endvim.api.nvim_set_keymap("n", "<leader>g", "<cmd>lua _lazygit_toggle()<CR>", {noremap=true, silent=true})

This will create a new terminal, but the specified command is not being run immediately. The command will run once the terminal is opened. Alternatively term:spawn() can be used to start the command in a background buffer without opening a terminal window yet. If the hidden key is set to true, this terminal will not be toggled by normal toggleterm commands such as :ToggleTerm or the open mapping. It will only open and close by using the returned terminal object. A mapping for toggling the terminal can be set as in the example above.

Alternatively the terminal can be specified with a count, which is the number that can be used to trigger this specific terminal. This can then be triggered using the current count e.g. :5ToggleTerm<CR>

locallazygit=Terminal:new({ cmd="lazygit", count=5 })

You can also set a custom layout for a terminal.

locallazygit=Terminal:new({
cmd="lazygit",
dir="git_dir",
direction="float",
float_opts= {
border="double",
},
-- function to run on opening the terminalon_open=function(term)
vim.cmd("startinsert!")
vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "<cmd>close<CR>", {noremap=true, silent=true})
end,
-- function to run on closing the terminalon_close=function(term)
vim.cmd("startinsert!")
end,
})
function_lazygit_toggle()
lazygit:toggle()
endvim.api.nvim_set_keymap("n", "<leader>g", "<cmd>lua _lazygit_toggle()<CR>", {noremap=true, silent=true})

WARNING: do not use any of the private functionality of the terminal or other non-public parts of the API as these can change in the future.

Statusline

To tell each terminal apart you can use the terminal buffer variable b:toggle_number in your statusline

" this is pseudo codeletstatusline.='%{&ft == "toggleterm" ? "terminal (".b:toggle_number.")" : ""}'

Custom commands

You can create your own commands by using the lua functions this plugin provides directly

command! -count=1 TermGitPush lua require'toggleterm'.exec("git push", <count>, 12)
command! -count=1 TermGitPushF lua require'toggleterm'.exec("git push -f", <count>, 12)

Open multiple terminals side-by-side

DirectionSupported
vertical✔️
horizontal✔️
tab✖️
float✖️

In your first terminal, you need to leave the TERMINAL mode using C-\C-N which can be remapped to Esc for ease of use. image

Then you type on: 2<C-\>, and the result: image

Explain:

  • 2: this is the terminal's number (or ID), your first terminal is 1 (e.g. your 3rd terminal will be 3<C-\>, so on).
  • C-\: this is the combined key mapping to the command :ToggleTerm.

FAQ

How do I get this plugin to work with Powershell?

Please check out the Wiki section on this topic.

About

A neovim lua plugin to help easily manage multiple terminal windows

Topics

Resources

Stars

5.6k stars

Watchers

21 watching

Forks

Sponsor this project

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

toggleterm.nvim

A neovim plugin to persist and toggle multiple terminals during an editing session

toggleterm in action

Multiple orientations

  • Float

floating window

  • Vertical

vertical-terms

  • Tab

tab orientation

Send commands to different terminals

exec

Winbar (Experimental/Nightly ONLY)

image

Requirements

This plugin only works in Neovim 0.7 or newer.

Installation

Using packer in lua

use {"akinsho/toggleterm.nvim", tag='*', config=function()
require("toggleterm").setup()
end}

Using lazy.nvim in lua

{
-- amongst your other plugins
{'akinsho/toggleterm.nvim', version="*", config=true}
-- or
{'akinsho/toggleterm.nvim', version="*", opts= {--[[ things you want to change go here]]}}
}

Using vim-plug in vimscript

Plug 'akinsho/toggleterm.nvim', {'tag' : '*'}
luarequire("toggleterm").setup()

You can/should specify a tag for the current major version of the plugin, to avoid breaking changes as this plugin evolves. To use a version of this plugin compatible with nvim versions less than 0.7 please use the tag v1.*.

Notices

  • 28/07/1990 — If using persist_mode terminal mappings should be changed to use wincmd instead otherwise persist mode will not work correctly. See here for details.

Why?

Neovim's terminal is a very cool, but not super ergonomic tool to use. I find that I often want to set a process going and leave it to continue to run in the background. I don't need to see it all the time. I just need to be able to refer back to it at intervals. I also sometimes want to create a new terminal and run a few commands.

Sometimes I want these side by side, and I really want these terminals to be easy to access. I also want my terminal to look different from non-terminal buffers, so I use winhighlight to darken them based on the Normal background colour.

This is the exact use case this was designed for. If that's your use case this might work for you.

Roadmap

All I really want this plugin to be is what I described above. A wrapper around the terminal functionality.

It basically (almost) does all that I need it to.

I won't be turning this into a REPL plugin or doing a bunch of complex stuff. If you find any issues, please consider a pull request not an issue. I'm also going to be pretty conservative about what I add.

Setup

This plugin must be explicitly enabled by using require("toggleterm").setup{}

Setting the open_mapping key to use for toggling the terminal(s) will set up mappings for normal mode. The open_mapping can be a key string or an array of key strings. If you prefix the mapping with a number that particular terminal will be opened. Otherwise if a prefix is not set, then the last toggled terminal will be opened. In case there are multiple terminals opened they'll all be closed, and on the next mapping key they'll be restored.

If you set the insert_mappings key to true, the mapping will also take effect in insert mode; similarly setting terminal_mappings to true will have the mappings take effect in the opened terminal.

However you will not be able to use a count with the open mapping in terminal and insert modes. You can create buffer specific mappings to exit terminal mode and then use a count with the open mapping. Check Terminal window mappings for an example of how to do this.

alternatively you can do this manually (not recommended but, your prerogative)

" setautocmd TermEnter term://*toggleterm#*\ tnoremap<silent><c-t><Cmd>exe v:count1 . "ToggleTerm"<CR>" By applying the mappings this way you can pass a count to your" mapping to open a specific window." For example: 2<C-t> will open terminal 2nnoremap<silent><c-t><Cmd>exe v:count1 . "ToggleTerm"<CR>inoremap<silent><c-t><Esc><Cmd>exe v:count1 . "ToggleTerm"<CR>

NOTE: Please ensure you have set hidden in your neovim config, otherwise the terminals will be discarded when closed.

WARNING: Please do not copy and paste this configuration! It is here to show what options are available. It is not written to be used as is.

require("toggleterm").setup{
-- size can be a number or function which is passed the current terminalsize=20 | function(term)
ifterm.direction=="horizontal" thenreturn15elseifterm.direction=="vertical" thenreturnvim.o.columns*0.4endend,
open_mapping=[[<c-\>]], -- or { [[<c-\>]], [[<c-¥>]] } if you also use a Japanese keyboard.on_create=fun(t: Terminal), -- function to run when the terminal is first createdon_open=fun(t: Terminal), -- function to run when the terminal openson_close=fun(t: Terminal), -- function to run when the terminal closeson_stdout=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stdouton_stderr=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stderron_exit=fun(t: Terminal, job: number, exit_code: number, name: string) -- function to run when terminal process exitshide_numbers=true, -- hide the number column in toggleterm buffersshade_filetypes= {},
autochdir=false, -- when neovim changes it current directory the terminal will change it's own when next it's openedhighlights= {
-- highlights which map to a highlight group name and a table of it's values-- NOTE: this is only a subset of values, any group placed here will be set for the terminal window splitNormal= {
guibg="<VALUE-HERE>",
},
NormalFloat= {
link='Normal'
},
FloatBorder= {
guifg="<VALUE-HERE>",
guibg="<VALUE-HERE>",
},
},
shade_terminals=true, -- NOTE: this option takes priority over highlights specified so if you specify Normal highlights you should set this to falseshading_factor='<number>', -- the percentage by which to lighten dark terminal background, default: -30shading_ratio='<number>', -- the ratio of shading factor for light/dark terminal background, default: -3start_in_insert=true,
insert_mappings=true, -- whether or not the open mapping applies in insert modeterminal_mappings=true, -- whether or not the open mapping applies in the opened terminalspersist_size=true,
persist_mode=true, -- if set to true (default) the previous terminal mode will be remembereddirection='vertical' | 'horizontal' | 'tab' | 'float',
close_on_exit=true, -- close the terminal window when the process exitsclear_env=false, -- use only environmental variables from `env`, passed to jobstart()-- Change the default shell. Can be a string or a function returning a stringshell=vim.o.shell,
auto_scroll=true, -- automatically scroll to the bottom on terminal output-- This field is only relevant if direction is set to 'float'float_opts= {
-- The border key is *almost* the same as 'nvim_open_win'-- see :h nvim_open_win for details on borders however-- the 'curved' border is a custom border type-- not natively supported but implemented in this plugin.border='single' | 'double' | 'shadow' | 'curved' | ...otheroptionssupportedbywinopen-- like `size`, width, height, row, and col can be a number or function which is passed the current terminalwidth=<value>,
height=<value>,
row=<value>,
col=<value>,
winblend=3,
zindex=<value>,
title_pos='left' | 'center' | 'right', positionofthetitleofthefloatingwindow
},
winbar= {
enabled=false,
name_formatter=function(term) -- term: Terminalreturnterm.nameend
},
responsiveness= {
-- breakpoint in terms of `vim.o.columns` at which terminals will start to stack on top of each other-- instead of next to each other-- default = 0 which means the feature is turned offhorizontal_breakpoint=135,
}
}

Usage

ToggleTerm

This is the command the mappings call under the hood. You can use it directly and prefix it with a count to target a specific terminal. This function also takes arguments size, dir, direction and name. e.g.

:ToggleTerm size=40dir=~/Desktop direction=horizontal name=desktop

If dir is specified on creation toggle term will open at the specified directory. If the terminal has already been opened at a particular directory it will remain in that directory.

The directory can also be specified as git_dir which toggleterm will then use to try and derive the git repo directory. NOTE: This will not work for git-worktrees or other more complex setups.

If size is specified, and the command opens a split (horizontal/vertical) terminal, the height/width of all terminals in the same direction will be changed to size.

If direction is specified, and the command opens a terminal, the terminal will be changed to the specified direction.

If name is specified, the display name is set for the toggled terminal. This name will be visible when using TermSelect command to indicate the specific terminal.

size and direction are ignored if the command closes a terminal.

Caveats

  • Having multiple terminals with different directions open at the same time is unsupported.

ToggleTermToggleAll

This command allows you to open all the previously toggled terminal in one go or close all the open terminals at once.

TermExec

This command allows you to open a terminal with a specific action. e.g. 2TermExec cmd="git status" dir=~/<my-repo-path> will run git status in terminal 2. note that the cmd argument must be quoted.

NOTE: the dir argument can also be optionally quoted if it contains spaces.

The cmd and dir arguments can also expand the same special keywords as :h expand e.g. TermExec cmd="echo %" will be expanded to TermExec cmd="echo /file/example"

These special keywords can be escaped using the \ character, if you want to print character as is.

The size, direction and name arguments are like the size, direction and name arguments of ToggleTerm.

By default, focus is returned to the original window after executing the command (except for floating terminals). Use argument go_back=0 to disable this behaviour.

You can send commands to a terminal without opening its window by using the open=0 argument.

see :h expand() for more details

TermNew

This command allows you to open a new terminal at the next available count. It's helpful in combination with TermSelect (see below) to work with terminals without needing to remember numbers. The size, dir, direction and name arguments work the same as in ToggleTerm.

TermSelect

This command uses vim.ui.select to allow a user to select a terminal to open or to focus it if it's already open. This can be useful if you have a lot of terminals and want to open a specific one.

Sending lines to the terminal

You can "send lines" to the toggled terminals with the following commands:

  • :ToggleTermSendCurrentLine <T_ID>: sends the whole line where you are standing with your cursor
  • :ToggleTermSendVisualLines <T_ID>: sends all the (whole) lines in your visual selection
  • :ToggleTermSendVisualSelection <T_ID>: sends only the visually selected text (this can be a block of text or a selection in a single line)

(<T_ID is an optional terminal ID parameter, which defines where should we send the lines. If the parameter is not provided, then the default is the first terminal)

Alternatively, for more fine-grained control and use in mappings, in lua:

localtrim_spaces=truevim.keymap.set("v", "<space>s", function()
require("toggleterm").send_lines_to_terminal("single_line", trim_spaces, { args=vim.v.count })
end)
-- Replace with these for the other two options-- require("toggleterm").send_lines_to_terminal("visual_lines", trim_spaces, { args = vim.v.count })-- require("toggleterm").send_lines_to_terminal("visual_selection", trim_spaces, { args = vim.v.count })-- For use as an operator map:-- Send motion to terminalvim.keymap.set("n", [[<leader><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("g@", "n", false)
end)
-- Double the command to send line to terminalvim.keymap.set("n", [[<leader><c-\><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("g@_", "n", false)
end)
-- Send whole filevim.keymap.set("n", [[<leader><leader><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("ggg@G''", "n", false)
end)

Set trim_spaces=false for sending to REPLs for whitespace-sensitive languages like python. (For python, you probably want to start ipython with ipython --no-autoindent.)

Example:

send_lines_example.mov

ToggleTermSetName

This function allows setting a display name for a terminal. This name is primarily used inside the winbar, and can be a more descriptive way to remember, which terminal is for what.

You can map this to a key and call it with a count, which will then prompt you a name for the terminal with the matching ID. Alternatively you can call it with just the name e.g. :ToggleTermSetName work<CR> this will the prompt you for which terminal it should apply to. Lastly you can call it without any arguments, and it will prompt you for which terminal it should apply to then prompt you for the name to use.

Set terminal shading

This plugin automatically shades terminal filetypes to be darker than other window you can disable this by setting shade_terminals = false in the setup object

require'toggleterm'.setup {
shade_terminals=false
}

alternatively you can set, which filetypes should be shaded by setting

-- fzf is just an examplerequire'toggleterm'.setup {
shade_filetypes= { "none", "fzf" }
}

setting "none" will allow normal terminal buffers to be highlighted.

Set persistent size

By default, this plugin will persist the size of horizontal and vertical terminals. Split terminals in the same direction always have the same size. You can disable this behaviour by setting persist_size = false in the setup object. Disabling this behaviour forces the opening terminal size to the size defined in the setup object.

require'toggleterm'.setup{
persist_size=false
}

Terminal window mappings

It can be helpful to add mappings to make moving in and out of a terminal easier once toggled, whilst still keeping it open.

function_G.set_terminal_keymaps()
localopts= {buffer=0}
vim.keymap.set('t', '<esc>', [[<C-\><C-n>]], opts)
vim.keymap.set('t', 'jk', [[<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)
vim.keymap.set('t', '<C-w>', [[<C-\><C-n><C-w>]], opts)
end-- if you only want these mappings for toggle term use term://*toggleterm#* insteadvim.cmd('autocmd! TermOpen term://* lua set_terminal_keymaps()')

Custom Terminals

lazy gitusing lazygit

Toggleterm also exposes the Terminal class so that this can be used to create custom terminals for showing terminal UIs like lazygit, htop etc.

Each terminal can take the following arguments:

Terminal:new {
cmd=string-- command to execute when creating the terminal e.g. 'top'display_name=string-- the name of the terminaldirection=string-- the layout for the terminal, same as the main config optionsdir=string-- the directory for the terminalclose_on_exit=bool-- close the terminal window when the process exitshighlights=table-- a table with highlightsenv=table-- key:value table with environmental variables passed to jobstart()clear_env=bool-- use only environmental variables from `env`, passed to jobstart()on_open=fun(t: Terminal) -- function to run when the terminal openson_close=fun(t: Terminal) -- function to run when the terminal closesauto_scroll=boolean-- automatically scroll to the bottom on terminal output-- callbacks for processing the outputon_stdout=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stdouton_stderr=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stderron_exit=fun(t: Terminal, job: number, exit_code: number, name: string) -- function to run when terminal process exits
}

If you want to spawn a custom terminal without running any command, you can omit the cmd option.

Custom terminal usage

localTerminal=require('toggleterm.terminal').Terminallocallazygit=Terminal:new({ cmd="lazygit", hidden=true })
function_lazygit_toggle()
lazygit:toggle()
endvim.api.nvim_set_keymap("n", "<leader>g", "<cmd>lua _lazygit_toggle()<CR>", {noremap=true, silent=true})

This will create a new terminal, but the specified command is not being run immediately. The command will run once the terminal is opened. Alternatively term:spawn() can be used to start the command in a background buffer without opening a terminal window yet. If the hidden key is set to true, this terminal will not be toggled by normal toggleterm commands such as :ToggleTerm or the open mapping. It will only open and close by using the returned terminal object. A mapping for toggling the terminal can be set as in the example above.

Alternatively the terminal can be specified with a count, which is the number that can be used to trigger this specific terminal. This can then be triggered using the current count e.g. :5ToggleTerm<CR>

locallazygit=Terminal:new({ cmd="lazygit", count=5 })

You can also set a custom layout for a terminal.

locallazygit=Terminal:new({
cmd="lazygit",
dir="git_dir",
direction="float",
float_opts= {
border="double",
},
-- function to run on opening the terminalon_open=function(term)
vim.cmd("startinsert!")
vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "<cmd>close<CR>", {noremap=true, silent=true})
end,
-- function to run on closing the terminalon_close=function(term)
vim.cmd("startinsert!")
end,
})
function_lazygit_toggle()
lazygit:toggle()
endvim.api.nvim_set_keymap("n", "<leader>g", "<cmd>lua _lazygit_toggle()<CR>", {noremap=true, silent=true})

WARNING: do not use any of the private functionality of the terminal or other non-public parts of the API as these can change in the future.

Statusline

To tell each terminal apart you can use the terminal buffer variable b:toggle_number in your statusline

" this is pseudo codeletstatusline.='%{&ft == "toggleterm" ? "terminal (".b:toggle_number.")" : ""}'

Custom commands

You can create your own commands by using the lua functions this plugin provides directly

command! -count=1 TermGitPush lua require'toggleterm'.exec("git push", <count>, 12)
command! -count=1 TermGitPushF lua require'toggleterm'.exec("git push -f", <count>, 12)

Open multiple terminals side-by-side

DirectionSupported
vertical✔️
horizontal✔️
tab✖️
float✖️

In your first terminal, you need to leave the TERMINAL mode using C-\C-N which can be remapped to Esc for ease of use. image

Then you type on: 2<C-\>, and the result: image

Explain:

  • 2: this is the terminal's number (or ID), your first terminal is 1 (e.g. your 3rd terminal will be 3<C-\>, so on).
  • C-\: this is the combined key mapping to the command :ToggleTerm.

FAQ

How do I get this plugin to work with Powershell?

Please check out the Wiki section on this topic.

About

A neovim lua plugin to help easily manage multiple terminal windows

Topics

Resources

Stars

5.6k stars

Watchers

21 watching

Forks

Sponsor this project

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

toggleterm.nvim

A neovim plugin to persist and toggle multiple terminals during an editing session

toggleterm in action

Multiple orientations

  • Float

floating window

  • Vertical

vertical-terms

  • Tab

tab orientation

Send commands to different terminals

exec

Winbar (Experimental/Nightly ONLY)

image

Requirements

This plugin only works in Neovim 0.7 or newer.

Installation

Using packer in lua

use {"akinsho/toggleterm.nvim", tag='*', config=function()
require("toggleterm").setup()
end}

Using lazy.nvim in lua

{
-- amongst your other plugins
{'akinsho/toggleterm.nvim', version="*", config=true}
-- or
{'akinsho/toggleterm.nvim', version="*", opts= {--[[ things you want to change go here]]}}
}

Using vim-plug in vimscript

Plug 'akinsho/toggleterm.nvim', {'tag' : '*'}
luarequire("toggleterm").setup()

You can/should specify a tag for the current major version of the plugin, to avoid breaking changes as this plugin evolves. To use a version of this plugin compatible with nvim versions less than 0.7 please use the tag v1.*.

Notices

  • 28/07/1990 — If using persist_mode terminal mappings should be changed to use wincmd instead otherwise persist mode will not work correctly. See here for details.

Why?

Neovim's terminal is a very cool, but not super ergonomic tool to use. I find that I often want to set a process going and leave it to continue to run in the background. I don't need to see it all the time. I just need to be able to refer back to it at intervals. I also sometimes want to create a new terminal and run a few commands.

Sometimes I want these side by side, and I really want these terminals to be easy to access. I also want my terminal to look different from non-terminal buffers, so I use winhighlight to darken them based on the Normal background colour.

This is the exact use case this was designed for. If that's your use case this might work for you.

Roadmap

All I really want this plugin to be is what I described above. A wrapper around the terminal functionality.

It basically (almost) does all that I need it to.

I won't be turning this into a REPL plugin or doing a bunch of complex stuff. If you find any issues, please consider a pull request not an issue. I'm also going to be pretty conservative about what I add.

Setup

This plugin must be explicitly enabled by using require("toggleterm").setup{}

Setting the open_mapping key to use for toggling the terminal(s) will set up mappings for normal mode. The open_mapping can be a key string or an array of key strings. If you prefix the mapping with a number that particular terminal will be opened. Otherwise if a prefix is not set, then the last toggled terminal will be opened. In case there are multiple terminals opened they'll all be closed, and on the next mapping key they'll be restored.

If you set the insert_mappings key to true, the mapping will also take effect in insert mode; similarly setting terminal_mappings to true will have the mappings take effect in the opened terminal.

However you will not be able to use a count with the open mapping in terminal and insert modes. You can create buffer specific mappings to exit terminal mode and then use a count with the open mapping. Check Terminal window mappings for an example of how to do this.

alternatively you can do this manually (not recommended but, your prerogative)

" setautocmd TermEnter term://*toggleterm#*\ tnoremap<silent><c-t><Cmd>exe v:count1 . "ToggleTerm"<CR>" By applying the mappings this way you can pass a count to your" mapping to open a specific window." For example: 2<C-t> will open terminal 2nnoremap<silent><c-t><Cmd>exe v:count1 . "ToggleTerm"<CR>inoremap<silent><c-t><Esc><Cmd>exe v:count1 . "ToggleTerm"<CR>

NOTE: Please ensure you have set hidden in your neovim config, otherwise the terminals will be discarded when closed.

WARNING: Please do not copy and paste this configuration! It is here to show what options are available. It is not written to be used as is.

require("toggleterm").setup{
-- size can be a number or function which is passed the current terminalsize=20 | function(term)
ifterm.direction=="horizontal" thenreturn15elseifterm.direction=="vertical" thenreturnvim.o.columns*0.4endend,
open_mapping=[[<c-\>]], -- or { [[<c-\>]], [[<c-¥>]] } if you also use a Japanese keyboard.on_create=fun(t: Terminal), -- function to run when the terminal is first createdon_open=fun(t: Terminal), -- function to run when the terminal openson_close=fun(t: Terminal), -- function to run when the terminal closeson_stdout=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stdouton_stderr=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stderron_exit=fun(t: Terminal, job: number, exit_code: number, name: string) -- function to run when terminal process exitshide_numbers=true, -- hide the number column in toggleterm buffersshade_filetypes= {},
autochdir=false, -- when neovim changes it current directory the terminal will change it's own when next it's openedhighlights= {
-- highlights which map to a highlight group name and a table of it's values-- NOTE: this is only a subset of values, any group placed here will be set for the terminal window splitNormal= {
guibg="<VALUE-HERE>",
},
NormalFloat= {
link='Normal'
},
FloatBorder= {
guifg="<VALUE-HERE>",
guibg="<VALUE-HERE>",
},
},
shade_terminals=true, -- NOTE: this option takes priority over highlights specified so if you specify Normal highlights you should set this to falseshading_factor='<number>', -- the percentage by which to lighten dark terminal background, default: -30shading_ratio='<number>', -- the ratio of shading factor for light/dark terminal background, default: -3start_in_insert=true,
insert_mappings=true, -- whether or not the open mapping applies in insert modeterminal_mappings=true, -- whether or not the open mapping applies in the opened terminalspersist_size=true,
persist_mode=true, -- if set to true (default) the previous terminal mode will be remembereddirection='vertical' | 'horizontal' | 'tab' | 'float',
close_on_exit=true, -- close the terminal window when the process exitsclear_env=false, -- use only environmental variables from `env`, passed to jobstart()-- Change the default shell. Can be a string or a function returning a stringshell=vim.o.shell,
auto_scroll=true, -- automatically scroll to the bottom on terminal output-- This field is only relevant if direction is set to 'float'float_opts= {
-- The border key is *almost* the same as 'nvim_open_win'-- see :h nvim_open_win for details on borders however-- the 'curved' border is a custom border type-- not natively supported but implemented in this plugin.border='single' | 'double' | 'shadow' | 'curved' | ...otheroptionssupportedbywinopen-- like `size`, width, height, row, and col can be a number or function which is passed the current terminalwidth=<value>,
height=<value>,
row=<value>,
col=<value>,
winblend=3,
zindex=<value>,
title_pos='left' | 'center' | 'right', positionofthetitleofthefloatingwindow
},
winbar= {
enabled=false,
name_formatter=function(term) -- term: Terminalreturnterm.nameend
},
responsiveness= {
-- breakpoint in terms of `vim.o.columns` at which terminals will start to stack on top of each other-- instead of next to each other-- default = 0 which means the feature is turned offhorizontal_breakpoint=135,
}
}

Usage

ToggleTerm

This is the command the mappings call under the hood. You can use it directly and prefix it with a count to target a specific terminal. This function also takes arguments size, dir, direction and name. e.g.

:ToggleTerm size=40dir=~/Desktop direction=horizontal name=desktop

If dir is specified on creation toggle term will open at the specified directory. If the terminal has already been opened at a particular directory it will remain in that directory.

The directory can also be specified as git_dir which toggleterm will then use to try and derive the git repo directory. NOTE: This will not work for git-worktrees or other more complex setups.

If size is specified, and the command opens a split (horizontal/vertical) terminal, the height/width of all terminals in the same direction will be changed to size.

If direction is specified, and the command opens a terminal, the terminal will be changed to the specified direction.

If name is specified, the display name is set for the toggled terminal. This name will be visible when using TermSelect command to indicate the specific terminal.

size and direction are ignored if the command closes a terminal.

Caveats

  • Having multiple terminals with different directions open at the same time is unsupported.

ToggleTermToggleAll

This command allows you to open all the previously toggled terminal in one go or close all the open terminals at once.

TermExec

This command allows you to open a terminal with a specific action. e.g. 2TermExec cmd="git status" dir=~/<my-repo-path> will run git status in terminal 2. note that the cmd argument must be quoted.

NOTE: the dir argument can also be optionally quoted if it contains spaces.

The cmd and dir arguments can also expand the same special keywords as :h expand e.g. TermExec cmd="echo %" will be expanded to TermExec cmd="echo /file/example"

These special keywords can be escaped using the \ character, if you want to print character as is.

The size, direction and name arguments are like the size, direction and name arguments of ToggleTerm.

By default, focus is returned to the original window after executing the command (except for floating terminals). Use argument go_back=0 to disable this behaviour.

You can send commands to a terminal without opening its window by using the open=0 argument.

see :h expand() for more details

TermNew

This command allows you to open a new terminal at the next available count. It's helpful in combination with TermSelect (see below) to work with terminals without needing to remember numbers. The size, dir, direction and name arguments work the same as in ToggleTerm.

TermSelect

This command uses vim.ui.select to allow a user to select a terminal to open or to focus it if it's already open. This can be useful if you have a lot of terminals and want to open a specific one.

Sending lines to the terminal

You can "send lines" to the toggled terminals with the following commands:

  • :ToggleTermSendCurrentLine <T_ID>: sends the whole line where you are standing with your cursor
  • :ToggleTermSendVisualLines <T_ID>: sends all the (whole) lines in your visual selection
  • :ToggleTermSendVisualSelection <T_ID>: sends only the visually selected text (this can be a block of text or a selection in a single line)

(<T_ID is an optional terminal ID parameter, which defines where should we send the lines. If the parameter is not provided, then the default is the first terminal)

Alternatively, for more fine-grained control and use in mappings, in lua:

localtrim_spaces=truevim.keymap.set("v", "<space>s", function()
require("toggleterm").send_lines_to_terminal("single_line", trim_spaces, { args=vim.v.count })
end)
-- Replace with these for the other two options-- require("toggleterm").send_lines_to_terminal("visual_lines", trim_spaces, { args = vim.v.count })-- require("toggleterm").send_lines_to_terminal("visual_selection", trim_spaces, { args = vim.v.count })-- For use as an operator map:-- Send motion to terminalvim.keymap.set("n", [[<leader><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("g@", "n", false)
end)
-- Double the command to send line to terminalvim.keymap.set("n", [[<leader><c-\><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("g@_", "n", false)
end)
-- Send whole filevim.keymap.set("n", [[<leader><leader><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("ggg@G''", "n", false)
end)

Set trim_spaces=false for sending to REPLs for whitespace-sensitive languages like python. (For python, you probably want to start ipython with ipython --no-autoindent.)

Example:

send_lines_example.mov

ToggleTermSetName

This function allows setting a display name for a terminal. This name is primarily used inside the winbar, and can be a more descriptive way to remember, which terminal is for what.

You can map this to a key and call it with a count, which will then prompt you a name for the terminal with the matching ID. Alternatively you can call it with just the name e.g. :ToggleTermSetName work<CR> this will the prompt you for which terminal it should apply to. Lastly you can call it without any arguments, and it will prompt you for which terminal it should apply to then prompt you for the name to use.

Set terminal shading

This plugin automatically shades terminal filetypes to be darker than other window you can disable this by setting shade_terminals = false in the setup object

require'toggleterm'.setup {
shade_terminals=false
}

alternatively you can set, which filetypes should be shaded by setting

-- fzf is just an examplerequire'toggleterm'.setup {
shade_filetypes= { "none", "fzf" }
}

setting "none" will allow normal terminal buffers to be highlighted.

Set persistent size

By default, this plugin will persist the size of horizontal and vertical terminals. Split terminals in the same direction always have the same size. You can disable this behaviour by setting persist_size = false in the setup object. Disabling this behaviour forces the opening terminal size to the size defined in the setup object.

require'toggleterm'.setup{
persist_size=false
}

Terminal window mappings

It can be helpful to add mappings to make moving in and out of a terminal easier once toggled, whilst still keeping it open.

function_G.set_terminal_keymaps()
localopts= {buffer=0}
vim.keymap.set('t', '<esc>', [[<C-\><C-n>]], opts)
vim.keymap.set('t', 'jk', [[<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)
vim.keymap.set('t', '<C-w>', [[<C-\><C-n><C-w>]], opts)
end-- if you only want these mappings for toggle term use term://*toggleterm#* insteadvim.cmd('autocmd! TermOpen term://* lua set_terminal_keymaps()')

Custom Terminals

lazy gitusing lazygit

Toggleterm also exposes the Terminal class so that this can be used to create custom terminals for showing terminal UIs like lazygit, htop etc.

Each terminal can take the following arguments:

Terminal:new {
cmd=string-- command to execute when creating the terminal e.g. 'top'display_name=string-- the name of the terminaldirection=string-- the layout for the terminal, same as the main config optionsdir=string-- the directory for the terminalclose_on_exit=bool-- close the terminal window when the process exitshighlights=table-- a table with highlightsenv=table-- key:value table with environmental variables passed to jobstart()clear_env=bool-- use only environmental variables from `env`, passed to jobstart()on_open=fun(t: Terminal) -- function to run when the terminal openson_close=fun(t: Terminal) -- function to run when the terminal closesauto_scroll=boolean-- automatically scroll to the bottom on terminal output-- callbacks for processing the outputon_stdout=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stdouton_stderr=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stderron_exit=fun(t: Terminal, job: number, exit_code: number, name: string) -- function to run when terminal process exits
}

If you want to spawn a custom terminal without running any command, you can omit the cmd option.

Custom terminal usage

localTerminal=require('toggleterm.terminal').Terminallocallazygit=Terminal:new({ cmd="lazygit", hidden=true })
function_lazygit_toggle()
lazygit:toggle()
endvim.api.nvim_set_keymap("n", "<leader>g", "<cmd>lua _lazygit_toggle()<CR>", {noremap=true, silent=true})

This will create a new terminal, but the specified command is not being run immediately. The command will run once the terminal is opened. Alternatively term:spawn() can be used to start the command in a background buffer without opening a terminal window yet. If the hidden key is set to true, this terminal will not be toggled by normal toggleterm commands such as :ToggleTerm or the open mapping. It will only open and close by using the returned terminal object. A mapping for toggling the terminal can be set as in the example above.

Alternatively the terminal can be specified with a count, which is the number that can be used to trigger this specific terminal. This can then be triggered using the current count e.g. :5ToggleTerm<CR>

locallazygit=Terminal:new({ cmd="lazygit", count=5 })

You can also set a custom layout for a terminal.

locallazygit=Terminal:new({
cmd="lazygit",
dir="git_dir",
direction="float",
float_opts= {
border="double",
},
-- function to run on opening the terminalon_open=function(term)
vim.cmd("startinsert!")
vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "<cmd>close<CR>", {noremap=true, silent=true})
end,
-- function to run on closing the terminalon_close=function(term)
vim.cmd("startinsert!")
end,
})
function_lazygit_toggle()
lazygit:toggle()
endvim.api.nvim_set_keymap("n", "<leader>g", "<cmd>lua _lazygit_toggle()<CR>", {noremap=true, silent=true})

WARNING: do not use any of the private functionality of the terminal or other non-public parts of the API as these can change in the future.

Statusline

To tell each terminal apart you can use the terminal buffer variable b:toggle_number in your statusline

" this is pseudo codeletstatusline.='%{&ft == "toggleterm" ? "terminal (".b:toggle_number.")" : ""}'

Custom commands

You can create your own commands by using the lua functions this plugin provides directly

command! -count=1 TermGitPush lua require'toggleterm'.exec("git push", <count>, 12)
command! -count=1 TermGitPushF lua require'toggleterm'.exec("git push -f", <count>, 12)

Open multiple terminals side-by-side

DirectionSupported
vertical✔️
horizontal✔️
tab✖️
float✖️

In your first terminal, you need to leave the TERMINAL mode using C-\C-N which can be remapped to Esc for ease of use. image

Then you type on: 2<C-\>, and the result: image

Explain:

  • 2: this is the terminal's number (or ID), your first terminal is 1 (e.g. your 3rd terminal will be 3<C-\>, so on).
  • C-\: this is the combined key mapping to the command :ToggleTerm.

FAQ

How do I get this plugin to work with Powershell?

Please check out the Wiki section on this topic.

About

A neovim lua plugin to help easily manage multiple terminal windows

Topics

Resources

Stars

5.6k stars

Watchers

21 watching

Forks

Sponsor this project

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

toggleterm.nvim

A neovim plugin to persist and toggle multiple terminals during an editing session

toggleterm in action

Multiple orientations

  • Float

floating window

  • Vertical

vertical-terms

  • Tab

tab orientation

Send commands to different terminals

exec

Winbar (Experimental/Nightly ONLY)

image

Requirements

This plugin only works in Neovim 0.7 or newer.

Installation

Using packer in lua

use {"akinsho/toggleterm.nvim", tag='*', config=function()
require("toggleterm").setup()
end}

Using lazy.nvim in lua

{
-- amongst your other plugins
{'akinsho/toggleterm.nvim', version="*", config=true}
-- or
{'akinsho/toggleterm.nvim', version="*", opts= {--[[ things you want to change go here]]}}
}

Using vim-plug in vimscript

Plug 'akinsho/toggleterm.nvim', {'tag' : '*'}
luarequire("toggleterm").setup()

You can/should specify a tag for the current major version of the plugin, to avoid breaking changes as this plugin evolves. To use a version of this plugin compatible with nvim versions less than 0.7 please use the tag v1.*.

Notices

  • 28/07/1990 — If using persist_mode terminal mappings should be changed to use wincmd instead otherwise persist mode will not work correctly. See here for details.

Why?

Neovim's terminal is a very cool, but not super ergonomic tool to use. I find that I often want to set a process going and leave it to continue to run in the background. I don't need to see it all the time. I just need to be able to refer back to it at intervals. I also sometimes want to create a new terminal and run a few commands.

Sometimes I want these side by side, and I really want these terminals to be easy to access. I also want my terminal to look different from non-terminal buffers, so I use winhighlight to darken them based on the Normal background colour.

This is the exact use case this was designed for. If that's your use case this might work for you.

Roadmap

All I really want this plugin to be is what I described above. A wrapper around the terminal functionality.

It basically (almost) does all that I need it to.

I won't be turning this into a REPL plugin or doing a bunch of complex stuff. If you find any issues, please consider a pull request not an issue. I'm also going to be pretty conservative about what I add.

Setup

This plugin must be explicitly enabled by using require("toggleterm").setup{}

Setting the open_mapping key to use for toggling the terminal(s) will set up mappings for normal mode. The open_mapping can be a key string or an array of key strings. If you prefix the mapping with a number that particular terminal will be opened. Otherwise if a prefix is not set, then the last toggled terminal will be opened. In case there are multiple terminals opened they'll all be closed, and on the next mapping key they'll be restored.

If you set the insert_mappings key to true, the mapping will also take effect in insert mode; similarly setting terminal_mappings to true will have the mappings take effect in the opened terminal.

However you will not be able to use a count with the open mapping in terminal and insert modes. You can create buffer specific mappings to exit terminal mode and then use a count with the open mapping. Check Terminal window mappings for an example of how to do this.

alternatively you can do this manually (not recommended but, your prerogative)

" setautocmd TermEnter term://*toggleterm#*\ tnoremap<silent><c-t><Cmd>exe v:count1 . "ToggleTerm"<CR>" By applying the mappings this way you can pass a count to your" mapping to open a specific window." For example: 2<C-t> will open terminal 2nnoremap<silent><c-t><Cmd>exe v:count1 . "ToggleTerm"<CR>inoremap<silent><c-t><Esc><Cmd>exe v:count1 . "ToggleTerm"<CR>

NOTE: Please ensure you have set hidden in your neovim config, otherwise the terminals will be discarded when closed.

WARNING: Please do not copy and paste this configuration! It is here to show what options are available. It is not written to be used as is.

require("toggleterm").setup{
-- size can be a number or function which is passed the current terminalsize=20 | function(term)
ifterm.direction=="horizontal" thenreturn15elseifterm.direction=="vertical" thenreturnvim.o.columns*0.4endend,
open_mapping=[[<c-\>]], -- or { [[<c-\>]], [[<c-¥>]] } if you also use a Japanese keyboard.on_create=fun(t: Terminal), -- function to run when the terminal is first createdon_open=fun(t: Terminal), -- function to run when the terminal openson_close=fun(t: Terminal), -- function to run when the terminal closeson_stdout=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stdouton_stderr=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stderron_exit=fun(t: Terminal, job: number, exit_code: number, name: string) -- function to run when terminal process exitshide_numbers=true, -- hide the number column in toggleterm buffersshade_filetypes= {},
autochdir=false, -- when neovim changes it current directory the terminal will change it's own when next it's openedhighlights= {
-- highlights which map to a highlight group name and a table of it's values-- NOTE: this is only a subset of values, any group placed here will be set for the terminal window splitNormal= {
guibg="<VALUE-HERE>",
},
NormalFloat= {
link='Normal'
},
FloatBorder= {
guifg="<VALUE-HERE>",
guibg="<VALUE-HERE>",
},
},
shade_terminals=true, -- NOTE: this option takes priority over highlights specified so if you specify Normal highlights you should set this to falseshading_factor='<number>', -- the percentage by which to lighten dark terminal background, default: -30shading_ratio='<number>', -- the ratio of shading factor for light/dark terminal background, default: -3start_in_insert=true,
insert_mappings=true, -- whether or not the open mapping applies in insert modeterminal_mappings=true, -- whether or not the open mapping applies in the opened terminalspersist_size=true,
persist_mode=true, -- if set to true (default) the previous terminal mode will be remembereddirection='vertical' | 'horizontal' | 'tab' | 'float',
close_on_exit=true, -- close the terminal window when the process exitsclear_env=false, -- use only environmental variables from `env`, passed to jobstart()-- Change the default shell. Can be a string or a function returning a stringshell=vim.o.shell,
auto_scroll=true, -- automatically scroll to the bottom on terminal output-- This field is only relevant if direction is set to 'float'float_opts= {
-- The border key is *almost* the same as 'nvim_open_win'-- see :h nvim_open_win for details on borders however-- the 'curved' border is a custom border type-- not natively supported but implemented in this plugin.border='single' | 'double' | 'shadow' | 'curved' | ...otheroptionssupportedbywinopen-- like `size`, width, height, row, and col can be a number or function which is passed the current terminalwidth=<value>,
height=<value>,
row=<value>,
col=<value>,
winblend=3,
zindex=<value>,
title_pos='left' | 'center' | 'right', positionofthetitleofthefloatingwindow
},
winbar= {
enabled=false,
name_formatter=function(term) -- term: Terminalreturnterm.nameend
},
responsiveness= {
-- breakpoint in terms of `vim.o.columns` at which terminals will start to stack on top of each other-- instead of next to each other-- default = 0 which means the feature is turned offhorizontal_breakpoint=135,
}
}

Usage

ToggleTerm

This is the command the mappings call under the hood. You can use it directly and prefix it with a count to target a specific terminal. This function also takes arguments size, dir, direction and name. e.g.

:ToggleTerm size=40dir=~/Desktop direction=horizontal name=desktop

If dir is specified on creation toggle term will open at the specified directory. If the terminal has already been opened at a particular directory it will remain in that directory.

The directory can also be specified as git_dir which toggleterm will then use to try and derive the git repo directory. NOTE: This will not work for git-worktrees or other more complex setups.

If size is specified, and the command opens a split (horizontal/vertical) terminal, the height/width of all terminals in the same direction will be changed to size.

If direction is specified, and the command opens a terminal, the terminal will be changed to the specified direction.

If name is specified, the display name is set for the toggled terminal. This name will be visible when using TermSelect command to indicate the specific terminal.

size and direction are ignored if the command closes a terminal.

Caveats

  • Having multiple terminals with different directions open at the same time is unsupported.

ToggleTermToggleAll

This command allows you to open all the previously toggled terminal in one go or close all the open terminals at once.

TermExec

This command allows you to open a terminal with a specific action. e.g. 2TermExec cmd="git status" dir=~/<my-repo-path> will run git status in terminal 2. note that the cmd argument must be quoted.

NOTE: the dir argument can also be optionally quoted if it contains spaces.

The cmd and dir arguments can also expand the same special keywords as :h expand e.g. TermExec cmd="echo %" will be expanded to TermExec cmd="echo /file/example"

These special keywords can be escaped using the \ character, if you want to print character as is.

The size, direction and name arguments are like the size, direction and name arguments of ToggleTerm.

By default, focus is returned to the original window after executing the command (except for floating terminals). Use argument go_back=0 to disable this behaviour.

You can send commands to a terminal without opening its window by using the open=0 argument.

see :h expand() for more details

TermNew

This command allows you to open a new terminal at the next available count. It's helpful in combination with TermSelect (see below) to work with terminals without needing to remember numbers. The size, dir, direction and name arguments work the same as in ToggleTerm.

TermSelect

This command uses vim.ui.select to allow a user to select a terminal to open or to focus it if it's already open. This can be useful if you have a lot of terminals and want to open a specific one.

Sending lines to the terminal

You can "send lines" to the toggled terminals with the following commands:

  • :ToggleTermSendCurrentLine <T_ID>: sends the whole line where you are standing with your cursor
  • :ToggleTermSendVisualLines <T_ID>: sends all the (whole) lines in your visual selection
  • :ToggleTermSendVisualSelection <T_ID>: sends only the visually selected text (this can be a block of text or a selection in a single line)

(<T_ID is an optional terminal ID parameter, which defines where should we send the lines. If the parameter is not provided, then the default is the first terminal)

Alternatively, for more fine-grained control and use in mappings, in lua:

localtrim_spaces=truevim.keymap.set("v", "<space>s", function()
require("toggleterm").send_lines_to_terminal("single_line", trim_spaces, { args=vim.v.count })
end)
-- Replace with these for the other two options-- require("toggleterm").send_lines_to_terminal("visual_lines", trim_spaces, { args = vim.v.count })-- require("toggleterm").send_lines_to_terminal("visual_selection", trim_spaces, { args = vim.v.count })-- For use as an operator map:-- Send motion to terminalvim.keymap.set("n", [[<leader><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("g@", "n", false)
end)
-- Double the command to send line to terminalvim.keymap.set("n", [[<leader><c-\><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("g@_", "n", false)
end)
-- Send whole filevim.keymap.set("n", [[<leader><leader><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("ggg@G''", "n", false)
end)

Set trim_spaces=false for sending to REPLs for whitespace-sensitive languages like python. (For python, you probably want to start ipython with ipython --no-autoindent.)

Example:

send_lines_example.mov

ToggleTermSetName

This function allows setting a display name for a terminal. This name is primarily used inside the winbar, and can be a more descriptive way to remember, which terminal is for what.

You can map this to a key and call it with a count, which will then prompt you a name for the terminal with the matching ID. Alternatively you can call it with just the name e.g. :ToggleTermSetName work<CR> this will the prompt you for which terminal it should apply to. Lastly you can call it without any arguments, and it will prompt you for which terminal it should apply to then prompt you for the name to use.

Set terminal shading

This plugin automatically shades terminal filetypes to be darker than other window you can disable this by setting shade_terminals = false in the setup object

require'toggleterm'.setup {
shade_terminals=false
}

alternatively you can set, which filetypes should be shaded by setting

-- fzf is just an examplerequire'toggleterm'.setup {
shade_filetypes= { "none", "fzf" }
}

setting "none" will allow normal terminal buffers to be highlighted.

Set persistent size

By default, this plugin will persist the size of horizontal and vertical terminals. Split terminals in the same direction always have the same size. You can disable this behaviour by setting persist_size = false in the setup object. Disabling this behaviour forces the opening terminal size to the size defined in the setup object.

require'toggleterm'.setup{
persist_size=false
}

Terminal window mappings

It can be helpful to add mappings to make moving in and out of a terminal easier once toggled, whilst still keeping it open.

function_G.set_terminal_keymaps()
localopts= {buffer=0}
vim.keymap.set('t', '<esc>', [[<C-\><C-n>]], opts)
vim.keymap.set('t', 'jk', [[<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)
vim.keymap.set('t', '<C-w>', [[<C-\><C-n><C-w>]], opts)
end-- if you only want these mappings for toggle term use term://*toggleterm#* insteadvim.cmd('autocmd! TermOpen term://* lua set_terminal_keymaps()')

Custom Terminals

lazy gitusing lazygit

Toggleterm also exposes the Terminal class so that this can be used to create custom terminals for showing terminal UIs like lazygit, htop etc.

Each terminal can take the following arguments:

Terminal:new {
cmd=string-- command to execute when creating the terminal e.g. 'top'display_name=string-- the name of the terminaldirection=string-- the layout for the terminal, same as the main config optionsdir=string-- the directory for the terminalclose_on_exit=bool-- close the terminal window when the process exitshighlights=table-- a table with highlightsenv=table-- key:value table with environmental variables passed to jobstart()clear_env=bool-- use only environmental variables from `env`, passed to jobstart()on_open=fun(t: Terminal) -- function to run when the terminal openson_close=fun(t: Terminal) -- function to run when the terminal closesauto_scroll=boolean-- automatically scroll to the bottom on terminal output-- callbacks for processing the outputon_stdout=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stdouton_stderr=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stderron_exit=fun(t: Terminal, job: number, exit_code: number, name: string) -- function to run when terminal process exits
}

If you want to spawn a custom terminal without running any command, you can omit the cmd option.

Custom terminal usage

localTerminal=require('toggleterm.terminal').Terminallocallazygit=Terminal:new({ cmd="lazygit", hidden=true })
function_lazygit_toggle()
lazygit:toggle()
endvim.api.nvim_set_keymap("n", "<leader>g", "<cmd>lua _lazygit_toggle()<CR>", {noremap=true, silent=true})

This will create a new terminal, but the specified command is not being run immediately. The command will run once the terminal is opened. Alternatively term:spawn() can be used to start the command in a background buffer without opening a terminal window yet. If the hidden key is set to true, this terminal will not be toggled by normal toggleterm commands such as :ToggleTerm or the open mapping. It will only open and close by using the returned terminal object. A mapping for toggling the terminal can be set as in the example above.

Alternatively the terminal can be specified with a count, which is the number that can be used to trigger this specific terminal. This can then be triggered using the current count e.g. :5ToggleTerm<CR>

locallazygit=Terminal:new({ cmd="lazygit", count=5 })

You can also set a custom layout for a terminal.

locallazygit=Terminal:new({
cmd="lazygit",
dir="git_dir",
direction="float",
float_opts= {
border="double",
},
-- function to run on opening the terminalon_open=function(term)
vim.cmd("startinsert!")
vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "<cmd>close<CR>", {noremap=true, silent=true})
end,
-- function to run on closing the terminalon_close=function(term)
vim.cmd("startinsert!")
end,
})
function_lazygit_toggle()
lazygit:toggle()
endvim.api.nvim_set_keymap("n", "<leader>g", "<cmd>lua _lazygit_toggle()<CR>", {noremap=true, silent=true})

WARNING: do not use any of the private functionality of the terminal or other non-public parts of the API as these can change in the future.

Statusline

To tell each terminal apart you can use the terminal buffer variable b:toggle_number in your statusline

" this is pseudo codeletstatusline.='%{&ft == "toggleterm" ? "terminal (".b:toggle_number.")" : ""}'

Custom commands

You can create your own commands by using the lua functions this plugin provides directly

command! -count=1 TermGitPush lua require'toggleterm'.exec("git push", <count>, 12)
command! -count=1 TermGitPushF lua require'toggleterm'.exec("git push -f", <count>, 12)

Open multiple terminals side-by-side

DirectionSupported
vertical✔️
horizontal✔️
tab✖️
float✖️

In your first terminal, you need to leave the TERMINAL mode using C-\C-N which can be remapped to Esc for ease of use. image

Then you type on: 2<C-\>, and the result: image

Explain:

  • 2: this is the terminal's number (or ID), your first terminal is 1 (e.g. your 3rd terminal will be 3<C-\>, so on).
  • C-\: this is the combined key mapping to the command :ToggleTerm.

FAQ

How do I get this plugin to work with Powershell?

Please check out the Wiki section on this topic.

About

A neovim lua plugin to help easily manage multiple terminal windows

Topics

Resources

Stars

5.6k stars

Watchers

21 watching

Forks

Sponsor this project

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

toggleterm.nvim

A neovim plugin to persist and toggle multiple terminals during an editing session

toggleterm in action

Multiple orientations

  • Float

floating window

  • Vertical

vertical-terms

  • Tab

tab orientation

Send commands to different terminals

exec

Winbar (Experimental/Nightly ONLY)

image

Requirements

This plugin only works in Neovim 0.7 or newer.

Installation

Using packer in lua

use {"akinsho/toggleterm.nvim", tag='*', config=function()
require("toggleterm").setup()
end}

Using lazy.nvim in lua

{
-- amongst your other plugins
{'akinsho/toggleterm.nvim', version="*", config=true}
-- or
{'akinsho/toggleterm.nvim', version="*", opts= {--[[ things you want to change go here]]}}
}

Using vim-plug in vimscript

Plug 'akinsho/toggleterm.nvim', {'tag' : '*'}
luarequire("toggleterm").setup()

You can/should specify a tag for the current major version of the plugin, to avoid breaking changes as this plugin evolves. To use a version of this plugin compatible with nvim versions less than 0.7 please use the tag v1.*.

Notices

  • 28/07/1990 — If using persist_mode terminal mappings should be changed to use wincmd instead otherwise persist mode will not work correctly. See here for details.

Why?

Neovim's terminal is a very cool, but not super ergonomic tool to use. I find that I often want to set a process going and leave it to continue to run in the background. I don't need to see it all the time. I just need to be able to refer back to it at intervals. I also sometimes want to create a new terminal and run a few commands.

Sometimes I want these side by side, and I really want these terminals to be easy to access. I also want my terminal to look different from non-terminal buffers, so I use winhighlight to darken them based on the Normal background colour.

This is the exact use case this was designed for. If that's your use case this might work for you.

Roadmap

All I really want this plugin to be is what I described above. A wrapper around the terminal functionality.

It basically (almost) does all that I need it to.

I won't be turning this into a REPL plugin or doing a bunch of complex stuff. If you find any issues, please consider a pull request not an issue. I'm also going to be pretty conservative about what I add.

Setup

This plugin must be explicitly enabled by using require("toggleterm").setup{}

Setting the open_mapping key to use for toggling the terminal(s) will set up mappings for normal mode. The open_mapping can be a key string or an array of key strings. If you prefix the mapping with a number that particular terminal will be opened. Otherwise if a prefix is not set, then the last toggled terminal will be opened. In case there are multiple terminals opened they'll all be closed, and on the next mapping key they'll be restored.

If you set the insert_mappings key to true, the mapping will also take effect in insert mode; similarly setting terminal_mappings to true will have the mappings take effect in the opened terminal.

However you will not be able to use a count with the open mapping in terminal and insert modes. You can create buffer specific mappings to exit terminal mode and then use a count with the open mapping. Check Terminal window mappings for an example of how to do this.

alternatively you can do this manually (not recommended but, your prerogative)

" setautocmd TermEnter term://*toggleterm#*\ tnoremap<silent><c-t><Cmd>exe v:count1 . "ToggleTerm"<CR>" By applying the mappings this way you can pass a count to your" mapping to open a specific window." For example: 2<C-t> will open terminal 2nnoremap<silent><c-t><Cmd>exe v:count1 . "ToggleTerm"<CR>inoremap<silent><c-t><Esc><Cmd>exe v:count1 . "ToggleTerm"<CR>

NOTE: Please ensure you have set hidden in your neovim config, otherwise the terminals will be discarded when closed.

WARNING: Please do not copy and paste this configuration! It is here to show what options are available. It is not written to be used as is.

require("toggleterm").setup{
-- size can be a number or function which is passed the current terminalsize=20 | function(term)
ifterm.direction=="horizontal" thenreturn15elseifterm.direction=="vertical" thenreturnvim.o.columns*0.4endend,
open_mapping=[[<c-\>]], -- or { [[<c-\>]], [[<c-¥>]] } if you also use a Japanese keyboard.on_create=fun(t: Terminal), -- function to run when the terminal is first createdon_open=fun(t: Terminal), -- function to run when the terminal openson_close=fun(t: Terminal), -- function to run when the terminal closeson_stdout=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stdouton_stderr=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stderron_exit=fun(t: Terminal, job: number, exit_code: number, name: string) -- function to run when terminal process exitshide_numbers=true, -- hide the number column in toggleterm buffersshade_filetypes= {},
autochdir=false, -- when neovim changes it current directory the terminal will change it's own when next it's openedhighlights= {
-- highlights which map to a highlight group name and a table of it's values-- NOTE: this is only a subset of values, any group placed here will be set for the terminal window splitNormal= {
guibg="<VALUE-HERE>",
},
NormalFloat= {
link='Normal'
},
FloatBorder= {
guifg="<VALUE-HERE>",
guibg="<VALUE-HERE>",
},
},
shade_terminals=true, -- NOTE: this option takes priority over highlights specified so if you specify Normal highlights you should set this to falseshading_factor='<number>', -- the percentage by which to lighten dark terminal background, default: -30shading_ratio='<number>', -- the ratio of shading factor for light/dark terminal background, default: -3start_in_insert=true,
insert_mappings=true, -- whether or not the open mapping applies in insert modeterminal_mappings=true, -- whether or not the open mapping applies in the opened terminalspersist_size=true,
persist_mode=true, -- if set to true (default) the previous terminal mode will be remembereddirection='vertical' | 'horizontal' | 'tab' | 'float',
close_on_exit=true, -- close the terminal window when the process exitsclear_env=false, -- use only environmental variables from `env`, passed to jobstart()-- Change the default shell. Can be a string or a function returning a stringshell=vim.o.shell,
auto_scroll=true, -- automatically scroll to the bottom on terminal output-- This field is only relevant if direction is set to 'float'float_opts= {
-- The border key is *almost* the same as 'nvim_open_win'-- see :h nvim_open_win for details on borders however-- the 'curved' border is a custom border type-- not natively supported but implemented in this plugin.border='single' | 'double' | 'shadow' | 'curved' | ...otheroptionssupportedbywinopen-- like `size`, width, height, row, and col can be a number or function which is passed the current terminalwidth=<value>,
height=<value>,
row=<value>,
col=<value>,
winblend=3,
zindex=<value>,
title_pos='left' | 'center' | 'right', positionofthetitleofthefloatingwindow
},
winbar= {
enabled=false,
name_formatter=function(term) -- term: Terminalreturnterm.nameend
},
responsiveness= {
-- breakpoint in terms of `vim.o.columns` at which terminals will start to stack on top of each other-- instead of next to each other-- default = 0 which means the feature is turned offhorizontal_breakpoint=135,
}
}

Usage

ToggleTerm

This is the command the mappings call under the hood. You can use it directly and prefix it with a count to target a specific terminal. This function also takes arguments size, dir, direction and name. e.g.

:ToggleTerm size=40dir=~/Desktop direction=horizontal name=desktop

If dir is specified on creation toggle term will open at the specified directory. If the terminal has already been opened at a particular directory it will remain in that directory.

The directory can also be specified as git_dir which toggleterm will then use to try and derive the git repo directory. NOTE: This will not work for git-worktrees or other more complex setups.

If size is specified, and the command opens a split (horizontal/vertical) terminal, the height/width of all terminals in the same direction will be changed to size.

If direction is specified, and the command opens a terminal, the terminal will be changed to the specified direction.

If name is specified, the display name is set for the toggled terminal. This name will be visible when using TermSelect command to indicate the specific terminal.

size and direction are ignored if the command closes a terminal.

Caveats

  • Having multiple terminals with different directions open at the same time is unsupported.

ToggleTermToggleAll

This command allows you to open all the previously toggled terminal in one go or close all the open terminals at once.

TermExec

This command allows you to open a terminal with a specific action. e.g. 2TermExec cmd="git status" dir=~/<my-repo-path> will run git status in terminal 2. note that the cmd argument must be quoted.

NOTE: the dir argument can also be optionally quoted if it contains spaces.

The cmd and dir arguments can also expand the same special keywords as :h expand e.g. TermExec cmd="echo %" will be expanded to TermExec cmd="echo /file/example"

These special keywords can be escaped using the \ character, if you want to print character as is.

The size, direction and name arguments are like the size, direction and name arguments of ToggleTerm.

By default, focus is returned to the original window after executing the command (except for floating terminals). Use argument go_back=0 to disable this behaviour.

You can send commands to a terminal without opening its window by using the open=0 argument.

see :h expand() for more details

TermNew

This command allows you to open a new terminal at the next available count. It's helpful in combination with TermSelect (see below) to work with terminals without needing to remember numbers. The size, dir, direction and name arguments work the same as in ToggleTerm.

TermSelect

This command uses vim.ui.select to allow a user to select a terminal to open or to focus it if it's already open. This can be useful if you have a lot of terminals and want to open a specific one.

Sending lines to the terminal

You can "send lines" to the toggled terminals with the following commands:

  • :ToggleTermSendCurrentLine <T_ID>: sends the whole line where you are standing with your cursor
  • :ToggleTermSendVisualLines <T_ID>: sends all the (whole) lines in your visual selection
  • :ToggleTermSendVisualSelection <T_ID>: sends only the visually selected text (this can be a block of text or a selection in a single line)

(<T_ID is an optional terminal ID parameter, which defines where should we send the lines. If the parameter is not provided, then the default is the first terminal)

Alternatively, for more fine-grained control and use in mappings, in lua:

localtrim_spaces=truevim.keymap.set("v", "<space>s", function()
require("toggleterm").send_lines_to_terminal("single_line", trim_spaces, { args=vim.v.count })
end)
-- Replace with these for the other two options-- require("toggleterm").send_lines_to_terminal("visual_lines", trim_spaces, { args = vim.v.count })-- require("toggleterm").send_lines_to_terminal("visual_selection", trim_spaces, { args = vim.v.count })-- For use as an operator map:-- Send motion to terminalvim.keymap.set("n", [[<leader><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("g@", "n", false)
end)
-- Double the command to send line to terminalvim.keymap.set("n", [[<leader><c-\><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("g@_", "n", false)
end)
-- Send whole filevim.keymap.set("n", [[<leader><leader><c-\>]], function()
set_opfunc(function(motion_type)
require("toggleterm").send_lines_to_terminal(motion_type, false, { args=vim.v.count })
end)
vim.api.nvim_feedkeys("ggg@G''", "n", false)
end)

Set trim_spaces=false for sending to REPLs for whitespace-sensitive languages like python. (For python, you probably want to start ipython with ipython --no-autoindent.)

Example:

send_lines_example.mov

ToggleTermSetName

This function allows setting a display name for a terminal. This name is primarily used inside the winbar, and can be a more descriptive way to remember, which terminal is for what.

You can map this to a key and call it with a count, which will then prompt you a name for the terminal with the matching ID. Alternatively you can call it with just the name e.g. :ToggleTermSetName work<CR> this will the prompt you for which terminal it should apply to. Lastly you can call it without any arguments, and it will prompt you for which terminal it should apply to then prompt you for the name to use.

Set terminal shading

This plugin automatically shades terminal filetypes to be darker than other window you can disable this by setting shade_terminals = false in the setup object

require'toggleterm'.setup {
shade_terminals=false
}

alternatively you can set, which filetypes should be shaded by setting

-- fzf is just an examplerequire'toggleterm'.setup {
shade_filetypes= { "none", "fzf" }
}

setting "none" will allow normal terminal buffers to be highlighted.

Set persistent size

By default, this plugin will persist the size of horizontal and vertical terminals. Split terminals in the same direction always have the same size. You can disable this behaviour by setting persist_size = false in the setup object. Disabling this behaviour forces the opening terminal size to the size defined in the setup object.

require'toggleterm'.setup{
persist_size=false
}

Terminal window mappings

It can be helpful to add mappings to make moving in and out of a terminal easier once toggled, whilst still keeping it open.

function_G.set_terminal_keymaps()
localopts= {buffer=0}
vim.keymap.set('t', '<esc>', [[<C-\><C-n>]], opts)
vim.keymap.set('t', 'jk', [[<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)
vim.keymap.set('t', '<C-w>', [[<C-\><C-n><C-w>]], opts)
end-- if you only want these mappings for toggle term use term://*toggleterm#* insteadvim.cmd('autocmd! TermOpen term://* lua set_terminal_keymaps()')

Custom Terminals

lazy gitusing lazygit

Toggleterm also exposes the Terminal class so that this can be used to create custom terminals for showing terminal UIs like lazygit, htop etc.

Each terminal can take the following arguments:

Terminal:new {
cmd=string-- command to execute when creating the terminal e.g. 'top'display_name=string-- the name of the terminaldirection=string-- the layout for the terminal, same as the main config optionsdir=string-- the directory for the terminalclose_on_exit=bool-- close the terminal window when the process exitshighlights=table-- a table with highlightsenv=table-- key:value table with environmental variables passed to jobstart()clear_env=bool-- use only environmental variables from `env`, passed to jobstart()on_open=fun(t: Terminal) -- function to run when the terminal openson_close=fun(t: Terminal) -- function to run when the terminal closesauto_scroll=boolean-- automatically scroll to the bottom on terminal output-- callbacks for processing the outputon_stdout=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stdouton_stderr=fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stderron_exit=fun(t: Terminal, job: number, exit_code: number, name: string) -- function to run when terminal process exits
}

If you want to spawn a custom terminal without running any command, you can omit the cmd option.

Custom terminal usage

localTerminal=require('toggleterm.terminal').Terminallocallazygit=Terminal:new({ cmd="lazygit", hidden=true })
function_lazygit_toggle()
lazygit:toggle()
endvim.api.nvim_set_keymap("n", "<leader>g", "<cmd>lua _lazygit_toggle()<CR>", {noremap=true, silent=true})

This will create a new terminal, but the specified command is not being run immediately. The command will run once the terminal is opened. Alternatively term:spawn() can be used to start the command in a background buffer without opening a terminal window yet. If the hidden key is set to true, this terminal will not be toggled by normal toggleterm commands such as :ToggleTerm or the open mapping. It will only open and close by using the returned terminal object. A mapping for toggling the terminal can be set as in the example above.

Alternatively the terminal can be specified with a count, which is the number that can be used to trigger this specific terminal. This can then be triggered using the current count e.g. :5ToggleTerm<CR>

locallazygit=Terminal:new({ cmd="lazygit", count=5 })

You can also set a custom layout for a terminal.

locallazygit=Terminal:new({
cmd="lazygit",
dir="git_dir",
direction="float",
float_opts= {
border="double",
},
-- function to run on opening the terminalon_open=function(term)
vim.cmd("startinsert!")
vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "<cmd>close<CR>", {noremap=true, silent=true})
end,
-- function to run on closing the terminalon_close=function(term)
vim.cmd("startinsert!")
end,
})
function_lazygit_toggle()
lazygit:toggle()
endvim.api.nvim_set_keymap("n", "<leader>g", "<cmd>lua _lazygit_toggle()<CR>", {noremap=true, silent=true})

WARNING: do not use any of the private functionality of the terminal or other non-public parts of the API as these can change in the future.

Statusline

To tell each terminal apart you can use the terminal buffer variable b:toggle_number in your statusline

" this is pseudo codeletstatusline.='%{&ft == "toggleterm" ? "terminal (".b:toggle_number.")" : ""}'

Custom commands

You can create your own commands by using the lua functions this plugin provides directly

command! -count=1 TermGitPush lua require'toggleterm'.exec("git push", <count>, 12)
command! -count=1 TermGitPushF lua require'toggleterm'.exec("git push -f", <count>, 12)

Open multiple terminals side-by-side

DirectionSupported
vertical✔️
horizontal✔️
tab✖️
float✖️

In your first terminal, you need to leave the TERMINAL mode using C-\C-N which can be remapped to Esc for ease of use. image

Then you type on: 2<C-\>, and the result: image

Explain:

  • 2: this is the terminal's number (or ID), your first terminal is 1 (e.g. your 3rd terminal will be 3<C-\>, so on).
  • C-\: this is the combined key mapping to the command :ToggleTerm.

FAQ

How do I get this plugin to work with Powershell?

Please check out the Wiki section on this topic.

About

A neovim lua plugin to help easily manage multiple terminal windows

Topics

Resources

Stars

5.6k stars

Watchers

21 watching

Forks

Sponsor this project

Contributors

Languages