Merge pull request #89 from kyazdani42/refacto/remove-buf-state-and-api

refacto: remove buf state and api
This commit is contained in:
Thomas Vigouroux 2020-06-19 15:45:28 +02:00 committed by GitHub
commit 516671fe9f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 134 additions and 283 deletions

View file

@ -131,19 +131,13 @@ Some of these features are :
You can find the roadmap [here](https://github.com/nvim-treesitter/nvim-treesitter/projects/1). You can find the roadmap [here](https://github.com/nvim-treesitter/nvim-treesitter/projects/1).
The roadmap and all features of this plugin are open to change, and any suggestion will be highly appreciated! The roadmap and all features of this plugin are open to change, and any suggestion will be highly appreciated!
## Api ## Utils
Nvim-treesitter exposes an api to extend node capabilites. You can retrieve the api like this: you can get some utility functions with
```lua ```lua
local ts_node_api = require 'nvim-treesitter'.get_node_api() local ts_utils = require 'nvim-treesitter.ts_utils'
``` ```
More information is available in the help file (`:help nvim-treesitter-utils`).
You can also retrieve the current state of the current buffer with:
```lua
local buf_state = require'nvim-treesitter'.get_buf_state()
```
More information is available in neovim documentation (`:help nvim-treesitter-api`).
## Supported Languages ## Supported Languages

View file

@ -91,26 +91,29 @@ A list of languages can be found at |:TSInstallInfo|
List modules state for the current session. List modules state for the current session.
============================================================================== ==============================================================================
API *nvim-treesitter-api* UTILS *nvim-treesitter-utils*
Nvim treesitter exposes extended functions to use on nodes and scopes. Nvim treesitter has some wrapper functions that you can retrieve with:
you can retrieve the api with:
> >
local ts_node_api = require 'nvim-treesitter'.get_node_api() local ts_utils = require 'nvim-treesitter.ts_utils'
< <
Methods Methods
get_node_text(node, bufnr) *ts_api.get_node_text* get_node_at_cursor(winnr) *ts_utils.get_node_at_cursor*
winnr will be 0 if nil
returns the node under the cursor
get_node_text(node, bufnr) *ts_utils.get_node_text*
return the text content of a node return the text content of a node
is_parent(dest, source) *ts_api.is_parent* is_parent(dest, source) *ts_utils.is_parent*
determines wether `dest` is a parent of `source` determines wether `dest` is a parent of `source`
return a boolean return a boolean
get_named_children(node) *ts_api.get_named_children* get_named_children(node) *ts_utils.get_named_children*
return a table of named children of `node` return a table of named children of `node`
get_next_node(node, allow_switch_parent, allow_next_parent) *ts_api.get_next_node* get_next_node(node, allow_switch_parent, allow_next_parent) *ts_utils.get_next_node*
return the next node within the same parent. return the next node within the same parent.
if no node is found, returns `nil`. if no node is found, returns `nil`.
if `allow_switch_parent` is true, it will allow switching parent if `allow_switch_parent` is true, it will allow switching parent
@ -118,42 +121,28 @@ get_next_node(node, allow_switch_parent, allow_next_parent) *ts_api.get_next_nod
if `allow_next_parent` is true, it will allow next parent if if `allow_next_parent` is true, it will allow next parent if
the node is the last node and the next parent doesn't have children. the node is the last node and the next parent doesn't have children.
get_previous_node(node, allow_switch_parents, allow_prev_parent) *ts_api.get_previous_node* get_previous_node(node, allow_switch_parents, allow_prev_parent) *ts_utils.get_previous_node*
return the previous node within the same parent. return the previous node within the same parent.
`allow_switch_parent` and `allow_prev_parent` follow the same rule `allow_switch_parent` and `allow_prev_parent` follow the same rule
as |ts_api.get_next_node| but if the node is the first node. as |ts_utils.get_next_node| but if the node is the first node.
containing_scope(node) *ts_api.containing_scope* containing_scope(node) *ts_utils.containing_scope*
return the smallest scope containing the node return the smallest scope containing the node
parent_scope(node, cursor_pos) *ts_api.parent_scope* parent_scope(node, cursor_pos) *ts_utils.parent_scope*
return the parent scope of the current scope that contains the node. return the parent scope of the current scope that contains the node.
`cursor_pos` should be `{ row = number, col = number }` `cursor_pos` should be `{ row = number, col = number }`
you can retrieve the cursor_pos with the buffer state
nested_scope(node, cursor_pos) *ts_api.nested_scope* nested_scope(node, cursor_pos) *ts_utils.nested_scope*
return the first scope within current scope that contains the node. return the first scope within current scope that contains the node.
`cursor_pos` should be `{ row = number, col = number }` `cursor_pos` should be `{ row = number, col = number }`
you can retrieve the cursor_pos with the buffer state
next_scope(node) *ts_api.next_scope* next_scope(node) *ts_utils.next_scope*
return the neighbour scope of the current node return the neighbour scope of the current node
previous_scope(node) *ts_api.previous_scope* previous_scope(node) *ts_utils.previous_scope*
return the previous neighbour scope of the current node return the previous neighbour scope of the current node
Nvim-treesitter also provides access to the state of the current buffer:
>
local cur_buf_state = require'nvim-treesitter'.get_buf_state()
print(vim.inspect(cur_buf_state))
--[[
{
cursor_pos = { row = number, col = number }, (current cursor pos in the buffer)
current_node = tsnode (smallest node the cursor is on)
}
]]--
<
============================================================================== ==============================================================================
FUNCTIONS *nvim-treesitter-functions* FUNCTIONS *nvim-treesitter-functions*

View file

@ -6,20 +6,21 @@
:TSInstallInfo nvim-treesitter.txt /*:TSInstallInfo* :TSInstallInfo nvim-treesitter.txt /*:TSInstallInfo*
:TSModuleInfo nvim-treesitter.txt /*:TSModuleInfo* :TSModuleInfo nvim-treesitter.txt /*:TSModuleInfo*
nvim-treesitter nvim-treesitter.txt /*nvim-treesitter* nvim-treesitter nvim-treesitter.txt /*nvim-treesitter*
nvim-treesitter-api nvim-treesitter.txt /*nvim-treesitter-api*
nvim-treesitter-commands nvim-treesitter.txt /*nvim-treesitter-commands* nvim-treesitter-commands nvim-treesitter.txt /*nvim-treesitter-commands*
nvim-treesitter-functions nvim-treesitter.txt /*nvim-treesitter-functions* nvim-treesitter-functions nvim-treesitter.txt /*nvim-treesitter-functions*
nvim-treesitter-intro nvim-treesitter.txt /*nvim-treesitter-intro* nvim-treesitter-intro nvim-treesitter.txt /*nvim-treesitter-intro*
nvim-treesitter-quickstart nvim-treesitter.txt /*nvim-treesitter-quickstart* nvim-treesitter-quickstart nvim-treesitter.txt /*nvim-treesitter-quickstart*
nvim-treesitter-utils nvim-treesitter.txt /*nvim-treesitter-utils*
nvim_treesitter#foldexpr() nvim-treesitter.txt /*nvim_treesitter#foldexpr()* nvim_treesitter#foldexpr() nvim-treesitter.txt /*nvim_treesitter#foldexpr()*
nvim_treesitter#statusline() nvim-treesitter.txt /*nvim_treesitter#statusline()* nvim_treesitter#statusline() nvim-treesitter.txt /*nvim_treesitter#statusline()*
ts_api.containing_scope nvim-treesitter.txt /*ts_api.containing_scope* ts_utils.containing_scope nvim-treesitter.txt /*ts_utils.containing_scope*
ts_api.get_named_children nvim-treesitter.txt /*ts_api.get_named_children* ts_utils.get_named_children nvim-treesitter.txt /*ts_utils.get_named_children*
ts_api.get_next_node nvim-treesitter.txt /*ts_api.get_next_node* ts_utils.get_next_node nvim-treesitter.txt /*ts_utils.get_next_node*
ts_api.get_node_text nvim-treesitter.txt /*ts_api.get_node_text* ts_utils.get_node_at_cursor nvim-treesitter.txt /*ts_utils.get_node_at_cursor*
ts_api.get_previous_node nvim-treesitter.txt /*ts_api.get_previous_node* ts_utils.get_node_text nvim-treesitter.txt /*ts_utils.get_node_text*
ts_api.is_parent nvim-treesitter.txt /*ts_api.is_parent* ts_utils.get_previous_node nvim-treesitter.txt /*ts_utils.get_previous_node*
ts_api.nested_scope nvim-treesitter.txt /*ts_api.nested_scope* ts_utils.is_parent nvim-treesitter.txt /*ts_utils.is_parent*
ts_api.next_scope nvim-treesitter.txt /*ts_api.next_scope* ts_utils.nested_scope nvim-treesitter.txt /*ts_utils.nested_scope*
ts_api.parent_scope nvim-treesitter.txt /*ts_api.parent_scope* ts_utils.next_scope nvim-treesitter.txt /*ts_utils.next_scope*
ts_api.previous_scope nvim-treesitter.txt /*ts_api.previous_scope* ts_utils.parent_scope nvim-treesitter.txt /*ts_utils.parent_scope*
ts_utils.previous_scope nvim-treesitter.txt /*ts_utils.previous_scope*

View file

@ -2,10 +2,9 @@ local api = vim.api
local install = require'nvim-treesitter.install' local install = require'nvim-treesitter.install'
local utils = require'nvim-treesitter.utils' local utils = require'nvim-treesitter.utils'
local ts_utils = require'nvim-treesitter.ts_utils'
local info = require'nvim-treesitter.info' local info = require'nvim-treesitter.info'
local configs = require'nvim-treesitter.configs' local configs = require'nvim-treesitter.configs'
local state = require'nvim-treesitter.state'
local ts_utils = require'nvim-treesitter.ts_utils'
local M = {} local M = {}
@ -21,20 +20,13 @@ function M.setup()
api.nvim_command(string.format("autocmd NvimTreesitter FileType %s %s", ft, cmd)) api.nvim_command(string.format("autocmd NvimTreesitter FileType %s %s", ft, cmd))
end end
end end
local cmd = string.format("lua require'nvim-treesitter.state'.attach_to_buffer(%s)", ft)
api.nvim_command(string.format('autocmd NvimTreesitter FileType %s %s', ft, cmd))
end end
state.run_update()
end end
function M.statusline(indicator_size) function M.statusline(indicator_size)
local indicator_size = indicator_size or 100 local indicator_size = indicator_size or 100
local bufnr = api.nvim_get_current_buf()
local buf_state = state.get_buf_state(bufnr)
if not buf_state then return "" end
local current_node = buf_state.current_node local current_node = ts_utils.get_node_at_cursor()
if not current_node then return "" end if not current_node then return "" end
local expr = current_node:parent() local expr = current_node:parent()
@ -56,13 +48,4 @@ function M.statusline(indicator_size)
end end
end end
function M.get_buf_state()
local bufnr = api.nvim_get_current_buf()
return state.exposed_state(bufnr)
end
function M.get_node_api()
return ts_utils
end
return M return M

View file

@ -1,137 +1,137 @@
local api = vim.api local api = vim.api
local queries = require'nvim-treesitter.query' local queries = require'nvim-treesitter.query'
local utils = require'nvim-treesitter.utils' local parsers = require'nvim-treesitter.parsers'
local parsers = {} local parserlist = {}
parsers.javascript = { parserlist.javascript = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-javascript", url = "https://github.com/tree-sitter/tree-sitter-javascript",
files = { "src/parser.c", "src/scanner.c" }, files = { "src/parser.c", "src/scanner.c" },
} }
} }
parsers.c = { parserlist.c = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-c", url = "https://github.com/tree-sitter/tree-sitter-c",
files = { "src/parser.c" } files = { "src/parser.c" }
} }
} }
parsers.cpp = { parserlist.cpp = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-cpp", url = "https://github.com/tree-sitter/tree-sitter-cpp",
files = { "src/parser.c", "src/scanner.cc" } files = { "src/parser.c", "src/scanner.cc" }
} }
} }
parsers.rust = { parserlist.rust = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-rust", url = "https://github.com/tree-sitter/tree-sitter-rust",
files = { "src/parser.c", "src/scanner.c" }, files = { "src/parser.c", "src/scanner.c" },
} }
} }
parsers.lua = { parserlist.lua = {
install_info = { install_info = {
url = "https://github.com/nvim-treesitter/tree-sitter-lua", url = "https://github.com/nvim-treesitter/tree-sitter-lua",
files = { "src/parser.c", "src/scanner.cc" } files = { "src/parser.c", "src/scanner.cc" }
} }
} }
parsers.python = { parserlist.python = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-python", url = "https://github.com/tree-sitter/tree-sitter-python",
files = { "src/parser.c", "src/scanner.cc" }, files = { "src/parser.c", "src/scanner.cc" },
} }
} }
parsers.go = { parserlist.go = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-go", url = "https://github.com/tree-sitter/tree-sitter-go",
files = { "src/parser.c" }, files = { "src/parser.c" },
} }
} }
parsers.ruby = { parserlist.ruby = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-ruby", url = "https://github.com/tree-sitter/tree-sitter-ruby",
files = { "src/parser.c", "src/scanner.cc" }, files = { "src/parser.c", "src/scanner.cc" },
} }
} }
parsers.bash = { parserlist.bash = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-bash", url = "https://github.com/tree-sitter/tree-sitter-bash",
files = { "src/parser.c", "src/scanner.cc" }, files = { "src/parser.c", "src/scanner.cc" },
} }
} }
parsers.php = { parserlist.php = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-php", url = "https://github.com/tree-sitter/tree-sitter-php",
files = { "src/parser.c", "src/scanner.cc" }, files = { "src/parser.c", "src/scanner.cc" },
} }
} }
parsers.java = { parserlist.java = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-java", url = "https://github.com/tree-sitter/tree-sitter-java",
files = { "src/parser.c" }, files = { "src/parser.c" },
} }
} }
parsers.html = { parserlist.html = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-html", url = "https://github.com/tree-sitter/tree-sitter-html",
files = { "src/parser.c", "src/scanner.cc" }, files = { "src/parser.c", "src/scanner.cc" },
} }
} }
parsers.julia = { parserlist.julia = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-julia", url = "https://github.com/tree-sitter/tree-sitter-julia",
files = { "src/parser.c", "src/scanner.c" }, files = { "src/parser.c", "src/scanner.c" },
} }
} }
parsers.json = { parserlist.json = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-json", url = "https://github.com/tree-sitter/tree-sitter-json",
files = { "src/parser.c" }, files = { "src/parser.c" },
} }
} }
parsers.css = { parserlist.css = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-css", url = "https://github.com/tree-sitter/tree-sitter-css",
files = { "src/parser.c", "src/scanner.c" }, files = { "src/parser.c", "src/scanner.c" },
} }
} }
parsers.ocaml = { parserlist.ocaml = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-ocaml", url = "https://github.com/tree-sitter/tree-sitter-ocaml",
files = { "src/parser.c", "src/scanner.cc" }, files = { "src/parser.c", "src/scanner.cc" },
} }
} }
parsers.swift = { parserlist.swift = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-swift", url = "https://github.com/tree-sitter/tree-sitter-swift",
files = { "src/parser.c" }, files = { "src/parser.c" },
} }
} }
parsers.csharp = { parserlist.csharp = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-c-sharp", url = "https://github.com/tree-sitter/tree-sitter-c-sharp",
files = { "src/parser.c", "src/scanner.c" }, files = { "src/parser.c", "src/scanner.c" },
} }
} }
parsers.typescript = { parserlist.typescript = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-typescript", url = "https://github.com/tree-sitter/tree-sitter-typescript",
files = { "src/parser.c", "src/scanner.c" }, files = { "src/parser.c", "src/scanner.c" },
@ -139,7 +139,7 @@ parsers.typescript = {
} }
} }
parsers.tsx = { parserlist.tsx = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-typescript", url = "https://github.com/tree-sitter/tree-sitter-typescript",
files = { "src/parser.c", "src/scanner.c" }, files = { "src/parser.c", "src/scanner.c" },
@ -147,63 +147,63 @@ parsers.tsx = {
} }
} }
parsers.scala = { parserlist.scala = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-scala", url = "https://github.com/tree-sitter/tree-sitter-scala",
files = { "src/parser.c", "src/scanner.c" }, files = { "src/parser.c", "src/scanner.c" },
} }
} }
parsers.haskell = { parserlist.haskell = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-haskell", url = "https://github.com/tree-sitter/tree-sitter-haskell",
files = { "src/parser.c", "src/scanner.cc" }, files = { "src/parser.c", "src/scanner.cc" },
} }
} }
parsers.markdown = { parserlist.markdown = {
install_info = { install_info = {
url = "https://github.com/ikatyang/tree-sitter-markdown", url = "https://github.com/ikatyang/tree-sitter-markdown",
files = { "src/parser.c", "src/scanner.cc" }, files = { "src/parser.c", "src/scanner.cc" },
} }
} }
parsers.toml = { parserlist.toml = {
install_info = { install_info = {
url = "https://github.com/ikatyang/tree-sitter-toml", url = "https://github.com/ikatyang/tree-sitter-toml",
files = { "src/parser.c", "src/scanner.c" }, files = { "src/parser.c", "src/scanner.c" },
} }
} }
parsers.vue = { parserlist.vue = {
install_info = { install_info = {
url = "https://github.com/ikatyang/tree-sitter-vue", url = "https://github.com/ikatyang/tree-sitter-vue",
files = { "src/parser.c", "src/scanner.cc" }, files = { "src/parser.c", "src/scanner.cc" },
} }
} }
parsers.elm = { parserlist.elm = {
install_info = { install_info = {
url = "https://github.com//razzeee/tree-sitter-elm", url = "https://github.com//razzeee/tree-sitter-elm",
files = { "src/parser.c", "src/scanner.cc" }, files = { "src/parser.c", "src/scanner.cc" },
} }
} }
parsers.yaml = { parserlist.yaml = {
install_info = { install_info = {
url = "https://github.com/ikatyang/tree-sitter-yaml", url = "https://github.com/ikatyang/tree-sitter-yaml",
files = { "src/parser.c", "src/scanner.cc" }, files = { "src/parser.c", "src/scanner.cc" },
} }
} }
parsers.nix = { parserlist.nix = {
install_info = { install_info = {
url = "https://github.com/cstrahan/tree-sitter-nix", url = "https://github.com/cstrahan/tree-sitter-nix",
files = { "src/parser.c", "src/scanner.cc" }, files = { "src/parser.c", "src/scanner.cc" },
} }
} }
parsers.regex = { parserlist.regex = {
install_info = { install_info = {
url = "https://github.com/tree-sitter/tree-sitter-regex", url = "https://github.com/tree-sitter/tree-sitter-regex",
files = { "src/parser.c" } files = { "src/parser.c" }
@ -245,7 +245,7 @@ local M = {}
local function enable_module(mod, bufnr, ft) local function enable_module(mod, bufnr, ft)
local bufnr = bufnr or api.nvim_get_current_buf() local bufnr = bufnr or api.nvim_get_current_buf()
local ft = ft or api.nvim_buf_get_option(bufnr, 'ft') local ft = ft or api.nvim_buf_get_option(bufnr, 'ft')
if not parsers[ft] or not config.modules[mod] then if not parserlist[ft] or not config.modules[mod] then
return return
end end
@ -275,12 +275,12 @@ local function enable_all(mod, ft)
end end
end end
if ft then if ft then
if utils.has_parser(ft) then if parsers.has_parser(ft) then
enable_mod_conf_autocmd(mod, ft) enable_mod_conf_autocmd(mod, ft)
end end
else else
for _, ft in pairs(M.available_parsers()) do for _, ft in pairs(M.available_parsers()) do
if utils.has_parser(ft) then if parsers.has_parser(ft) then
enable_mod_conf_autocmd(mod, ft) enable_mod_conf_autocmd(mod, ft)
end end
end end
@ -291,7 +291,7 @@ end
local function disable_module(mod, bufnr, ft) local function disable_module(mod, bufnr, ft)
local bufnr = bufnr or api.nvim_get_current_buf() local bufnr = bufnr or api.nvim_get_current_buf()
local ft = ft or api.nvim_buf_get_option(bufnr, 'ft') local ft = ft or api.nvim_buf_get_option(bufnr, 'ft')
if not parsers[ft] or not config.modules[mod] then if not parserlist[ft] or not config.modules[mod] then
return return
end end
@ -360,7 +360,7 @@ M.commands = {
-- @param mod: module (string) -- @param mod: module (string)
-- @param ft: filetype (string) -- @param ft: filetype (string)
function M.is_enabled(mod, ft) function M.is_enabled(mod, ft)
if not M.get_parser_configs()[ft] or not utils.has_parser(ft) then if not M.get_parser_configs()[ft] or not parsers.has_parser(ft) then
return false return false
end end
@ -404,11 +404,11 @@ function M.setup(user_data)
end end
function M.get_parser_configs() function M.get_parser_configs()
return parsers return parserlist
end end
function M.available_parsers() function M.available_parsers()
return vim.tbl_keys(parsers) return vim.tbl_keys(parserlist)
end end
function M.available_modules() function M.available_modules()

View file

@ -1,11 +1,13 @@
local api = vim.api local api = vim.api
local state = require'nvim-treesitter.state'
local configs = require'nvim-treesitter.configs' local configs = require'nvim-treesitter.configs'
local ts_utils = require'nvim-treesitter.ts_utils' local ts_utils = require'nvim-treesitter.ts_utils'
local parsers = require'nvim-treesitter.parsers'
local M = {} local M = {}
local selections = {}
local function update_selection(buf, node) local function update_selection(buf, node)
local start_row, start_col, end_row, end_col = node:range() local start_row, start_col, end_row, end_col = node:range()
@ -18,32 +20,49 @@ local function update_selection(buf, node)
vim.fn.setpos(".", { buf, end_row+1, end_col+1, 0 }) vim.fn.setpos(".", { buf, end_row+1, end_col+1, 0 })
end end
function M.init_selection()
local buf = api.nvim_get_current_buf()
local node = ts_utils.get_node_at_cursor()
selections[buf] = { [1] = node }
update_selection(buf, node)
end
local function visual_selection_range()
local _, csrow, cscol, _ = unpack(vim.fn.getpos("'<"))
local _, cerow, cecol, _ = unpack(vim.fn.getpos("'>"))
if csrow < cerow then
return csrow-1, cscol-1, cerow-1, cecol-1
else
return cerow-1, cecol-1, csrow-1, cscol-1
end
end
local function range_matches(node)
local csrow, cscol, cerow, cecol = visual_selection_range()
local srow, scol, erow, ecol = node:range()
return srow == csrow and scol == cscol and erow == cerow and ecol == cecol
end
local function select_incremental(get_parent) local function select_incremental(get_parent)
return function() return function()
local buf = api.nvim_get_current_buf() local buf = api.nvim_get_current_buf()
local buf_state = state.get_buf_state(buf) local nodes = selections[buf]
local node -- initialize incremental selection with current selection
-- initialize incremental selection with current range if not nodes or #nodes == 0 or not range_matches(nodes[#nodes]) then
if #buf_state.selection.nodes == 0 then local csrow, cscol, cerow, cecol = visual_selection_range()
local cur_range = buf_state.selection.range local root = parsers.get_parser().tree:root()
if not cur_range then local node = root:named_descendant_for_range(csrow, cscol, cerow, cecol)
local _, cursor_row, cursor_col, _ = unpack(vim.fn.getpos(".")) update_selection(buf, node)
cur_range = { cursor_row, cursor_col, cursor_row, cursor_col + 1 } selections[buf] = { [1] = node }
end return
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 end
node = get_parent(nodes[#nodes])
if not node then return end if not node then return end
if node ~= buf_state.selection.nodes[#buf_state.selection.nodes] then if node ~= nodes[#nodes] then
state.insert_selection_node(buf, node) table.insert(nodes, node)
end end
update_selection(buf, node) update_selection(buf, node)
@ -60,13 +79,10 @@ end)
function M.node_decremental() function M.node_decremental()
local buf = api.nvim_get_current_buf() local buf = api.nvim_get_current_buf()
local buf_state = state.get_buf_state(buf) local nodes = selections[buf]
if not nodes or #nodes < 2 then return end
local nodes = buf_state.selection.nodes
if #nodes < 2 then return end
state.pop_selection_node(buf)
table.remove(selections[buf])
local node = nodes[#nodes] local node = nodes[#nodes]
update_selection(buf, node) update_selection(buf, node)
end end
@ -76,14 +92,14 @@ function M.attach(bufnr)
local config = configs.get_module('incremental_selection') local config = configs.get_module('incremental_selection')
for funcname, mapping in pairs(config.keymaps) do for funcname, mapping in pairs(config.keymaps) do
local mode
if funcname == "init_selection" then if funcname == "init_selection" then
local cmd = ":lua require'nvim-treesitter.incremental_selection'.node_incremental()<CR>" mode = 'n'
api.nvim_buf_set_keymap(buf, 'n', mapping, cmd, { silent = true })
else else
local cmd = string.format(":lua require'nvim-treesitter.incremental_selection'.%s()<CR>", funcname) mode = 'v'
api.nvim_buf_set_keymap(buf, 'v', mapping, cmd, { silent = true })
end end
local cmd = string.format(":lua require'nvim-treesitter.incremental_selection'.%s()<CR>", funcname)
api.nvim_buf_set_keymap(buf, mode, mapping, cmd, { silent = true })
end end
end end

View file

@ -4,6 +4,7 @@ local luv = vim.loop
local configs = require'nvim-treesitter.configs' local configs = require'nvim-treesitter.configs'
local utils = require'nvim-treesitter.utils' local utils = require'nvim-treesitter.utils'
local parsers = require'nvim-treesitter.parsers'
local M = {} local M = {}
@ -128,7 +129,7 @@ M.ensure_installed = function(languages)
end end
for _, ft in ipairs(languages) do for _, ft in ipairs(languages) do
if not utils.has_parser(ft) then if not parsers.has_parser(ft) then
install(ft) install(ft)
end end
end end

View file

@ -5,7 +5,7 @@ local api = vim.api
local ts = vim.treesitter local ts = vim.treesitter
local queries = require'nvim-treesitter.query' local queries = require'nvim-treesitter.query'
local utils = require'nvim-treesitter.utils' local parsers = require'nvim-treesitter.parsers'
local M = { local M = {
locals = {} locals = {}
@ -18,7 +18,7 @@ function M.collect_locals(bufnr)
local query = queries.get_query(ft, 'locals') local query = queries.get_query(ft, 'locals')
if not query then return end if not query then return end
local parser = utils.get_parser(bufnr, ft) local parser = parsers.get_parser(bufnr, ft)
if not parser then return end if not parser then return end
local root = parser:parse():root() local root = parser:parse():root()

View file

@ -10,9 +10,10 @@ function M.has_parser(lang)
end end
function M.get_parser(bufnr, lang) function M.get_parser(bufnr, lang)
local buf = bufnr or api.nvim_get_current_buf()
local lang = lang or api.nvim_buf_get_option(buf, 'ft')
if M.has_parser(lang) then if M.has_parser(lang) then
local buf = bufnr or api.nvim_get_current_buf()
local lang = lang or api.nvim_buf_get_option(buf, 'ft')
if not M[buf] then if not M[buf] then
M[buf] = {} M[buf] = {}
end end

View file

@ -1,122 +0,0 @@
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
function M.exposed_state(bufnr)
local buf_state = buffers[bufnr]
return {
cursor_pos = buf_state.cursor_pos,
current_node = buf_state.current_node
}
end
return M

View file

@ -1,6 +1,7 @@
local api = vim.api local api = vim.api
local locals = require'nvim-treesitter.locals' local locals = require'nvim-treesitter.locals'
local parsers = require'nvim-treesitter.parsers'
local M = {} local M = {}
@ -205,4 +206,10 @@ function M.previous_scope(node)
end end
end end
function M.get_node_at_cursor(winnr)
local cursor = api.nvim_win_get_cursor(winnr or 0)
local root = parsers.get_parser().tree:root()
return root:named_descendant_for_range(cursor[1]-1,cursor[2],cursor[1]-1,cursor[2])
end
return M return M

View file

@ -45,23 +45,4 @@ function M.get_cache_dir()
return nil, 'Invalid cache rights, $XDG_CACHE_HOME or /tmp should be read/write' return nil, 'Invalid cache rights, $XDG_CACHE_HOME or /tmp should be read/write'
end end
function M.has_parser(lang)
local lang = lang or api.nvim_buf_get_option(0, 'filetype')
return #api.nvim_get_runtime_file('parser/' .. lang .. '.so', false) > 0
end
function M.get_parser(bufnr, lang)
if M.has_parser() then
local buf = bufnr or api.nvim_get_current_buf()
local lang = lang or api.nvim_buf_get_option(buf, 'ft')
if not M[buf] then
M[buf] = {}
end
if not M[buf][lang] then
M[buf][lang] = ts.get_parser(buf, lang)
end
return M[buf][lang]
end
end
return M return M