Skip to content

kawre/neotab.nvim

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

46 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🧩 neotab.nvim

Simple yet convenient Neovim plugin for tabbing in and out of brackets, parentheses, quotes, and more.

demo.mp4

why neotab.nvim

Unlike other similar plugins that tabout out of treesitter nodes, neotab.nvim uses simple logic to move in and out of pairs or find the next best matching pair.

This approach ensures a consistent behavior regardless of the file type or the state of the parsed treesitter tree.

This plugin doesn't aim to replace existing similar plugins. Instead, it offers a different, less fancy but more predictable and consistent method for tabbing out of pairs.

πŸ“¦ Installation

{
    "kawre/neotab.nvim",
    event = "InsertEnter",
    opts = {
        -- configuration goes here
    },
}

πŸ› οΈ Configuration

To see full configuration types check types.lua

βš™οΈ default configuration

{
    tabkey = "<Tab>",
    act_as_tab = true,
    behavior = "nested", ---@type ntab.behavior
    pairs = { ---@type ntab.pair[]
        { open = "(", close = ")" },
        { open = "[", close = "]" },
        { open = "{", close = "}" },
        { open = "'", close = "'" },
        { open = '"', close = '"' },
        { open = "`", close = "`" },
        { open = "<", close = ">" },
    },
    exclude = {},
    smart_punctuators = {
        enabled = false,
        semicolon = {
            enabled = false,
            ft = { "cs", "c", "cpp", "java" },
        },
        escape = {
            enabled = false,
            triggers = {}, ---@type table<string, ntab.trigger>
        },
    },
}

tabkey

the key that triggers the tabout action

to not bind to any key, set it to ""

tabkey = "<Tab>",

act_as_tab

fallback to tab, if tabout action is not available

act_as_tab = true,

behavior

nested

prioritize valid nested pairs first

nested.mp4

closing

prioritize closing pair first

closing.mp4

exclude

ignore these filetypes for tabout

exclude = {},

smart punctuators

semicolon (experimental)

intellij like behavior for semicolons

semicolon = {
    enabled = false,
    ft = { "cs", "c", "cpp", "java" },
},

escape

escapes pairs with specified punctuators

configuration from demo.mp4

escape = {
    enabled = true,
    triggers = { ---@type table<string, ntab.trigger>
        ["+"] = {
            pairs = {
                { open = '"', close = '"' },
            },
            -- string.format(format, typed_char)
            format = " %s ", -- " + "
            ft = { "java" },
        },
        [","] = {
            pairs = {
                { open = "'", close = "'" },
                { open = '"', close = '"' },
            },
            format = "%s ", -- ", "
        },
        ["="] = {
            pairs = {
                { open = "(", close = ")" },
            },
            ft = { "javascript", "typescript" },
            format = " %s> ", -- ` => `
            -- string.match(text_between_pairs, cond)
            cond = "^$", -- match only pairs with empty content
        },
    },
},

When the ft is defined, the corresponding trigger will apply to the specified file types. Otherwise, it will be effective no matter the file type.

πŸš€ Usage

There is a high chance neotab.nvim won't work out of the box, because of other plugins/config overriding the tabkey keymap.

To help you find the location that overrides the tabkey you can use

:verbose imap <Tab>

Plug API

Mode plug action
i <Plug>(neotab-out) tabout
i <Plug>(neotab-out-luasnip) (experimental) tabout before luasnip

🍴 Recipes

LuaSnip and lazy.nvim integration example

  1. set tabkey to ""

  2. set <Plug>(neotab-out) as a fallback to luasnip

{
    "L3MON4D3/LuaSnip",
    build = "make install_jsregexp",
    dependencies = { "neotab.nvim", },
    keys = {
        {
            "<Tab>",
            function()
                return require("luasnip").jumpable(1) --
                        and "<Plug>luasnip-jump-next"
                    or "<Plug>(neotab-out)"
            end,
            expr = true,
            silent = true,
            mode = "i",
        },
    },
}

nvim-cmp and luasnip integration example

  1. set tabkey to ""

  2. set require("neotab").tabout() as a fallback to both nvim-cmp and luasnip

local cmp = require("cmp")
local luasnip = require("luasnip")
local neotab = require("neotab")
["<Tab>"] = cmp.mapping(function()
    if cmp.visible() then
        cmp.select_next_item()
    elseif luasnip.jumpable(1) then
        luasnip.jump(1)
    else
        neotab.tabout()
    end
end),

πŸ™Œ Credits

Releases

No releases published

Packages

No packages published

Languages