First and foremost I want a floating window that sticks around while I'm doing other things, so I can have notes to look at, function signatures or definitions on screen, or even just a clear space to note down a shopping list before I forget.
- Rationale
- Minimal Setup
- Usage
- Installation
- Builtin
- Extras
- User extension
- API
- Types
- Internal Documentation
- Internal Types
minimum config in Lazy:
{
"mathematicalninja/floating.nvim",
config = function()
require("floating").setup({})
end
}The main functionality of this plugin is the .toggle function. This opens new windows if none exist, focuses one if there's an unfocused one, and closes a focused one.
If you want to make your own keymaps, the following syntax should work for any of the builtin, extra, or user defined styles.
e.g. for duplicate:
local float = require("floating")
vim.keymap.set(
"n",
"<leader>fd",
function()
float.toggle("duplicate")
end,
{}
)There is also the .open function to allow multiple windows of the same type to be open (in which case .toggle will focus the first one, or close a focused one).
There is also the option to call .toggle_hide if you'd like to keep the content of the buffer/window, but move it to "the background" rather than closing it.
If you want to make your own keymaps, the following syntax should work for any of the buitlin, extra, or user defined styles.
e.g. for scratch:
local float = require("floating")
vim.keymap.set(
"n",
"<leader>fs",
function()
float.toggle_hide("scratch")
end,
{}
)If you want greater granularity over where windows are opened, or shortcut closing/hiding them, then the functions open, close, and hide are provided.
Example:
local float = require("floating")
vim.keymap.set(
"n",
"<leader>fo",
function()
float.open({
style_name = "scratch",
pos = "mc",
is_not_scratch = true,
})
end,
{desc = "[o]pens a float for shopping lists"}
)
vim.keymap.set(
"n",
"<leader>fc",
function()
float.close({
pos = "mc",
style_name = "shopping"
})
end,
{desc = "[c]loses the floating shopping list"}
)
vim.keymap.set(
"n",
"<leader>fh",
function()
float.hide({
pos = "mc",
style_name = "shopping"
})
end,
{desc = "[h]ides the floating shopping list"}
)setup_opts.dont_load_default_user_commands is used to skip default user command creation, so if left nil, then defaults are loaded.
The module comes with a command for each Builtin Styles. Loads the following Vim commands:
each calling toggle for that style.
setup_opts.dont_use_default_keymaps is used to skip default user keymap creation, so if left nil, then defaults are loaded.
The module comes with keymaps for each of the Builtin Styles in "n" mode.
Calling local FLOAT = require("floating").setup(opts) creates an object (in this case FLOAT) that can be used in user keymaps etc.
Note: .setup() needs to be called.
I developed this with Lazy as my manager. If it has errors loading with other managers please let me know and I'll try extending it to work with them.
{
"mathematicalninja/floating.nvim",
-- If you wish to extend functionality you may need dependencies.
dependencies = { },
config = function()
local float = require("floating").setup({
-- dev = true,
-- positions = {},
-- styles = {},
-- extras = {
-- positions = {},
-- styles = {},
-- },
-- dont_load_default_user_commands = false,
-- dont_use_default_keymaps = true,
})
end
}The options for the .setup function are contained in the type Setup_Opts.
---@alias Setup_Opts {
--- dev: boolean | nil,
--- dont_load_default_user_commands: boolean | nil,
--- dont_use_default_keymaps: boolean | nil,
--- styles:{[style_name]:STYLE},
--- positions: {[position_abrv]:POSITION},
--- extras: {
--- positions:extra_positions[],
--- styles:extra_styles[],
--- }
--- }- Type: boolean | nil
- Default value: nil
- Default behaviour: does nothing, as it should.
- Purpose: Used for testing purposes, exposes a user_commands for each window position, or allows me to create temporary and possibly buggy commands/keymaps while building.
No guarantee it won't cause problems, use at your own risk.
- Type: {[position_abrv]:POSITION}
- Default value: {}
- Default behaviour: loads the positions from builtin
- Purpose: Allows end users to pass in a table of their own custom positions.
- Type: {[style_name]:STYLE}
- Default value: {}
- Default behaviour: loads the styles from builtin
- Purpose: Allows end users to pass in a table of their own custom styles.
-
Type: {
styles:extra_styles[],
positions:extra_positions[],
}
- Default value: nil
- Default behaviour: does nothing.
- Purpose: This is used to load in more esoteric styles and positions that I though most users would have little intererst in, but I have don't want to clutter up my .config files with.
- Type: extra_styles[] | nil
- Default value: nil
- Default behaviour: does nothing.
- Purpose: a list of string that are the names of the extra styles to be loaded.
Example:
extras.styles = {
"clock_tl",
}- Type: extra_positions[] | nil
- Default value: nil
- Default behaviour: does nothing.
- Purpose: a list of string that are the names of the extra positions to be loaded.
Example:
extras.positions = {
"clock_tl",
}- Type: boolean | nil
- Default value: nil
- Default behaviour: loads the default commands.
- Purpose: loads commands for each builtin style (e.g. FloatToggleScratch) so you can set your own keymaps or use via command line.
- Type: boolean | nil
- Default value: nil
- Default behaviour: loads the default keymaps.
- Purpose: loads the default keymaps for each builtin style to allow "out of the box" functionality.
A full (lazy) example that I use for an international clock popup,
{
"mathematicalninja/floating.nvim",
config = function()
local opts = {
dev = true,
positions = {
clock_tr = function()
--- @module "floating"
--- @alias position_abrv
--- | "clock_tr"
--- @alias style_name
--- | "clock_tr"
--- @type Setup_Opts
---@type config_and_position
local R = {}
local col = vim.o.columns
R.pos = "clock_tr"
R.name_location = "footer"
R.config = {
width = 5,
height = 1,
col = col,
row = 0,
anchor = "NW",
title = "",
title_pos = "center",
relative = "editor",
style = "minimal", -- No extra UI elements, e.g. status bar.
border = { "", "", "", "", "", "═", "╚", "║" },
}
return R
end,
},
styles = {
clock_tr = {
name = "clock_tr",
positions = { "clock_tr" },
dont_focus = true,
INIT = function(FLOAT)
FLOAT.state.style_data.clock_tl = {}
end,
setup = function(STATE)
local time_offset = 8
local time_table = os.date("*t", os.time() + time_offset * 3600)
local M = tonumber(time_table.min)
local H = tonumber(time_table.hour)
local digits = {
["0"] = "🯰",
["1"] = "🯱",
["2"] = "🯲",
["3"] = "🯳",
["4"] = "🯴",
["5"] = "🯵",
["6"] = "🯶",
["7"] = "🯷",
["8"] = "🯸",
["9"] = "🯹",
}
local min = string.format("%02d", M)
local min_array = {
digits[string.sub(min, 1, 1)],
digits[string.sub(min, 2, 2)],
}
local hour = string.format("%02d", H)
local hour_array = {
digits[string.sub(hour, 1, 1)],
digits[string.sub(hour, 2, 2)],
}
local time = hour_array[1] .. hour_array[2] .. ":" .. min_array[1] .. min_array[2]
STATE.style_data.clock_tl = {
time = time,
}
end,
-- `style` is run after the new window is opened.
style = function(opts)
local buf = opts.bufwin.buf
vim.api.nvim_buf_set_lines( --
buf,
0,
-1,
false,
{ opts.state.style_data.clock_tl.time }
)
end,
},
},
extras = { --
positions = { "clock_tl" },
styles = { "clock_tl" },
},
dont_load_default_user_commands = false,
dont_use_default_keymaps = false,
}
local float = require("floating").setup(opts)
vim.keymap.set("n", "<leader><leader>p", function()
float.toggle("clock_tr")
end, {})
end,
}This plugin comes with some builtin "styles" for floating windows and "positions" to put them in.
see styles for details.
Fills a corner with a "scratch" buffer, matching the language of the buffer you call the function from.
Allows for language highlighting while making quick mock-ups or psudo-code.
Example:
local float = require("floating")
vim.keymap.set( --
"n",
"<leader>fs",
function()
float.toggle("scratch")
end,
{ desc = "Toggles a [f]loating [s]cratch buffer sharing tiletype with the current buffer." }
)Fills a corner with the current buffer.
Useful for
- keeping a function signature on screen while deeper in it's body.
- holding a type signature that's being used in a different place.
- referencing a similar piece of code.
Example:
local float = require("floating")
vim.keymap.set( --
"n",
"<leader>fd",
function()
float.toggle("duplicate")
end,
{ desc = "Toggles a [f]loating window with a [d]uplicate of the current buffer in it." }
)A completely ordinary buffer.
90% of it's purpose if to be a baseline for the other styles so you don't need to code in every property.
10% is to allow a throwaway buffer that has a special one off use, e.g. shopping lists.
Example:
local float = require("floating")
vim.keymap.set( --
"n",
"<leader>ff",
function()
float.toggle("default")
end,
{ desc = "Toggles a [f]loating de[f]ault buffer/window with no special features." }
)See positions for details.
Builtin positions can be indexed by name, for use in a position_abrv[] list when opening a style using FLOAT.open()
[!NOTE] the builtin positions allow for a title/footer to be indexed by the name_location field in a style's definition.
This will use titles (above the window) if the floating window is at the bottom of the screen, and a footer (below the window) if the floating window is at the top or middle of the screen.
my_style = {
-- ...
style = function(opts)
--
conf[opts.conf_pos.name_location] = "Wow, a buffer."
vim.api.nvim_win_set_config(opts.bufwin.win, conf)
end
}valid values:
local corners = {
"tr", -- top right
"tl", -- top left
"br", -- bottom right
"bl", -- bottom left
}45% of the screen in one of the corners, with rounded border.
I like a little bit more space around it then 50% size would give, especially when opening multiple windows.
valid values:
local corners = {
"bp", -- bottom pop-up
"cp", -- center pop-up
"tp", -- top pop-up
}Small "pop-up" 1 row tall, and about 45% of the screen wide,
valid values:
local corners = {
"bb", -- bottom bar
"tb", -- top bar
}Full bar 1 row tall across the whole screen.
valid values:
local specials = {
"mc",
}A very mini (1/16th of the area) window in the dead center of the screen.
There are some more unusual styles and positions that I feel are not needed for most uses, but I wanted them for some personal edge-cases.
They can be loaded in by name in as shown here.
More unusual styles that I feel most unhelpful, but I found enough of a use for to keep in.
Loaded in by name as shown here.
valid values:
local corners = {
"clock_tl", -- top left corner clock
"clock_tr", -- top right corner clock
"clock_bl", -- bottom left corner clock
"clock_br", -- bottom right corner clock
}A pop-up clock showing the current time, I use it in full-screen mode so I can forget what the time is, but check when I feel like it, great for zen coding.
More unusual positions that I feel most unhelpful, but I found enough of a use for to keep in.
Loaded in by name as shown here.
valid values:
local corners = {
"clock_tl", -- top left corner clock
"clock_tr", -- top right corner clock
"clock_bl", -- bottom left corner clock
"clock_br", -- bottom right corner clock
}A 5 wide popup (with partial border) in the corner of the screen. Ideal for writing "14:22" in.
This module has 4 major components, two of which are designed for user extensions: Styles and Positions.
Positions are functions that return a table with signature:
---@alias Position_Return {
--- pos: position_abrv,
--- name_location:"footer" | "title",
--- config:vim.api.keyset.win_config,
--- }This plugin is designed to allow users to add positions that they want floating windows in (e.g. I like a tiny clock).
This extension comes in the form of the opts.positions table which has key value pairs of type
---@alias Setup_Opts {
--- positions: {[position_abrv]:POSITION},
--- ...
--- }See position_abrv, POSITIONS.
The reason that these are coded as functions that return tables rather than hard coded tables is to allow relative calculations on position and size to happen when the window is opened.
e.g.
local col = math.floor(vim.o.columns * 0.275)Note: position.pos must match the key used to index it in the opts.positions table, as the .pos is used to index the created table.
pos.name has type position_abrv which is an extendable collection of strings:
When a new position is added it's abrv can be appended by duplicating the alias special_abrv, e.g. to add a "clock":
---@alias special_abrv
--- | "clock"this gives a duplicate warning, but allows types to be used without error, only if they are defined in the code. This is especially useful in Styles where a list of positions is needed, and can easily be typo'd.
type "header"|"footer" tells the module whether a window's (optional) title goes above (header) or below (footer) the window.
Names are defined in style see style.style
style = function(opts)
-- ...
conf[opts.conf_pos.name_location] = "UTC"
-- ...
end
This config is calculated when this position function is called, and allows dynamic config settings. The result is ultimately merged with defaults and passed tovim.api.nvim_open_win.
See |api-win_config| in nvim help for details.
Some notable config options:
{
width = 5,
height = 1,
col = 1,
row = 1,
title = "",
title_pos = "center",
footer = "",
footer_pos = "left",
focusable = false,
}An example is the "clock" I have briefly pop up on my screen:
---@alias special_abrv
--- | 'clock_tl'
opts.positions = {
---@type POSITION
clock_tl = function()
return {
pos = "clock_tl",
name_location = "footer",
config = {
width = 5,
height = 1,
col = 1,
row = 1,
title = "",
title_pos = "center",
relative = "editor",
style = "minimal", -- No extra UI elements, e.g. status bar.
border = "shadow",
},
}
end
}Styles are class like tables (as classes don't truly exist in lua - which is tables all the way down) that have a collection of Methods and some hard coded values.
Styles are used to "fancify" windows or to add functionality after it's been opened.
e.g. Setting file-type, puting text, or setting up auto-commands.
---@alias STYLE {
--- name: style_name,
--- positions: position_abrv[],
--- dont_focus: boolean | nil,
--- is_not_scratch: boolean | nil,
--- INIT: fun(FLOAT:FLOAT),
--- setup: fun(STATE:STATE),
--- style: (fun(opts:{
--- state:STATE,
--- bufwin:bufwin,
--- conf_pos:config_and_position,
--- data:table, --- individual float styles define what their data looks like.
--- })),
--- push: (fun(
--- STATE:STATE,
--- bufwin_pos:bufwin_pos,
--- )),
--- pop: (fun(
--- STATE:STATE,
--- bufwin_state:bufwin_state,
--- )),
--- }opts.styles = {
clock = {
name = "clock",
positions = { "clock_tl" },
dont_focus = true,
INIT = function(FLOAT)
FLOAT.state.style_data.clock = {}
end,
setup = function(STATE)
local time_offset = 8
local time_table = os.date("*t", os.time() + time_offset * 3600)
local M = tonumber(time_table.min)
local H = tonumber(time_table.hour)
local digits = {
["0"] = "🯰",
["1"] = "🯱",
["2"] = "🯲",
["3"] = "🯳",
["4"] = "🯴",
["5"] = "🯵",
["6"] = "🯶",
["7"] = "🯷",
["8"] = "🯸",
["9"] = "🯹",
}
local min = string.format("%02d", M)
local min_array = {
digits[string.sub(min, 1, 1)],
digits[string.sub(min, 2, 2)],
}
local hour = string.format("%02d", H)
local hour_array = {
digits[string.sub(hour, 1, 1)],
digits[string.sub(hour, 2, 2)],
}
local time = hour_array[1] .. hour_array[2] .. ":" .. min_array[1] .. min_array[2]
STATE.style_data.clock = {
time = time,
}
end,
-- `style` is run after the new window is opened.
style = function(opts)
local buf = opts.bufwin.buf
vim.api.nvim_buf_set_lines( --
buf,
0,
-1,
false,
{ opts.state.style_data.clock.time }
)
end,
}
}2 of the 4 major components of this plugin (STATE and ACTIONS) are designed for a mix of internal use and user consumption, some of which is exposed and documented here.
The other 2 (POSITIONS and STYLES) are designed to provide extensibility to the user,
Therefore this plugin comes with some "out of the box" functions that you can use to allow greater granularity in control.
While making this plugin I ensured (as I always try to) that there was a strict type system in place, this is opt in in lua so feel free to ignore it.
While more types are defined for internal use, I document here the types that are exposed for user consumption.
Using LuaDocs allows
---@module "floating"which will import the types from the module as long as lua can resolve require("floating") which is the case when using Lazy.
Alternatively most of the plugin's types can be found in the file floating/dev.lua. Note that style_name and position_abrv are defined and extended in the files relating to those positions/styles so couldn't be fully included here.
Here follows the functions that can be accessed via
require("floating")[function_name]()along with:
- Their Purpose
- Their Parameters
- Their Return Value (if not nil)
- Example Usage
Opens new windows, switches to them if you de-focus them (e.g. with "w"), and closes them if they're focused.
Automatically chooses position from the style's chosen preferences. See [style.positions](#tystpos
To hide instead of closing see: toggle_hide
type: style_name
a string, the name of the style to toggle
local float = require("floating").setup()
vim.keymap.set(
"n",
"<leader>fd",
function()
float.toggle("duplicate")
end,
{}
)Opens new windows, switches to them if you de-focus them (e.g. with <C-w>w), and hides them if they're focused.
Automatically chooses position from the style's chosen preferences. See [style.positions](#tystpos
To close instead of hiding see: toggle_close
type: style_name
a string, the name of the style to toggle
local float = require("floating").setup()
vim.keymap.set(
"n",
"<leader>fd",
function()
float.toggle_hide("duplicate")
end,
{}
)Allows a user to open a specific float style in a specific position.
Mainly for when you want to allow multiple windows of the same style to be open at once, or to open styles in unusual positions.
Takes a single option table with the following fields:
style_name is the name of the (possibly user defined) style.
required field
pos is the abbreviation of the (possibly user defined) position.
required field
is_not_scratch is used to make a "real" buffer as this plugin defaults to scratch buffers, see |vim.api.nvim_create_buf|.
- default value: nil
- default behaviour: new buffer (if created) is a throwaway buffer.
buf is used to specify a buffer if an already existing one is to be used in the float (e.g. buf = 0 for duplicate buffers).
- default value: nil
- default behaviour: a new buffer is created.
type: config_and_position
---@alias config_and_position {
--- config:vim.api.keyset.win_config,
--- pos:position_abrv,
--- name_location: "footer"|"title",
--- }local float = require("floating")
---@type Actions.Open.opts
open_opts = {
style_name = "scratch",
pos = "tr",
is_not_scratch = nil,
buf = nil,
}
local float = require("floating").setup()
vim.keymap.set(
"n",
"<leader>fo",
function()
float.open(open_opts)
end,
{})Allows a user to hide a floating window based on style or position.
Allows for more manual control, e.g. making semi-permanent scratch buffers that hide until you close them.
takes a single option table with the following fields:
style_name is the name of the (possibly user defined) style.
pos is the abbreviation of the (possibly user defined) position.
bufwin_state the exact specification of an open window.Mainly used to allow functions to call this when they know the state.
If an exact window's state is provided: closes that window.
If only a style name is provided: hides the last window of that style opened.
If only a position is provided: hides the last opened window in that position.
If both are provided: hides the most recently opened window that is both in that position and of that style.
If neither are provided: does nothing.
local float = require("floating").setup()
vim.keymap.set(--
"n",
"<leader>fh",
function()
float.hide({pos="tl", style="scratch"})
end,
{ desc = "hides the scratch window in the top left" }
)Allows a user to close a floating window based on style or position.
takes a single option table with the following fields:
style_name is the name of the (possibly user defined) style.
pos is the abbreviation of the (possibly user defined) position.
bufwin_state the exact specification of an open window.Mainly used to allow functions to call this when they know the state.
If an exact window's state is provided: closes that window.
If only a style name is provided: closes the last window of that style opened.
If only a position is provided: closes the last opened window in that position.
If both are provided: closes the most recently opened window that is both in that position and of that style.
If neither are provided: does nothing.
local float = require("floating")
vim.keymap.set(--
"n",
"<leader>fh",
function()
float.close({pos="tl", style="scratch"})
end,
{ desc = "closes the scratch window in the top left" }
)Used internally to add styles to the state object.
Technically could allow a user to add styles after FLOAT.setup has been run. I can think of times where this might be helpful, so it's an exposed function.
local float = require("floating")
local style_table = {
-- user definition
}
float.attach_style(style_table)---@alias bufwin { buf:integer, win:integer }Type used to simplify passing parameters.
---@alias bufwin_pos {
--- buf:integer,
--- win:integer,
--- position: position_abrv,
--- }Type used to simplify passing parameters.
---@alias bufwin_style {
--- buf:integer,
--- win:integer,
--- style_name:style_name,
--- }Type used to simplify passing parameters.
---@alias bufwin_state {
--- buf:integer,
--- win:integer,
--- position: position_abrv,
--- style_name:style_name,
--- }Type used to track the state of a bufwin, most notably used in STATE.window_states.
---@alias extra_styles
--- | "clock_tl"
--- | "clock_tr"
--- | "clock_bl"
--- | "clock_br"Optional extra styles that I have not finalised, or think are impractical and niche.
---@alias position_abrv
--- | corner_abrv
--- | popup_abrv
--- | bar_abrv
--- | special_abrv
--- | extra_positionsThe full collection of abbreviations used to identify valid positions.
---@alias corner_abrv
--- | 'tr' # Top Right
--- | 'tl' # Top Left
--- | 'br' # Bottom Right
--- | 'bl' # Bottom LeftUsed to index corner positions.
---@alias popup_abrv
--- | 'tp' # Top Pop-up -- small pop-up
--- | 'cp' # Center Pop-up -- small pop-up
--- | 'bp' # Bottom Pop-up -- small pop-upUsed to index popup positions.
---@alias bar_abrv
--- | 'tb' # Top Bar -- full bar across top
--- | 'bb' # Bottom Bar -- full bar across bottomUsed to index bar positions.
---@alias special_abrv
--- | 'mc' # Mini Center -- a mini popup in the very centerUsed to index special positions.
---@alias extra_positions
--- | "clock_tl"
--- | "clock_tr"
--- | "clock_bl"
--- | "clock_br"Used to index extra positions.
---@alias config_and_position {
--- config:vim.api.keyset.win_config,
--- pos:position_abrv,
--- name_location: "footer"|"title",
--- }The full options object that gets used internally by the draw function, detailing where to open a window, where its "title"/"footer" goes, and the valid nvim config.
---@alias FLOAT {
--- actions: ACTIONS,
--- state: STATE,
--- attach_style: fun(STYLE:STYLE),
--- style_tables: {[style_name]:STYLE},
--- positions: {[position_abrv]:POSITION},
--- draw: FLOAT.draw,
--- open: fun(
--- opts:{
--- style_name:style_name,
--- pos:position_abrv,
--- is_not_scratch:boolean | nil,
--- buf: integer | nil,
--- },
--- ),
--- close: fun(bufwin_state:bufwin_state),
--- hide: fun(bufwin_state:bufwin_state),
--- toggle: fun(style_name:style_name, pos: position_abrv | nil),
--- toggle_hide: fun(style_name:style_name, pos: position_abrv | nil),
--- }The Core of the plugin, holds the STATE of the plugin, exposes functions to the user, and holds the configured positions and styles
---@alias POSITION fun():config_and_positionThe "config function" for a position.
Returns the config_and_position that is passed into the draw function that defines what a window looks like and where it is.
Function is called when a window is to be opened, allowing for dynamic configuration (e.g. checking current number of lines/columns).
---@alias STYLE {
--- name: style_name,
--- positions: position_abrv[],
--- dont_focus: boolean | nil,
--- is_not_scratch: boolean | nil,
--- INIT: (fun(
--- FLOAT:FLOAT,
--- ):nil) | nil,
--- setup: (fun(STATE:STATE)),
--- style: (fun(opts:{
--- state:STATE,
--- bufwin:bufwin,
--- conf_pos:config_and_position,
--- data:table, --- individual float styles define what their data looks like.
--- }):nil),
--- push: (fun(
--- STATE:STATE,
--- bufwin_pos:bufwin_pos,
--- ):nil),
--- pop: (fun(
--- STATE:STATE,
--- bufwin_state:bufwin_state,
--- ):nil),
--- }The full configuration that is provided to define the look, internal state storage, and any behaviour/functionallity of the window.
type: style_name Required field.
style_name are simply strings that are extended as with position_abrv.
This is used in two major ways:
- indexing in the data that the style stores in the global STATE object.
- calling the specific style's methods when handling a floating window.
This means that it must be identical to the key used to index it in the opts.styles table.
type: position_abrv[] Required field.
In a STYLE table, positions is a list of positions that can be used to open a window. They are checked in order to see if the global STATE object has an open window in that position and then if uses the first free (or opens in the 1st position in from the list if they are all occupied).
- type: boolean | nil
- default value: nil
- default behaviour: moves into the window when it's been set up.
If set to true then the window will not focus on creation or through require("floating").toggle(style).
Used for "info" windows rather than "editing" windows.
- type: boolean | nil
- default value: nil
- default behaviour: makes an editable buffer.
If set to true then the buffer will be created as a scratch buffer see |help:nvim_create_buf()| for more details..
- type: (fun(FLOAT:FLOAT:nil) | nil
- default value: function(FLOAT) end
This is called for each STYLE table when the module is loaded, before each style is initialised, STATE[style_name] = {} is set.
This allows the user to define a data object that can be used during style.setup which is needed if the style needs some data from before entering the new window (e.g. old buffer's file-type) to decide what it's doing.
See STATE.style_data
- type: fun(state:state:nil
- required field.
This function is called right before a new window (or it's buffer) is opened/created, so data can be stored in STATE[style_name] and window configuration overrides can be calculated.
type:fun(opts:{
state:[STATE](#types-state),
bufwin:[bufwin](#types-bufwin),
conf_pos:[config_and_position](#types-configandposition),
data:[table](#types-statestyledata),
})
required field.
This is the function that's called right after a window is opened (usually from inside the window) to allow for the actual styling to happen. E.g. setting file-type, inserting text, and so on.
These are largely not-needed, indeed their default does nothing. They exist to allow individual styles to hold state for multiple windows.
largely not-needed,
style.push could store a list of currently open windows of a type, allowing cycling through that list as the "in-focus" window.
---@alias push fun(
--- STATE:STATE,
--- bufwin_pos:bufwin_pos,
--- ):nillargely not-needed,
style.pop is used to clean up this data when a window is closed.
---@alias pop fun(
--- STATE:STATE,
--- bufwin_pos:bufwin_pos,
--- ):nilsee Installation: Options for more details.
The options that are passed into the modules requires("floating").setup(opts)
---@alias Setup_Opts {
--- dev: boolean | nil,
--- dont_load_default_user_commands: boolean | nil,
--- dont_use_default_keymaps: boolean | nil,
--- styles:{[style_name]:STYLE},
--- positions: {[position_abrv]:POSITION},
--- extras: {
--- positions:extra_positions[],
--- styles:extra_styles[],
--- }
--- }Note that this has internal types that you really shouldn't be messing around with, but one type is exposed (a class) to allow you to add your own data structure for new style types.
-- adds type support for this style's data.
---@class STATE.style_data
---@field duplicate? {
--- old_buf:integer,
--- bufwins : bufwin_pos[],
--- }The main goal is to store temporary data for a single buffer during the creation process.
If more permanent data is needed or multiple buffers need data for a single style type then see style.push and style.pop.
The following is included for completeness (and to assist in future development), but should not be used externally, though it could technically be accessed (e.g. require("floating").state.get_last_index() is a valid function call) there is no guarantee that these internal functions and behaviours won't be changed in breaking ways.
Used internally by the open function to draw the window after open sets up data, allowing STATE.style_data to setup data from before the window is drawn.
opts:{
position:[position_abrv](#types-positionabrv),
buf:integer | nil,
dont_focus:boolean | nil,
}
{
bufwin:[bufwin](#types-bufwin) , -- {-1, -1} for a failed attempt.
draw_opts:[config_and_position](#types-configandposition)
}
local float = require("floating")
float.draw({
position="tr",
buf=0,
dont_focus=true,
})---@alias STATE {
--- window_states:bufwin_state[],
--- style_data:STATE.style_data,
--- check:fun(
--- STATE:STATE,
--- position_abrv:position_abrv,
--- ),
--- get_last_win:(fun(
--- STATE:STATE,
--- ):bufwin_state | nil),
--- get_last_index:(fun(
--- STATE:STATE,
--- ):integer | nil),
--- get_first_free_position:(fun(
--- STATE:STATE,
--- position_list:position_abrv[],
--- ):position_abrv),
--- push_win:(fun(
--- STATE:STATE,
--- bufwin_state:bufwin_state,
--- ):boolean),
--- toggle:(fun(
--- FLOAT:FLOAT,
--- style_name:style_name,
--- )),
--- toggle_hide:(fun(
--- FLOAT:FLOAT,
--- style_name:style_name,
--- )),
--- }A global list of open windows.
---@class STATE.style_dataA blank slate for styles to impose their own data structure into.
e.g.
---@class STATE.style_data
---@field scratch? {
--- filetype:string,
--- }---@type fun(
--- STATE:STATE,
--- position_abrv:position_abrv,
--- ),See STATE, position_abrv
Checks to see if a specific position is empty to open a new window in it. Ignores closed windows.
---@type fun(STATE:STATE):(bufwin_state | nil)See STATE, bufwin_state
Returns the most recently opened window. Hidden windows are ignored.
---@type fun(STATE):(integer | nil)See STATE.
returns the index of the last opened window in the STATE.window_states table.
Ignores hidden windows.
---@type fun(
--- STATE:STATE,
--- position_list:position_abrv[],
--- ):position_abrvSee STATE, position_abrv
given a list of positions returns the first one that doesn't contain an open window. If all are full, returns the first position_abrv in the list.
---@type fun(
--- STATE:STATE,
--- bufwin_state:bufwin_state,
--- ):booleanSee STATE, position_abrv.
Adds a bufwin along with it's position and style to the STATE.
---@type fun(
--- FLOAT:FLOAT,
--- style_name:style_name,
--- )See FLOAT, style_name
Is exposed to user as the toggle function, without the FLOAT needing to be passed.
Full details in toggle.
---@type fun(
--- FLOAT:FLOAT,
--- style_name:style_name,
--- )See FLOAT, style_name
Is exposed to user as the toggle_hide function, without the FLOAT needing to be passed.
Full details in toggle.
---@alias ACTIONS {
--- close:ACTIONS.close,
--- close_last:ACTIONS.close_last,
--- draw:ACTIONS.draw,
--- ensure_buffer:ACTIONS.ensure_buffer,
--- hide:ACTIONS.hide,
--- new_scratch_buffer:ACTIONS.new_scratch_buffer,
--- open:ACTIONS.open,
---}The collection of non-state-dependant functions that the plugin needs to be able to perform.
---@alias ACTIONS.draw fun(
--- position:position_abrv,
--- buf:integer | nil,
--- dont_focus:boolean | nil,
--- ): {
--- bufwin:bufwin, -- {-1, -1} for a failed attempt.
--- draw_opts:config_and_position,
--- }See position_abrv, bufwin, and config_and_position.
Is exposed to the rest of the plugin (not the user) as FLOAT.draw.
Used for creating new windows while allowing setup to be separated.
---@alias ACTIONS.open fun(
--- FLOAT:FLOAT,
--- opts: {
--- style_name:style_name,
--- pos:position_abrv,
--- is_not_scratch:boolean | nil,
--- buf: integer | nil,
--- }
--- )see FLOAT, style_name, position_abrv.
Opens a particular style in a particular position.
Exposed to the user without the FLOAT dependency as FLOAT.opne.
---@alias ACTIONS.close fun(
--- FLOAT:FLOAT,
--- opts: {
--- bufwin_state:bufwin_state | nil,
--- pos:position_abrv | nil,
--- style_name:style_name | nil,
--- },
--- )see FLOAT, bufwin_state, position_abrv
Closes a specific window, or the most recent one matching position or state.
Priorities:
- Specific bufwin_state given.
- both position and style given: closes the most recently opened window that matches both.
- If style or position are given: closes the most recently opened window that matches the given.
---@alias ACTIONS.close_last fun(
--- FLOAT:FLOAT,
--- opts: {
--- position_list:position_abrv[] | nil,
--- style:STYLE | nil,
--- },
--- ):boolean | nilcloses the most recently opened window, either by position or style.
---@alias ACTIONS.hide fun(
--- FLOAT:FLOAT,
--- opts: {
--- bufwin_state:bufwin_state | nil,
--- pos:position_abrv | nil,
--- style_name:style_name | nil,
--- },
--- )Hides a window either by position or state.
---@alias ACTIONS.hide_last fun(
--- FLOAT:FLOAT,
--- opts: {
--- position_list:position_abrv[] | nil,
--- style:STYLE | nil,
--- },
--- ):boolean | nilhides a specific window, or the most recent one matching position or state.
Priorities:
- Specific bufwin_state given.
- both position and style given: closes the most recently opened window that matches both.
- If style or position are given: closes the most recently opened window that matches the given.