From 68b5ecfac8e6897adb76a86b040b23ab3167b8ad Mon Sep 17 00:00:00 2001 From: blackadress Date: Thu, 27 Jan 2022 20:59:31 -0500 Subject: [PATCH 01/10] added json parser, and req variable parser --- lua/rest-nvim/curl/init.lua | 11 +- lua/rest-nvim/init.lua | 1 + lua/rest-nvim/json_parser/init.lua | 274 +++++++++++++++++++++++++++++ lua/rest-nvim/request/init.lua | 17 ++ plugin/rest-nvim.vim | 40 +++-- tests/basic_get.http | 3 + 6 files changed, 329 insertions(+), 17 deletions(-) create mode 100644 lua/rest-nvim/json_parser/init.lua diff --git a/lua/rest-nvim/curl/init.lua b/lua/rest-nvim/curl/init.lua index c0f6fbdf..5ae11edc 100644 --- a/lua/rest-nvim/curl/init.lua +++ b/lua/rest-nvim/curl/init.lua @@ -1,6 +1,7 @@ local utils = require("rest-nvim.utils") local curl = require("plenary.curl") local config = require("rest-nvim.config") +local json = require("rest-nvim.json_parser") local log = require("plenary.log").new({ plugin = "rest.nvim", level = "debug" }) local M = {} @@ -40,7 +41,7 @@ M.get_or_create_buf = function() return new_bufnr end -local function create_callback(method, url) +local function create_callback(method, url, req_var) return function(res) if res.exit ~= 0 then log.error("[rest.nvim] " .. utils.curl_error(res.exit)) @@ -94,6 +95,12 @@ local function create_callback(method, url) -- format JSON body res.body = vim.fn.system("jq", res.body) end + -- 1. check if there exists a variable for saving the json-data + -- 2. parse the json and get the data on to memory? + if json_body and req_var ~= '' then + local parsed = json.decode(res.body) + print(parsed[req_var]) + end local lines = utils.split(res.body, "\n") local line_count = vim.api.nvim_buf_line_count(res_bufnr) - 1 vim.api.nvim_buf_set_lines(res_bufnr, line_count, line_count + #lines, false, lines) @@ -145,7 +152,7 @@ M.curl_cmd = function(opts) log.debug("[rest.nvim] Request preview:\n" .. curl_cmd) return else - opts.callback = vim.schedule_wrap(create_callback(opts.method, opts.url)) + opts.callback = vim.schedule_wrap(create_callback(opts.method, opts.url, opts.req_var)) curl[opts.method](opts) end end diff --git a/lua/rest-nvim/init.lua b/lua/rest-nvim/init.lua index 7e20a162..cb30438d 100644 --- a/lua/rest-nvim/init.lua +++ b/lua/rest-nvim/init.lua @@ -29,6 +29,7 @@ rest.run = function(verbose) bufnr = result.bufnr, start_line = result.start_line, end_line = result.end_line, + req_var = result.req_var, } if not verbose then diff --git a/lua/rest-nvim/json_parser/init.lua b/lua/rest-nvim/json_parser/init.lua new file mode 100644 index 00000000..caa4e19d --- /dev/null +++ b/lua/rest-nvim/json_parser/init.lua @@ -0,0 +1,274 @@ +-- +-- json.lua +-- +-- Copyright (c) 2020 rxi +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of +-- this software and associated documentation files (the "Software"), to deal in +-- the Software without restriction, including without limitation the rights to +-- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +-- of the Software, and to permit persons to whom the Software is furnished to do +-- so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all +-- copies or substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +-- SOFTWARE. +-- +-- +-- Thanks rxi for this awesome json library <3 +-- https://github.com/rxi/json.lua +-- just got the decoding part, enconding may not be necessary + +local json = { _version = "0.1.2" } +local parse + +local function create_set(...) + local res = {} + for i = 1, select("#", ...) do + res[ select(i, ...) ] = true + end + return res +end + +local space_chars = create_set(" ", "\t", "\r", "\n") +local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",") +local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u") +local literals = create_set("true", "false", "null") + +local literal_map = { + [ "true" ] = true, + [ "false" ] = false, + [ "null" ] = nil, +} + + +local function next_char(str, idx, set, negate) + for i = idx, #str do + if set[str:sub(i, i)] ~= negate then + return i + end + end + return #str + 1 +end + + +local function decode_error(str, idx, msg) + local line_count = 1 + local col_count = 1 + for i = 1, idx - 1 do + col_count = col_count + 1 + if str:sub(i, i) == "\n" then + line_count = line_count + 1 + col_count = 1 + end + end + error( string.format("%s at line %d col %d", msg, line_count, col_count) ) +end + + +local function codepoint_to_utf8(n) + -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa + local f = math.floor + if n <= 0x7f then + return string.char(n) + elseif n <= 0x7ff then + return string.char(f(n / 64) + 192, n % 64 + 128) + elseif n <= 0xffff then + return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128) + elseif n <= 0x10ffff then + return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128, + f(n % 4096 / 64) + 128, n % 64 + 128) + end + error( string.format("invalid unicode codepoint '%x'", n) ) +end + + +local function parse_unicode_escape(s) + local n1 = tonumber( s:sub(1, 4), 16 ) + local n2 = tonumber( s:sub(7, 10), 16 ) + -- Surrogate pair? + if n2 then + return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000) + else + return codepoint_to_utf8(n1) + end +end + + +local function parse_string(str, i) + local res = "" + local j = i + 1 + local k = j + + while j <= #str do + local x = str:byte(j) + + if x < 32 then + decode_error(str, j, "control character in string") + + elseif x == 92 then -- `\`: Escape + res = res .. str:sub(k, j - 1) + j = j + 1 + local c = str:sub(j, j) + if c == "u" then + local hex = str:match("^[dD][89aAbB]%x%x\\u%x%x%x%x", j + 1) + or str:match("^%x%x%x%x", j + 1) + or decode_error(str, j - 1, "invalid unicode escape in string") + res = res .. parse_unicode_escape(hex) + j = j + #hex + else + if not escape_chars[c] then + decode_error(str, j - 1, "invalid escape char '" .. c .. "' in string") + end + res = res .. escape_char_map_inv[c] + end + k = j + 1 + + elseif x == 34 then -- `"`: End of string + res = res .. str:sub(k, j - 1) + return res, j + 1 + end + + j = j + 1 + end + + decode_error(str, i, "expected closing quote for string") +end + + +local function parse_number(str, i) + local x = next_char(str, i, delim_chars) + local s = str:sub(i, x - 1) + local n = tonumber(s) + if not n then + decode_error(str, i, "invalid number '" .. s .. "'") + end + return n, x +end + + +local function parse_literal(str, i) + local x = next_char(str, i, delim_chars) + local word = str:sub(i, x - 1) + if not literals[word] then + decode_error(str, i, "invalid literal '" .. word .. "'") + end + return literal_map[word], x +end + + +local function parse_array(str, i) + local res = {} + local n = 1 + i = i + 1 + while 1 do + local x + i = next_char(str, i, space_chars, true) + -- Empty / end of array? + if str:sub(i, i) == "]" then + i = i + 1 + break + end + -- Read token + x, i = parse(str, i) + res[n] = x + n = n + 1 + -- Next token + i = next_char(str, i, space_chars, true) + local chr = str:sub(i, i) + i = i + 1 + if chr == "]" then break end + if chr ~= "," then decode_error(str, i, "expected ']' or ','") end + end + return res, i +end + + +local function parse_object(str, i) + local res = {} + i = i + 1 + while 1 do + local key, val + i = next_char(str, i,space_chars, true) + -- Empty / end of object? + if str:sub(i, i) == "}" then + i = i + 1 + break + end + -- Read key + if str:sub(i, i) ~= '"' then + decode_error(str, i, "expected string for key") + end + key, i = parse(str, i) + -- Read ':' delimiter + i = next_char(str, i, space_chars, true) + if str:sub(i, i) ~= ":" then + decode_error(str, i, "expected ':' after key") + end + i = next_char(str, i + 1, space_chars, true) + -- Read value + val, i = parse(str, i) + -- Set + res[key] = val + -- Next token + i = next_char(str, i, space_chars, true) + local chr = str:sub(i, i) + i = i + 1 + if chr == "}" then break end + if chr ~= "," then decode_error(str, i, "expected '}' or ','") end + end + return res, i +end + + +local char_func_map = { + [ '"' ] = parse_string, + [ "0" ] = parse_number, + [ "1" ] = parse_number, + [ "2" ] = parse_number, + [ "3" ] = parse_number, + [ "4" ] = parse_number, + [ "5" ] = parse_number, + [ "6" ] = parse_number, + [ "7" ] = parse_number, + [ "8" ] = parse_number, + [ "9" ] = parse_number, + [ "-" ] = parse_number, + [ "t" ] = parse_literal, + [ "f" ] = parse_literal, + [ "n" ] = parse_literal, + [ "[" ] = parse_array, + [ "{" ] = parse_object, +} + + +parse = function(str, idx) + local chr = str:sub(idx, idx) + local f = char_func_map[chr] + if f then + return f(str, idx) + end + decode_error(str, idx, "unexpected character '" .. chr .. "'") +end + + +function json.decode(str) + if type(str) ~= "string" then + error("expected argument of type string, got " .. type(str)) + end + local res, idx = parse(str, next_char(str, 1, space_chars, true)) + idx = next_char(str, idx, space_chars, true) + if idx <= #str then + decode_error(str, idx, "trailing garbage") + end + return res +end + +return json diff --git a/lua/rest-nvim/request/init.lua b/lua/rest-nvim/request/init.lua index eb305eaa..77e127cc 100644 --- a/lua/rest-nvim/request/init.lua +++ b/lua/rest-nvim/request/init.lua @@ -128,6 +128,11 @@ local function start_request() return vim.fn.search("^GET\\|^POST\\|^PUT\\|^PATCH\\|^DELETE", "cbn", 1) end +-- checks if request has variables +local function request_var(url_line) + return vim.fn.search("^#@", 'cbn', url_line - 1) +end + -- end_request will find the next request line (e.g. POST http://localhost:8081/foo) -- and returns the linenumber before this request line or the end of the buffer -- @param bufnr The buffer nummer of the .http-file @@ -172,6 +177,11 @@ local function parse_url(stmt) } end +local function parse_req_var(stmt) + local parsed = stmt:sub(3) + return parsed +end + local M = {} M.get_current_request = function() local curpos = vim.fn.getcurpos() @@ -185,6 +195,12 @@ M.get_current_request = function() local parsed_url = parse_url(vim.fn.getline(start_line)) + local req_var_line = request_var(start_line) + local parsed_req_var_str = '' + if req_var_line ~= 0 then + parsed_req_var_str = parse_req_var(vim.fn.getline(req_var_line)) + end + local headers, body_start = get_headers(bufnr, start_line, end_line) local body = get_body(bufnr, body_start, end_line) @@ -203,6 +219,7 @@ M.get_current_request = function() bufnr = bufnr, start_line = start_line, end_line = end_line, + req_var = parsed_req_var_str, } end diff --git a/plugin/rest-nvim.vim b/plugin/rest-nvim.vim index 69f7dabd..89b76447 100644 --- a/plugin/rest-nvim.vim +++ b/plugin/rest-nvim.vim @@ -1,18 +1,28 @@ -if !has('nvim-0.5') - echoerr 'Rest.nvim requires at least nvim-0.5. Please update or uninstall' - finish -endif +" if !has('nvim-0.5') +" echoerr 'Rest.nvim requires at least nvim-0.5. Please update or uninstall' +" finish +" endif +" +" if exists('g:loaded_rest_nvim') | finish | endif +" +" nnoremap RestNvim :lua require('rest-nvim').run() +" nnoremap RestNvimPreview :lua require('rest-nvim').run(true) +" nnoremap RestNvimLast :lua require('rest-nvim').last() +" +" let s:save_cpo = &cpo +" set cpo&vim +" +" let &cpo = s:save_cpo +" unlet s:save_cpo -if exists('g:loaded_rest_nvim') | finish | endif +" let g:loaded_rest_nvim = 1 +" -nnoremap RestNvim :lua require('rest-nvim').run() -nnoremap RestNvimPreview :lua require('rest-nvim').run(true) -nnoremap RestNvimLast :lua require('rest-nvim').last() +function! YourFirstPlugin() + " dont forget to remove this ... + lua for k in pairs(package.loaded) do if k:match("^rest%-nvim") then package.loaded[k] = nil end end +endfun -let s:save_cpo = &cpo -set cpo&vim - -let &cpo = s:save_cpo -unlet s:save_cpo - -let g:loaded_rest_nvim = 1 +augroup YourFirstPlugin + autocmd! +augroup END diff --git a/tests/basic_get.http b/tests/basic_get.http index eb814b02..42670e53 100644 --- a/tests/basic_get.http +++ b/tests/basic_get.http @@ -1 +1,4 @@ +#@page GET https://reqres.in/api/users?page=5 + + From b9b6dd9c15b485d059581c5c25393e7d6d66a809 Mon Sep 17 00:00:00 2001 From: blackadress Date: Fri, 28 Jan 2022 22:16:22 -0500 Subject: [PATCH 02/10] allow for request variables on file --- lua/rest-nvim/curl/init.lua | 3 +-- lua/rest-nvim/init.lua | 2 ++ lua/rest-nvim/utils/init.lua | 47 +++++++++++++++++++++++++++++++++++- tests/basic_get.http | 9 ++++++- 4 files changed, 57 insertions(+), 4 deletions(-) diff --git a/lua/rest-nvim/curl/init.lua b/lua/rest-nvim/curl/init.lua index 5ae11edc..d3c5e7ad 100644 --- a/lua/rest-nvim/curl/init.lua +++ b/lua/rest-nvim/curl/init.lua @@ -98,8 +98,7 @@ local function create_callback(method, url, req_var) -- 1. check if there exists a variable for saving the json-data -- 2. parse the json and get the data on to memory? if json_body and req_var ~= '' then - local parsed = json.decode(res.body) - print(parsed[req_var]) + REQ_VAR_STORE[req_var] = json.decode(res.body) end local lines = utils.split(res.body, "\n") local line_count = vim.api.nvim_buf_line_count(res_bufnr) - 1 diff --git a/lua/rest-nvim/init.lua b/lua/rest-nvim/init.lua index cb30438d..c534783a 100644 --- a/lua/rest-nvim/init.lua +++ b/lua/rest-nvim/init.lua @@ -5,6 +5,8 @@ local curl = require("rest-nvim.curl") local Opts = {} local LastOpts = {} +REQ_VAR_STORE = {__loaded = true} + rest.setup = function(user_configs) config.set(user_configs or {}) end diff --git a/lua/rest-nvim/utils/init.lua b/lua/rest-nvim/utils/init.lua index 72c4f17a..b9988c1d 100644 --- a/lua/rest-nvim/utils/init.lua +++ b/lua/rest-nvim/utils/init.lua @@ -116,10 +116,17 @@ M.read_document_variables = function() for node in root:iter_children() do local type = node:type() + -- check if variable has assigned other variable, e.g. + -- foo: {{bar}} + -- if so, then replace {{bar}} with the proper value + -- {{bar}} can only be a request variable + if type == "header" then local name = node:named_child(0) local value = node:named_child(1) - variables[M.get_node_value(name, bufnr)] = M.get_node_value(value, bufnr) + local value_processed = M.replace_req_varibles(M.get_node_value(value, bufnr)) + -- local value_processed = M.get_node_value(value, bufnr) + variables[M.get_node_value(name, bufnr)] = value_processed elseif type ~= "comment" then break end @@ -135,6 +142,44 @@ M.read_variables = function() return vim.tbl_extend("force", first, second, third) end + +-- replaces the variables that have assigned another variable, e.g. +-- foo: {{bar}} or foo: {{bar.baz}} +-- when `bar` has a value in REQ_VAR_STORE +M.replace_req_varibles = function(value_str) + -- first check if 'value_str' has the form {{bar}} + -- if not then return them as is + local match = string.match(value_str, "{{[^}]+}}") + if match == nil then + return value_str + end + + match = match:gsub("{", ""):gsub("}", "") + + -- split the value_str, e.g. + -- 'foo.bar.baz' -> {'foo', 'bar', 'baz'} + local splitted_values = {} + for var in match:gmatch("([^.]+)") do + table.insert(splitted_values, var) + end + + local result = REQ_VAR_STORE + if not result.__loaded then + error(string.format("The rest-nvim's global JSON has been unset, it is needed", match)) + end + for _, val in pairs(splitted_values) do + if result[val] then + result = result[val] + print('result get value from global json', result) + else + result = '' + break + end + end + + return result +end + -- replace_vars replaces the env variables fields in the provided string -- with the env variable value -- @param str Where replace the placers for the env variables diff --git a/tests/basic_get.http b/tests/basic_get.http index 42670e53..8aa6ac86 100644 --- a/tests/basic_get.http +++ b/tests/basic_get.http @@ -1,4 +1,11 @@ -#@page +page: 5 + +varprueba: {{something.page}} +urltest: {{something.support.url}} +#@something GET https://reqres.in/api/users?page=5 +#### +GET https://reqres.in/api/users?page={{varprueba}} +GET {{urltest}} From 3e7e2a225f2a25dc178df8880c38e870553d74c4 Mon Sep 17 00:00:00 2001 From: blackadress Date: Sat, 29 Jan 2022 11:20:05 -0500 Subject: [PATCH 03/10] format and some light refactoring --- lua/rest-nvim/curl/init.lua | 5 ++--- lua/rest-nvim/init.lua | 3 ++- lua/rest-nvim/request/init.lua | 17 ++++++++++++++--- lua/rest-nvim/utils/init.lua | 32 +++++++++++++++----------------- plugin/rest-nvim.vim | 1 - tests/basic_get.http | 10 ---------- 6 files changed, 33 insertions(+), 35 deletions(-) diff --git a/lua/rest-nvim/curl/init.lua b/lua/rest-nvim/curl/init.lua index d3c5e7ad..dba14d12 100644 --- a/lua/rest-nvim/curl/init.lua +++ b/lua/rest-nvim/curl/init.lua @@ -95,9 +95,8 @@ local function create_callback(method, url, req_var) -- format JSON body res.body = vim.fn.system("jq", res.body) end - -- 1. check if there exists a variable for saving the json-data - -- 2. parse the json and get the data on to memory? - if json_body and req_var ~= '' then + -- parse the json response and store the data on memory + if json_body and req_var ~= "" then REQ_VAR_STORE[req_var] = json.decode(res.body) end local lines = utils.split(res.body, "\n") diff --git a/lua/rest-nvim/init.lua b/lua/rest-nvim/init.lua index c534783a..61fab724 100644 --- a/lua/rest-nvim/init.lua +++ b/lua/rest-nvim/init.lua @@ -5,7 +5,8 @@ local curl = require("rest-nvim.curl") local Opts = {} local LastOpts = {} -REQ_VAR_STORE = {__loaded = true} +-- global variable, used to store request variables' data +REQ_VAR_STORE = { __loaded = true } rest.setup = function(user_configs) config.set(user_configs or {}) diff --git a/lua/rest-nvim/request/init.lua b/lua/rest-nvim/request/init.lua index 77e127cc..5e113d15 100644 --- a/lua/rest-nvim/request/init.lua +++ b/lua/rest-nvim/request/init.lua @@ -128,9 +128,17 @@ local function start_request() return vim.fn.search("^GET\\|^POST\\|^PUT\\|^PATCH\\|^DELETE", "cbn", 1) end --- checks if request has variables +-- request_var will find the request variable if it exists, e.g. +-- ``` +-- #@foo +-- GET http://localhost:8081/bar +-- ```` +-- of the current request and returns the linenumber of the found request variable +-- the current request, +-- variable is defined as the variable that starts with '#@' one line above the request line +-- @param url_line The request line local function request_var(url_line) - return vim.fn.search("^#@", 'cbn', url_line - 1) + return vim.fn.search("^#@", "cbn", url_line - 1) end -- end_request will find the next request line (e.g. POST http://localhost:8081/foo) @@ -177,6 +185,9 @@ local function parse_url(stmt) } end +-- parse_req_var returns a string with the name of the request variable, e.g. +-- #@foo -> parse_req_var -> foo +-- @param stmt the request variable (#@foo) local function parse_req_var(stmt) local parsed = stmt:sub(3) return parsed @@ -196,7 +207,7 @@ M.get_current_request = function() local parsed_url = parse_url(vim.fn.getline(start_line)) local req_var_line = request_var(start_line) - local parsed_req_var_str = '' + local parsed_req_var_str = "" if req_var_line ~= 0 then parsed_req_var_str = parse_req_var(vim.fn.getline(req_var_line)) end diff --git a/lua/rest-nvim/utils/init.lua b/lua/rest-nvim/utils/init.lua index b9988c1d..4ce04fe9 100644 --- a/lua/rest-nvim/utils/init.lua +++ b/lua/rest-nvim/utils/init.lua @@ -116,16 +116,12 @@ M.read_document_variables = function() for node in root:iter_children() do local type = node:type() - -- check if variable has assigned other variable, e.g. - -- foo: {{bar}} - -- if so, then replace {{bar}} with the proper value - -- {{bar}} can only be a request variable if type == "header" then local name = node:named_child(0) local value = node:named_child(1) + -- check if variable has assigned other variable, e.g. foo: {{bar}} local value_processed = M.replace_req_varibles(M.get_node_value(value, bufnr)) - -- local value_processed = M.get_node_value(value, bufnr) variables[M.get_node_value(name, bufnr)] = value_processed elseif type ~= "comment" then break @@ -142,13 +138,12 @@ M.read_variables = function() return vim.tbl_extend("force", first, second, third) end - --- replaces the variables that have assigned another variable, e.g. --- foo: {{bar}} or foo: {{bar.baz}} --- when `bar` has a value in REQ_VAR_STORE +-- replaces the variables that have assigned another variable, e.g. foo: {{bar}} or foo: {{bar.baz}} +-- if so, then replace {{bar}} or {{bar.baz}} with the proper value else return the same string +-- only works if `bar` is a key in REQ_VAR_STORE +-- @param value_str the value to evaluate M.replace_req_varibles = function(value_str) - -- first check if 'value_str' has the form {{bar}} - -- if not then return them as is + -- first check if 'value_str' has the form {{bar}} if not then return them as is local match = string.match(value_str, "{{[^}]+}}") if match == nil then return value_str @@ -156,23 +151,26 @@ M.replace_req_varibles = function(value_str) match = match:gsub("{", ""):gsub("}", "") - -- split the value_str, e.g. - -- 'foo.bar.baz' -> {'foo', 'bar', 'baz'} + -- split the value_str, e.g. 'foo.bar.baz' -> {'foo', 'bar', 'baz'} local splitted_values = {} for var in match:gmatch("([^.]+)") do table.insert(splitted_values, var) end local result = REQ_VAR_STORE - if not result.__loaded then - error(string.format("The rest-nvim's global JSON has been unset, it is needed", match)) + if not result.__loaded then + error( + string.format( + "rest-nvim's global JSON variable has been unset, it is needed to get %s from there", + match + ) + ) end for _, val in pairs(splitted_values) do if result[val] then result = result[val] - print('result get value from global json', result) else - result = '' + result = "" break end end diff --git a/plugin/rest-nvim.vim b/plugin/rest-nvim.vim index 89b76447..8be244b0 100644 --- a/plugin/rest-nvim.vim +++ b/plugin/rest-nvim.vim @@ -19,7 +19,6 @@ " function! YourFirstPlugin() - " dont forget to remove this ... lua for k in pairs(package.loaded) do if k:match("^rest%-nvim") then package.loaded[k] = nil end end endfun diff --git a/tests/basic_get.http b/tests/basic_get.http index 8aa6ac86..eb814b02 100644 --- a/tests/basic_get.http +++ b/tests/basic_get.http @@ -1,11 +1 @@ -page: 5 - -varprueba: {{something.page}} -urltest: {{something.support.url}} -#@something GET https://reqres.in/api/users?page=5 - -#### -GET https://reqres.in/api/users?page={{varprueba}} - -GET {{urltest}} From 7c3e92b1c9ca9ff0bd1d50258c76f10d762232f1 Mon Sep 17 00:00:00 2001 From: blackadress Date: Sat, 29 Jan 2022 11:30:20 -0500 Subject: [PATCH 04/10] basic usage example, and removed dev stuff --- plugin/rest-nvim.vim | 39 +++++++++++------------------ tests/request_vars/basic_usage.http | 14 +++++++++++ 2 files changed, 29 insertions(+), 24 deletions(-) create mode 100644 tests/request_vars/basic_usage.http diff --git a/plugin/rest-nvim.vim b/plugin/rest-nvim.vim index 8be244b0..69f7dabd 100644 --- a/plugin/rest-nvim.vim +++ b/plugin/rest-nvim.vim @@ -1,27 +1,18 @@ -" if !has('nvim-0.5') -" echoerr 'Rest.nvim requires at least nvim-0.5. Please update or uninstall' -" finish -" endif -" -" if exists('g:loaded_rest_nvim') | finish | endif -" -" nnoremap RestNvim :lua require('rest-nvim').run() -" nnoremap RestNvimPreview :lua require('rest-nvim').run(true) -" nnoremap RestNvimLast :lua require('rest-nvim').last() -" -" let s:save_cpo = &cpo -" set cpo&vim -" -" let &cpo = s:save_cpo -" unlet s:save_cpo +if !has('nvim-0.5') + echoerr 'Rest.nvim requires at least nvim-0.5. Please update or uninstall' + finish +endif -" let g:loaded_rest_nvim = 1 -" +if exists('g:loaded_rest_nvim') | finish | endif -function! YourFirstPlugin() - lua for k in pairs(package.loaded) do if k:match("^rest%-nvim") then package.loaded[k] = nil end end -endfun +nnoremap RestNvim :lua require('rest-nvim').run() +nnoremap RestNvimPreview :lua require('rest-nvim').run(true) +nnoremap RestNvimLast :lua require('rest-nvim').last() -augroup YourFirstPlugin - autocmd! -augroup END +let s:save_cpo = &cpo +set cpo&vim + +let &cpo = s:save_cpo +unlet s:save_cpo + +let g:loaded_rest_nvim = 1 diff --git a/tests/request_vars/basic_usage.http b/tests/request_vars/basic_usage.http new file mode 100644 index 00000000..f0fce44d --- /dev/null +++ b/tests/request_vars/basic_usage.http @@ -0,0 +1,14 @@ +page: {{response.page}} +url: {{response.support.url}} + +# normal var +foo: 4 + +#@response +GET https://reqres.in/api/users?page=5 + +GET https://reqres.in/api/users?page={{foo}} + +GET https://reqres.in/api/users?page={{page}} + +GET {{url}} From 9204928b0de7ec51f3a20a66fe5384dc2ac7b6f7 Mon Sep 17 00:00:00 2001 From: blackadress Date: Mon, 31 Jan 2022 20:14:37 -0500 Subject: [PATCH 05/10] deleted json library, using vim.json instead --- lua/rest-nvim/curl/init.lua | 3 +- lua/rest-nvim/json_parser/init.lua | 274 ----------------------------- 2 files changed, 1 insertion(+), 276 deletions(-) delete mode 100644 lua/rest-nvim/json_parser/init.lua diff --git a/lua/rest-nvim/curl/init.lua b/lua/rest-nvim/curl/init.lua index dba14d12..49ffdaac 100644 --- a/lua/rest-nvim/curl/init.lua +++ b/lua/rest-nvim/curl/init.lua @@ -1,7 +1,6 @@ local utils = require("rest-nvim.utils") local curl = require("plenary.curl") local config = require("rest-nvim.config") -local json = require("rest-nvim.json_parser") local log = require("plenary.log").new({ plugin = "rest.nvim", level = "debug" }) local M = {} @@ -97,7 +96,7 @@ local function create_callback(method, url, req_var) end -- parse the json response and store the data on memory if json_body and req_var ~= "" then - REQ_VAR_STORE[req_var] = json.decode(res.body) + REQ_VAR_STORE[req_var] = vim.json.decode(res.body) end local lines = utils.split(res.body, "\n") local line_count = vim.api.nvim_buf_line_count(res_bufnr) - 1 diff --git a/lua/rest-nvim/json_parser/init.lua b/lua/rest-nvim/json_parser/init.lua deleted file mode 100644 index caa4e19d..00000000 --- a/lua/rest-nvim/json_parser/init.lua +++ /dev/null @@ -1,274 +0,0 @@ --- --- json.lua --- --- Copyright (c) 2020 rxi --- --- Permission is hereby granted, free of charge, to any person obtaining a copy of --- this software and associated documentation files (the "Software"), to deal in --- the Software without restriction, including without limitation the rights to --- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies --- of the Software, and to permit persons to whom the Software is furnished to do --- so, subject to the following conditions: --- --- The above copyright notice and this permission notice shall be included in all --- copies or substantial portions of the Software. --- --- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --- SOFTWARE. --- --- --- Thanks rxi for this awesome json library <3 --- https://github.com/rxi/json.lua --- just got the decoding part, enconding may not be necessary - -local json = { _version = "0.1.2" } -local parse - -local function create_set(...) - local res = {} - for i = 1, select("#", ...) do - res[ select(i, ...) ] = true - end - return res -end - -local space_chars = create_set(" ", "\t", "\r", "\n") -local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",") -local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u") -local literals = create_set("true", "false", "null") - -local literal_map = { - [ "true" ] = true, - [ "false" ] = false, - [ "null" ] = nil, -} - - -local function next_char(str, idx, set, negate) - for i = idx, #str do - if set[str:sub(i, i)] ~= negate then - return i - end - end - return #str + 1 -end - - -local function decode_error(str, idx, msg) - local line_count = 1 - local col_count = 1 - for i = 1, idx - 1 do - col_count = col_count + 1 - if str:sub(i, i) == "\n" then - line_count = line_count + 1 - col_count = 1 - end - end - error( string.format("%s at line %d col %d", msg, line_count, col_count) ) -end - - -local function codepoint_to_utf8(n) - -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa - local f = math.floor - if n <= 0x7f then - return string.char(n) - elseif n <= 0x7ff then - return string.char(f(n / 64) + 192, n % 64 + 128) - elseif n <= 0xffff then - return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128) - elseif n <= 0x10ffff then - return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128, - f(n % 4096 / 64) + 128, n % 64 + 128) - end - error( string.format("invalid unicode codepoint '%x'", n) ) -end - - -local function parse_unicode_escape(s) - local n1 = tonumber( s:sub(1, 4), 16 ) - local n2 = tonumber( s:sub(7, 10), 16 ) - -- Surrogate pair? - if n2 then - return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000) - else - return codepoint_to_utf8(n1) - end -end - - -local function parse_string(str, i) - local res = "" - local j = i + 1 - local k = j - - while j <= #str do - local x = str:byte(j) - - if x < 32 then - decode_error(str, j, "control character in string") - - elseif x == 92 then -- `\`: Escape - res = res .. str:sub(k, j - 1) - j = j + 1 - local c = str:sub(j, j) - if c == "u" then - local hex = str:match("^[dD][89aAbB]%x%x\\u%x%x%x%x", j + 1) - or str:match("^%x%x%x%x", j + 1) - or decode_error(str, j - 1, "invalid unicode escape in string") - res = res .. parse_unicode_escape(hex) - j = j + #hex - else - if not escape_chars[c] then - decode_error(str, j - 1, "invalid escape char '" .. c .. "' in string") - end - res = res .. escape_char_map_inv[c] - end - k = j + 1 - - elseif x == 34 then -- `"`: End of string - res = res .. str:sub(k, j - 1) - return res, j + 1 - end - - j = j + 1 - end - - decode_error(str, i, "expected closing quote for string") -end - - -local function parse_number(str, i) - local x = next_char(str, i, delim_chars) - local s = str:sub(i, x - 1) - local n = tonumber(s) - if not n then - decode_error(str, i, "invalid number '" .. s .. "'") - end - return n, x -end - - -local function parse_literal(str, i) - local x = next_char(str, i, delim_chars) - local word = str:sub(i, x - 1) - if not literals[word] then - decode_error(str, i, "invalid literal '" .. word .. "'") - end - return literal_map[word], x -end - - -local function parse_array(str, i) - local res = {} - local n = 1 - i = i + 1 - while 1 do - local x - i = next_char(str, i, space_chars, true) - -- Empty / end of array? - if str:sub(i, i) == "]" then - i = i + 1 - break - end - -- Read token - x, i = parse(str, i) - res[n] = x - n = n + 1 - -- Next token - i = next_char(str, i, space_chars, true) - local chr = str:sub(i, i) - i = i + 1 - if chr == "]" then break end - if chr ~= "," then decode_error(str, i, "expected ']' or ','") end - end - return res, i -end - - -local function parse_object(str, i) - local res = {} - i = i + 1 - while 1 do - local key, val - i = next_char(str, i,space_chars, true) - -- Empty / end of object? - if str:sub(i, i) == "}" then - i = i + 1 - break - end - -- Read key - if str:sub(i, i) ~= '"' then - decode_error(str, i, "expected string for key") - end - key, i = parse(str, i) - -- Read ':' delimiter - i = next_char(str, i, space_chars, true) - if str:sub(i, i) ~= ":" then - decode_error(str, i, "expected ':' after key") - end - i = next_char(str, i + 1, space_chars, true) - -- Read value - val, i = parse(str, i) - -- Set - res[key] = val - -- Next token - i = next_char(str, i, space_chars, true) - local chr = str:sub(i, i) - i = i + 1 - if chr == "}" then break end - if chr ~= "," then decode_error(str, i, "expected '}' or ','") end - end - return res, i -end - - -local char_func_map = { - [ '"' ] = parse_string, - [ "0" ] = parse_number, - [ "1" ] = parse_number, - [ "2" ] = parse_number, - [ "3" ] = parse_number, - [ "4" ] = parse_number, - [ "5" ] = parse_number, - [ "6" ] = parse_number, - [ "7" ] = parse_number, - [ "8" ] = parse_number, - [ "9" ] = parse_number, - [ "-" ] = parse_number, - [ "t" ] = parse_literal, - [ "f" ] = parse_literal, - [ "n" ] = parse_literal, - [ "[" ] = parse_array, - [ "{" ] = parse_object, -} - - -parse = function(str, idx) - local chr = str:sub(idx, idx) - local f = char_func_map[chr] - if f then - return f(str, idx) - end - decode_error(str, idx, "unexpected character '" .. chr .. "'") -end - - -function json.decode(str) - if type(str) ~= "string" then - error("expected argument of type string, got " .. type(str)) - end - local res, idx = parse(str, next_char(str, 1, space_chars, true)) - idx = next_char(str, idx, space_chars, true) - if idx <= #str then - decode_error(str, idx, "trailing garbage") - end - return res -end - -return json From e9350821b5f65d2c97468cacb37b664dbc553a59 Mon Sep 17 00:00:00 2001 From: blackadress Date: Wed, 2 Feb 2022 21:07:42 -0500 Subject: [PATCH 06/10] removed lua global variable --- lua/rest-nvim/curl/init.lua | 4 +++- lua/rest-nvim/init.lua | 4 +--- lua/rest-nvim/utils/init.lua | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lua/rest-nvim/curl/init.lua b/lua/rest-nvim/curl/init.lua index 49ffdaac..78290c7c 100644 --- a/lua/rest-nvim/curl/init.lua +++ b/lua/rest-nvim/curl/init.lua @@ -96,7 +96,9 @@ local function create_callback(method, url, req_var) end -- parse the json response and store the data on memory if json_body and req_var ~= "" then - REQ_VAR_STORE[req_var] = vim.json.decode(res.body) + local req_var_store = vim.api.nvim_get_var('req_var_store') + req_var_store[req_var] = vim.json.decode(res.body) + vim.api.nvim_set_var('req_var_store', req_var_store) end local lines = utils.split(res.body, "\n") local line_count = vim.api.nvim_buf_line_count(res_bufnr) - 1 diff --git a/lua/rest-nvim/init.lua b/lua/rest-nvim/init.lua index 61fab724..2498fb50 100644 --- a/lua/rest-nvim/init.lua +++ b/lua/rest-nvim/init.lua @@ -5,9 +5,7 @@ local curl = require("rest-nvim.curl") local Opts = {} local LastOpts = {} --- global variable, used to store request variables' data -REQ_VAR_STORE = { __loaded = true } - +vim.api.nvim_set_var("req_var_store", { __loaded = true }) rest.setup = function(user_configs) config.set(user_configs or {}) end diff --git a/lua/rest-nvim/utils/init.lua b/lua/rest-nvim/utils/init.lua index 4ce04fe9..82f29f32 100644 --- a/lua/rest-nvim/utils/init.lua +++ b/lua/rest-nvim/utils/init.lua @@ -140,7 +140,7 @@ end -- replaces the variables that have assigned another variable, e.g. foo: {{bar}} or foo: {{bar.baz}} -- if so, then replace {{bar}} or {{bar.baz}} with the proper value else return the same string --- only works if `bar` is a key in REQ_VAR_STORE +-- only works if `bar` is a key in req_var_store -- @param value_str the value to evaluate M.replace_req_varibles = function(value_str) -- first check if 'value_str' has the form {{bar}} if not then return them as is @@ -157,7 +157,7 @@ M.replace_req_varibles = function(value_str) table.insert(splitted_values, var) end - local result = REQ_VAR_STORE + local result = vim.api.nvim_get_var('req_var_store') if not result.__loaded then error( string.format( From 831942646ca1a6b55e4386c7f7b627a8b971a5c0 Mon Sep 17 00:00:00 2001 From: blackadress Date: Wed, 17 Aug 2022 13:44:44 -0500 Subject: [PATCH 07/10] chore: updated variables to new changes from main --- lua/rest-nvim/curl/init.lua | 4 +++- lua/rest-nvim/request/init.lua | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lua/rest-nvim/curl/init.lua b/lua/rest-nvim/curl/init.lua index 2ba3a070..f6e70d36 100644 --- a/lua/rest-nvim/curl/init.lua +++ b/lua/rest-nvim/curl/init.lua @@ -133,8 +133,10 @@ local function create_callback(method, url, req_var) }, false, {}) end end + -- check if the response is a json -- parse the json response and store the data on memory - if json_body and req_var ~= "" then + if content_type == "json" and req_var ~= "" then + print('content_type', content_type) local req_var_store = vim.api.nvim_get_var('req_var_store') req_var_store[req_var] = vim.json.decode(res.body) vim.api.nvim_set_var('req_var_store', req_var_store) diff --git a/lua/rest-nvim/request/init.lua b/lua/rest-nvim/request/init.lua index 99fc874d..16d043c6 100644 --- a/lua/rest-nvim/request/init.lua +++ b/lua/rest-nvim/request/init.lua @@ -168,8 +168,8 @@ end -- GET http://localhost:8081/bar -- ```` -- of the current request and returns the linenumber of the found request variable --- the current request, --- variable is defined as the variable that starts with '#@' one line above the request line +-- the request variable is defined as the variable that starts with '#@' +-- one line above the request line in the example the variable would be 'foo' -- @param url_line The request line local function request_var(url_line) return vim.fn.search("^#@", "cbn", url_line - 1) From bb9ada06ecee10cab82682c16ee4de942321b594 Mon Sep 17 00:00:00 2001 From: blackadress Date: Wed, 17 Aug 2022 13:57:45 -0500 Subject: [PATCH 08/10] chore: debugger print deleted --- lua/rest-nvim/curl/init.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/lua/rest-nvim/curl/init.lua b/lua/rest-nvim/curl/init.lua index f6e70d36..c0d00ba9 100644 --- a/lua/rest-nvim/curl/init.lua +++ b/lua/rest-nvim/curl/init.lua @@ -136,7 +136,6 @@ local function create_callback(method, url, req_var) -- check if the response is a json -- parse the json response and store the data on memory if content_type == "json" and req_var ~= "" then - print('content_type', content_type) local req_var_store = vim.api.nvim_get_var('req_var_store') req_var_store[req_var] = vim.json.decode(res.body) vim.api.nvim_set_var('req_var_store', req_var_store) From db64cd60c931a345663f424b91fc9a8e8234722a Mon Sep 17 00:00:00 2001 From: blackadress Date: Thu, 20 Apr 2023 09:01:33 -0500 Subject: [PATCH 09/10] added support for accesing elements in array --- lua/rest-nvim/utils/init.lua | 7 ++++++- tests/request_vars/basic_usage.http | 5 ++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lua/rest-nvim/utils/init.lua b/lua/rest-nvim/utils/init.lua index bd6efed0..449813c8 100644 --- a/lua/rest-nvim/utils/init.lua +++ b/lua/rest-nvim/utils/init.lua @@ -245,10 +245,15 @@ M.replace_req_varibles = function(value_str) -- split the value_str, e.g. 'foo.bar.baz' -> {'foo', 'bar', 'baz'} local splitted_values = {} for var in match:gmatch("([^.]+)") do + -- try to parse 'var' as number + local x = tonumber(var) + if x then + var = x + 1 + end table.insert(splitted_values, var) end - local result = vim.api.nvim_get_var('req_var_store') + local result = vim.api.nvim_get_var("req_var_store") if not result.__loaded then error( string.format( diff --git a/tests/request_vars/basic_usage.http b/tests/request_vars/basic_usage.http index f0fce44d..05a50d55 100644 --- a/tests/request_vars/basic_usage.http +++ b/tests/request_vars/basic_usage.http @@ -1,14 +1,17 @@ page: {{response.page}} url: {{response.support.url}} +userid: {{response.data.0.id}} # normal var foo: 4 #@response -GET https://reqres.in/api/users?page=5 +GET https://reqres.in/api/users?page=2 GET https://reqres.in/api/users?page={{foo}} GET https://reqres.in/api/users?page={{page}} GET {{url}} + +GET https://reqres.in/api/users/{{userid}} From 92b80bc91b33558eedadc431425a85893aec180d Mon Sep 17 00:00:00 2001 From: blackadress Date: Mon, 17 Jul 2023 14:53:13 -0500 Subject: [PATCH 10/10] Sync to main --- .github/workflows/default.yml | 4 +- README.md | 12 ++ doc/rest-nvim.txt | 20 ++ contrib/flake.lock => flake.lock | 0 contrib/flake.nix => flake.nix | 72 +++----- ftplugin/http.vim | 1 + lua/rest-nvim/config/init.lua | 1 + lua/rest-nvim/curl/init.lua | 79 ++++---- lua/rest-nvim/init.lua | 173 +++++++++++++++--- lua/rest-nvim/request/init.lua | 164 +++++++++-------- lua/rest-nvim/utils/init.lua | 8 + plugin/rest-nvim.vim | 6 + ...scm-1.rockspec => rest.nvim-scm-3.rockspec | 3 +- 13 files changed, 363 insertions(+), 180 deletions(-) rename contrib/flake.lock => flake.lock (100%) rename contrib/flake.nix => flake.nix (65%) create mode 100644 ftplugin/http.vim rename rest.nvim-scm-1.rockspec => rest.nvim-scm-3.rockspec (94%) diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml index 1e75b9c0..77783097 100644 --- a/.github/workflows/default.yml +++ b/.github/workflows/default.yml @@ -7,8 +7,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: cachix/install-nix-action@v18 + - uses: cachix/install-nix-action@v21 with: nix_path: nixpkgs=channel:nixos-unstable - run: | - nix develop ./contrib -c make test + nix develop .#ci -c make test diff --git a/README.md b/README.md index 024f74e4..88529dd3 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ have to leave Neovim! ## Notices +- **2023-07-12**: tagged 0.2 release before changes for 0.10 compatibility - **2021-11-04**: HTTP Tree-Sitter parser now depends on JSON parser for the JSON bodies detection, please install it too. - **2021-08-26**: We have deleted the syntax file for HTTP files to start using the tree-sitter parser instead, @@ -77,6 +78,9 @@ use { result = { -- toggle showing URL, HTTP info, headers at top the of result window show_url = true, + -- show the generated curl command in case you want to launch + -- the same request via the terminal (can be verbose) + show_curl_command = false, show_http_info = true, show_headers = true, -- executables or functions for formatting response body [optional] @@ -149,6 +153,13 @@ request method (e.g. `GET`) and run `rest.nvim`. --- +### Debug + + +Run `export DEBUG_PLENARY="debug"` before starting nvim. Logs will appear most +likely in ~/.cache/nvim/rest.nvim.log + + ## Contribute 1. Fork it (https://github.com/rest-nvim/rest.nvim/fork) @@ -162,6 +173,7 @@ test`. ## Related software +- [vim-rest-console](https://github.com/diepm/vim-rest-console) - [Hurl](https://hurl.dev/) - [HTTPie](https://httpie.io/) - [httpYac](https://httpyac.github.io/) diff --git a/doc/rest-nvim.txt b/doc/rest-nvim.txt index efc8dcbc..ce7d9132 100644 --- a/doc/rest-nvim.txt +++ b/doc/rest-nvim.txt @@ -21,6 +21,7 @@ CONTENTS *rest-nvim-contents* 3. Import body from external file......|rest-nvim-usage-external-files| 4. Environment Variables........|rest-nvim-usage-environment-variables| 5. Dynamic Variables................|rest-nvim-usage-dynamic-variables| + 6. Callbacks................................|rest-nvim-usage-callbacks| 5. Known issues..........................................|rest-nvim-issues| 6. License..............................................|rest-nvim-license| 7. Contributing....................................|rest-nvim-contributing| @@ -119,6 +120,9 @@ COMMANDS *rest-nvim-usage-commands* Same as `RestNvim` but it returns the cURL command without executing the request. Intended for debugging purposes. +- `:RestLog` + Shows `rest.nvim` logs (export DEBUG_PLENARY=debug for more logs). + - `:RestSelectEnv path/to/env` Set the path to an env file. @@ -220,6 +224,22 @@ You can extend or overwrite built-in dynamic variables, with the config key ` },` `})` +=============================================================================== +CALLBACKS *rest-nvim-usage-callbacks* + +rest.nvim fires different events upon requests: + - a User RestStartRequest event when launching the request + - a User RestStopRequest event when the requests finishes or errors out + +vim.api.nvim_create_autocmd("User", { +pattern = "RestStartRequest", +once = true, + callback = function(opts) + print("IT STARTED") + vim.pretty_print(opts) + end, +}) + =============================================================================== KNOWN ISSUES *rest-nvim-issues* diff --git a/contrib/flake.lock b/flake.lock similarity index 100% rename from contrib/flake.lock rename to flake.lock diff --git a/contrib/flake.nix b/flake.nix similarity index 65% rename from contrib/flake.nix rename to flake.nix index 3587bbc7..84538380 100644 --- a/contrib/flake.nix +++ b/flake.nix @@ -13,40 +13,11 @@ mkDevShell = luaVersion: let - # luaPkgs = pkgs."lua${luaVersion}".pkgs; luaEnv = pkgs."lua${luaVersion}".withPackages (lp: with lp; [ + busted luacheck luarocks ]); - neovimConfig = pkgs.neovimUtils.makeNeovimConfig { - plugins = with pkgs.vimPlugins; [ - { - plugin = packer-nvim; - type = "lua"; - config = '' - require('packer').init({ - luarocks = { - python_cmd = 'python' -- Set the python command to use for running hererocks - }, - }) - -- require my own manual config - require('init-manual') - ''; - } - { plugin = (nvim-treesitter.withPlugins ( - plugins: with plugins; [ - tree-sitter-lua - tree-sitter-http - tree-sitter-json - ] - )); - } - { plugin = plenary-nvim; } - ]; - customRC = ""; - wrapRc = false; - }; - myNeovim = pkgs.wrapNeovimUnstable pkgs.neovim-unwrapped neovimConfig; in pkgs.mkShell { name = "rest-nvim"; @@ -54,8 +25,6 @@ pkgs.sumneko-lua-language-server luaEnv pkgs.stylua - myNeovim - # pkgs.neovim # assume user has one already installed ]; shellHook = let @@ -67,30 +36,45 @@ tree-sitter-json ] ))]; - # opt = map (x: x.plugin) pluginsPartitioned.right; }; - # }; packDirArgs.myNeovimPackages = myVimPackage; in '' - cat <<-EOF > minimal.vim - set rtp+=. - set packpath^=${pkgs.vimUtils.packDir packDirArgs} - EOF + export DEBUG_PLENARY="debug" + cat <<-EOF > minimal.vim + set rtp+=. + set packpath^=${pkgs.vimUtils.packDir packDirArgs} + EOF ''; }; in { - # packages = { - # default = self.packages.${system}.luarocks-51; - # luarocks-51 = mkPackage "5_1"; - # luarocks-52 = mkPackage "5_2"; - # }; - devShells = { default = self.devShells.${system}.luajit; + ci = let + neovimConfig = pkgs.neovimUtils.makeNeovimConfig { + plugins = with pkgs.vimPlugins; [ + { plugin = (nvim-treesitter.withPlugins ( + plugins: with plugins; [ + tree-sitter-lua + tree-sitter-http + tree-sitter-json + ] + )); + } + { plugin = plenary-nvim; } + ]; + customRC = ""; + wrapRc = false; + }; + myNeovim = pkgs.wrapNeovimUnstable pkgs.neovim-unwrapped neovimConfig; + in + (mkDevShell "jit").overrideAttrs(oa: { + buildInputs = oa.buildInputs ++ [ myNeovim ]; + }); + luajit = mkDevShell "jit"; lua-51 = mkDevShell "5_1"; lua-52 = mkDevShell "5_2"; diff --git a/ftplugin/http.vim b/ftplugin/http.vim new file mode 100644 index 00000000..9c2e80a0 --- /dev/null +++ b/ftplugin/http.vim @@ -0,0 +1 @@ +set commentstring=#\ %s diff --git a/lua/rest-nvim/config/init.lua b/lua/rest-nvim/config/init.lua index fdc754fd..d78d2e77 100644 --- a/lua/rest-nvim/config/init.lua +++ b/lua/rest-nvim/config/init.lua @@ -10,6 +10,7 @@ local config = { timeout = 150, }, result = { + show_curl_command = true, show_url = true, show_http_info = true, show_headers = true, diff --git a/lua/rest-nvim/curl/init.lua b/lua/rest-nvim/curl/init.lua index fb9b7795..fe1a624c 100644 --- a/lua/rest-nvim/curl/init.lua +++ b/lua/rest-nvim/curl/init.lua @@ -15,6 +15,22 @@ local function is_executable(x) return false end +local function format_curl_cmd(res) + local cmd = "curl" + + for _, value in pairs(res) do + if string.sub(value, 1, 1) == "-" then + cmd = cmd .. " " .. value + else + cmd = cmd .. " '" .. value .. "'" + end + end + + -- remote -D option + cmd = string.gsub(cmd, "-D '%S+' ", "") + return cmd +end + -- get_or_create_buf checks if there is already a buffer with the rest run results -- and if the buffer does not exists, then create a new one M.get_or_create_buf = function() @@ -24,9 +40,9 @@ M.get_or_create_buf = function() local existing_bufnr = vim.fn.bufnr(tmp_name) if existing_bufnr ~= -1 then -- Set modifiable - vim.api.nvim_buf_set_option(existing_bufnr, "modifiable", true) + vim.api.nvim_set_option_value("modifiable", true, { buf = existing_bufnr }) -- Prevent modified flag - vim.api.nvim_buf_set_option(existing_bufnr, "buftype", "nofile") + vim.api.nvim_set_option_value("buftype", "nofile", { buf = existing_bufnr }) -- Delete buffer content vim.api.nvim_buf_set_lines( existing_bufnr, @@ -37,21 +53,21 @@ M.get_or_create_buf = function() ) -- Make sure the filetype of the buffer is httpResult so it will be highlighted - vim.api.nvim_buf_set_option(existing_bufnr, "ft", "httpResult") + vim.api.nvim_set_option_value("ft", "httpResult", { buf = existing_bufnr }) return existing_bufnr end -- Create new buffer - local new_bufnr = vim.api.nvim_create_buf(false, "nomodeline") + local new_bufnr = vim.api.nvim_create_buf(false, true) vim.api.nvim_buf_set_name(new_bufnr, tmp_name) - vim.api.nvim_buf_set_option(new_bufnr, "ft", "httpResult") - vim.api.nvim_buf_set_option(new_bufnr, "buftype", "nofile") + vim.api.nvim_set_option_value("ft", "httpResult", { buf = new_bufnr }) + vim.api.nvim_set_option_value("buftype", "nofile", { buf = new_bufnr }) return new_bufnr end -local function create_callback(method, url, script_str, req_var) +local function create_callback(curl_cmd, method, url, script_str, req_var) return function(res) if res.exit ~= 0 then log.error("[rest.nvim] " .. utils.curl_error(res.exit)) @@ -63,7 +79,7 @@ local function create_callback(method, url, script_str, req_var) -- get content type for _, header in ipairs(res.headers) do if string.lower(header):find("^content%-type") then - content_type = header:match("application/(%l+)") or header:match("text/(%l+)") + content_type = header:match("application/([-a-z]+)") or header:match("text/(%l+)") break end end @@ -83,6 +99,11 @@ local function create_callback(method, url, script_str, req_var) end end + -- This can be quite verbose so let user control it + if config.get("result").show_curl_command then + vim.api.nvim_buf_set_lines(res_bufnr, 0, 0, false, { "Command: " .. curl_cmd }) + end + if config.get("result").show_url then --- Add metadata into the created buffer (status code, date, etc) -- Request statement (METHOD URL) @@ -157,9 +178,15 @@ local function create_callback(method, url, script_str, req_var) end -- append response container - res.body = "#+RESPONSE\n" .. res.body .. "\n#+END" + local buf_content = "#+RESPONSE\n" + if utils.is_binary_content_type(content_type) then + buf_content = buf_content .. "Binary answer" + else + buf_content = buf_content .. res.body + end + buf_content = buf_content .. "\n#+END" - local lines = utils.split(res.body, "\n") + local lines = utils.split(buf_content, "\n") local line_count = vim.api.nvim_buf_line_count(res_bufnr) - 1 vim.api.nvim_buf_set_lines(res_bufnr, line_count, line_count + #lines, false, lines) @@ -174,7 +201,7 @@ local function create_callback(method, url, script_str, req_var) end vim.cmd(cmd_split .. res_bufnr) -- Set unmodifiable state - vim.api.nvim_buf_set_option(res_bufnr, "modifiable", false) + vim.api.nvim_set_option_value("modifiable", false, { buf = res_bufnr }) end -- Send cursor in response buffer to start @@ -201,32 +228,19 @@ local function create_callback(method, url, script_str, req_var) end end -local function format_curl_cmd(res) - local cmd = "curl" - - for _, value in pairs(res) do - if string.sub(value, 1, 1) == "-" then - cmd = cmd .. " " .. value - else - cmd = cmd .. " '" .. value .. "'" - end - end - - -- remote -D option - cmd = string.gsub(cmd, "-D '%S+' ", "") - return cmd -end - -- curl_cmd runs curl with the passed options, gets or creates a new buffer -- and then the results are printed to the recently obtained/created buffer -- @param opts (table) curl arguments: -- - yank_dry_run (boolean): displays the command -- - arguments are forwarded to plenary M.curl_cmd = function(opts) - if opts.dry_run then - local res = curl[opts.method](opts) - local curl_cmd = format_curl_cmd(res) + -- plenary's curl module is strange in the sense that with "dry_run" it returns the command + -- otherwise it starts the request :/ + local dry_run_opts = vim.tbl_extend("force", opts, { dry_run = true }) + local res = curl[opts.method](dry_run_opts) + local curl_cmd = format_curl_cmd(res) + if opts.dry_run then if config.get("yank_dry_run") then vim.cmd("let @+=" .. string.format("%q", curl_cmd)) end @@ -234,8 +248,9 @@ M.curl_cmd = function(opts) vim.api.nvim_echo({ { "[rest.nvim] Request preview:\n", "Comment" }, { curl_cmd } }, false, {}) return else - opts.callback = - vim.schedule_wrap(create_callback(opts.method, opts.url, opts.script_str, opts.req_var)) + opts.callback = vim.schedule_wrap( + create_callback(curl_cmd, opts.method, opts.url, opts.script_str, opts.req_var) + ) curl[opts.method](opts) end end diff --git a/lua/rest-nvim/init.lua b/lua/rest-nvim/init.lua index 2f9ab492..0ca3f8c7 100644 --- a/lua/rest-nvim/init.lua +++ b/lua/rest-nvim/init.lua @@ -1,10 +1,17 @@ -local request = require("rest-nvim.request") +local backend = require("rest-nvim.request") local config = require("rest-nvim.config") local curl = require("rest-nvim.curl") local log = require("plenary.log").new({ plugin = "rest.nvim" }) +local utils = require("rest-nvim.utils") +local path = require("plenary.path") local rest = {} local Opts = {} +local defaultRequestOpts = { + verbose = false, + highlight = false, +} + local LastOpts = {} vim.api.nvim_set_var("req_var_store", { __loaded = true }) @@ -12,12 +19,15 @@ rest.setup = function(user_configs) config.set(user_configs or {}) end + -- run will retrieve the required request information from the current buffer -- and then execute curl -- @param verbose toggles if only a dry run with preview should be executed (true = preview) rest.run = function(verbose) - local ok, result = request.get_current_request() + local ok, result = backend.get_current_request() if not ok then + log.error("Failed to run the http request:") + log.error(result) vim.api.nvim_err_writeln("[rest.nvim] Failed to get the current HTTP request: " .. result) return end @@ -30,47 +40,138 @@ end -- @param string filename to load -- @param opts table -- 1. keep_going boolean keep running even when last request failed +-- 2. verbose boolean rest.run_file = function(filename, opts) log.info("Running file :" .. filename) - local new_buf = vim.api.nvim_create_buf(false, false) + opts = vim.tbl_deep_extend( + "force", -- use value from rightmost map + defaultRequestOpts, + opts or {} + ) + + -- 0 on error or buffer handle + local new_buf = vim.api.nvim_create_buf(true, false) vim.api.nvim_win_set_buf(0, new_buf) vim.cmd.edit(filename) - local last_line = vim.fn.line("$") - - -- reset cursor position - vim.fn.cursor(1, 1) - local curpos = vim.fn.getcurpos() - while curpos[2] <= last_line do - local ok, req = request.buf_get_request(new_buf, curpos) - if ok then - -- request.print_request(req) - curpos[2] = req.end_line + 1 - rest.run_request(req, opts) + + local requests = backend.buf_list_requests(new_buf) + for _, req in pairs(requests) do + rest.run_request(req, opts) + end + + return true +end + +-- replace variables in header values +local function splice_headers(headers) + for name, value in pairs(headers) do + headers[name] = utils.replace_vars(value) + end + return headers +end + +-- return the spliced/resolved filename +-- @param string the filename w/o variables +local function load_external_payload(fileimport_string) + local fileimport_spliced = utils.replace_vars(fileimport_string) + if path:new(fileimport_spliced):is_absolute() then + return fileimport_spliced + else + local file_dirname = vim.fn.expand("%:p:h") + local file_name = path:new(path:new(file_dirname), fileimport_spliced) + return file_name:absolute() + end +end + + +-- @param headers table HTTP headers +-- @param payload table of the form { external = bool, filename_tpl= path, body_tpl = string } +-- with body_tpl an array of lines +local function splice_body(headers, payload) + local external_payload = payload.external + local lines -- array of strings + if external_payload then + local importfile = load_external_payload(payload.filename_tpl) + if not utils.file_exists(importfile) then + error("import file " .. importfile .. " not found") + end + -- TODO we dont necessarily want to load the file, it can be slow + -- https://github.com/rest-nvim/rest.nvim/issues/203 + lines = utils.read_file(importfile) + else + lines = payload.body_tpl + end + local content_type = "" + for key, val in pairs(headers) do + if string.lower(key) == "content-type" then + content_type = val + break + end + end + local has_json = content_type:find("application/[^ ]*json") + + local body = "" + local vars = utils.read_variables() + -- nvim_buf_get_lines is zero based and end-exclusive + -- but start_line and stop_line are one-based and inclusive + -- magically, this fits :-) start_line is the CRLF between header and body + -- which should not be included in the body, stop_line is the last line of the body + for _, line in ipairs(lines) do + body = body .. utils.replace_vars(line, vars) + end + + local is_json, json_body = pcall(vim.json.decode, body) + + if is_json and json_body then + if has_json then + -- convert entire json body to string. + return vim.fn.json_encode(json_body) else - return false, req + -- convert nested tables to string. + for key, val in pairs(json_body) do + if type(val) == "table" then + json_body[key] = vim.fn.json_encode(val) + end + end + return vim.fn.json_encode(json_body) end end - return true end +-- run will retrieve the required request information from the current buffer +-- and then execute curl +-- @param req table see validate_request to check the expected format +-- @param opts table +-- 1. keep_going boolean keep running even when last request failed rest.run_request = function(req, opts) + -- TODO rename result to request local result = req + local curl_raw_args = config.get("skip_ssl_verification") and vim.list_extend(result.raw, { "-k" }) + or result.raw opts = vim.tbl_deep_extend( "force", -- use value from rightmost map - { verbose = false }, -- defaults + defaultRequestOpts, opts or {} ) + -- if we want to pass as a file, we pass nothing to plenary + local spliced_body = nil + if not req.body.inline and req.body.filename_tpl then + curl_raw_args = vim.tbl_extend("force", curl_raw_args, { + '--data-binary', '@'..load_external_payload(req.body.filename_tpl)}) + else + spliced_body = splice_body(result.headers, result.body) + end + Opts = { method = result.method:lower(), url = result.url, -- plenary.curl can't set http protocol version -- http_version = result.http_version, - headers = result.headers, - raw = config.get("skip_ssl_verification") and vim.list_extend(result.raw, { "-k" }) - or result.raw, - body = result.body, + headers = splice_headers(result.headers), + raw = curl_raw_args, + body = spliced_body, dry_run = opts.verbose, bufnr = result.bufnr, start_line = result.start_line, @@ -83,11 +184,27 @@ rest.run_request = function(req, opts) LastOpts = Opts end - if config.get("highlight").enabled then - request.highlight(result.bufnr, result.start_line, result.end_line) + if opts.highlight then + backend.highlight(result.bufnr, result.start_line, result.end_line) end + local request_id = vim.loop.now() + local data = { + requestId = request_id, + request = req, + } + + vim.api.nvim_exec_autocmds("User", { + pattern = "RestStartRequest", + modeline = false, + data = data, + }) local success_req, req_err = pcall(curl.curl_cmd, Opts) + vim.api.nvim_exec_autocmds("User", { + pattern = "RestStopRequest", + modeline = false, + data = vim.tbl_extend("keep", { status = success_req, message = req_err }, data), + }) if not success_req then vim.api.nvim_err_writeln( @@ -106,7 +223,7 @@ rest.last = function() end if config.get("highlight").enabled then - request.highlight(LastOpts.bufnr, LastOpts.start_line, LastOpts.end_line) + backend.highlight(LastOpts.bufnr, LastOpts.start_line, LastOpts.end_line) end local success_req, req_err = pcall(curl.curl_cmd, LastOpts) @@ -119,12 +236,12 @@ rest.last = function() end end -rest.request = request +rest.request = backend -rest.select_env = function(path) +rest.select_env = function(env_file) if path ~= nil then - vim.validate({ path = { path, "string" } }) - config.set({ env_file = path }) + vim.validate({ env_file = { env_file, "string" } }) + config.set({ env_file = env_file }) else print("No path given") end diff --git a/lua/rest-nvim/request/init.lua b/lua/rest-nvim/request/init.lua index b958fa97..7854c928 100644 --- a/lua/rest-nvim/request/init.lua +++ b/lua/rest-nvim/request/init.lua @@ -1,11 +1,11 @@ local utils = require("rest-nvim.utils") -local path = require("plenary.path") local log = require("plenary.log").new({ plugin = "rest.nvim" }) local config = require("rest-nvim.config") -- get_importfile returns in case of an imported file the absolute filename -- @param bufnr Buffer number, a.k.a id -- @param stop_line Line to stop searching +-- @return tuple filename and whether we should inline it when invoking curl local function get_importfile_name(bufnr, start_line, stop_line) -- store old cursor position local oldpos = vim.fn.getcurpos() @@ -18,18 +18,13 @@ local function get_importfile_name(bufnr, start_line, stop_line) if import_line > 0 then local fileimport_string local fileimport_line - local fileimport_spliced + local fileimport_inlined fileimport_line = vim.api.nvim_buf_get_lines(bufnr, import_line - 1, import_line, false) + -- check second char against '@' (meaning "dont inline") + fileimport_inlined = string.sub(fileimport_line[1], 2, 2) ~= "@" fileimport_string = - string.gsub(fileimport_line[1], "<", "", 1):gsub("^%s+", ""):gsub("%s+$", "") - fileimport_spliced = utils.replace_vars(fileimport_string) - if path:new(fileimport_spliced):is_absolute() then - return fileimport_spliced - else - local file_dirname = vim.fn.expand("%:p:h") - local file_name = path:new(path:new(file_dirname), fileimport_spliced) - return file_name:absolute() - end + string.gsub(fileimport_line[1], "<@?", "", 1):gsub("^%s+", ""):gsub("%s+$", "") + return fileimport_inlined, fileimport_string end return nil end @@ -41,26 +36,22 @@ end -- @param bufnr Buffer number, a.k.a id -- @param start_line Line where body starts -- @param stop_line Line where body stops --- @param has_json True if content-type is set to json -local function get_body(bufnr, start_line, stop_line, has_json) +-- @return table { external = bool; filename_tpl or body_tpl; } +local function get_body(bufnr, start_line, stop_line) -- first check if the body should be imported from an external file - local importfile = get_importfile_name(bufnr, start_line, stop_line) - local lines + local inline, importfile = get_importfile_name(bufnr, start_line, stop_line) + local lines -- an array of strings if importfile ~= nil then - if not utils.file_exists(importfile) then - error("import file " .. importfile .. " not found") - end - lines = utils.read_file(importfile) + return { external = true, inline = inline, filename_tpl = importfile } else - lines = vim.api.nvim_buf_get_lines(bufnr, start_line - 1, stop_line, false) + lines = vim.api.nvim_buf_get_lines(bufnr, start_line, stop_line, false) end - local body = "" - local vars = utils.read_variables() -- nvim_buf_get_lines is zero based and end-exclusive -- but start_line and stop_line are one-based and inclusive -- magically, this fits :-) start_line is the CRLF between header and body -- which should not be included in the body, stop_line is the last line of the body + local lines2 = {} for _, line in ipairs(lines) do -- stop if a script opening tag is found if line:find("{%%") then @@ -68,28 +59,11 @@ local function get_body(bufnr, start_line, stop_line, has_json) end -- Ignore commented lines with and without indent if not utils.contains_comments(line) then - body = body .. utils.replace_vars(line, vars) - end - end - - local is_json, json_body = pcall(vim.json.decode, body) - - if is_json then - if has_json then - -- convert entire json body to string. - return vim.fn.json_encode(json_body) - else - -- convert nested tables to string. - for key, val in pairs(json_body) do - if type(val) == "table" then - json_body[key] = vim.fn.json_encode(val) - end - end - return vim.fn.json_encode(json_body) + lines2[#lines2 + 1] = line end end - return body + return { external = false, inline = false, body_tpl = lines2 } end local function get_response_script(bufnr, start_line, stop_line) @@ -161,7 +135,7 @@ local function get_headers(bufnr, start_line, end_line) local header_name, header_value = line_content:match("^(.-): ?(.*)$") if not utils.contains_comments(header_name) then - headers[header_name] = utils.replace_vars(header_value) + headers[header_name] = header_value end ::continue:: end @@ -177,6 +151,7 @@ local function get_curl_args(bufnr, headers_end, end_line) local curl_args = {} local body_start = end_line + log.debug("Getting curl args between lines", headers_end, " and ", end_line) for line_number = headers_end, end_line do local line_content = vim.fn.getbufline(bufnr, line_number)[1] @@ -345,49 +320,93 @@ M.buf_get_request = function(bufnr, curpos) headers["host"] = nil end - local content_type = "" - - for key, val in pairs(headers) do - if string.lower(key) == "content-type" then - content_type = val - break - end - end - - local body = get_body(bufnr, body_start, end_line, content_type:find("application/[^ ]*json")) + local body = get_body(bufnr, body_start, end_line) local script_str = get_response_script(bufnr, headers_end, end_line) + -- TODO this should just parse the request without modifying external state + -- eg move to run_request if config.get("jump_to_request") then utils.move_cursor(bufnr, start_line) else utils.move_cursor(bufnr, curpos[2], curpos[3]) end - return true, - { - method = parsed_url.method, - url = parsed_url.url, - http_version = parsed_url.http_version, - headers = headers, - raw = curl_args, - body = body, - bufnr = bufnr, - start_line = start_line, - end_line = end_line, - script_str = script_str, - req_var = parsed_req_var_str, - } + local req = { + method = parsed_url.method, + url = parsed_url.url, + http_version = parsed_url.http_version, + headers = headers, + raw = curl_args, + body = body, + bufnr = bufnr, + start_line = start_line, + end_line = end_line, + script_str = script_str, + req_var = parsed_req_var_str, + } + + return true, req end M.print_request = function(req) + print(M.stringify_request(req)) +end + +-- converts request into string, helpful for debug +-- full_body boolean +M.stringify_request = function(req, opts) + opts = vim.tbl_deep_extend( + "force", -- use value from rightmost map + { full_body = false, headers = true }, -- defaults + opts or {} + ) local str = [[ - version: ]] .. req.url .. [[\n + url : ]] .. req.url .. [[\n method: ]] .. req.method .. [[\n - start_line: ]] .. tostring(req.start_line) .. [[\n - end_line: ]] .. tostring(req.end_line) .. [[\n - ]] - print(str) + range : ]] .. tostring(req.start_line) .. [[ -> ]] .. tostring(req.end_line) .. [[\n + ]] + + if req.http_version then + str = str .. "\nhttp_version: " .. req.http_version .. "\n" + end + + if opts.headers then + for name, value in pairs(req.headers) do + str = str .. "header '" .. name .. "'=" .. value .. "\n" + end + end + + if opts.full_body then + if req.body then + local res = req.body + str = str .. "body: " .. res .. "\n" + end + end + + -- here we should just display the beginning of the request + return str +end + +M.buf_list_requests = function(buf, _opts) + local last_line = vim.fn.line("$") + local requests = {} + + -- reset cursor position + vim.fn.cursor({ 1, 1 }) + local curpos = vim.fn.getcurpos() + log.debug("Listing requests for buf ", buf) + while curpos[2] <= last_line do + local ok, req = M.buf_get_request(buf, curpos) + if ok then + curpos[2] = req.end_line + 1 + requests[#requests + 1] = req + else + break + end + end + -- log.debug("found " , #requests , "requests") + return requests end local select_ns = vim.api.nvim_create_namespace("rest-nvim") @@ -406,8 +425,7 @@ M.highlight = function(bufnr, start_line, end_line) higroup, { start_line - 1, 0 }, { end_line - 1, end_column }, - "c", - false + { regtype = "c", inclusive = false } ) vim.defer_fn(function() diff --git a/lua/rest-nvim/utils/init.lua b/lua/rest-nvim/utils/init.lua index e8e0d8d5..e11014bb 100644 --- a/lua/rest-nvim/utils/init.lua +++ b/lua/rest-nvim/utils/init.lua @@ -5,6 +5,14 @@ math.randomseed(os.time()) local M = {} +M.binary_content_types = { + "octet-stream", +} + +M.is_binary_content_type = function(content_type) + return vim.tbl_contains(M.binary_content_types, content_type) +end + -- move_cursor moves the cursor to the desired position in the provided buffer -- @param bufnr Buffer number, a.k.a id -- @param line the desired line diff --git a/plugin/rest-nvim.vim b/plugin/rest-nvim.vim index 110b2d1f..21a2c32c 100644 --- a/plugin/rest-nvim.vim +++ b/plugin/rest-nvim.vim @@ -12,6 +12,12 @@ nnoremap RestNvimLast :lua require('rest-nvim').last() command! -nargs=? -complete=file RestSelectEnv :lua require('rest-nvim').select_env() +lua << EOF + vim.api.nvim_create_user_command('RestLog', function() + vim.cmd(string.format('tabnew %s', vim.fn.stdpath('cache')..'/rest.nvim.log')) +end, { desc = 'Opens the rest.nvim log.', }) +EOF + let s:save_cpo = &cpo set cpo&vim diff --git a/rest.nvim-scm-1.rockspec b/rest.nvim-scm-3.rockspec similarity index 94% rename from rest.nvim-scm-1.rockspec rename to rest.nvim-scm-3.rockspec index dffbccff..9f432d00 100644 --- a/rest.nvim-scm-1.rockspec +++ b/rest.nvim-scm-3.rockspec @@ -1,4 +1,4 @@ -local MAJOR, REV = "0.1", "-2" +local MAJOR, REV = "scm", "-3" rockspec_format = "3.0" package = "rest.nvim" version = MAJOR .. REV @@ -32,6 +32,7 @@ end build = { type = "builtin", copy_directories = { + 'doc', 'plugin' } }