summaryrefslogtreecommitdiff
path: root/lua/warp/col_selectors/grid.lua
blob: 2ee24a9943deb273d64d01f0a837998d1d3df113 (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
local vim = assert(vim)

local util = require('warp.util')
local M = {}

local big_line, col_map = (function ()
  -- Longest possible line alternating between vowels and (vowels + consanants)
  -- which does not have a repeated substring of length 2.
  --
  -- Size is 5*(26 + 21) + 1
  --
  -- It can reference up 235 unique columns. That should be enough even for
  -- Java.
  local big_line =
         "tetaoinuserahodilucemafoyiwugepabovikuxeqajozitunesarohidulecamofiyuw"
      .. "egapobivukexaqojizutonasirehudelacomifuyewagopibuvekaxoqijuzenotisuri"
      .. "hadalocumefeyawogipubevakoxiqujezanicimuhedosorufayoligupebavowixuqej"
      .. "azokieaueoaiuaeiouooeeuuiiaat"
  local col_map = {}
  local i = 0

  while i < #big_line do
    local sub = big_line:sub(i, i + 1)
    if col_map[sub] then
      -- Sanity check
      error("repeated sequence: '" .. sub .. "'", 2)
    end
    col_map[sub] = i
    i = i + 1
  end

  return big_line, col_map
end)()

local function char_at(s, i)
  local m = (i % #s) + 1
  return string.sub(s, m, m)
end

M.strategy = function()
  local leftcol = vim.fn.winsaveview().leftcol
  local filter

  return util.wrap_col_selector({
    display = function()
      local curpos = vim.api.nvim_win_get_cursor(0)
      local line_at = vim.fn.getline(curpos[1])
      local current_win = vim.api.nvim_get_current_win();
      local wininfo = vim.fn.getwininfo(current_win)[1]

      local width = wininfo.width - wininfo.textoff
      if vim.o.virtualedit ~= 'all' then
        width = math.min(#line_at + 1, width)
      end
      if vim.o.virtualedit == 'onemore' then
        width = width + 1
      end

      local unfiltered = big_line:sub(leftcol + 1, width)
      local line = unfiltered

      if filter then
        line = ""
        local i = 1
        while i <= #unfiltered do
          local curch = char_at(unfiltered, i - 1)
          if curch == filter then
            line = line .. char_at(unfiltered, i)
          else
            line = line .. ' '
          end
          i = i + 1
        end
      end

      return line
    end,

    on_char = function(ch)
      if not filter then
        if ch == '$' or ch == '^' then
          vim.cmd("normal! " .. ch)
          return false
        elseif not ch:match('[a-z]') then
          vim.cmd("normal! f" .. ch)
          return false
        else
          filter = ch
          return true
        end
      else
        if col_map[filter .. ch] then
          vim.cmd("normal! " .. col_map[filter .. ch] .. "|")
        end
      end

      return false
    end
  })
end

M.run = function ()
  print(big_line)
  M.strategy().run()
end


return M