summary refs log tree commit diff
path: root/.config/nvim/lua/mod/win.lua
diff options
context:
space:
mode:
authorRobert Günzler <r@gnzler.io>2026-09-27 17:38:39 +0200
committerRobert Günzler <r@gnzler.io>2026-09-27 17:38:39 +0200
commit0860db73ae6fd9a6f6347219d820bf026a6b8b91 (patch)
tree11318c3670d1c32c5aa0bf404c22fba3bf63fc53 /.config/nvim/lua/mod/win.lua
parent4e34cbf9673aeaba252e01df554a0d204e83c5e2 (diff)
downloaddotfiles-master.tar.gz
Automated-commit-by: dots
Signed-off-by: Robert Günzler <r@gnzler.io>
Diffstat (limited to '.config/nvim/lua/mod/win.lua')
-rw-r--r--.config/nvim/lua/mod/win.lua110
1 files changed, 110 insertions, 0 deletions
diff --git a/.config/nvim/lua/mod/win.lua b/.config/nvim/lua/mod/win.lua
new file mode 100644
index 0000000..e5c5f71
--- /dev/null
+++ b/.config/nvim/lua/mod/win.lua
@@ -0,0 +1,110 @@
+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', '<cmd>quit!<cr>', { 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