# toggleterm.nvim **Repository Path**: yunduozhai/toggleterm.nvim ## Basic Information - **Project Name**: toggleterm.nvim - **Description**: A neovim lua plugin to help easily manage multiple terminal windows.fork from "akinsho/toggleterm.nvim" - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: bugfix/check-existence-float-hls - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-08-26 - **Last Updated**: 2024-08-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: nvim ## README

toggleterm.nvim

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

![screenshot](./github/toggleterm.gif "Toggleterm in action") ### Multiple orientations - **Float** ![floating window](https://user-images.githubusercontent.com/22454918/115306123-42d2ac00-a15f-11eb-84fc-c4246ee82a09.png) - **Vertical** ![vertical orientation](./github/vertical-terms.png) - **Tab** ![tab orientation](https://user-images.githubusercontent.com/22454918/133490969-6a59e623-79db-4ca7-a73b-ef4b24a73b91.gif) ### Send commands to different terminals ![exec](https://user-images.githubusercontent.com/22454918/112119367-36d1e980-8bb5-11eb-9787-5936391127a3.gif) ## Requirements This plugin only works in _Neovim 0.7_ or newer. ## Installation Using packer in lua ```lua use {"akinsho/toggleterm.nvim", tag = 'v1.*', config = function() require("toggleterm").setup() end} ``` Using vim-plug in vimscript ```vim Plug 'akinsho/toggleterm.nvim', tag = 'v1.*' ``` 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.*`. ## 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 setup mappings for _normal_ mode If you prefix the mapping with a number that particular terminal will be opened. If you set the `insert_mappings` key to true, the mapping will also take effect in insert mode; similarly setting `terminal_mappings` to 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) ```vim " set autocmd TermEnter term://*toggleterm#* \ tnoremap exe v:count1 . "ToggleTerm" " By applying the mappings this way you can pass a count to your " mapping to open a specific window. " For example: 2 will open terminal 2 nnoremap exe v:count1 . "ToggleTerm" inoremap exe v:count1 . "ToggleTerm" ``` **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 be used as is. ```lua require("toggleterm").setup{ -- size can be a number or function which is passed the current terminal size = 20 | function(term) if term.direction == "horizontal" then return 15 elseif term.direction == "vertical" then return vim.o.columns * 0.4 end end, open_mapping = [[]], on_open = fun(t: Terminal), -- function to run when the terminal opens on_close = fun(t: Terminal), -- function to run when the terminal closes on_stdout = fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stdout on_stderr = fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stderr on_exit = fun(t: Terminal, job: number, exit_code: number, name: string) -- function to run when terminal process exits hide_numbers = true, -- hide the number column in toggleterm buffers shade_filetypes = {}, highlights = { -- 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 split Normal = { guibg = "", }, NormalFloat = { link = 'Normal' }, FloatBorder = { guifg = "", guibg = "", }, }, shade_terminals = true, -- NOTE: this option takes priority over highlights specified so if you specify Normal highlights you should set this to false shading_factor = '', -- the degree by which to darken to terminal colour, default: 1 for dark backgrounds, 3 for light start_in_insert = true, insert_mappings = true, -- whether or not the open mapping applies in insert mode terminal_mappings = true, -- whether or not the open mapping applies in the opened terminals persist_size = true, persist_mode = true, -- if set to true (default) the previous terminal mode will be remembered direction = 'vertical' | 'horizontal' | 'tab' | 'float', close_on_exit = true, -- close the terminal window when the process exits shell = vim.o.shell, -- change the default shell -- 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' | ... other options supported by win open width = , height = , winblend = 3, } } ``` ### 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` and `direction`. e.g. ```vim :ToggleTerm size=40 dir=~/Desktop direction=horizontal ``` 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 currently 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. `size` and `direction` are ignored if the command closes a terminal. #### Caveats - Having multiple terminals with different directions open at the same time is currently unsupported. ### `ToggleTermToggleAll` This command allows you to open all the previously toggled terminal in one go or close all the currently open terminals at once. ### `TermExec` This command allows you to open a terminal with a specific action. e.g. `2TermExec cmd="git status" dir=~/` 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` and `direction` arguments are like the `size` and `direction` 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 ### Sending lines to the terminal You can "send lines" to the toggled terminals with the following commands: - `:ToggleTermSendCurrentLine `: sends the whole line where you are currently standing with your cursor - `:ToggleTermSendVisualLines `: sends all of the (whole) lines in your visual selection - `:ToggleTermSendVisualSelection `: sends only the visually selected text (this can be a block of text or a selection in a single line) (` Example: ### 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 ```lua require'toggleterm'.setup { shade_terminals = false } ``` alternatively you can set _which_ filetypes should be shaded by setting ```lua -- fzf is just an example require'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. ```lua 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. ```lua function _G.set_terminal_keymaps() local opts = {noremap = true} vim.api.nvim_buf_set_keymap(0, 't', '', [[]], opts) vim.api.nvim_buf_set_keymap(0, 't', 'jk', [[]], opts) vim.api.nvim_buf_set_keymap(0, 't', '', [[h]], opts) vim.api.nvim_buf_set_keymap(0, 't', '', [[j]], opts) vim.api.nvim_buf_set_keymap(0, 't', '', [[k]], opts) vim.api.nvim_buf_set_keymap(0, 't', '', [[l]], opts) end -- if you only want these mappings for toggle term use term://*toggleterm#* instead vim.cmd('autocmd! TermOpen term://* lua set_terminal_keymaps()') ``` ### Custom Terminals ![lazy git](https://user-images.githubusercontent.com/22454918/116447435-e69f1480-a84f-11eb-86dd-19fa29646aa1.png) _using [lazygit](https://github.com/jesseduffield/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: ```lua Terminal:new { cmd = string -- command to execute when creating the terminal e.g. 'top' direction = string -- the layout for the terminal, same as the main config options dir = string -- the directory for the terminal close_on_exit = bool -- close the terminal window when the process exits highlights = table -- a table with highlights env = 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 opens on_close = fun(t: Terminal) -- function to run when the terminal closes -- callbacks for processing the output on_stdout = fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stdout on_stderr = fun(t: Terminal, job: number, data: string[], name: string) -- callback for processing output on stderr on_exit = fun(t: Terminal, job: number, exit_code: number, name: string) -- function to run when terminal process exits } ``` #### Custom terminal usage ```lua local Terminal = require('toggleterm.terminal').Terminal local lazygit = Terminal:new({ cmd = "lazygit", hidden = true }) function _lazygit_toggle() lazygit:toggle() end vim.api.nvim_set_keymap("n", "g", "lua _lazygit_toggle()", {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` ```lua local lazygit = Terminal:new({ cmd = "lazygit", count = 5 }) ``` You can also set a custom layout for a terminal. ```lua local lazygit = Terminal:new({ cmd = "lazygit", dir = "git_dir", direction = "float", float_opts = { border = "double", }, -- function to run on opening the terminal on_open = function(term) vim.cmd("startinsert!") vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "close", {noremap = true, silent = true}) end, -- function to run on closing the terminal on_close = function(term) vim.cmd("Closing terminal") end, }) function _lazygit_toggle() lazygit:toggle() end vim.api.nvim_set_keymap("n", "g", "lua _lazygit_toggle()", {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 In order to tell each terminal apart you can use the terminal buffer variable `b:toggle_number` in your statusline ```vim " this is pseudo code let statusline .= '%{&ft == "toggleterm" ? "terminal (".b:toggle_number.")" : ""}' ``` ### Custom commands You can create your on commands by using the lua functions this plugin provides directly ```vim command! -count=1 TermGitPush lua require'toggleterm'.exec("git push", , 12) command! -count=1 TermGitPushF lua require'toggleterm'.exec("git push -f", , 12) ``` ### Open multiple terminals side-by-side | Direction | Supported | | ---------- | --------- | | 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](https://user-images.githubusercontent.com/31947091/133395516-22fef1e6-633d-4964-9175-f76fabf66794.png) Then you type on: `2`, and the result: ![image](https://user-images.githubusercontent.com/31947091/133396789-fdf68b30-3a8c-440b-822f-6549f282c4fc.png) Explain: - `2`: this is the terminal's number (or ID), your first terminal is `1` (e.g. your 3rd terminal will be `3`, so on). - C-\\: this is the combined key mapping to the command `:ToggleTerm`.