Code Monkey home page Code Monkey logo

toggleterm.nvim's Introduction

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' : '*'}

lua require("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)

" set
autocmd 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 2
nnoremap <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 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 = [[<c-\>]], -- or { [[<c-\>]], [[<c-¥>]] } if you also use a Japanese keyboard.
  on_create = fun(t: Terminal), -- function to run when the terminal is first created
  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 = {},
  autochdir = false, -- when neovim changes it current directory the terminal will change it's own when next it's opened
  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 = "<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 false
  shading_factor = '<number>', -- the percentage by which to lighten terminal background, default: -30 (gets multiplied by -3 if background is 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
   -- Change the default shell. Can be a string or a function returning a string
  shell = 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' | ... other options supported by win open
    -- like `size`, width, height, row, and col can be a number or function which is passed the current terminal
    width = <value>,
    height = <value>,
    row = <value>,
    col = <value>,
    winblend = 3,
    zindex = <value>,
    title_pos = 'left' | 'center' | 'right', position of the title of the floating window
  },
  winbar = {
    enabled = false,
    name_formatter = function(term) --  term: Terminal
      return term.name
    end
  },
}

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=40 dir=~/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

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:

local trim_spaces = true
vim.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 terminal
vim.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 terminal
vim.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 file
vim.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 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.

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()
  local opts = {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#* instead
vim.cmd('autocmd! TermOpen term://* lua set_terminal_keymaps()')

Custom Terminals

lazy git using 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 terminal
  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
  auto_scroll = boolean -- automatically scroll to the bottom on terminal output
  -- 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
}

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

Custom terminal usage

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", "<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>

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

You can also set a custom layout for a terminal.

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", "<cmd>close<CR>", {noremap = true, silent = true})
  end,
  -- function to run on closing the terminal
  on_close = function(term)
    vim.cmd("startinsert!")
  end,
})

function _lazygit_toggle()
  lazygit:toggle()
end

vim.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 code
let statusline .= '%{&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

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

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.

toggleterm.nvim's People

Contributors

5c077m4n avatar akinsho avatar asmodeus812 avatar aspeddro avatar bluedrink9 avatar daxtorim avatar genesistms avatar github-actions[bot] avatar hat0uma avatar jedrzejboczar avatar l-kershaw avatar morgsmccauley avatar n3wborn avatar penryu avatar pipoprods avatar raffaem avatar ramojus avatar romgrk avatar samclercky avatar stevanmilic avatar tornaxo7 avatar towry avatar tristone13th avatar ttytm avatar uyha avatar verf avatar willothy avatar xiyaowong avatar yuanyuyuan avatar zeertzjq avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

toggleterm.nvim's Issues

Track whether in insert mode or not during toggle

Hi, thanks for making this plugin! It is awesome!

I like the start_in_insert = true feature a lot. However, sometimes (for example, when I am looking at output of a lot of tests), I use C-\ C-n to exit insert mode and scroll up, and toggle to get to the test file in question. However, if I want to refer to the test output again, now when I toggle back to the terminal it enters insert mode and goes back to the terminal input and I have to scroll back again.

It would be nice if the plugin can track whether the user is in insert mode or not and choose not to enter insert mode if a user has C-\ C-n in the terminal.

One way I think this could be achieved is by using autocommands that work only in the terminal. Thoughts?

Question: How to toggle view with all the terminals?

Thanks for the great plugin.
I have a question is there a way to have a command that toggles view with all the terminals that were created?
For example:
I created terminal with CTRl-\ than I created another terminal with a :ToggleTerm 2
which leads to this view

Screenshot_2021-06-04_12-44-39

Than I want to hide all terminals (:ToggleTerm all alike) and continue to work on editing files and after some time to toggle it again and have same view as before - 2 terminals bellow editing window (cause now CTRL -\ will only toggle one of the terminals, not all of them).
This behaviour is similar to tmux prefix-z command which toggles maximize one pane. Or something like toggle terminal in heavy IDE-s like vscode, idea etc.

Add an explicit "install" section?

I'm pretty new to use using vim/neovim and still finding my way around installing plugins/editing my config.

It seems like there's no consistent naming scheme for neovim/vim plugins, so I had to try a couple plugin names before the plugin installed successfully.

Suggestion:
add an install section with directions like

if you're using Packer as your plugin manager install this plugin using:

        use "akinsho/nvim-toggleterm.lua"

