diff --git a/.stylua.toml b/.stylua.toml
new file mode 100644
index 0000000..51091a8
--- /dev/null
+++ b/.stylua.toml
@@ -0,0 +1,10 @@
+indent_type = "Spaces"
+indent_width = 2
+column_width = 120
+line_endings = "Unix"
+quote_style = "AutoPreferDouble"
+call_parentheses = "Always"
+collapse_simple_statement = "Never"
+
+[sort_requires]
+enabled = false
diff --git a/README.md b/README.md
index 126505c..579f0fc 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,9 @@ when complete
## Installation
+
+- Using vim-plug
+
```vim
" This is a requirement, which implements some useful window management
" items for neovim
@@ -13,6 +16,19 @@ Plug 'nvim-lua/plenary.nvim'
Plug 'nvim-lua/popup.nvim'
```
+
+
+- Using lazy.nvim
+
+```lua
+{
+ 'nvim-lua/popup.nvim',
+ dependencies = { 'nvim-lua/plenary.nvim' },
+}
+```
+
+
+
## Goals
Provide an API that is compatible with the vim `popup_*` APIs. After
diff --git a/lua/popup/_compat.lua b/lua/popup/_compat.lua
index 17d9c27..9ed4f75 100644
--- a/lua/popup/_compat.lua
+++ b/lua/popup/_compat.lua
@@ -1,3 +1,4 @@
local compat = {}
return compat
+--- vim:ts=2:sts=2:sw=2:et:
diff --git a/lua/popup/init.lua b/lua/popup/init.lua
index e6ff845..9ebbb98 100644
--- a/lua/popup/init.lua
+++ b/lua/popup/init.lua
@@ -7,46 +7,56 @@ local Border = require("plenary.window.border")
local Window = require("plenary.window")
local utils = require("popup.utils")
+---@class popup.PositionMap
+---@field topleft "NW"
+---@field topright "NE"
+---@field botleft "SW"
+---@field botright "SE"
+
+---@param options table
+---@param key string
+---@param default table
+---@return any
+local function dict_default(options, key, default)
+ return options[key] ~= nil and options[key] or default[key]
+end
+
local popup = {}
+---@type popup.PositionMap
popup._pos_map = {
- topleft="NW",
- topright="NE",
- botleft="SW",
- botright="SE",
+ topleft = "NW",
+ topright = "NE",
+ botleft = "SW",
+ botright = "SE",
}
-
--- Keep track of hidden popups, so we can load them with popup.show()
+--- Keep track of hidden popups, so we can load them with popup.show()
+---@type table
popup._hidden = {}
-
-local function dict_default(options, key, default)
- if options[key] == nil then
- return default[key]
- else
- return options[key]
- end
-end
-
-- Callbacks to be called later by popup.execute_callback
popup._callbacks = {}
+---@param what integer|string|table
+---@param vim_options table
+---@return integer, table
function popup.create(what, vim_options)
local bufnr
- if type(what) == 'number' then
+
+ if type(what) == "number" then
bufnr = what
else
bufnr = vim.api.nvim_create_buf(false, true)
assert(bufnr, "Failed to create buffer")
- vim.api.nvim_buf_set_option(bufnr, "bufhidden", "wipe")
+ vim.api.nvim_set_option_value("bufhidden", "wipe", { buf = bufnr })
-- TODO: Handle list of lines
- if type(what) == 'string' then
- what = {what}
+ if type(what) == "string" then
+ what = { what }
else
- assert(type(what) == 'table', '"what" must be a table')
+ assert(type(what) == "table", '"what" must be a table')
end
-- padding List with numbers, defining the padding
@@ -72,18 +82,18 @@ function popup.create(what, vim_options)
pad_left = padding[4] or 0
end
- local left_padding = string.rep(' ', pad_left)
- local right_padding = string.rep(' ', pad_right)
+ local left_padding = string.rep(" ", pad_left)
+ local right_padding = string.rep(" ", pad_right)
for index = 1, #what do
- what[index] = string.format('%s%s%s', left_padding, what[index], right_padding)
+ what[index] = string.format("%s%s%s", left_padding, what[index], right_padding)
end
for _ = 1, pad_top do
- table.insert(what, 1, '')
+ table.insert(what, 1, "")
end
for _ = 1, pad_below do
- table.insert(what, '')
+ table.insert(what, "")
end
end
@@ -91,26 +101,27 @@ function popup.create(what, vim_options)
end
local option_defaults = {
- posinvert = true
+ posinvert = true,
}
local win_opts = {}
win_opts.relative = "editor"
+ ---@type fun(pos_str: string, dim: string): integer
local cursor_relative_pos = function(pos_str, dim)
- assert(string.find(pos_str,'^cursor'), "Invalid value for " .. dim)
- win_opts.relative = 'cursor'
+ assert(string.find(pos_str, "^cursor"), "Invalid value for " .. dim)
+ win_opts.relative = "cursor"
local line = 0
- if (pos_str):match "cursor%+(%d+)" then
- line = line + tonumber((pos_str):match "cursor%+(%d+)")
- elseif (pos_str):match "cursor%-(%d+)" then
- line = line - tonumber((pos_str):match "cursor%-(%d+)")
+ if (pos_str):match("cursor%+(%d+)") then
+ line = line + tonumber((pos_str):match("cursor%+(%d+)"))
+ elseif (pos_str):match("cursor%-(%d+)") then
+ line = line - tonumber((pos_str):match("cursor%-(%d+)"))
end
return line
end
if vim_options.line then
- if type(vim_options.line) == 'string' then
+ if type(vim_options.line) == "string" then
win_opts.row = cursor_relative_pos(vim_options.line, "row")
else
win_opts.row = vim_options.line
@@ -122,7 +133,7 @@ function popup.create(what, vim_options)
end
if vim_options.col then
- if type(vim_options.col) == 'string' then
+ if type(vim_options.col) == "string" then
win_opts.col = cursor_relative_pos(vim_options.col, "col")
else
win_opts.col = vim_options.col
@@ -133,7 +144,7 @@ function popup.create(what, vim_options)
end
if vim_options.pos then
- if vim_options.pos == 'center' then
+ if vim_options.pos == "center" then
-- TODO: Do centering..
else
win_opts.anchor = popup._pos_map[vim_options.pos]
@@ -150,7 +161,7 @@ function popup.create(what, vim_options)
-- , the popup is moved to the left so as to fit the
-- , contents on the screen. Set to TRUE to disable this.
- win_opts.style = 'minimal'
+ win_opts.style = "minimal"
-- Feels like maxheight, minheight, maxwidth, minwidth will all be related
--
@@ -160,10 +171,10 @@ function popup.create(what, vim_options)
-- minwidth Minimum width of the contents, excluding border, padding and scrollbar.
local width = vim_options.width or 1
local height
- if type(what) == 'number' then
+ if type(what) == "number" then
height = vim.api.nvim_buf_line_count(what)
else
- for _, v in ipairs(what) do
+ for _, v in next, what do
width = math.max(width, #v)
end
height = #what
@@ -176,7 +187,7 @@ function popup.create(what, vim_options)
-- , vertically and there is more space on the other side
-- , then the popup is placed on the other side of the
-- , position indicated by "line".
- if dict_default(vim_options, 'posinvert', option_defaults) then
+ if dict_default(vim_options, "posinvert", option_defaults) then
if win_opts.anchor == "NW" or win_opts.anchor == "NE" then
if win_opts.row + win_opts.height > vim.o.lines and win_opts.row * 2 > vim.o.lines then
-- Don't know why, but this is how vim adjusts it
@@ -205,12 +216,11 @@ function popup.create(what, vim_options)
win_id = vim.api.nvim_open_win(bufnr, false, win_opts)
end
-
-- Moved, handled after since we need the window ID
if vim_options.moved then
- if vim_options.moved == 'any' then
- vim.lsp.util.close_preview_autocmd({'CursorMoved', 'CursorMovedI'}, win_id)
- elseif vim_options.moved == 'word' then
+ if vim_options.moved == "any" then
+ vim.lsp.util.close_preview_autocmd({ "CursorMoved", "CursorMovedI" }, win_id)
+ elseif vim_options.moved == "word" then
-- TODO: Handle word, WORD, expr, and the range functions... which seem hard?
end
else
@@ -218,7 +228,7 @@ function popup.create(what, vim_options)
vim.cmd(
string.format(
"autocmd BufDelete %s ++once ++nested :lua require('plenary.window').try_close(%s, true)",
- (silent and "") or '',
+ (silent and "") or "",
bufnr,
win_id
)
@@ -227,18 +237,22 @@ function popup.create(what, vim_options)
if vim_options.time then
local timer = vim.loop.new_timer()
- timer:start(vim_options.time, 0, vim.schedule_wrap(function()
- Window.try_close(win_id, false)
- end))
+ timer:start(
+ vim_options.time,
+ 0,
+ vim.schedule_wrap(function()
+ Window.try_close(win_id, false)
+ end)
+ )
end
-- Buffer Options
if vim_options.cursorline then
- vim.api.nvim_win_set_option(win_id, 'cursorline', true)
+ vim.api.nvim_set_option_value("cursorline", true, { win = win_id })
end
if vim_options.wrap ~= nil then
- vim.api.nvim_win_set_option(win_id, 'wrap', vim_options.wrap)
+ vim.api.nvim_set_option_value("wrap", vim_options.wrap, { win = win_id })
end
-- ===== Not Implemented Options =====
@@ -267,7 +281,7 @@ function popup.create(what, vim_options)
if vim_options.border then
should_show_border = true
- if type(vim_options.border) == 'boolean' or vim.tbl_isempty(vim_options.border) then
+ if type(vim_options.border) == "boolean" or vim.tbl_isempty(vim_options.border) then
border_options.border_thickness = Border._default_thickness
elseif #vim_options.border == 4 then
border_options.border_thickness = {
@@ -277,10 +291,7 @@ function popup.create(what, vim_options)
left = utils.bounded(vim_options.border[4], 0, 1),
}
else
- error(string.format(
- "Invalid configuration for border: %s",
- vim.inspect(vim_options.border)
- ))
+ error(string.format("Invalid configuration for border: %s", vim.inspect(vim_options.border)))
end
elseif vim_options.border == false then
should_show_border = false
@@ -303,19 +314,19 @@ function popup.create(what, vim_options)
local b_top, b_right, b_bot, b_left, b_topleft, b_topright, b_botright, b_botleft
if vim_options.borderchars == nil then
- b_top , b_right , b_bot , b_left , b_topleft , b_topright , b_botright , b_botleft =
- "═" , "║" , "═" , "║" , "╔" , "╗" , "╝" , "╚"
+ b_top, b_right, b_bot, b_left, b_topleft, b_topright, b_botright, b_botleft =
+ "═", "║", "═", "║", "╔", "╗", "╝", "╚"
elseif #vim_options.borderchars == 1 then
local b_char = vim_options.borderchars[1]
- b_top , b_right , b_bot , b_left , b_topleft , b_topright , b_botright , b_botleft =
- b_char , b_char , b_char , b_char , b_char , b_char , b_char , b_char
+ b_top, b_right, b_bot, b_left, b_topleft, b_topright, b_botright, b_botleft =
+ b_char, b_char, b_char, b_char, b_char, b_char, b_char, b_char
elseif #vim_options.borderchars == 2 then
local b_char = vim_options.borderchars[1]
local c_char = vim_options.borderchars[2]
- b_top , b_right , b_bot , b_left , b_topleft , b_topright , b_botright , b_botleft =
- b_char , b_char , b_char , b_char , c_char , c_char , c_char , c_char
+ b_top, b_right, b_bot, b_left, b_topleft, b_topright, b_botright, b_botleft =
+ b_char, b_char, b_char, b_char, c_char, c_char, c_char, c_char
elseif #vim_options.borderchars == 8 then
- b_top , b_right , b_bot , b_left , b_topleft , b_topright , b_botright , b_botleft = unpack(vim_options.borderchars)
+ b_top, b_right, b_bot, b_left, b_topleft, b_topright, b_botright, b_botleft = unpack(vim_options.borderchars)
else
error(string.format('Not enough arguments for "borderchars"'))
end
@@ -342,11 +353,15 @@ function popup.create(what, vim_options)
end
if vim_options.highlight then
- vim.api.nvim_win_set_option(win_id, 'winhl', string.format('Normal:%s', vim_options.highlight))
+ vim.api.nvim_set_option_value("winhl", string.format("Normal:%s", vim_options.highlight), { win = win_id })
end
if vim_options.borderhighlight then
- vim.api.nvim_win_set_option(border.win_id, 'winhl', string.format('Normal:%s', vim_options.borderhighlight))
+ vim.api.nvim_set_option_value(
+ "winhl",
+ string.format("Normal:%s", vim_options.borderhighlight),
+ { win = border.win_id }
+ )
end
-- enter
@@ -370,7 +385,13 @@ function popup.create(what, vim_options)
vim_options.callback(win_id, what[row])
vim.api.nvim_win_close(win_id, true)
end
- vim.api.nvim_buf_set_keymap(bufnr, 'n', '', 'lua require"popup".execute_callback(' .. bufnr .. ')', {noremap = true})
+ vim.api.nvim_buf_set_keymap(
+ bufnr,
+ "n",
+ "",
+ 'lua require"popup".execute_callback(' .. bufnr .. ")",
+ { noremap = true }
+ )
end
-- TODO: Perhaps there's a way to return an object that looks like a window id,
@@ -382,6 +403,7 @@ function popup.create(what, vim_options)
}
end
+---@param bufnr integer
function popup.execute_callback(bufnr)
if popup._callbacks[bufnr] then
local wrapper = popup._callbacks[bufnr]
@@ -391,3 +413,5 @@ function popup.execute_callback(bufnr)
end
return popup
+
+--- vim:ts=2:sts=2:sw=2:et:
diff --git a/lua/popup/utils.lua b/lua/popup/utils.lua
index 18815d9..a2ca7a4 100644
--- a/lua/popup/utils.lua
+++ b/lua/popup/utils.lua
@@ -1,12 +1,15 @@
-
local utils = {}
utils.bounded = function(value, min, max)
min = min or 0
max = max or math.huge
- if min then value = math.max(value, min) end
- if max then value = math.min(value, max) end
+ if min then
+ value = math.max(value, min)
+ end
+ if max then
+ value = math.min(value, max)
+ end
return value
end
@@ -18,7 +21,7 @@ utils.apply_defaults = function(original, defaults)
original = vim.deepcopy(original)
- for k, v in pairs(defaults) do
+ for k, v in next, defaults do
if original[k] == nil then
original[k] = v
end
@@ -28,3 +31,4 @@ utils.apply_defaults = function(original, defaults)
end
return utils
+--- vim:ts=2:sts=2:sw=2:et:
diff --git a/lua/tests/basic_popup_spec.lua b/lua/tests/basic_popup_spec.lua
index d7fd0ba..9839a9f 100644
--- a/lua/tests/basic_popup_spec.lua
+++ b/lua/tests/basic_popup_spec.lua
@@ -1,76 +1,77 @@
-require('plenary.reload').reload_module('popup')
+require("plenary.reload").reload_module("popup")
-local popup = require('popup')
+local popup = require("popup")
local test_level = 10
-vim.cmd [[highlight PopupColor1 ctermbg=lightblue guibg=lightblue]]
-vim.cmd [[highlight PopupColor2 ctermbg=lightcyan guibg=lightcyan]]
+vim.cmd([[highlight PopupColor1 ctermbg=lightblue guibg=lightblue]])
+vim.cmd([[highlight PopupColor2 ctermbg=lightcyan guibg=lightcyan]])
if test_level < 1 then
- popup.create('hello there', {
+ popup.create("hello there", {
line = 3,
col = 11,
minwidth = 20,
- highlight = 'PopupColor1'
+ highlight = "PopupColor1",
})
end
if test_level < 2 then
- popup.create(
- {'another one', 'another two', 'another three'},
- {
- line = 3,
- col = 25,
- minwidth = 20
- })
+ popup.create({ "another one", "another two", "another three" }, {
+ line = 3,
+ col = 25,
+ minwidth = 20,
+ })
end
if test_level == 3 then
-- Test some borders
- popup.create('hello border', {
+ popup.create("hello border", {
line = 2,
col = 3,
- border = {}
+ border = {},
})
end
-
if test_level == 4 then
- popup.create('hello padding', {
- line = 2, col = 23, padding = {}
+ popup.create("hello padding", {
+ line = 2,
+ col = 23,
+ padding = {},
})
end
if test_level == 5 then
- popup.create('hello padding', {
- line = 2, col = 23, border = {}, padding = {}
+ popup.create("hello padding", {
+ line = 2,
+ col = 23,
+ border = {},
+ padding = {},
})
end
-
if test_level == 6 then
- popup.create('all the plus signs', {
+ popup.create("all the plus signs", {
line = 8,
col = 55,
padding = { 0, 3, 0, 3 },
-- border = { 0, 1, 0, 1 }
- borderchars = {"+"}
+ borderchars = { "+" },
})
end
if test_level == 7 then
- popup.create('all the plus signs', {
+ popup.create("all the plus signs", {
line = 8,
col = 55,
padding = { 0, 3, 0, 3 },
-- border = { 0, 1, 0, 1 }
- borderchars = {"-", "+"}
+ borderchars = { "-", "+" },
})
end
if test_level == 8 then
- popup.create('just some longer text', {
+ popup.create("just some longer text", {
-- title = 'coool',
line = 8,
col = 55,
@@ -83,7 +84,7 @@ end
if test_level == 9 then
local bufnr = vim.api.nvim_create_buf(false, false)
- vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {'pass bufnr 1', 'pass bufnr 2'})
+ vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, { "pass bufnr 1", "pass bufnr 2" })
popup.create(bufnr, {
line = 8,
col = 55,
@@ -95,9 +96,11 @@ if test_level == 10 then
popup.create({ "option 1", "option 2" }, {
line = "cursor+2",
col = "cursor+2",
- border = { 1, 1, 1, 1},
- enter = true,
- cursorline = true,
- callback = function(win_id, sel) print(sel) end,
+ border = { 1, 1, 1, 1 },
+ enter = true,
+ cursorline = true,
+ callback = function(win_id, sel)
+ print(sel)
+ end,
})
end