floating.nvim
is a floating window manager.
It is centered around storing/restoring/managing custom window layouts along with their associated 'actions'
It aims to be easy to use & easy to customize.
note: background terminal jobs are highest priority TODO, coming soon.
Using vim-plug
Plug 'fhill2/floating.nvim'
Using dein
call dein#add('fhill2/floating.nvim')
Using packer.nvim
use "fhill2/floating.nvim"
-- 1 of the ways to open a window, see 'Views' below for more info
require "floating".open(
{
view1 = "center",
view1_action = {"open_file", string.format("%s/%s", vim.fn.stdpath("config"), "init.lua")}
}
)
-- close all views/windows
-- <C-w>w :q also works for an individual view
require "floating".close_all()
-- focus view/window by its unique name (make sure to specify the name: view1 = {name = 'my_window'})
-- params (all optional)
-- 1st: name of view
-- 2nd: 'one' or 'two - if {dual = true} 'two' will focus 2nd window in the view (default 'one')
-- 3rd: toggle: true/false - true to toggle between your last window and floating window (default 'true')
require'floating'.focus('my_window')
-- focusing the most recently opened view/window
-- focus() without specifying a name will fallback to the most recently opened view
require'floating'.focus()
require'floating'.focus(nil, 'two') -- to focus 2nd window of most recently opened view
-- focus cycle through all visible floating windows
require'floating'.focus_cycle('next') -- 'next' or 'prev'
If you are a telescope.nvim user, floating.nvim
configuration will be familiar, as floating.nvim
aims to implement the same configuration style.
customizations can be applied globally or individually per window.
- Global Customization affecting all views/windows can be done through the
setup()
method (see defaults below) - Individual Customization affecting a single view or window can be done:
- manually by passing
opts
toopen()
- by writing to
user_actions
oruser_views
table insetup()
, see below.
- manually by passing
require "floating".setup {
defaults = {
-- nvim_open_win() standard params
width = 0.9, -- 0-1 = 0%-100%
height = 0.3, -- 0-1 = 0%-100%
x = 0, -- right -, left +
y = 0, -- down -, up +
relative = "editor", -- 'editor'/'win'
style = "minimal", -- 'minimal' only
-- single & dual
pin = "bot", -- top/topright/right/botright/bot/botleft/left/topleft
winblend = 15,
margin = {1, 1, 1, 1},
enter = false, -- true/false or 'one'/'two'
toggle = true,
on_close = 'buffers',
-- single & dual - height adjustment
grow = true, -- true/false
grow_direction = "down", -- 'up'/'down'
content_height = false, -- true/false
max_height = 40, -- in row/line count
-- single & dual border
border = true, -- true/false - show/hide border
border_thickness = {1, 1, 1, 1},
borderchars = {"─", "│", "─", "│", "╭", "╮", "╯", "╰"},
title = "win1",
-- dual window only settings
dual = false, -- true/false
layout = "vertical", -- 'vertical'/'horizontal'
split = 0.5,
gap = 0
-- dual window only settings (duplicates)
--two_title = 'win2',
--two_grow = false,
--two_max_height = 40,
--two_grow_direction = false,
--two_content_height = false,
--two_margin = {1,1,1,1},
},
user_views = {},
user_actions = {},
user_exits = {},
}
- Views (tables)
- a configuration passed to open() command that affecting/layout of the window.
- After open() is finished, the view configuration is stored internally to manage the windows.
- a View can contain 1 or 2 windows, setting dual = true will open another window linked to the main window.
- Actions (functions)
- functions run on the window, after the window is created
- Without actions,
floating.nvim
can only open an empty window/buffer (e.g no highlighting, folding & additional customizations added)
Switching different Actions with Views allows for an easy way to customize without any duplicated configuration etc.
The aim is to cover the most popular/used View & Action configs... so everyone who wants to simply open a file in a window doesn't have to write their own 'Action' function for it. See List of Built-in Views & Actions for a complete overview!
require "floating".open(
{
view1 = {
width = 0.9,
height = 0.4,
border = true,
pin = "bot"
}
}
)
user views are individual window configs you can store into your config and load on demand.
if viewX
key is a string instead of a table, floating.nvim
will look for the value of the string in user_presets
table of setup()
before opening any windows.
If the string value (preset name) isn't found in user_views
, it checks default_views
-- setup() attached to init.lua
require "floating".setup {
user_view_presets = {
user_view_1 = {width = 0.4, height = 0.4},
user_view_2 = {}
}
}
-- from script, cmdline, luafile etc
require "floating".open(
{
view1 = "user_view_1" -- config values loaded: { width = 0.4, height = 0.4 }
}
)
-- If you want to change some config values of the preset you loaded, use 2nd argument.
-- This works the same for default or user views
require "floating".open(
{
view1 = {"user_view_1", {width = 0.8, border = true}}
-- config values loaded: { width = 0.8, height = 0.4, border = true }
}
)
specifying an action function to be executed on the buffer after window open.
require "floating".open(
{
view1 = {width = 0.8, height = 0.4, border = true},
-- 1st arg of a custom action is 'pass through' opts. 2nd arg is your custom opts.
view1_action = function(opts, custom_opts)
local write = {"setting a folder marker", "<-- custom", "fold", "-->", "add some highlights", "", ""}
-- write to buffer
vim.api.nvim_buf_set_lines(opts.bufnr, 0, -1, false, write)
-- add some custom fold markers
vim.cmd([[set foldmethod=marker]])
vim.cmd([[set foldmarker=<--,-->]])
-- add some highlights
vim.api.nvim_buf_add_highlight(opts.bufnr, -1, "String", 0, 0, -1)
vim.api.nvim_buf_add_highlight(opts.bufnr, -1, "Error", 4, 0, -1)
end
}
)
You can load user or default actions in the same way you can load user/default views You can also have more than 1 action run on window open()
-- 1st arg of a custom action is 'pass through' opts. 2nd arg is your custom opts.
require "floating".setup {
user_actions = {
user_action_1 = function(opts, custom_opts)
vim.api.nvim_buf_set_lines(opts.bufnr, 0, -1, false, {custom_opts.write})
end
}
}
require "floating".open(
{
view1 = "user_view_1",
view1_action = {"user_action_1", {write = {"abc", "def"}}} -- writes 'abc' 'def' to buffer of opened window
}
)
-- load default actions in the same way
require "floating".open(
{
view1 = "user_view_1",
view1_action = {"open_file", string.format("%s/%s", vim.fn.stdpath("config"), "init.lua")}
}
)
-- load multiple actions on the window (syntax 1)
you can combine action functions saved in config with anonymous functions and they be will all be executed on the buffer
require "floating".open(
{
view1 = "user_view_1",
view1_action = {
{"open_file", string.format("%s/%s", vim.fn.stdpath("config"), "init.lua")},
function() -- do something else here after the file has opened.. end,
{'buf_write', 'writing this string to buffer'}
}
)
exits are a function run on the window when it's closed. Useful for making sure anything in your custom actions are shut down the way you want.
configure exit_actions
the same way (see loading user or default actions above), change _action
to _exit_action
.
require "floating".open(
{
view1 = {},
view1_action = {},
view1_exit_action = {},
}
Options with 🔷 affect the single window if dual=false
, or window 1 if dual=true
.
Append two_
to key name to affect window 2 when dual=true
:
view1 = {dual = true, one_title = "win 1 border title", two_title = "win 2 border title"}
-- same for actions!
view1_two_action = {"open_term"}
🔷 | Keys | Description | Options |
---|---|---|---|
dual |
opens an additional window linked to the main window | boolean | |
width |
specify width of window as a % of editor or win dimensions | 0-1 | |
height |
specify height of window as % of editor or win dimensions | 0-1 | |
x |
Relative offset applied to window after all other calculations | NUM or -NUM | |
y |
Relative offset applied to window after all other calculations | NUM or -NUM | |
relative |
Equivalent to nvim_open_win | 'win' or 'editor | |
style |
Equivalent to nvim_open_win | 'minimal' | |
pin |
pin window to a side or corner of the window/editor | string: edge or corner. see pin | |
winblend |
How transparent the floating window should be. | NUM | |
🔷 | margin |
like CSS - reduces window edges from outside border | {1,1,1,1} |
enter |
if/what window should be focused after window open | boolean | |
toggle |
calling open() on the same view config will close the opened window | boolean | |
name optionally assign a unique name to your view so you can target it after open |
string | ||
on_close |
when closing view, close 'buffers'(and windows) or 'windows' only (use to persist terminal etc) | 'buffers'/'windows' | |
Height Adjustment Options |
|||
🔷 | grow |
after win open, adjusts window height to buffer contents on buffer keystroke input | boolean |
🔷 | grow_direction |
see grow. if pin is disabled, manually specify grow direction. | 'up' or 'down' |
🔷 | content_height |
after win open, 1 off, adjusts window height to buffer contents | boolean |
🔷 | max_height |
maximum height limit window can grow to | NUM |
Border Options |
|||
border |
Enable/disable border | boolean | |
border_thickness |
Border thickness | {1,1,1,1} | |
borderchars |
Border appearance | see default config | |
🔷 | title |
Border title | string |
These Options are enabled if dual=true
Keys | Description | Options |
---|---|---|
layout |
left/right dual window or top/bot dual window | 'horizontal' or 'vertical' |
split |
Increase window size 1, decrease window size 2 etc. in % | 0 - 1 |
gap |
quicker config for padding, only reduces the 2 connecting edges of a dual window | NUM |
max_height
affects content_height
and grow
max_height
doesn't affect height
if pin
is enabled, grow direction
is disabled
Action & Exit functions are called within nvim_buf_call()
, so any commands used in your custom function are executed on the buffer.
custom function options start at arg2, 1st is opts passthrough.
source code for default actions are in floating/config
These are a list of useful variables available within action & exit functions:
Keys | Description | Options |
---|---|---|
opts.self |
the table object of the current view instance (class) | {} |
opts.bufnr |
the bufnr the function is being executed on | NUM |
opts.winnr |
the winnr the function is being executed on | NUM |
opts.one_two |
if dual=true , the index of the window |
'one' or 'two' |
opts.single_dual |
whatever you set dual key to when opening | boolean |
Multiple views can be opened from a single open() command
require "floating".open(
{
view1 = {width = 0.8, height = 0.4},
view1_action = {"open_file", string.format("%s/%s", vim.fn.stdpath("config"), "init.lua")},
view2 = "content_auto",
view2_action = {"buf_write", "welcome to floating.nvim"},
view3 = {dual = true, pin = "bot"},
view3_action = {"open_term"},
view3_two_action = {"open_term"}
}
)
default_view_presets = {
center = {
width = 0.8,
height = 0.8
},
content_auto = {
content_height = true,
grow = true
},
dual_content_auto = {
content_height = true,
two_content_height = true,
grow = true,
two_grow = true
}
}
These are all current defaults Views & Actions & how to call them
-- open a file
require "floating".open(
{
view1 = {},
view1_action = {"open_file", string.format("%s/%s", vim.fn.stdpath("config"), "init.lua")}
}
)
-- write to buffer
-- currently can only write 1 line :D need to fix
require "floating".open(
{
view1 = {},
view1_action = {"buf_write", "welcome to floating.nvim"}
}
)
-- open a terminal window
-- coming soon: open and run a command, output of terminal to buffer etc...
-- to persist terminal after closing window: view = { on_close = 'windows'}
require "floating".open(
{
view1 = {},
view1_action = {"open_term"}
}
)
-- any other ideas?? post them in Issues!!
Single Window Layout Calculation flow: Pin > Offset> Margin > Open Buffer/Window/Border > Content Height
Dual Window Layout Calculation flow: Pin > Offset > > Gap > Split > Margin > Open Buffers/Windows/Borders > Content Height
Load multiple actions better managing - closing, focusing telescope integration - view/focus/open/close windows replace some parts with vim.lsp.util functions focus cycle between opened windows uniquely naming windows and focusing by their name better integration sending windows to the background and reopening them (npm watch)
All contributions are welcome & appreciated, submit a PR :)
Being able to use floating.nvim
in your own lua files!
TODO: docs coming soon