Ecosyste.ms: Awesome

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

Awesome Lists | Featured Topics | Projects

https://github.com/folke/edgy.nvim

Easily create and manage predefined window layouts, bringing a new edge to your workflow
https://github.com/folke/edgy.nvim

neovim neovim-lua-plugin neovim-plugin neovim-ui

Last synced: 5 days ago
JSON representation

Easily create and manage predefined window layouts, bringing a new edge to your workflow

Awesome Lists containing this project

README

        

# 🪟 edgy.nvim

A Neovim plugin to easily create and manage predefined window layouts,
bringing a new edge to your workflow.

![image](https://github.com/folke/edgy.nvim/assets/292349/35e2b30c-4099-4f37-8830-48584529bfd5)

## ✨ Features

- 🔄 Automatically move windows (including floating windows) in a pre-defined layout
- 📐 Manage layouts while keeping your main editor splits untouched.
- 🔧 Personalize **edgebar** window options to fit your style.
- 📌 Pinned views are always shown in the edgebar even when they have no windows.
- ⌨️ Make navigation easier with personalized buffer-local _keymaps_ for **edgebar** windows.
- 🎆 Pretty animations (works well with [mini.animate](https://github.com/echasnovski/mini.animate))
- 🧩 Works with any plugin. Check [Show and Tell](https://github.com/folke/edgy.nvim/discussions/categories/show-and-tell)
for snippets to integrate even better
with plugins like [neo-tree.nvim](https://github.com/nvim-neo-tree/neo-tree.nvim),
[bufferline.nvim](https://github.com/akinsho/bufferline.nvim)

## ⚠️ Limitations

- fully **collapsing** windows only works with the global statusline.
- **edgebar** windows can not be **resized** like normal windows.
It's tricky to detect if a window was resized by the user or by a plugin.
Check the config section about `keys`. Regular window keymaps have been added
for resizing windows.
- requires **Neovim >= 0.9.2** or **Neovim >= 0.10.0 (after June 5, 2023)**
for proper folding. If you're on an older nightly, you can set `fix_win_height`
to `true` to make it work.
- some flickering may occur when windows are being moved in their
correct position. Should be minimal, but may be more visible for some plugins
that don't set the buffer `filetype` during the frame where the window was created.

## 📦 Installation

Install the plugin with your preferred package manager:

[lazy.nvim](https://github.com/folke/lazy.nvim):

```lua
{
"folke/edgy.nvim",
event = "VeryLazy",
opts = {}
}
```

> If you're not using **lazy.nvim**, make sure to call `require("edgy").setup(opts?)`.

Recommended **Neovim** options:

```lua
-- views can only be fully collapsed with the global statusline
vim.opt.laststatus = 3
-- Default splitting will cause your main splits to jump when opening an edgebar.
-- To prevent this, set `splitkeep` to either `screen` or `topline`.
vim.opt.splitkeep = "screen"
```

## ⚙️ Configuration

**edgy.nvim** comes with the following defaults:

```lua
{
left = {}, ---@type (Edgy.View.Opts|string)[]
bottom = {}, ---@type (Edgy.View.Opts|string)[]
right = {}, ---@type (Edgy.View.Opts|string)[]
top = {}, ---@type (Edgy.View.Opts|string)[]

---@type table
options = {
left = { size = 30 },
bottom = { size = 10 },
right = { size = 30 },
top = { size = 10 },
},
-- edgebar animations
animate = {
enabled = true,
fps = 100, -- frames per second
cps = 120, -- cells per second
on_begin = function()
vim.g.minianimate_disable = true
end,
on_end = function()
vim.g.minianimate_disable = false
end,
-- Spinner for pinned views that are loading.
-- if you have noice.nvim installed, you can use any spinner from it, like:
-- spinner = require("noice.util.spinners").spinners.circleFull,
spinner = {
frames = { "⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏" },
interval = 80,
},
},
-- enable this to exit Neovim when only edgy windows are left
exit_when_last = false,
-- close edgy when all windows are hidden instead of opening one of them
-- disable to always keep at least one edgy split visible in each open section
close_when_all_hidden = true,
-- global window options for edgebar windows
---@type vim.wo
wo = {
-- Setting to `true`, will add an edgy winbar.
-- Setting to `false`, won't set any winbar.
-- Setting to a string, will set the winbar to that string.
winbar = true,
winfixwidth = true,
winfixheight = false,
winhighlight = "WinBar:EdgyWinBar,Normal:EdgyNormal",
spell = false,
signcolumn = "no",
},
-- buffer-local keymaps to be added to edgebar buffers.
-- Existing buffer-local keymaps will never be overridden.
-- Set to false to disable a builtin.
---@type table
keys = {
-- close window
["q"] = function(win)
win:close()
end,
-- hide window
[""] = function(win)
win:hide()
end,
-- close sidebar
["Q"] = function(win)
win.view.edgebar:close()
end,
-- next open window
["]w"] = function(win)
win:next({ visible = true, focus = true })
end,
-- previous open window
["[w"] = function(win)
win:prev({ visible = true, focus = true })
end,
-- next loaded window
["]W"] = function(win)
win:next({ pinned = false, focus = true })
end,
-- prev loaded window
["[W"] = function(win)
win:prev({ pinned = false, focus = true })
end,
-- increase width
[">"] = function(win)
win:resize("width", 2)
end,
-- decrease width
[""] = function(win)
win:resize("width", -2)
end,
-- increase height
["+"] = function(win)
win:resize("height", 2)
end,
-- decrease height
["-"] = function(win)
win:resize("height", -2)
end,
-- reset all custom sizing
["="] = function(win)
win.view.edgebar:equalize()
end,
},
icons = {
closed = " ",
open = " ",
},
-- enable this on Neovim <= 0.10.0 to properly fold edgebar windows.
-- Not needed on a nightly build >= June 5, 2023.
fix_win_height = vim.fn.has("nvim-0.10.0") == 0,
}
```

### 👁️ `Edgy.View.Opts`

| **Property** | **Type** | **Description** |
| --------------| ------------------------------ | ----------------------------------------------------------------------------------------------------------- |
| **ft** | `string` | File type of the view |
| **filter** | `fun(buf:buffer, win:window)?` | Optional function to filter buffers and windows |
| **title** | `string?` or `fun():string` | Optional title of the view. Defaults to the capitalized filetype |
| **size** | `number` or `fun():number` | Size of the short edge of the edgebar. For edgebars, this is the minimum width. For panels, minimum height. |
| **pinned** | `boolean?` | If true, the view will always be shown in the edgebar even when it has no windows |
| **collapsed** | `boolean?` | If true, the view will be initially closed/collapsed in the edgebar |
| **open** | `fun()` or `string` | Function or command to open a pinned view |
| **wo** | `vim.wo?` | View-specific window options |

## 🚀 Usage

Just open windows/buffers as you normally do, but now they will be displayed
in your layout.

### ⌨️ Keymaps for Edgebar Windows

| **Keymap** | **Description** |
| ---------- | ----------------------- |
| `q` | Close the window |
| `` | Hide the window |
| `Q` | Close the edgebar |
| `]w`, `[w` | Next/Prev open window |
| `]W`, `[W` | Next/Prev loaded window |

### 🔌 API

- `require("edgy").select(pos?, filter?)` select a window with `vim.ui.select`
in the given position or in all edgebars using an optional filter
- `require("edgy").close(pos?)` close all edgebars or a edgebar in the given position
- `require("edgy").open(pos?)` open all pinned views in the given position
- `require("edgy").toggle(pos?)` toggle all pinned views in the given position
- `require("edgy").goto_main()` move the cursor to the last focused main window
- `require("edgy").get_win(window?)` get the Edgy.Window object for the given window
or the current window

## 🪟 Example Setup

```lua
{
"folke/edgy.nvim",
event = "VeryLazy",
init = function()
vim.opt.laststatus = 3
vim.opt.splitkeep = "screen"
end,
opts = {
bottom = {
-- toggleterm / lazyterm at the bottom with a height of 40% of the screen
{
ft = "toggleterm",
size = { height = 0.4 },
-- exclude floating windows
filter = function(buf, win)
return vim.api.nvim_win_get_config(win).relative == ""
end,
},
{
ft = "lazyterm",
title = "LazyTerm",
size = { height = 0.4 },
filter = function(buf)
return not vim.b[buf].lazyterm_cmd
end,
},
"Trouble",
{ ft = "qf", title = "QuickFix" },
{
ft = "help",
size = { height = 20 },
-- only show help buffers
filter = function(buf)
return vim.bo[buf].buftype == "help"
end,
},
{ ft = "spectre_panel", size = { height = 0.4 } },
},
left = {
-- Neo-tree filesystem always takes half the screen height
{
title = "Neo-Tree",
ft = "neo-tree",
filter = function(buf)
return vim.b[buf].neo_tree_source == "filesystem"
end,
size = { height = 0.5 },
},
{
title = "Neo-Tree Git",
ft = "neo-tree",
filter = function(buf)
return vim.b[buf].neo_tree_source == "git_status"
end,
pinned = true,
collapsed = true, -- show window as closed/collapsed on start
open = "Neotree position=right git_status",
},
{
title = "Neo-Tree Buffers",
ft = "neo-tree",
filter = function(buf)
return vim.b[buf].neo_tree_source == "buffers"
end,
pinned = true,
collapsed = true, -- show window as closed/collapsed on start
open = "Neotree position=top buffers",
},
{
title = function()
local buf_name = vim.api.nvim_buf_get_name(0) or "[No Name]"
return vim.fn.fnamemodify(buf_name, ":t")
end,
ft = "Outline",
pinned = true,
open = "SymbolsOutlineOpen",

},
-- any other neo-tree windows
"neo-tree",
},
},
}
```

## 🐯 Tips & tricks

- disable edgy for a window/buffer by setting `vim.b[buf].edgy_disable`
or `vim.w[win].edgy_disable`. You can even set this after the facts.
Edgy will then expunge the window from the layout.

- check the [Show and Tell](https://github.com/folke/edgy.nvim/discussions/categories/show-and-tell)
section of the github discussions for snippets for better integration
with plugins like [neo-tree.nvim](https://github.com/nvim-neo-tree/neo-tree.nvim),
[bufferline.nvim](https://github.com/akinsho/bufferline.nvim), ...