local vim = assert(vim) local M = {} local cons = "tnshrdlcumwfgypkbvjxqz" -- 21 local vowel = "aeiou" -- 5 local hsel1 = "tnshrdlcumwfgypkbvjxqz" -- 21 local hsel2 = "aeiou" -- 5 local function char_at(s, i) local m = (i % #s) + 1 return string.sub(s, m, m) end local function new_panel(buf, row, col, width, height) local w = vim.api.nvim_open_win(buf, false, { relative = 'win', row = row, col = col, width = width, height = height, focusable = true, style = 'minimal' }) vim.api.nvim_win_set_option(w, "winhighlight", "Normal:WarpNormal") return w end M.open_vertical = function() local current_win = vim.api.nvim_get_current_win() local height = vim.api.nvim_win_get_height(current_win) local topline = vim.fn.line('w0') local width_of_garbage = vim.fn.getwininfo(current_win)[1].textoff M.row_map = {} M.vert_buf = vim.api.nvim_create_buf(0, 1) local line = 0 M.vert_lines = {} local real_width = math.max(3, width_of_garbage) while line < height do local t = char_at(cons, line) .. char_at(vowel, line) table.insert(M.vert_lines, (' '):rep(real_width - 3) .. t .. ' ') M.row_map[t] = topline + line line = line + 1 end vim.api.nvim_buf_set_lines(M.vert_buf, 0, -1, 0, M.vert_lines) return new_panel(M.vert_buf, 0, 0, real_width, height); end M.open_horiz = function() local current_win = vim.api.nvim_get_current_win() local curpos = vim.api.nvim_win_get_cursor(0) local topline = vim.fn.line('w0') local width_of_garbage = vim.fn.getwininfo(current_win)[1].textoff local width = vim.api.nvim_win_get_width(current_win) - width_of_garbage M.horiz_bufnr = vim.api.nvim_create_buf(0, 1) local line_at = vim.fn.getline(curpos[1]) local max_width = math.min(width, #line_at + 1) return new_panel(M.horiz_bufnr, curpos[1] - topline + 1, width_of_garbage - 1, max_width + 2, 1) end M.filter_horiz_string = function(ch) local new_horiz_line = '' local i = 1 while i <= #M.horiz_line do local curch = char_at(M.horiz_line, i - 1) if curch == ch then new_horiz_line = new_horiz_line .. char_at(M.horiz_line, i) else new_horiz_line = new_horiz_line .. ' ' end i = i + 1 end vim.api.nvim_buf_set_lines(M.horiz_bufnr, 0, -1, 0, {' ' .. new_horiz_line}) end M.filter_vert_text = function(ch) local new_vert_text = {} for _, t in pairs(M.vert_lines) do local str = t:gsub("^%s*" .. ch, function(m) return (' '):rep(#m) end) if t:match('^%s*' .. ch) then table.insert(new_vert_text, str) else table.insert(new_vert_text, "") end end M.vert_lines = new_vert_text vim.api.nvim_buf_set_lines(M.vert_buf, 0, -1, 0, M.vert_lines) end local function next_char() vim.cmd("redraw!") return vim.fn.nr2char(vim.fn.getchar()) end M.run = function(strat_fn) if not strat_fn then strat_fn = require('warp.strategy.default').default_col_strategy end local current_pos = vim.api.nvim_win_get_cursor(0) local old_scroll = vim.o.scrolloff vim.o.scrolloff = 0 (function() local w local cleanup = function(win) vim.api.nvim_buf_delete(vim.api.nvim_win_get_buf(win), {force = true}) end local read_row = function() w = M.open_vertical() local vch1 = next_char() if vch1 == '\x1b' then return elseif vch1 == '.' then return current_pos[1] else M.filter_vert_text(vch1) local vch2 = next_char() if vch1 == '\x1b' then return end return M.row_map[vch1 .. vch2] end end local r = read_row() if w then cleanup(w) w = nil end if not r then return end vim.api.nvim_win_set_cursor(0, {r, current_pos[2]}) local strat = strat_fn() w = M.open_horiz() local disp = strat.display() if disp then vim.api .nvim_buf_set_lines(M.horiz_bufnr, 0, -1, 0, {' ' .. disp}) local ch = next_char() while ch ~= '\x1b' and strat.on_char(ch) do vim.api.nvim_buf_set_lines(M.horiz_bufnr, 0, -1, 0, {' ' .. strat.display()}) ch = next_char() end end cleanup(w) end)() vim.o.scrolloff = old_scroll end return M