🦿 tabout.nvim
Supercharge your workflow and start tabbing out from parentheses, quotes, and similar contexts today.
💡 examples
Before | Key | After | Setting |
---|---|---|---|
{ | } |
<Tab> |
{} | |
- |
{ |"string" } |
<Tab> |
{ "string"| } |
ignore_beginning = true |
{ |"string" } |
<Tab> |
{ ....|"string"} |
ignore_beginning = false, act_as_tab = true, |
{ "string"| } |
<S-Tab> |
{ |"string" } |
- |
|#[macro_use] |
<Tab> |
#[macro_use]| |
tabouts = {{open = '#', close = ']'}} |
📦 requirements
- nvim >= 0.5
- nvim-treesitter
💾 installation
packer
-- Lua
use {
'abecodes/tabout.nvim',
config = function()
require('tabout').setup {
tabkey = '<Tab>', -- key to trigger tabout, set to an empty string to disable
backwards_tabkey = '<S-Tab>', -- key to trigger backwards tabout, set to an empty string to disable
act_as_tab = true, -- shift content if tab out is not possible
act_as_shift_tab = false, -- reverse shift content if tab out is not possible (if your keyboard/terminal supports <S-Tab>)
enable_backwards = true, -- well ...
completion = true, -- if the tabkey is used in a completion pum
tabouts = {
{open = "'", close = "'"},
{open = '"', close = '"'},
{open = '`', close = '`'},
{open = '(', close = ')'},
{open = '[', close = ']'},
{open = '{', close = '}'}
},
ignore_beginning = true, --[[ if the cursor is at the beginning of a filled element it will rather tab out than shift the content ]]
exclude = {} -- tabout will ignore these filetypes
}
end,
wants = {'nvim-treesitter'}, -- or require if not used so far
after = {'completion-nvim'} -- if a completion plugin is using tabs load it before
}
If you use another plugin manager just make sure tabout.nvim
is loaded after
nvim-treesitter
and any completion that already uses your tabkey.
🛠️ options
tabkey
Set the key you want to use to trigger tabout.
-- default
tabkey = '<Tab>'
backwards_tabkey
Set the key you want to use to trigger tabout backwards.
-- default
backwards_tabkey = '<S-Tab>'
act_as_tab
If a tab out is not possible shift the content.
-- default
act_as_tab = true
act_as_shift_tab
If a backwards tab out is not possible reverse shift the content. (Depends on keyboard/terminal if it will work)
-- default
act_as_shift_tab = false
enable_backwards
Disable if you just want to move forward
-- default
enable_backwards = true
completion
Consider using the Plug API and setting this to false
If you use a completion pum that also uses the tab key for a smart scroll function. Setting this to true will disable tab out when the pum is open and execute the smart scroll function instead.
See here how to ingegrate tabout.vim
into more complex
completions with snippets.
-- default
completion = true
tabouts
Here you can add more symbols you want to tab out from.
open an close can only contain one character for now
-- default
tabouts = {
{open = "'", close = "'"},
{open = '"', close = '"'},
{open = '`', close = '`'},
{open = '(', close = ')'},
{open = '[', close = ']'},
{open = '{', close = '}'}
}
ignore_beginning
If set to true you can also tab out from the beginning of a string, object property, etc.
-- default
ignore_beginning = true
more complex keybindings
You can set tabkey
and backwards_tabkey
to empty strings and define more complex
keybindings instead.
For example, to make <Tab>
and <S-Tab>
work with
nvim-compe,
vim-vsnip and this plugin:
require("tabout").setup({
tabkey = "",
backwards_tabkey = "",
})
local function replace_keycodes(str)
return vim.api.nvim_replace_termcodes(str, true, true, true)
end
function _G.tab_binding()
if vim.fn.pumvisible() ~= 0 then
return replace_keycodes("<C-n>")
elseif vim.fn["vsnip#available"](1) ~= 0 then
return replace_keycodes("<Plug>(vsnip-expand-or-jump)")
else
return replace_keycodes("<Plug>(Tabout)")
end
end
function _G.s_tab_binding()
if vim.fn.pumvisible() ~= 0 then
return replace_keycodes("<C-p>")
elseif vim.fn["vsnip#jumpable"](-1) ~= 0 then
return replace_keycodes("<Plug>(vsnip-jump-prev)")
else
return replace_keycodes("<Plug>(TaboutBack)")
end
end
vim.api.nvim_set_keymap("i", "<Tab>", "v:lua.tab_binding()", {expr = true})
vim.api.nvim_set_keymap("i", "<S-Tab>", "v:lua.s_tab_binding()", {expr = true})
Note that some other plugins that also use <Tab>
and <S-Tab>
might provide already
handlers to avoid clashes with tabout.nvim
.
For example nvim-cmp mappings can be
created using a function that accepts a callback. When the fallback is called
tabout.nvim
is working out of the box and there is no need for special
configurations.
The example below shows nvim-cmp
with luasnip
mappings using the fallback function:
['<Tab>'] = function(fallback)
if cmp.visible() then
cmp.select_next_item()
elseif luasnip.expand_or_jumpable() then
vim.fn.feedkeys(vim.api.nvim_replace_termcodes('<Plug>luasnip-expand-or-jump', true, true, true), '')
else
fallback()
end
end,
['<S-Tab>'] = function(fallback)
if cmp.visible() then
cmp.select_prev_item()
elseif luasnip.jumpable(-1) then
vim.fn.feedkeys(vim.api.nvim_replace_termcodes('<Plug>luasnip-jump-prev', true, true, true), '')
else
fallback()
end
end,
To make <Tab>
and <S-Tab>
work with vim-vsnip
:
["<Tab>"] = function(fallback)
if cmp.visible() then
-- cmp.select_next_item()
cmp.confirm(
{
behavior = cmp.ConfirmBehavior.Insert,
select = true
}
)
elseif vim.fn["vsnip#available"](1) ~= 0 then
vim.fn.feedkeys(vim.api.nvim_replace_termcodes("<Plug>(vsnip-expand-or-jump)", true, true, true), "")
else
fallback()
end
end,
["<S-Tab>"] = function(fallback)
if cmp.visible() then
cmp.select_prev_item()
elseif vim.fn["vsnip#available"](1) ~= 0 then
vim.fn.feedkeys(vim.api.nvim_replace_termcodes("<Plug>(vsnip-jump-prev)", true, true, true), "")
else
fallback()
end
end,
See here for more
nvim-cmp
examples.
🤖 plug api
Mode | plug | action |
---|---|---|
i | <Plug>(Tabout) |
tabout of current context (current line) |
i | <Plug>(TaboutMulti) |
tabout of current context (multiple lines) |
i | <Plug>(TaboutBack) |
tabout backwards of current context (current line) |
i | <Plug>(TaboutBackMulti) |
tabout backwards of current context (multiple lines) |
multiline tabout
-- A multiline tabout setup could look like this
vim.api.nvim_set_keymap('i', '<A-x>', "<Plug>(TaboutMulti)", {silent = true})
vim.api.nvim_set_keymap('i', '<A-z>', "<Plug>(TaboutBackMulti)", {silent = true})
📋 commands
command | triggers |
---|---|
Tabout | 🚨 DEPRECATED tries to tab out of current context |
TaboutBack | 🚨 DEPRECATED tries to tab out backwards of current context |
TaboutToggle | (de)activates the plugin |
⚠️ exceptions
tabout.nvim
only works with
nvim-treesitter's supported filetypes.
✅ todo
- tabout in blockcomment strings
- allow multi line tabout
- support multi character tabouts