local M = {} local util = require("warp.util") local cons = "tnshrdlcumwfgypkbvjxqz" -- 21 local vowel = "aeiou" -- 5 local function char_at(s, i) local m = (i % #s) + 1 return string.sub(s, m, m) end local function open_vertical(opts) 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 local row_map = {} local left_buf = vim.api.nvim_create_buf(0, 1) local right_buf = vim.api.nvim_create_buf(0, 1) local line = 0 local real_width = math.max(3, width_of_garbage) local left_lines = {} local right_lines = {} local undecorated_lines = {} local function pad_left(t) return (' '):rep(real_width - 3) .. t .. ' ' end local function pad_right(t) return ' ' .. t .. ' ' end while line < height do local t = char_at(cons, line) .. char_at(vowel, line) table.insert(undecorated_lines, t) table.insert(left_lines, pad_left(t)) table.insert(right_lines, pad_right(t)) row_map[t] = topline + line line = line + 1 end vim.api.nvim_buf_set_lines(left_buf, 0, -1, 0, left_lines) vim.api.nvim_buf_set_lines(right_buf, 0, -1, 0, right_lines) -- local curpos = vim.api.nvim_win_get_cursor(0) util.new_panel(left_buf, 0, 0, real_width, height) if opts.two_columns then local pos = vim.o.textwidth + width_of_garbage pos = math.min(vim.o.textwidth == 0 and 999999 or pos, vim.api.nvim_win_get_width(0) - 4) util.new_panel(right_buf, 0, pos, 4, height) end return { row_map = row_map, cleanup = function () vim.api.nvim_buf_delete(left_buf, {force = true}) vim.api.nvim_buf_delete(right_buf, {force = true}) end, filter_vert_text = function(ch) local new_left_text = {} local new_right_text = {} for _, t in pairs(undecorated_lines) do local str = t:gsub("^" .. ch, function(m) return (' '):rep(#m) end) if t:match('^' .. ch) then table.insert(new_left_text, pad_left(str)) table.insert(new_right_text, pad_right(str)) else table.insert(new_left_text, "") table.insert(new_right_text, "") end end vim.api.nvim_buf_set_lines(left_buf, 0, -1, 0, new_left_text) vim.api.nvim_buf_set_lines(right_buf, 0, -1, 0, new_right_text) end } end M.read_row = function(opts) local data if not opts then opts = {} end local row = (function () data = open_vertical(opts) local vch1 = util.next_char() if vch1 == '\x1b' then return elseif vch1 == '.' then return '.' else data.filter_vert_text(vch1) local vch2 = util.next_char() if vch1 == '\x1b' then return end return data.row_map[vch1 .. vch2] end end)() data.cleanup() return row end M.with_opts = function(opts) return { read_row = function() return M.read_row(opts) end } end return M