Files
input-form.nvim/lua/input-form/inputs/text.lua
2026-04-06 00:51:27 +03:00

93 lines
2.4 KiB
Lua

--- Single-line text input component.
local utils = require("input-form.utils")
local M = {}
M.__index = M
--- Create a new text input from its spec.
---@param spec table { name, label, default? }
---@return table
function M.new(spec)
return setmetatable({
type = "text",
name = spec.name,
label = spec.label or spec.name,
_value = spec.default or "",
buf = nil,
win = nil,
}, M)
end
--- Number of content rows (excluding the label line) this input occupies.
function M:height()
return 1
end
function M:is_bordered()
return true
end
--- Create the backing buffer and floating window.
---@param layout table { row, col, width }
function M:mount(layout)
self.buf = vim.api.nvim_create_buf(false, true)
vim.bo[self.buf].buftype = "nofile"
vim.bo[self.buf].bufhidden = "wipe"
vim.bo[self.buf].swapfile = false
utils.mark_form_buffer(self.buf)
vim.api.nvim_buf_set_lines(self.buf, 0, -1, false, { self._value })
local win_cfg = {
relative = "editor",
row = layout.row,
col = layout.col,
width = layout.width,
height = 1,
style = "minimal",
focusable = true,
zindex = 50,
}
if layout.border then
win_cfg.border = layout.border
win_cfg.title = " " .. self.label .. " "
win_cfg.title_pos = "left"
end
self.win = vim.api.nvim_open_win(self.buf, false, win_cfg)
vim.wo[self.win].winhl =
"NormalFloat:InputFormField,FloatBorder:InputFormFieldBorder,FloatTitle:InputFormFieldTitle"
end
--- Return current value (from the buffer if mounted, otherwise the cached value).
function M:value()
if self.buf and vim.api.nvim_buf_is_valid(self.buf) then
local lines = vim.api.nvim_buf_get_lines(self.buf, 0, -1, false)
return lines[1] or ""
end
return self._value
end
--- Close the window and buffer, caching the current value.
function M:unmount()
self._value = self:value()
if self.win and vim.api.nvim_win_is_valid(self.win) then
vim.api.nvim_win_close(self.win, true)
end
if self.buf and vim.api.nvim_buf_is_valid(self.buf) then
vim.api.nvim_buf_delete(self.buf, { force = true })
end
self.win = nil
self.buf = nil
end
--- Give this input focus and enter insert mode at the end of the line.
function M:focus()
if self.win and vim.api.nvim_win_is_valid(self.win) then
vim.api.nvim_set_current_win(self.win)
local line = self:value()
vim.api.nvim_win_set_cursor(self.win, { 1, #line })
end
end
return M