summaryrefslogtreecommitdiff
path: root/lua
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2024-03-10 23:53:04 -0600
committerJosh Rahm <joshuarahm@gmail.com>2024-03-10 23:53:04 -0600
commit2aff69b0bb55f398d199db687617ed35d0335d5b (patch)
tree135b46b6a689b1cb59a49fbbebb8c4a095429ba1 /lua
parent64fb2114f35889eff0a082200471ce3ca33e43bf (diff)
downloadnvim-warp-2aff69b0bb55f398d199db687617ed35d0335d5b.tar.gz
nvim-warp-2aff69b0bb55f398d199db687617ed35d0335d5b.tar.bz2
nvim-warp-2aff69b0bb55f398d199db687617ed35d0335d5b.zip
Added multiple strategies for deteriming the column.
Doing a full grid select can be intimidating. A word-wise strat is probably a good thing to have.
Diffstat (limited to 'lua')
-rw-r--r--lua/warp.lua74
-rw-r--r--lua/warp/strategy/default.lua92
-rw-r--r--lua/warp/strategy/null.lua12
-rw-r--r--lua/warp/strategy/words.lua84
4 files changed, 206 insertions, 56 deletions
diff --git a/lua/warp.lua b/lua/warp.lua
index d3b6337..a2332f4 100644
--- a/lua/warp.lua
+++ b/lua/warp.lua
@@ -19,7 +19,7 @@ local function new_panel(buf, row, col, width, height)
col = col,
width = width,
height = height,
- focusable = false,
+ focusable = true,
style = 'minimal'
})
vim.api.nvim_win_set_option(w, "winhighlight", "Normal:WarpNormal")
@@ -57,35 +57,8 @@ M.open_horiz = function()
local width = vim.api.nvim_win_get_width(current_win) - width_of_garbage
M.horiz_bufnr = vim.api.nvim_create_buf(0, 1)
- local col = 0
- local line = ''
-
- local v = ''
- local c = nil
- local i = 0
local line_at = vim.fn.getline(curpos[1])
- M.col_map = {}
local max_width = math.min(width, #line_at + 1)
- while col < max_width do
- v = char_at(hsel1, i)
- if c then
- if M.col_map[v .. c] then break end
- M.col_map[c .. v] = col - 1
- end
- c = char_at(hsel2, i)
- if M.col_map[c .. v] then break end
- line = line .. v
- col = col + 1
- if col < max_width then
- line = line .. c
- M.col_map[v .. c] = col - 1
- col = col + 1
- i = i + 1
- end
- end
-
- vim.api.nvim_buf_set_lines(M.horiz_bufnr, 0, -1, 0, {' ' .. line})
- M.horiz_line = line
return new_panel(M.horiz_bufnr, curpos[1] - topline + 1, width_of_garbage - 1,
max_width + 2, 1)
@@ -127,7 +100,11 @@ local function next_char()
return vim.fn.nr2char(vim.fn.getchar())
end
-M.run = function()
+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
@@ -164,36 +141,21 @@ M.run = function()
vim.api.nvim_win_set_cursor(0, {r, current_pos[2]})
- local read_col = function()
- w = M.open_horiz()
- local hch1 = next_char()
-
- if hch1 == '\x1b' then
- return nil
- elseif hch1 == '.' then
- return current_pos[2]
- elseif not hch1:match('[a-z]') then
- return hch1
- else
- M.filter_horiz_string(hch1)
-
- local hch2 = next_char()
- if hch2 == '\x1b' then return end
- return M.col_map[hch1 .. hch2]
+ 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
- local c = read_col()
- if w then cleanup(w) end
- if not c then return end
-
- if c == '$' or c == '^' then
- vim.cmd("normal! " .. c)
- elseif type(c) == 'string' then
- vim.cmd("normal! f" .. c)
- else
- vim.cmd("normal! " .. (c + 1) .. "|") -- handle multibyte characters
- end
+ cleanup(w)
end)()
vim.o.scrolloff = old_scroll
diff --git a/lua/warp/strategy/default.lua b/lua/warp/strategy/default.lua
new file mode 100644
index 0000000..55019d8
--- /dev/null
+++ b/lua/warp/strategy/default.lua
@@ -0,0 +1,92 @@
+local vim = assert(vim)
+
+local M = {}
+
+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 make_big_line()
+ local col = 0
+ local line = ''
+
+ local v = ''
+ local c = nil
+ local i = 0
+ local col_map = {}
+ while true do
+ v = char_at(hsel1, i)
+ if c then
+ if col_map[v .. c] then break end
+ col_map[c .. v] = col
+ end
+ c = char_at(hsel2, i)
+ if col_map[c .. v] then break end
+ line = line .. v
+ col = col + 1
+ line = line .. c
+ col_map[v .. c] = col
+ col = col + 1
+ i = i + 1
+ end
+
+ return line, col_map
+end
+
+local big_line, col_map = make_big_line()
+
+M.default_strategy = function ()
+ local filter
+
+ return {
+ display = function ()
+ local curpos = vim.api.nvim_win_get_cursor(0)
+ local line_at = vim.fn.getline(curpos[1])
+ local unfiltered = big_line:sub(1, #line_at + 1)
+ 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
+
+return M
diff --git a/lua/warp/strategy/null.lua b/lua/warp/strategy/null.lua
new file mode 100644
index 0000000..9464547
--- /dev/null
+++ b/lua/warp/strategy/null.lua
@@ -0,0 +1,12 @@
+local vim = assert(vim)
+
+local M = {}
+
+M.null_strategy = function ()
+ return {
+ display = function () return nil end,
+ on_char = function () return false end
+ }
+end
+
+return M
diff --git a/lua/warp/strategy/words.lua b/lua/warp/strategy/words.lua
new file mode 100644
index 0000000..d255203
--- /dev/null
+++ b/lua/warp/strategy/words.lua
@@ -0,0 +1,84 @@
+local vim = assert(vim)
+
+local M = {}
+local alphabet = "etansihrdlocumwfgypkbvjxqz"
+
+local function split_lines(line)
+ local i
+ local j = 1
+
+ local chars_to_col = {}
+ local col_to_chars = {}
+
+ local run_regex = function(rx, off)
+ if #alphabet < j then
+ return
+ end
+
+ if not off then
+ off = 0
+ end
+
+ i = 0
+ while true do
+ i = string.find(line, rx, i)
+ if i == nil then break end
+ i = i + 1
+
+ if #alphabet < j then
+ return
+ end
+
+ local nextalph = alphabet:sub(j, j)
+ j = j + 1
+ chars_to_col[nextalph] = i + off
+ col_to_chars[i + off] = nextalph
+ end
+ end
+
+ run_regex("%W%w")
+ run_regex("%s%S")
+ run_regex("%w%W", - 1)
+
+ local winstr = ""
+ i = 1
+ while i <= #line do
+ if col_to_chars[i] then
+ winstr = winstr .. col_to_chars[i]
+ else
+ winstr = winstr .. " "
+ end
+ i = i + 1
+ end
+
+ return winstr, chars_to_col
+end
+
+M.words_strategy = function ()
+ local chartab
+
+ return {
+ display = function ()
+ local curpos = vim.api.nvim_win_get_cursor(0)
+ local line_at = vim.fn.getline(curpos[1])
+ local str, tab = split_lines(line_at)
+ chartab = tab
+ return str
+ end,
+
+ on_char = function (ch)
+ if ch == '$' or ch == '^' then
+ vim.cmd("normal! " .. ch)
+ elseif not ch:match('[a-z]') then
+ vim.cmd("normal! f" .. ch)
+ else
+ if chartab[ch] then
+ vim.cmd("norma! " .. chartab[ch] .. "|")
+ end
+ end
+ return false
+ end
+ }
+end
+
+return M