diff options
| author | Stephan Seitz <stephan.seitz@fau.de> | 2020-06-21 20:38:00 +0200 |
|---|---|---|
| committer | Thomas Vigouroux <39092278+vigoux@users.noreply.github.com> | 2020-07-14 22:34:43 +0200 |
| commit | 69cabc69be49bc37c8a9bbb7def1415504b489b2 (patch) | |
| tree | cc4925d6ce00654c181a7cb4d2eef3dc488a324b /lua/nvim-treesitter/textobjects.lua | |
| parent | c42c38a8346dd9edda96477b774d3e086cd73650 (diff) | |
Add textobjects module
Diffstat (limited to 'lua/nvim-treesitter/textobjects.lua')
| -rw-r--r-- | lua/nvim-treesitter/textobjects.lua | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/lua/nvim-treesitter/textobjects.lua b/lua/nvim-treesitter/textobjects.lua new file mode 100644 index 00000000..cf81b596 --- /dev/null +++ b/lua/nvim-treesitter/textobjects.lua @@ -0,0 +1,96 @@ +local api = vim.api +local ts = vim.treesitter + +local configs = require "nvim-treesitter.configs" +local parsers = require "nvim-treesitter.parsers" +local queries = require'nvim-treesitter.query' +local locals = require'nvim-treesitter.locals' +local ts_utils = require'nvim-treesitter.ts_utils' + +local M = {} + +function M.select_textobject(query_string) + local bufnr = vim.api.nvim_get_current_buf() + local ft = api.nvim_buf_get_option(bufnr, "ft") + if not ft then return end + local lang = parsers.ft_to_lang(ft) + + local row, col = unpack(vim.api.nvim_win_get_cursor(0)) + row = row - 1 + + local matches = {} + + if string.match(query_string, '^@.*') then + matches = locals.get_capture_matches(bufnr, query_string, 'textobjects') + else + local parser = parsers.get_parser(bufnr, lang) + local root = parser:parse():root() + local start_row, _, end_row, _ = root:range() + + local nested = {} + local query = ts.parse_query(lang, query_string) + for m in queries.iter_prepared_matches(query, root, bufnr, start_row, end_row) do + for _, n in pairs(m) do + if n.node then + table.insert(matches, n.node) + end + end + end + end + + local match_length + local smallest_range + + for _, m in pairs(matches) do + if ts_utils.is_in_node_range(m, row, col) then + local length = ts_utils.node_length(m) + if not match_length or length < match_length then + smallest_range = m + match_length = length + end + end + end + + if smallest_range then + ts_utils.update_selection(bufnr, smallest_range) + end +end + +function M.attach(bufnr, lang) + local buf = bufnr or api.nvim_get_current_buf() + local config = configs.get_module("textobjects") + local lang = lang or parsers.ft_to_lang(api.nvim_buf_get_option(bufnr, "ft")) + + for mapping, query in pairs(config.keymaps) do + if type(query) == 'table' then + query = query[lang] + elseif not queries.get_query(lang, 'textobjects') then + query = nil + end + if query then + local cmd = ":lua require'nvim-treesitter.textobjects'.select_textobject('"..query.."')<CR>" + api.nvim_buf_set_keymap(buf, "o", mapping, cmd, {silent = true}) + 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 = configs.get_module("textobjects") + local lang = parsers.ft_to_lang(api.nvim_buf_get_option(bufnr, "ft")) + + for mapping, query in pairs(config.keymaps) do + if type(query) == 'table' then + query = query[lang] + elseif not queries.get_query(lang, 'textobjects') then + query = nil + end + if query then + api.nvim_buf_del_keymap(buf, "o", mapping) + api.nvim_buf_del_keymap(buf, "v", mapping) + end + end +end + +return M |
