summaryrefslogtreecommitdiff
path: root/lua/nvim-treesitter/state.lua
diff options
context:
space:
mode:
authorkiyan42 <yazdani.kiyan@protonmail.com>2020-05-08 11:22:59 +0200
committerkiyan42 <yazdani.kiyan@protonmail.com>2020-05-12 16:16:48 +0200
commit45dcebb15f1a954eba2bcb3ae4c1a03f710a1f2a (patch)
tree50cbca8e9615d69a8ff9aca6b33a35abb32f9363 /lua/nvim-treesitter/state.lua
parent307c78aa1e2cc5e499469fe892108b7fcf6cdb5e (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/state.lua')
-rw-r--r--lua/nvim-treesitter/state.lua114
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