From eecbe11a8c35e422c039d819013d94222d23218c Mon Sep 17 00:00:00 2001 From: hsanson <900716+hsanson@users.noreply.github.com> Date: Thu, 7 Mar 2024 15:16:41 +0900 Subject: [PATCH] Add treesitter support This PR uses treesitter hurl parser to locate the HURL entry at the current cursor position. This is more efficient and reliable than parsing based on HTTP verbs and allows executing HurlRunnerAt from any place as long as it is inside a HURL entry. --- README.md | 14 ++++++++--- lua/hurl/health.lua | 17 ++++++++++++- lua/hurl/http_utils.lua | 56 ++++++++++++++++------------------------- lua/hurl/main.lua | 6 ++--- 4 files changed, 50 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 6836883..5fb96db 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,10 @@ Add the following configuration to your Neovim setup with [lazy.nvim](https://gi ```lua { "jellydn/hurl.nvim", - dependencies = { "MunifTanjim/nui.nvim" }, + dependencies = { + "MunifTanjim/nui.nvim", + "nvim-treesitter/nvim-treesitter" + }, ft = "hurl", opts = { -- Show debugging info @@ -56,6 +59,9 @@ Add the following configuration to your Neovim setup with [lazy.nvim](https://gi } ``` +When configuring nvim-treesitter add `hurl` to the `ensure_installed` list of +parsers. + Simple demo in split mode: [![Show in split mode](https://i.gyazo.com/19492e8b5366cec3f22d5fd97a63f37a.gif)](https://gyazo.com/19492e8b5366cec3f22d5fd97a63f37a) @@ -127,7 +133,7 @@ Select a range of lines and press `h` to execute the request or run `Hur ### Run at current line -Place your cursor on the line you want to run and press `a` or run `HurlRunnerAt` command to execute the request. It need be one of the HTTP methods listed: GET, POST, PUT, DELETE, PATCH. +Place your cursor on a HURL entry and press `a` or run `HurlRunnerAt` command to execute the entry request. [![Run at current line in popup mode](https://i.gyazo.com/20efd2cf3f73238bd57e79fc662208b1.gif)](https://gyazo.com/20efd2cf3f73238bd57e79fc662208b1) @@ -139,11 +145,11 @@ Run `HurlVerbose` command to execute the request in verbose mode. The response w ### Run to entry -Place your cursor on the line you want to run to that entry and press `te` or run `HurlRunnerToEntry` command to execute the request. It need be one of the HTTP methods listed: GET, POST, PUT, DELETE, PATCH. +Place your cursor on the line you want to run to that entry and press `te` or run `HurlRunnerToEntry` command to execute the request. [![Run to entry in split mode](https://i.gyazo.com/14d47adbfcab9e945f89e020b83328a9.gif)](https://gyazo.com/14d47adbfcab9e945f89e020b83328a9) -Note: it's running to that entry and ignore the remaining of the file. It is useful for debugging purposes. +Note: it's running from start of file to the selected entry and ignore the remaining of the file. It is useful for debugging purposes. ### Toggle Mode diff --git a/lua/hurl/health.lua b/lua/hurl/health.lua index a450f00..dfccdfe 100644 --- a/lua/hurl/health.lua +++ b/lua/hurl/health.lua @@ -5,7 +5,7 @@ local ok = vim.health.ok or vim.health.report_ok local error = vim.health.error or vim.health.report_error -- Add health check for default formatter: jq and prettier -function M.check() +M.check = function() start('hurl.nvim health check') local jq = vim.fn.executable('jq') local prettier = vim.fn.executable('prettier') @@ -22,6 +22,21 @@ function M.check() ok('prettier found') end + local ts + if xpcall( + function() ts = require("nvim-treesitter-language") end, + function(e) ts = e end) + then + ok('nvim-treesitter found') + if ts.language.get_lang('hurl') == 'hurl' then + ok(' hurl parser installed') + else + error(' hurl parser not found') + end + else + error('nvim-treesitter not found') + end + ok('hurl.nvim: All good!') end diff --git a/lua/hurl/http_utils.lua b/lua/hurl/http_utils.lua index 7127305..56508dd 100644 --- a/lua/hurl/http_utils.lua +++ b/lua/hurl/http_utils.lua @@ -31,46 +31,32 @@ local function find_http_verb(line, current_line_number) end end ---- Find the HTTP verbs in the current buffer ----@return table -local function find_http_verb_positions_in_buffer() - local buf = vim.api.nvim_get_current_buf() - local total_lines = vim.api.nvim_buf_line_count(buf) - local cursor = vim.api.nvim_win_get_cursor(0) - local current_line_number = cursor[1] +--- Find the closest HURL entry at the current cursor position. +local function find_hurl_entry_positions_in_buffer() + local ts = vim.treesitter + local node = ts.get_node() - local next_entry = 0 - local current_index = 0 - local current_verb = nil - local end_line = total_lines -- Default to the last line of the buffer - - for i = 1, total_lines do - local line = vim.api.nvim_buf_get_lines(buf, i - 1, i, false)[1] - local result = find_http_verb(line, i) - if result then - next_entry = next_entry + 1 - if i == current_line_number then - current_index = next_entry - current_verb = result - elseif current_verb and i > current_verb.line_number then - end_line = i - 1 -- The end line of the current verb is the line before the next verb starts - break -- No need to continue once the end line of the current verb is found - end - end + while node and node:type() ~= "entry" do + node = node:parent() end - if current_verb and current_index == next_entry then - -- If the current verb is the last one, the end line is the last line of the buffer - end_line = total_lines + if not node then + return { + current = 0, + start_line = nil, + end_line = nil, + } + else + local r1, _, _ = node:start() + local r2, _, _ = node:end_() + return { + current = r1 + 1, + start_line = r1 + 1, + end_line = r2 + 1 + } end - - return { - current = current_index, - start_line = current_verb and current_verb.line_number or nil, - end_line = end_line, - } end -M.find_http_verb_positions_in_buffer = find_http_verb_positions_in_buffer +M.find_hurl_entry_positions_in_buffer = find_hurl_entry_positions_in_buffer return M diff --git a/lua/hurl/main.lua b/lua/hurl/main.lua index 1ab5848..f3338f2 100644 --- a/lua/hurl/main.lua +++ b/lua/hurl/main.lua @@ -346,7 +346,7 @@ function M.setup() -- Run request at current line if there is a HTTP method utils.create_cmd('HurlRunnerAt', function(opts) - local result = http.find_http_verb_positions_in_buffer() + local result = http.find_hurl_entry_positions_in_buffer() if result.current > 0 and result.start_line and result.end_line then utils.log_info( 'hurl: running request at line ' .. result.start_line .. ' to ' .. result.end_line @@ -360,7 +360,7 @@ function M.setup() -- Run request to current entry if there is a HTTP method utils.create_cmd('HurlRunnerToEntry', function(opts) - local result = http.find_http_verb_positions_in_buffer() + local result = http.find_hurl_entry_positions_in_buffer() if result.current > 0 then opts.fargs = opts.fargs or {} opts.fargs = vim.list_extend(opts.fargs, { '--to-entry', result.current }) @@ -390,7 +390,7 @@ function M.setup() utils.create_cmd('HurlVerbose', function(opts) -- It should be the same logic with run at current line but with verbose flag -- The response will be sent to quickfix - local result = http.find_http_verb_positions_in_buffer() + local result = http.find_hurl_entry_positions_in_buffer() if result.current > 0 and result.start_line and result.end_line then utils.log_info( 'hurl: running request at line ' .. result.start_line .. ' to ' .. result.end_line