I'd be happy to contribute a PR if this is something worthwhile.

Buffer deletion causes error

If you call :bdelete! on a toggleterm buffer, you will have Failed to close window: win id - does not exist error.

Add option to hide numbers

Locally I've removed the display of numbers from the terminal buffer since I don't think terminal's need that. The actually aren't visible in vim 8+'s terminal. I thought it might add this as a configurable option so other users can have it. I'll implement this in the coming weeks but if anyone has an opinion of why it shouldn't be the default please post here

Open mappings only in normal mode?

Is there a way to toggle the terminal only when in normal mode, using the provided open_mapping settings? Or can this only be done using the manual way? I'm new to neovim (and lua), so apologies in advance if this is a dumb question.

This is what I'd like:

In normal mode ` will toggle a terminal and in insert I'd have it mapped to Ctrl + ` .

PS:I tried a different mapping as an experimentation, but I couldn't get it to work. It was: <leader> o t and I used [[<leader>ot]] as the value of open_mappings. Am I formatting it wrong?

Open mapping opens a second window

Config:

require'toggleterm'.setup{
  size = 20,
  open_mapping = [[<c-space>]],
  shade_filetypes = {},
  shade_terminals = true,
  -- shading_factor = '<number>' -- the degree by which to darken to terminal colour, default: 1 for dark backgrounds, 3 for light
  start_in_insert = true,
  persist_size = true,
  -- direction = 'vertical' | 'horizontal',
}

After first mapping:
Screenshot from 2021-05-10 08-09-17

After second mapping:
Screenshot from 2021-05-10 08-09-22

Can't remember what was the previous time I updated but this started happening just after I updated just now.

Integration with Terminal File Managers

Question

How could one go on about integrating this plugin with programs such as joshuto, nnn, lf, and ranger?

Acknowledgments

I know that this is already somewhat possible as you can open a terminal that runs the program on startup and then just open the file from there, however, I have found that this does not work.

What is expected is that when you open a file with your terminal file manager, it opens a new buffer with the selected file, however, what actually happens is that the terminal uses a new instance of neovim within itself and edits the file there.

Example:

Reality

Goal

Create a template that can be used to easily integrate terminal file managers with neovim using this plugin.

Question: Change direction dynamically?

Is there a way for me to toggle a terminal, and then want to toggle another terminal, but in a different direction/orientation? It looks like right now, the direction is just hard-coded into the setup.

Allow the user to customize terminal size

Currently, the terminal size is hardcoded in plugin/toggleterm.vim and plugin/toggleterm.vim to 12 rows in the call to exec().

A variable like g:toggleterm_size could easily be created and allow the user to set their preference by feeding it to toggleterm.exec

Something similar could be done to the split direction to allow vsplit, although it'd require a bit more work.

Sending current line number to terminal?

Is there a way to send the line number with TermExec? I know it's available to vim via line('.'), but that doesn't appear to be one of the things that the expand command expands.

Context: I'm trying to use the :TermExec command to execute ruby specs. To run all the specs in a file, I have this key binding:

vim.api.nvim_set_keymap('n', '<Leader>q', "<cmd>1TermExec cmd='bundle exec rspec %'<CR>", {})

That works great for executing entire files of specs. But Rspec has a feature that allows executing only the spec on a single line. To do this, I can append the line to the end of the filename, like so: rspec my_spec.rb:23. Based on the expand documentation, I thought that the following might work, but I guess my spec buffers aren't sourced script files: nvim says no line number to use for "<sflnum>".

vim.api.nvim_set_keymap('n', '<Leader>q', "<cmd>1TermExec cmd='bundle exec rspec %:<sflnum>'<CR>", {})

Add vim help documentation

It'll be really helpful to have the help documentation (help-tags? Don't know how is it call) for Neovim. Right now I've to come to github and search if what i've want to do is possible. (awesome plugin by the way!)

I could help if you need a hand!

Error on Terminal Toggle

I keep getting this error when I toggle the terminal:

Screen Shot 2021-04-16 at 9 13 59 AM

Here is my mapping in my init.vim:

Screen Shot 2021-04-16 at 9 14 39 AM

Please let me know if I am doing something wrong. Thanks!

Error starting terminal OutOfProcessMediatorBasse

I'm using neovim (v0.5.0) on windows.
My shell is set to pwsh.exe. Starting a default terminal (so not using the plugin) works via the command :terminal

