Skip to content

Commit e285fef

Browse files
authored
Merge pull request #9 from fidgetingbits/get-buffer-selection
refactor: improve cursorless.lua function readability
2 parents 60637a4 + ad527d9 commit e285fef

File tree

1 file changed

+36
-110
lines changed

1 file changed

+36
-110
lines changed

cursorless.nvim/lua/cursorless/cursorless.lua

Lines changed: 36 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -7,118 +7,44 @@ local M = {}
77
-- window_get_visible_lines
88
-- { [1] = 28, [2] = 74 }
99
function M.window_get_visible_lines()
10-
-- print('window_get_visible_lines()')
11-
return { vim.fn.line("w0"), vim.fn.line("w$") }
10+
-- print('window_get_visible_lines()')
11+
return { vim.fn.line("w0"), vim.fn.line("w$") }
1212
end
1313

14-
-- https://www.reddit.com/r/neovim/comments/p4u4zy/how_to_pass_visual_selection_range_to_lua_function/
15-
-- https://neovim.io/doc/user/api.html#nvim_win_get_cursor()
14+
-- Get the coordinates of the current selection
15+
-- To manually test follow these steps:
16+
-- 1. In command mode :vmap <c-a> <Cmd>lua print(vim.inspect(require('cursorless').buffer_get_selection()))<Cr>
17+
-- 2. type "hello" on the first line and "world" on the second line
18+
-- 3. Enter visual mode and select "hello" on the first line and continue selection with "world"
19+
-- on the second line.
20+
-- 4. Hit ctrl+a to show the selection: {1, 1, 2, 5, false}
21+
-- 5. Hit 'o' to swap the cursor position and hit ctrl+a again: {1, 1, 2, 5, true}
1622
--
17-
-- luacheck:ignore 631
18-
-- e.g. run in command mode :vmap <c-a> <Cmd>lua print(vim.inspect(require('cursorless').buffer_get_selection()))<Cr>
19-
-- then go in visual mode with "v" and select "hello" on the first line and continue selection with "air"
20-
-- on the second line.
21-
-- Then hit ctrl+b and it will show the selection
22-
-- cline=2, ccol=2, vline=1, vcol=1
23-
-- sline=1, scol=1, eline=2, ecol=3, reverse=false
24-
-- { 1, 1, 2, 3, false }
25-
--
26-
-- if instead you select from the end of the "air" word on the second line
27-
-- and select up to the beginning of "hello" on the first line
28-
-- cline=1, ccol=0, vline=3, vcol=3
29-
-- sline=1, scol=1, eline=2, ecol=3, reverse=true
30-
-- { 1, 1, 2, 3, true }
31-
--
32-
-- if you want to directly see how it is parsed in the node extension, you can use the below:
33-
-- e.g. run in command mode :vmap <c-a> <Cmd>:call CursorlessLoadExtension()<Cr>
34-
-- and again use ctrl+a after selecting the text
23+
-- If you want to directly see how it is parsed in the node extension:
24+
-- 1. run in command mode :vmap <c-a> <Cmd>:call CursorlessLoadExtension()<Cr>
25+
-- 2. Select some text and hit ctrl+a
3526
function M.buffer_get_selection()
36-
-- print('buffer_get_selection()')
37-
local modeInfo = vim.api.nvim_get_mode()
38-
local mode = modeInfo.mode
39-
40-
local cursor = vim.api.nvim_win_get_cursor(0)
41-
local cline, ccol = cursor[1], cursor[2]
42-
local vline, vcol = vim.fn.line("v"), vim.fn.col("v")
43-
-- print(('cline=%d, ccol=%d, vline=%d, vcol=%d'):format(cline, ccol, vcol, vcol))
44-
45-
local sline, scol
46-
local eline, ecol
47-
local reverse
48-
if cline == vline then
49-
-- if ccol <= vcol then
50-
if ccol < vcol then
51-
sline, scol = cline, ccol
52-
eline, ecol = vline, vcol
53-
scol = scol + 1
54-
reverse = true
55-
else
56-
sline, scol = vline, vcol
57-
eline, ecol = cline, ccol
58-
ecol = ecol + 1
59-
reverse = false
60-
end
61-
elseif cline < vline then
62-
sline, scol = cline, ccol
63-
eline, ecol = vline, vcol
64-
scol = scol + 1
65-
reverse = true
66-
else
67-
sline, scol = vline, vcol
68-
eline, ecol = cline, ccol
69-
ecol = ecol + 1
70-
reverse = false
71-
end
72-
73-
if mode == "V" or mode == "CTRL-V" or mode == "\22" then
74-
scol = 1
75-
ecol = nil
76-
end
77-
78-
-- print(
79-
-- ('sline=%d, scol=%d, eline=%d, ecol=%d, reverse=%s'):format(
80-
-- sline,
81-
-- scol,
82-
-- eline,
83-
-- ecol,
84-
-- tostring(reverse)
85-
-- )
86-
-- )
87-
return { sline, scol, eline, ecol, reverse }
88-
end
89-
90-
-- https://www.reddit.com/r/neovim/comments/p4u4zy/how_to_pass_visual_selection_range_to_lua_function/
91-
-- luacheck:ignore 631
92-
-- e.g. run in command mode :vmap <c-b> <Cmd>lua print(vim.inspect(require('cursorless').buffer_get_selection_text()))<Cr>
93-
-- then go in visual mode with "v" and select "hello" on the first line and continue selection with "air"
94-
-- on the second line.
95-
-- Then hit ctrl+b and it will show the selection
96-
-- { "hello", "air" }
97-
function M.buffer_get_selection_text()
98-
-- print('buffer_get_selection_text()')
99-
local sline, scol, eline, ecol, _ =
100-
unpack(require("talon.cursorless").buffer_get_selection())
101-
102-
local lines = vim.api.nvim_buf_get_lines(0, sline - 1, eline, 0)
103-
if #lines == 0 then
104-
return
105-
end
27+
local start_pos = vim.fn.getpos("v") -- start of visual selection
28+
local start_line, start_col = start_pos[2], start_pos[3]
29+
local end_pos = vim.fn.getpos(".") -- end of visual selection (cursor position)
30+
local end_line, end_col = end_pos[2], end_pos[3]
31+
local reverse = false
32+
local mode = vim.api.nvim_get_mode().mode
10633

