local M = {} function M.open(name, content, opts) if name == '' then return end if #content == 0 then return end local opts = opts or {} local autoclose = opts.autoclose or false local buf_opts = opts.buf or { buftype = '' } local win_opts = opts.win or false -- profiles if type(win_opts) == 'table' and type(win_opts[1] == 'string') then local profile = win_opts[1] local overwrites = unpack(win_opts, 2) if profile == 'emplace' then win_opts = false elseif profile == 'smallsplit' then win_opts = { split = 'above', win = 0, height = 20, } elseif profile == 'popup' then local winh = vim.api.nvim_win_get_height(0) local winw = vim.api.nvim_win_get_width(0) local winsize = 0.5 win_opts = { relative = 'win', height = math.floor(winh * winsize), width = math.floor(winw * winsize), row = math.floor((winh * 0.5) - (0.5 * (winh * winsize))), col = math.floor((winw * 0.5) - (0.5 * (winw * winsize))), style = 'minimal', border = 'single', zindex = 99, title = name, } end if overwrites then for k, v in pairs(overwrites) do win_opts[k] = v end end end local bufnr = vim.api.nvim_create_buf(false, true) assert(bufnr ~= 0, 'Failed to create buffer') vim.bo[bufnr].modifiable = true vim.api.nvim_buf_set_name(bufnr, name) vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, content) for k, v in pairs(buf_opts) do vim.bo[bufnr][k] = v end -- without win_opts (by default) replace current buffer local winid = 0 if win_opts then winid = vim.api.nvim_open_win(0, not autoclose, win_opts) assert(winid ~= 0, 'Failed to create window') end vim.keymap.set('n', 'q', 'quit!', { silent = true, buffer = bufnr }) if autoclose then local group = 'modwin_' .. vim.base64.encode(vim.uv.random(16)) local group_id = vim.api.nvim_create_augroup(group, {}) vim.api.nvim_create_autocmd('WinClosed', { pattern = tostring(winid), group = group_id, callback = function() vim.api.nvim_create_augroup(group, {}) M.winid = nil end, }) vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, { group = group_id, callback = function() vim.api.nvim_create_augroup(group, {}) pcall(vim.api.nvim_win_close, winid, true) end, }) end vim.api.nvim_win_set_buf(winid, bufnr) return { bufnr, winid } end function M.popup(name, content, opts) local defaults = { autoclose = true, buf = { bufhidden = 'wipe', buftype = 'nofile', modifiable = false, }, win = { 'popup' }, } opts = opts or {} opts = vim.tbl_deep_extend('force', defaults, opts) M.open(name, content, opts) end return M