When using the plugin I get a quick error message before the terminal is closed:

at System.Management.Automation.Remoting.OutOfProcessUtils.ProcessData(String data, DataProcessingDeleegates callback)
at System.Management.Automation.Remoting.Server.OutOfProcessMediatorBase.ProcessingThreadStart(Object state)

I didn't change the default config a lot:

require("toggleterm").setup{
  function(term)
    if term.direction == "horizontal" then
      return 15
    elseif term.direction == "vertical" then
      return vim.o.columns * 0.4
    end
  end,
  open_mapping = [[<Leader>t]],
  hide_numbers = true, 
  shade_filetypes = {},
  shade_terminals = true,
  shading_factor = '1', 
  start_in_insert = true,
  insert_mappings = true, 
  persist_size = true,
  direction = 'float', 
  close_on_exit = true, 
  shell = "pwsh.exe", 
  float_opts = {
    border = 'single', 
    width = 80,
    height = 100,
    winblend = 3,
    highlights = {
      border = "Normal",
      background = "Normal",
    }
  }
}

Terminal opening blocking on ToggleTerm

In my experience so far, the :ToggleTerm command is really very slow.
It takes about 3-4 seconds to spawn the terminal in a split.
I believe making the process asynchronous would help a bit.

Failed to close window

When I toggle the terminal I get this error message:

Failed to close window: win id - does not exist

my config:

require("toggleterm").setup {
size = 20,
open_mapping = [[]],
hide_numbers = true,
shade_filetypes = {},
shade_terminals = true,
shading_factor = 1,
start_in_insert = true,
insert_mappings = true,
persist_size = true,
direction = "horizontal",
close_on_exit = true,
shell = vim.o.shell,
float_opts = {
border = "single",
winblend = 3,
highlights = {
border = "Normal",
background = "Normal",
},
},
}

Couldn't find a terminal to close after using custom terminal

Thanks for the fantastic extension, I assume this is a bug.

  1. ToggleTerm to make a new terminal
  2. Enter normal mode (jk on my setup)
  3. Open custom terminal (lazygit)
  4. press q to quit lazygit custom terminal
  5. Now you are back in the original terminal, ToggleTerm = "Couldn't find a terminal to close" error, the terminal must be exited manually with exit

in init.vim

" toggle terminal
nnoremap <silent><leader>t :ToggleTerm<CR>

lua <<EOF
require("toggleterm").setup{ size = 80, direction = 'vertical' }
local Terminal  = require('toggleterm.terminal').Terminal
local lazygit = Terminal:new({ cmd = "lazygit", hidden = true, direction = "float" })
function _lazygit_toggle()
  lazygit:toggle()
end

vim.api.nvim_set_keymap("n", "<leader>g", "<cmd>lua _lazygit_toggle()<CR>", {noremap = true, silent = true})
EOF

I tried your other lazygit setup, and got the same results, apart from the terminal needed confirmation to close. Is this needed for lazygit to work well?:

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", "<cmd>close<CR>", {noremap = true, silent = true})
  end,
  -- function to run on closing the terminal
  on_close = function(term)
    vim.cmd("Closing terminal")
  end,
})

I don't really understand how Lua works, so please forgive any obvious mistake I have made. I am happy to just have one terminal toggling and lazygit in a floating window, would be perfect :)

Cursor look in insert mode

The cursor still looks like a block when in the terminal in insert mode and it can be a bit confusing.

Is this intended or is there a way to have the default behaviour?

ToggleTerm + Bufferline

Firstly, thank you very much @akinsho and team for these great NeoVim plugins!!!
I really appreciate it

This regards toggleTerm & bufferline

I can't find a more appropriate place to ask, but what would be the best way of making a terminal buffer that can appear in the buffer line but still be toggled?

:Terminal works well, but it's not a ToggleTerm, thus can't be hidden

:ToggleTerm direction=window works well, but doesn't appear in the bufferline

I'm not sure how best to approach this, thanks in advance for the help!

toggle back to nvim

How to toggle back to the neovim editor from the float/vertical terminal. At the moment, I tried ctrl+w+ctrl+w, but it is not working? Any solutions?

Error on float term

First off, thanks for the great plugin!

I was excited to test the new float term functionality, but am getting an error. It's entirely possible I'm doing something wrong in my configuration. The documentation is not entirely clear.

