Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/kawre/neotab.nvim

Tabout plugin for Neovim
https://github.com/kawre/neotab.nvim

lua neovim neovim-plugin smart-semicolon tabout

Last synced: about 13 hours ago
JSON representation

Tabout plugin for Neovim

Awesome Lists containing this project

README

        

# 🧩 neotab.nvim

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

https://github.com/kawre/neotab.nvim/assets/69250723/86754608-352e-4d6f-b2a6-cf5b6fd848a9

## 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

- [lazy.nvim]

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

## 🛠️ Configuration

To see full configuration types check [types.lua](./lua/neotab/types.lua)

### ⚙️ default configuration

```lua
{
tabkey = "",
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
},
},
}
```

### tabkey

the key that triggers the `tabout` action

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

```lua
tabkey = "",
```

### act_as_tab

fallback to tab, if `tabout` action is not available

```lua
act_as_tab = true,
```

### behavior

#### nested

prioritize valid nested pairs first

https://github.com/kawre/neotab.nvim/assets/69250723/3ad6c1ef-814f-431c-a8c0-fcdc85b560cf

#### closing

prioritize closing pair first

https://github.com/kawre/neotab.nvim/assets/69250723/fdb7158d-ec09-437e-9c20-580cdff0719a

### exclude

ignore these filetypes for `tabout`

```lua
exclude = {},
```

## smart punctuators

### semicolon (experimental)

intellij like behavior for semicolons

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

### escape

escapes pairs with specified punctuators

configuration from `demo.mp4`

```lua
escape = {
enabled = true,
triggers = { ---@type table
["+"] = {
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](#tabkey) keymap.

To help you find the location that overrides the [tabkey](#tabkey) you can use

```
:verbose imap
```

### Plug API

| Mode | plug | action |
| ---- | ---------------------------- | ------------------------------------ |
| i | `(neotab-out)` | tabout |
| i | `(neotab-out-luasnip)` | (experimental) tabout before luasnip |

## 🍴 Recipes

### [LuaSnip] and [lazy.nvim] integration example

1. set [tabkey](#tabkey) to `""`

2. set `(neotab-out)` as a fallback to luasnip

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

### [nvim-cmp] and [luasnip] integration example

1. set [tabkey](#tabkey) to `""`

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

```lua
local cmp = require("cmp")
local luasnip = require("luasnip")
local neotab = require("neotab")
```

```lua
[""] = 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

- [tabout.nvim](https://github.com/abecodes/tabout.nvim)

- [TabOut plugin for vscode](https://github.com/albertromkes/tabout)

[lazy.nvim]: https://github.com/folke/lazy.nvim
[luasnip]: https://github.com/L3MON4D3/LuaSnip
[neotab.nvim]: https://github.com/kawre/neotab.nvim
[nvim-cmp]: https://github.com/hrsh7th/nvim-cmp