A floating vim.ui.input buffer that auto-resizes to fit its contents.
0

Configure Feed

Select the types of activity you want to include in your feed.

fix wrapping estimation logic

r0nsha (Jun 27, 2025, 1:03 PM +0300) 80276380 15a18cd3

+20 -50
+20 -50
lua/wrapinput.lua
··· 12 12 ---@type wrapinput.Config 13 13 local defaults = { 14 14 default = "", 15 - padding = 20, 16 - max_width = 60, 15 + padding = 10, 16 + max_width = 50, 17 17 max_height = 6, 18 18 win = { 19 19 title = "Input: ", ··· 39 39 ---@param text string 40 40 ---@param width integer 41 41 ---@return string[] 42 - local function guesstimate_wrapped_lines(text, width) 43 - local breakat = vim.o.breakat 44 - local linebreak = vim.wo.linebreak 45 - local showbreak = vim.o.showbreak 46 - local showbreak_width = vim.fn.strdisplaywidth(showbreak) 47 - 48 - local result = {} 49 - local current_line = "" 50 - local current_width = 0 51 - local last_break_idx = nil 42 + local function split_wrapped_lines(text, width) 43 + if text == "" then 44 + return {} 45 + end 52 46 53 - local i = 1 54 - while i <= #text do 55 - local char = text:sub(i, i) 56 - 57 - local char_width = vim.fn.strdisplaywidth(char) 58 - 59 - -- Track legal break point 60 - if breakat:find(vim.pesc(char), 1, true) then 61 - last_break_idx = #current_line + 1 62 - end 63 - 64 - -- If this char would overflow screen width 65 - if current_width + char_width > width then 66 - if linebreak and last_break_idx then 67 - table.insert(result, current_line:sub(1, last_break_idx)) 68 - i = i - (#current_line - last_break_idx) 69 - elseif last_break_idx then 70 - table.insert(result, current_line:sub(1, last_break_idx)) 71 - i = i - (#current_line - last_break_idx) 72 - else 73 - table.insert(result, current_line) 74 - end 47 + ---@type string[] 48 + local lines = {} 49 + local textlen = vim.fn.strchars(text, true) 75 50 76 - -- Reset for wrapped line 77 - current_line = showbreak 78 - current_width = showbreak_width 79 - last_break_idx = nil 80 - else 81 - current_line = current_line .. char 82 - current_width = current_width + char_width 83 - i = i + 1 84 - end 85 - end 51 + local i = 0 52 + while i < textlen do 53 + local len = i + width <= textlen and width or textlen - i 54 + local new_line = vim.fn.strcharpart(text, i, len) 86 55 87 - if #current_line > 0 then 88 - table.insert(result, current_line) 56 + table.insert(lines, new_line) 57 + i = i + len 89 58 end 90 59 91 - return result 60 + return lines 92 61 end 93 62 94 63 ---@param winnr integer 95 64 ---@param bufnr integer 96 65 ---@param config wrapinput.Config 97 66 local function resize(winnr, bufnr, config) 98 - local line = vim.api.nvim_buf_get_lines(bufnr, 0, 1, false)[1] 67 + local text = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) 68 + local line = table.concat(text, "") 99 69 100 70 if line == "" then 101 71 vim.api.nvim_win_set_width(winnr, config.padding) ··· 103 73 return 104 74 end 105 75 106 - local lines = guesstimate_wrapped_lines(line, config.max_width) 76 + local lines = split_wrapped_lines(line, config.max_width) 107 77 108 78 local lens = vim.tbl_map(function(l) 109 79 return vim.fn.strdisplaywidth(l) ··· 167 137 ---@param opts table 168 138 ---@param on_confirm fun(input: string?) 169 139 function M.input(config, opts, on_confirm) 170 - config = vim.tbl_deep_extend("force", defaults, config, opts, { win = { title = config.prompt } }) 140 + config = vim.tbl_deep_extend("force", defaults, config, opts, { win = { title = opts.prompt } }) 171 141 on_confirm = on_confirm or function() end 172 142 173 143 config = vim.tbl_deep_extend(