summaryrefslogtreecommitdiff
path: root/lua/warp/row_selectors/grid.lua
blob: bd9509fb78d1373ce26e71937e7b425ca921552d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
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(4, 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