diff options
| author | Kiyan Yazdani <yazdani.kiyan@protonmail.com> | 2020-05-12 16:20:13 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-05-12 16:20:13 +0200 |
| commit | 5a66c38b9ff49f0f0b45afa95816c77e18cc9886 (patch) | |
| tree | 542e99206f53df84efa75edd303c6a2f41b98fd9 /lua/nvim-treesitter/state.lua | |
| parent | ca2680edce9191a19610ad6563827aa802131313 (diff) | |
| parent | 45dcebb15f1a954eba2bcb3ae4c1a03f710a1f2a (diff) | |
Merge pull request #45 from kyazdani42/refacto-feat/buf-state-update
refacto/feat: better handling of parser updates
Diffstat (limited to 'lua/nvim-treesitter/state.lua')
| -rw-r--r-- | lua/nvim-treesitter/state.lua | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/lua/nvim-treesitter/state.lua b/lua/nvim-treesitter/state.lua new file mode 100644 index 00000000..9da07ae1 --- /dev/null +++ b/lua/nvim-treesitter/state.lua @@ -0,0 +1,114 @@ +local api = vim.api + +local utils = require'nvim-treesitter.utils' + +local M = {} + +local buffers = {} + +local g_mode = api.nvim_get_mode().mode + +local function get_selection_range() + local _, vstart_row, vstart_col, _ = unpack(vim.fn.getpos("v")) + local _, cursor_row, cursor_col, _ = unpack(vim.fn.getpos(".")) + if vstart_row < cursor_row then + return vstart_row, vstart_col, cursor_row, cursor_col + else + return cursor_row, cursor_col, vstart_row, vstart_col + end +end + +function M.update() + local bufnr = api.nvim_get_current_buf() + local buf_config = buffers[bufnr] + if not buf_config then return end + + local mode = api.nvim_get_mode().mode + local cursor = api.nvim_win_get_cursor(0) + local row = cursor[1] + local col = cursor[2] + if row == buf_config.cursor_pos.row + and col == buf_config.cursor_pos.col + and mode == g_mode + then + return + end + + local root = buf_config.parser.tree:root() + if not root then return end + + local new_node = root:named_descendant_for_range(row - 1, col, row - 1, col) + + if new_node ~= buf_config.current_node then + buf_config.current_node = new_node + end + + -- We only want to update the range when the incremental selection has not started yet + if mode == "v" and #buf_config.selection.nodes == 0 then + local row_start, col_start, row_end, col_end = get_selection_range() + buf_config.selection.range = { row_start, col_start, row_end, col_end } + elseif mode ~= "v" then + buf_config.selection.nodes = {} + buf_config.selection.range = nil + end + + g_mode = mode + buf_config.cursor_pos.row = row + buf_config.cursor_pos.col = col +end + +function M.insert_selection_node(bufnr, range) + local buf_config = buffers[bufnr] + if not buf_config then return end + + table.insert(buffers[bufnr].selection.nodes, range) +end + +function M.pop_selection_node(bufnr) + local buf_config = buffers[bufnr] + if not buf_config then return end + + table.remove( + buffers[bufnr].selection.nodes, + #buffers[bufnr].selection.nodes + ) +end + +function M.run_update() + local cmd = "lua require'nvim-treesitter.state'.update()" + api.nvim_command('autocmd NvimTreesitter CursorMoved * '..cmd) +end + +function M.attach_to_buffer(ft) + local bufnr = api.nvim_get_current_buf() + local ft = ft or api.nvim_buf_get_option(bufnr, 'ft') + + if buffers[bufnr] then return end + + local parser = utils.get_parser(bufnr, ft) + if not parser then return end + + buffers[bufnr] = { + cursor_pos = {}, + current_node = nil, + selection = { + range = nil, + nodes = {} + }, + parser = parser, + } + + M.update() + api.nvim_buf_attach(bufnr, false, { + -- TODO(kyazdani): on lines should only parse the changed content + -- TODO(kyazdani): add a timer to avoid too frequent updates + on_lines = function(_, buf) buffers[buf].parser:parse() end, + on_detach = function(bufnr) buffers[bufnr] = nil end, + }) +end + +function M.get_buf_state(bufnr) + return buffers[bufnr] +end + +return M |