I am setting direction = 'float', which by looking at the code seems to be the way to opt in, although in the read me documentation float was not presented as an option (although float_opts is). I set up float_opts with some values and get this error when invoking the terminal:

Screen Shot 2021-04-20 at 10 40 41 AM

I tried removing the border key, and removing float_opts entirely, but no dice.

Any help would be appreciated.

Thanks again!

Plugin uses leader key in insert mode and normal mode

let mapleader = "\<Space>"

" toggle line numbers                          < example, does not trigger in insert mode
nnoremap <silent><leader>n :set invnumber<CR>

lua <<EOF
require("toggleterm").setup{ size = 80, direction = 'vertical', open_mapping = [[<leader>t]] }
local Terminal  = require('toggleterm.terminal').Terminal
local lazygit = Terminal:new({ cmd = "lazygit", hidden = true, direction = "float" })

function _lazygit_toggle()
  lazygit:toggle()
end

vim.api.nvim_set_keymap("n", "<leader>g", "<cmd>lua _lazygit_toggle()<CR>", {noremap = true, silent = true})
EOF

When using space as the leader key now there is a delay after pressing every space in insert mode. The terminal can be toggled from insert mode, I assume this is an error as the leader key is expected to work from normal mode? I am not an expert in this, but that is how it works with all my other mappings.

With the above setup, whenever pressing space in insert mode Neovim acts as if there are potentially more keys in the sequence expected. It is like when you have jk as escape and press j then there is a delay while it waits to see if you press k.

I have installed the latest nightly (Linux appimage):

nvim --version
NVIM v0.5.0-dev+1358-g192ea01ed

Question :: (Re)-focus on open terminal window using it's count number

First of all, excellent plugin and thanks a million for putting effort in this (and other) plugins. I'm using nvim-toggleterm daily in my workflow with a few custom functions for my specific preferences.

One thing I haven't been able to figure out yet is how to navigate to a terminal window based on it's count number, regardless if the terminal window is already open (but not focused) or not opened (anymore).

  • If the terminal window hasn't been opened yet or if I have previously closed the terminal window (but left it running in the background), i'm fine using :toggle to open the terminal window (again). However, if I focus on a non-terminal window and use :toggle to refer to the specific terminal window to focus on, it closes the already open terminal window and errors out with Failed to close window: win id - [0-9]{1,4} does not exist (mind the in-place regex).

I can of course move to the terminal window using, for instance, 2wincmd w, or whatever number the window got assigned. It however requires me to look at the statusline to find out the window number to determine which one i'll have to move to, which obviously is less optimal than it could be ;-).

Is there a way to refocus on an already open terminal window by referring to it's number (set using count = [0-9]+) making use of an nvim-toggleterm function or similar ? This way I can hook a keymapping to it, preferably the same keymapping I already use to toggle it so I can keep using one keymapping per function.

For convenience, the nvim-toggleterm snippet i'm using with NVIM v0.5.0-dev+61aefaf29 on MacOS here below:

nvim-toggleterm Lua
require('toggleterm').setup {
  close_on_exit = true,
  float_opts = {
    border = 'curved'
  },
  persist_size = false
}

local terminal_default_float = require('toggleterm.terminal').Terminal:new({
  count = 50,
  direction = 'float',
  on_open = function(term)
    vim.api.nvim_buf_set_keymap(term.bufnr, 'n', 'q', '<cmd>close<cr>', { noremap = true, silent = true })
    vim.api.nvim_buf_set_keymap(term.bufnr, 't', '<c-k>', '<c-\\><c-n><cmd>close<cr><c-w><c-p>', { noremap = true })
    vim.wo.cursorcolumn = false
    vim.wo.cursorline = false
    vim.cmd('VimadeBufDisable')
    vim.cmd("startinsert!")
  end,
  on_close = function(term)
    vim.cmd("quit!")
  end
})

local terminal_horizontal_one = require('toggleterm.terminal').Terminal:new({
  count = 11,
  direction = 'horizontal',
  on_open = function(term)
    vim.api.nvim_buf_set_keymap(term.bufnr, 'n', 'q', '<cmd>close<cr>', { noremap = true, silent = true })
    vim.api.nvim_buf_set_keymap(term.bufnr, 't', '<c-b>', '<c-\\><c-n><cmd>close<cr><c-w><c-p>', { noremap = true, silent = true })
    vim.api.nvim_buf_set_keymap(term.bufnr, 't', '<c-k>', '<c-\\><c-n><c-w><c-p>', { noremap = true, silent = true })
    vim.wo.cursorcolumn = false
    vim.wo.cursorline = false
    vim.cmd('VimadeBufDisable')
    vim.cmd("startinsert!")
  end,
  on_close = function(term)
    vim.cmd("quit!")
  end
})

