diff options
| author | kiyan42 <yazdani.kiyan@protonmail.com> | 2020-05-08 11:22:59 +0200 |
|---|---|---|
| committer | kiyan42 <yazdani.kiyan@protonmail.com> | 2020-05-12 16:16:48 +0200 |
| commit | 45dcebb15f1a954eba2bcb3ae4c1a03f710a1f2a (patch) | |
| tree | 50cbca8e9615d69a8ff9aca6b33a35abb32f9363 /lua/nvim-treesitter/incremental_selection.lua | |
| parent | 307c78aa1e2cc5e499469fe892108b7fcf6cdb5e (diff) | |
refacto/feat: better handling of parser updates
features:
- node_movement is moving between scopes.
- add selection initialization from normal mode
- add a decremental selection
improvements:
- attach to buffer to run tree parsing on change
- run state update on CursorMoved
- the buffer state is:
```
{
cursor_pos = { row=row, col=col },
current_node = node_under_cursor,
selection = {
range = nil, -- activates when starting a selection
nodes = {} -- filling up when starting an incremental selection
},
parser = parser, -- parser for current buffer
}
```
- refacto all the modules reliant on parsing the tree, update the current nodes, get the current nodes...
fixes:
- fix has_parser to look for .so libraries
- fix should select the whole file when selection root in selection
Diffstat (limited to 'lua/nvim-treesitter/incremental_selection.lua')
| -rw-r--r-- | lua/nvim-treesitter/incremental_selection.lua | 111 |
1 files changed, 68 insertions, 43 deletions
diff --git a/lua/nvim-treesitter/incremental_selection.lua b/lua/nvim-treesitter/incremental_selection.lua index 70eefe37..ea7a9f71 100644 --- a/lua/nvim-treesitter/incremental_selection.lua +++ b/lua/nvim-treesitter/incremental_selection.lua @@ -1,77 +1,102 @@ local api = vim.api -local utils = require'nvim-treesitter.utils' -local parsers = require'nvim-treesitter.parsers' -local M = {} -local function node_range_to_vim(node) - if not node then return end +local state = require'nvim-treesitter.state' +local configs = require'nvim-treesitter.configs' +local ts_utils = require'nvim-treesitter.ts_utils' + +local M = {} +local function update_selection(buf, node) local start_row, start_col, end_row, end_col = node:range() - local select_range = [[ - call cursor(%d, %d) - normal v - call cursor(%d, %d) - ]] - local exec_command = string.format(select_range, - start_row+1, start_col+1, - end_row+1, end_col+1) + if end_row == vim.fn.line('$') then + end_col = #vim.fn.getline('$') + end - api.nvim_exec(exec_command, false) + vim.fn.setpos(".", { buf, start_row+1, start_col+1, 0 }) + vim.fn.nvim_exec("normal v", false) + vim.fn.setpos(".", { buf, end_row+1, end_col+1, 0 }) end -local function select_incremental(increment_func) +local function select_incremental(get_parent) return function() - local buf, sel_start_line, sel_start_col, _ = unpack(vim.fn.getpos("'<")) - local buf, sel_end_line, sel_end_col, _ = unpack(vim.fn.getpos("'>")) - - local node = nil - if parsers.has_parser() then - local root = parsers.get_parser():parse():root() - node = root:named_descendant_for_range(sel_start_line-1, sel_start_col-1, sel_end_line-1, sel_end_col) - local node_start_row, node_start_col, node_end_row, node_end_col = node:range() - - if (sel_start_line-1) == node_start_row and (sel_start_col-1) == node_start_col - and (sel_end_line-1) == node_end_row and sel_end_col == node_end_col then - node = increment_func(node) + local buf = api.nvim_get_current_buf() + local buf_state = state.get_buf_state(buf) + + local node + -- initialize incremental selection with current range + if #buf_state.selection.nodes == 0 then + local cur_range = buf_state.selection.range + if not cur_range then + local _, cursor_row, cursor_col, _ = unpack(vim.fn.getpos(".")) + cur_range = { cursor_row, cursor_col, cursor_row, cursor_col + 1 } end + + local root = buf_state.parser.tree:root() + if not root then return end + + node = root:named_descendant_for_range(cur_range[1]-1, cur_range[2]-1, cur_range[3]-1, cur_range[4]-1) + else + node = get_parent(buf_state.selection.nodes[#buf_state.selection.nodes]) + end + + if not node then return end + + if node ~= buf_state.selection.nodes[#buf_state.selection.nodes] then + state.insert_selection_node(buf, node) end - return node_range_to_vim(node) + update_selection(buf, node) end end M.node_incremental = select_incremental(function(node) - if node then - return node:parent() or node - end + return node:parent() or node end) M.scope_incremental = select_incremental(function(node) - if node then - return utils.smallest_containing_scope(node:parent() or node) - end + return ts_utils.containing_scope(node:parent() or node) end) +function M.node_decremental() + local buf = api.nvim_get_current_buf() + local buf_state = state.get_buf_state(buf) + + local nodes = buf_state.selection.nodes + if #nodes < 2 then return end + + state.pop_selection_node(buf) + + local node = nodes[#nodes] + update_selection(buf, node) +end + function M.attach(bufnr) local buf = bufnr or api.nvim_get_current_buf() - local config = require'nvim-treesitter.configs'.get_module('incremental_selection') + local config = configs.get_module('incremental_selection') for funcname, mapping in pairs(config.keymaps) do - api.nvim_buf_set_keymap(buf, 'v', mapping, - string.format(":lua require'nvim-treesitter.incremental_selection'.%s()<CR>", funcname), { silent = true }) - api.nvim_buf_set_keymap(buf, 'o', mapping, - string.format(":normal v%s<CR>", mapping), { silent = true }) + + if funcname == "init_selection" then + local cmd = ":lua require'nvim-treesitter.incremental_selection'.node_incremental()<CR>" + api.nvim_buf_set_keymap(buf, 'n', mapping, cmd, { silent = true }) + else + local cmd = string.format(":lua require'nvim-treesitter.incremental_selection'.%s()<CR>", funcname) + api.nvim_buf_set_keymap(buf, 'v', mapping, cmd, { silent = true }) + end end end function M.detach(bufnr) local buf = bufnr or api.nvim_get_current_buf() - local config = require'nvim-treesitter.configs'.get_module('incremental_selection') - for _, mapping in pairs(config.keymaps) do - api.nvim_buf_del_keymap(buf, 'v', mapping) - api.nvim_buf_del_keymap(buf, 'o', mapping) + local config = configs.get_module('incremental_selection') + for f, mapping in pairs(config.keymaps) do + if f == "init_selection" then + api.nvim_buf_del_keymap(buf, 'n', mapping) + else + api.nvim_buf_del_keymap(buf, 'v', mapping) + end end end |
