From e647356210b23224e5bcc8893cfbcb031bad3ed4 Mon Sep 17 00:00:00 2001 From: Thomas Vigouroux Date: Sat, 18 Apr 2020 17:39:03 +0200 Subject: style: add editorconfig --- .editorconfig | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..bb6a1423e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +tab_width = 8 +end_of_line = lf +insert_final_newline = true +charset = utf-8 + +[{Makefile,**/Makefile,runtime/doc/*.txt}] +indent_style = tab +indent_size = 8 -- cgit v1.2.3-70-g09d2 From e51b25dce209f0d560785c841fd3e4c667b12b9e Mon Sep 17 00:00:00 2001 From: Thomas Vigouroux Date: Sat, 18 Apr 2020 17:40:26 +0200 Subject: feat: add some utils to read queries --- lua/nvim-treesitter/lib.lua | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 lua/nvim-treesitter/lib.lua diff --git a/lua/nvim-treesitter/lib.lua b/lua/nvim-treesitter/lib.lua new file mode 100644 index 000000000..328e4a571 --- /dev/null +++ b/lua/nvim-treesitter/lib.lua @@ -0,0 +1,19 @@ +-- Treesitter utils + +local api = vim.api +local ts = vim.treesitter + +local M = {} + +local function read_query_file(fname) + return table.concat(vim.fn.readfile(fname), '\n') +end + +function M.get_query(ft, query_name) + local query_files = api.nvim_get_runtime_file(string.format('queries/%s/%s.scm', ft, query_name), false) + if #query_files > 0 then + return ts.parse_query(ft, read_query_file(query_files[1])) + end +end + +return M -- cgit v1.2.3-70-g09d2 From 00f871ab51e6d094c0cd83dc4668dbe7ec047d04 Mon Sep 17 00:00:00 2001 From: Thomas Vigouroux Date: Sat, 18 Apr 2020 19:21:01 +0200 Subject: feat: add an example locals query This will be the guide for the implementation of locals extraction, which is treesitters name of definition/scope. --- queries/lua/locals.scm | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 queries/lua/locals.scm diff --git a/queries/lua/locals.scm b/queries/lua/locals.scm new file mode 100644 index 000000000..a7b15d1e5 --- /dev/null +++ b/queries/lua/locals.scm @@ -0,0 +1,45 @@ +;;; DECLARATIONS AND SCOPES + +;; Variable and field declarations +((variable_declarator + (identifier) @definition) + (set! kind "v")) + +((variable_declarator + (field_expression object:(*) @definition.associated (property_identifier) @definition)) + (set! kind "v")) + +;; Parameters +((local_function + (parameters (identifier) @definition)) + (set! kind "v")) +((function + (parameters (identifier) @definition)) + (set! kind "v")) + +;; Function definitions +;; Functions definitions creates both a definition and a new scope +((function + (function_name_field + object: (identifier) @definition.associated + (property_identifier) @definition)) @scope + (set! kind "m")) + +((function + (function_name (identifier) @definition)) @scope + (set! kind "f")) + +((local_function + (identifier) @definition) @scope + (set! kind "f")) + +((if_statement) @scope) +((for_in_statement) @scope) +((repeat_statement) @scope) +;; Loops +((loop_expression + (identifier) @definition) + (set! kind "v")) + +;;; REFERENCES +((identifier) @reference) -- cgit v1.2.3-70-g09d2 From 5897d72b075991e4de5876c918be186d4551cf12 Mon Sep 17 00:00:00 2001 From: Thomas Vigouroux Date: Sat, 18 Apr 2020 19:32:51 +0200 Subject: feat: add empty setup function Will be used later to setup everything so that a language works properly in each situation. --- lua/nvim-treesitter.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 lua/nvim-treesitter.lua diff --git a/lua/nvim-treesitter.lua b/lua/nvim-treesitter.lua new file mode 100644 index 000000000..cbed117d2 --- /dev/null +++ b/lua/nvim-treesitter.lua @@ -0,0 +1,10 @@ +local api = vim.api + +local M = {} + +-- This function sets up everythin needed for a given language +-- this is the main interface through the plugin +function M.setup(lang) +end + +return M -- cgit v1.2.3-70-g09d2 From 2526baf4cc5ea540188345c856adb162ce102674 Mon Sep 17 00:00:00 2001 From: Thomas Vigouroux Date: Sun, 19 Apr 2020 09:45:54 +0200 Subject: feat: add parsers module and better match iter The `parsers` module manages parsers for us, for now only in a really basic way. iter_prepared_mathes iters on an enhanced versions of the matches, where captures are directly accessible via their names to allow things like : ((itentifier) @def.first (identifier) @def.last) To be handled like this in lua: match.def.first match.def.last Also adds a `set!` predicate to allow setting data within the prepared match (see queries/lua/locals.scm) for examples. --- lua/nvim-treesitter.lua | 3 ++ lua/nvim-treesitter/lib.lua | 19 ----------- lua/nvim-treesitter/parsers.lua | 21 ++++++++++++ lua/nvim-treesitter/query.lua | 76 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 19 deletions(-) delete mode 100644 lua/nvim-treesitter/lib.lua create mode 100644 lua/nvim-treesitter/parsers.lua create mode 100644 lua/nvim-treesitter/query.lua diff --git a/lua/nvim-treesitter.lua b/lua/nvim-treesitter.lua index cbed117d2..ab3edf071 100644 --- a/lua/nvim-treesitter.lua +++ b/lua/nvim-treesitter.lua @@ -1,10 +1,13 @@ local api = vim.api +local parsers = require'nvim-treesitter.parsers' local M = {} -- This function sets up everythin needed for a given language -- this is the main interface through the plugin function M.setup(lang) + if parsers.has_parser(lang) then + end end return M diff --git a/lua/nvim-treesitter/lib.lua b/lua/nvim-treesitter/lib.lua deleted file mode 100644 index 328e4a571..000000000 --- a/lua/nvim-treesitter/lib.lua +++ /dev/null @@ -1,19 +0,0 @@ --- Treesitter utils - -local api = vim.api -local ts = vim.treesitter - -local M = {} - -local function read_query_file(fname) - return table.concat(vim.fn.readfile(fname), '\n') -end - -function M.get_query(ft, query_name) - local query_files = api.nvim_get_runtime_file(string.format('queries/%s/%s.scm', ft, query_name), false) - if #query_files > 0 then - return ts.parse_query(ft, read_query_file(query_files[1])) - end -end - -return M diff --git a/lua/nvim-treesitter/parsers.lua b/lua/nvim-treesitter/parsers.lua new file mode 100644 index 000000000..c85177733 --- /dev/null +++ b/lua/nvim-treesitter/parsers.lua @@ -0,0 +1,21 @@ +local api = vim.api +local ts = vim.treesitter + +local M = {} + +function M.has_parser(lang) + local lang = lang or api.nvim_buf_get_option(0, 'filetype') + return #api.nvim_get_runtime_file('parser/' .. lang .. '.*', false) > 0 +end + +function M.get_parser(bufnr) + if M.has_parser() then + local buf = bufnr or api.nvim_get_current_buf() + if not M[buf] then + M[buf] = ts.get_parser(buf) + end + return M[buf] + end +end + +return M diff --git a/lua/nvim-treesitter/query.lua b/lua/nvim-treesitter/query.lua new file mode 100644 index 000000000..be650c795 --- /dev/null +++ b/lua/nvim-treesitter/query.lua @@ -0,0 +1,76 @@ +-- Treesitter utils + +local api = vim.api +local ts = vim.treesitter + +local M = {} + +local function read_query_file(fname) + return table.concat(vim.fn.readfile(fname), '\n') +end + +function M.get_query(ft, query_name) + local query_files = api.nvim_get_runtime_file(string.format('queries/%s/%s.scm', ft, query_name), false) + if #query_files > 0 then + return ts.parse_query(ft, read_query_file(query_files[1])) + end +end + +function M.iter_prepared_matches(query, qnode, bufnr, start_row, end_row) + -- A function that splits a string on '.' + local function split(string) + local t = {} + for str in string.gmatch(string, "([^.]+)") do + table.insert(t, str) + end + + return t + end + + -- Given a path (i.e. a List(String)) this functions inserts value at path + local function insert_to_path(object, path, value) + local curr_obj = object + + for index=1,(#path -1) do + if curr_obj[path[index]] == nil then + curr_obj[path[index]] = {} + end + + curr_obj = curr_obj[path[index]] + end + + curr_obj[path[#path]] = value + end + + local matches = query:iter_matches(qnode, bufnr, start_row, end_row) + + return function() + local pattern, match = matches() + if pattern ~= nil then + local prepared_match = {} + + -- Extract capture names from each match + for id, node in pairs(match) do + local name = query.captures[id] -- name of the capture in the query + if name ~= nil then + local path = split(name) + insert_to_path(prepared_match, path, node) + end + end + + -- Add some predicates for testing + local preds = query.info.patterns[pattern] + if preds then + for _, pred in pairs(preds) do + if pred[1] == "set!" and pred[2] ~= nil then + insert_to_path(prepared_match, split(pred[2]), pred[3]) + end + end + end + + return prepared_match + end + end +end + +return M -- cgit v1.2.3-70-g09d2