local terminal_horizontal_two = require('toggleterm.terminal').Terminal:new({
  count = 12,
  direction = 'horizontal',
  on_open = function(term)
    vim.api.nvim_buf_set_keymap(term.bufnr, 'n', 'q', '<cmd>close<cr>', { noremap = true, silent = true })
    vim.api.nvim_buf_set_keymap(term.bufnr, 't', '<c-b>', '<c-\\><c-n><cmd>close<cr><c-w><c-p>', { noremap = true, silent = true })
    vim.api.nvim_buf_set_keymap(term.bufnr, 't', '<c-k>', '<c-\\><c-n><c-w><c-p>', { noremap = true, silent = true })
    vim.wo.cursorcolumn = false
    vim.wo.cursorline = false
    vim.cmd('VimadeBufDisable')
    vim.cmd("startinsert!")
  end,
  on_close = function(term)
    vim.cmd("quit!")
  end
})

local terminal_horizontal_three = require('toggleterm.terminal').Terminal:new({
  count = 13,
  direction = 'horizontal',
  on_open = function(term)
    vim.api.nvim_buf_set_keymap(term.bufnr, 'n', 'q', '<cmd>close<cr>', { noremap = true, silent = true })
    vim.api.nvim_buf_set_keymap(term.bufnr, 't', '<c-b>', '<c-\\><c-n><cmd>close<cr><c-w><c-p>', { noremap = true, silent = true })
    vim.api.nvim_buf_set_keymap(term.bufnr, 't', '<c-k>', '<c-\\><c-n><c-w><c-p>', { noremap = true, silent = true })
    vim.wo.cursorcolumn = false
    vim.wo.cursorline = false
    vim.cmd('VimadeBufDisable')
    vim.cmd("startinsert!")
  end,
  on_close = function(term)
    vim.cmd("quit!")
  end
})

function _terminal_default_float_toggle()
  terminal_default_float:toggle()
end

function _terminal_horizontal_one_toggle()
  terminal_horizontal_one:toggle()
end

function _terminal_horizontal_two_toggle()
  terminal_horizontal_two:toggle()
end

function _terminal_horizontal_three_toggle()
  terminal_horizontal_three:toggle()
end

local terminal_tig = require('toggleterm.terminal').Terminal:new({
  cmd = 'tig',
  count = 60,
  direction = 'float',
  on_open = function(term)
    vim.api.nvim_buf_set_keymap(term.bufnr, 'n', 'q', '<cmd>close<cr>', { noremap = true, silent = true })
    vim.api.nvim_buf_set_keymap(term.bufnr, 't', '<c-k>', '<c-\\><c-n><cmd>close<cr><c-w><c-p>', { noremap = true })
    vim.wo.cursorcolumn = false
    vim.wo.cursorline = false
    vim.cmd('VimadeBufDisable')
    vim.cmd("startinsert!")
  end,
  on_close = function(term)
    vim.cmd("quit!")
  end
})

local terminal_lazygit = require('toggleterm.terminal').Terminal:new({
  cmd = 'lazygit',
  count = 61,
  direction = 'float',
  on_open = function(term)
    vim.api.nvim_buf_set_keymap(term.bufnr, 'n', 'q', '<cmd>close<cr>', { noremap = true, silent = true })
    vim.api.nvim_buf_set_keymap(term.bufnr, 't', '<c-k>', '<c-\\><c-n><cmd>close<cr><c-w><c-p>', { noremap = true })
    vim.wo.cursorcolumn = false
    vim.wo.cursorline = false
    vim.cmd('VimadeBufDisable')
    vim.cmd("startinsert!")
  end,
  on_close = function(term)
    vim.cmd("quit!")
  end
})