107-
local startText, endText
108-
if #lines == 1 then
109-
startText = string.sub(lines[1], scol, ecol)
110-
else
111-
startText = string.sub(lines[1], scol)
112-
endText = string.sub(lines[#lines], 1, ecol)
113-
end
34+
-- Invert the values depending on if the cursor is before the start
35+
if end_line < start_line or end_col < start_col then
36+
start_line, start_col, end_line, end_col = end_line, end_col, start_line, start_col
37+
reverse = true
38+
end
11439

115-
local selection = { startText }
116-
if #lines > 2 then
117-
vim.list_extend(selection, vim.list_slice(lines, 2, #lines - 1))
118-
end
119-
table.insert(selection, endText)
40+
-- See https://github.com/cursorless-dev/cursorless/issues/2537 if you want to add more modes
41+
if mode == "V" then
42+
-- Line and block-based visual modes are line-based, so we don't need to track the columns
43+
start_col = 1
44+
end_col = nil
45+
end
12046

121-
return selection
47+
return { start_line, start_col, end_line, end_col, reverse }
12248
end
12349

12450
-- https://github.com/nvim-treesitter/nvim-treesitter/blob/master/lua/nvim-treesitter/ts_utils.lua#L278
@@ -131,11 +57,11 @@ end
13157
-- for example it will highlight the last function name (nvim_win_set_cursor).
13258
-- another example is :tmap <c-b> <Cmd>lua require("talon.cursorless").select_range(4, 0, 4, 38)<Cr>
13359
-- NOTE: works for any mode (n,i,v,nt) except in t mode
134-
function M.select_range(start_x, start_y, end_x, end_y)
135-
vim.cmd([[normal! :noh]])
136-
vim.api.nvim_win_set_cursor(0, { start_x, start_y })
137-
vim.cmd([[normal v]])
138-
vim.api.nvim_win_set_cursor(0, { end_x, end_y })
60+
function M.select_range(start_line, start_col, end_line, end_col)
61+
vim.cmd([[normal! :noh]])
62+
vim.api.nvim_win_set_cursor(0, { start_line, start_col })
63+
vim.cmd([[normal v]])
64+
vim.api.nvim_win_set_cursor(0, { end_line, end_col })
13965
end
14066

14167
return M

0 commit comments

Comments
 (0)