local terminal_k9s = require('toggleterm.terminal').Terminal:new({
  cmd = 'k9s',
  count = 62,
  direction = 'float',
  on_open = function(term)
    vim.api.nvim_buf_set_keymap(term.bufnr, 'n', 'q', '<cmd>close<cr>', { noremap = true, silent = true })
    vim.api.nvim_buf_set_keymap(term.bufnr, 't', '<c-k>', '<c-\\><c-n><cmd>close<cr><c-w><c-p>', { noremap = true })
    vim.wo.cursorcolumn = false
    vim.wo.cursorline = false
    vim.cmd('VimadeBufDisable')
    vim.cmd("startinsert!")
  end,
  on_close = function(term)
    vim.cmd("quit!")
  end
})

function _terminal_tig_toggle()
  terminal_tig:toggle()
end

function _terminal_lazygit_toggle()
  terminal_lazygit:toggle()
end

function _terminal_k9s_toggle()
  terminal_k9s:toggle()
end
Used keymapping references
lua _terminal_horizontal_one_toggle()
lua _terminal_horizontal_two_toggle()
lua _terminal_horizontal_three_toggle()
lua _terminal_default_float_toggle()
lua _terminal_k9s_toggle()
lua _terminal_lazygit_toggle()
lua _terminal_tig_toggle

why i can't work in the same termninal

i use the latest neovim and plugin,my config is below:

require"toggleterm".setup{
  size = 20,
  open_mapping = [[<c-A-\>]],
  shade_filetypes = {},
  shade_terminals = true,
  shading_factor = '<number>',
  start_in_insert = true,
  persist_size = true,
  direction = 'horizontal',
}

before i can use number and this keymap([c-a-]) use the same serial number term to run diffrent command in their respective term,but now it can't, every time it open a new term with clear info, then the command I ran is missing, it can't be reduced.
What can I do to achieve the previous effect?

Should delete buffer on process exit.

I made a custom floating buffer and if I close the shell by doing exit, the buffer is taken off focus but is still hidden. When I toggle the custom floating terminal again, it shows the last session with a [Process exited 0] at the end of terminal. The expected behaviour should be to delete buffer on process exit.

Multiple terminals

Hello, I have been trying without success to manage mapping keys to toggling multiple terminals. I can manage to open the terminal by using the open_mapping keymap but when I am already in an open terminal and in terminal mode, I cannot do 2<C-> to open another terminal because it just writes the letter 2 into the terminal and then just closes it.

Prevent Esc Switching to Normal Mode

When I use the plugin for a floating lazygit window I want to be able to press esc to cancel a commit, etc instead of being put in normal mode (not really useful in lazygit). I tried adding

    on_open = function(term)
        vim.api.nvim_buf_set_keymap(term.bufnr, 'i', '<Esc>', '<NOP>', {noremap = true, silent = true})
    end

but it doesn't seem to work. Any ideas?

Feature Idea: dynamic switch of direction for open terminal ?

In can be nice to be able to switch direction of already opened terminal.
E.g: if you launch a server in a terminal, you would want to have it in float or window direction most of the time, but when it's debug time, it's nice to have it in vertical or horizontal

Question: Is it possible to set different keybindings to toggle different layouts with specific purposes ?

Right now I'm using vim-floaterm to spawn a terminal with lazygit like this:

2021-Apr-26_1

And that's the only thing I use floaterm for. It's just to have a nice integration of git inside neovim. Then I use toggleterm to toggle a terminal easily in a more classical horizontal layout.

However I wonder if I can achieve what I do with floaterm with just using toggleterm, which has more options like also spawning windows in floating mode. But I haven't figured out how to set custom keybindings to specific layouts or terminals.

For example, to toggle the terminal I have <A-t> and for floaterm with the lazygit command I have <leader>gg , what I want to do is to set one specific keybind to toggle toggleterm in floating mode executing the lazygit command, and then my regular for the terminal in horizontal layout.

The problem I found is that the open_mappings option for toggling terminal is global, and it doesn't work for specific layouts with specific keybindings for those layouts. So if create a function to open toggleterm in floating mode and executing the lazygit command, then the toggle keybinding will only work for that specific terminal.

So the question is:

  • Can I set an specific keybinding for different layouts/terminals ?
  • If it's not possible, How difficult is it to implement ?

[Bug] horizontal term should close if it is the last window

E5108: Error executing lua ...ack/packer/opt/nvim-toggleterm.lua/lua/toggleterm/ui.lua:256: Vim:E444: Cannot close last window
This was thrown when I was trying to exit from a file buffer while a horizontal toggle term instance is opening
Expected behavior :wq on file buffer exit both file buffer and the horizontal toggle term.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.