Skip to content

Commit e326b56

Browse files
feat: refactor writing to buffer
1 parent c186d3e commit e326b56

File tree

4 files changed

+167
-63
lines changed

4 files changed

+167
-63
lines changed

lua/rest-nvim/curl/init.lua

+39-38
Original file line numberDiff line numberDiff line change
@@ -76,20 +76,14 @@ M.get_or_create_buf = function()
7676
local existing_bufnr = vim.fn.bufnr(tmp_name)
7777
if existing_bufnr ~= -1 then
7878
-- Set modifiable
79-
vim.api.nvim_set_option_value("modifiable", true, { buf = existing_bufnr})
79+
vim.api.nvim_set_option_value("modifiable", true, { buf = existing_bufnr })
8080
-- Prevent modified flag
81-
vim.api.nvim_set_option_value("buftype", "nofile", { buf = existing_bufnr})
81+
vim.api.nvim_set_option_value("buftype", "nofile", { buf = existing_bufnr })
8282
-- Delete buffer content
83-
vim.api.nvim_buf_set_lines(
84-
existing_bufnr,
85-
0,
86-
vim.api.nvim_buf_line_count(existing_bufnr) - 1,
87-
false,
88-
{}
89-
)
83+
vim.api.nvim_buf_set_lines(existing_bufnr, 0, -1, false, {})
9084

9185
-- Make sure the filetype of the buffer is httpResult so it will be highlighted
92-
vim.api.nvim_set_option_value("ft", "httpResult", { buf = existing_bufnr } )
86+
vim.api.nvim_set_option_value("ft", "httpResult", { buf = existing_bufnr })
9387

9488
return existing_bufnr
9589
end
@@ -116,9 +110,29 @@ local function create_callback(curl_cmd, opts)
116110
return
117111
end
118112
local res_bufnr = M.get_or_create_buf()
119-
local header_lines = res.headers
113+
114+
local headers = utils.filter(res.headers, function(value)
115+
return value ~= ""
116+
end, false)
117+
118+
headers = utils.map(headers, function(value)
119+
local _, _, http, status = string.find(value, "^(HTTP.*)%s+(%d+)%s*$")
120+
vim.print(value, http, status)
121+
122+
if http and status then
123+
return http .. " " .. utils.http_status(tonumber(status))
124+
end
125+
126+
return value
127+
end)
128+
129+
headers = utils.split_list(headers, function(value)
130+
return string.find(value, "^HTTP.*$")
131+
end)
132+
120133
res.headers = parse_headers(res.headers)
121-
local content_type = res.headers[utils.key(res.headers,'content-type')]
134+
135+
local content_type = utils.get_value(res.headers, "content-type")
122136
if content_type then
123137
content_type = content_type:match("application/([-a-z]+)") or content_type:match("text/(%l+)")
124138
end
@@ -139,45 +153,32 @@ local function create_callback(curl_cmd, opts)
139153
end
140154
end
141155

142-
-- This can be quite verbose so let user control it
143-
if config.get("result").show_curl_command then
144-
vim.api.nvim_buf_set_lines(res_bufnr, 0, 0, false, { "Command: " .. curl_cmd })
145-
end
146-
147156
if config.get("result").show_url then
148157
--- Add metadata into the created buffer (status code, date, etc)
149158
-- Request statement (METHOD URL)
150-
vim.api.nvim_buf_set_lines(res_bufnr, 0, 0, false, { method:upper() .. " " .. url })
159+
utils.write_block(res_bufnr, { method:upper() .. " " .. url }, false)
160+
end
161+
162+
-- This can be quite verbose so let user control it
163+
if config.get("result").show_curl_command then
164+
utils.write_block(res_bufnr, { "Command: " .. curl_cmd }, true)
151165
end
152166

153167
if config.get("result").show_http_info then
154-
local line_count = vim.api.nvim_buf_line_count(res_bufnr)
155-
local separator = config.get("result").show_url and 0 or 1
156168
-- HTTP version, status code and its meaning, e.g. HTTP/1.1 200 OK
157-
vim.api.nvim_buf_set_lines(
158-
res_bufnr,
159-
line_count - separator,
160-
line_count - separator,
161-
false,
162-
{ "HTTP/1.1 " .. utils.http_status(res.status) }
163-
)
169+
utils.write_block(res_bufnr, { "HTTP/1.1 " .. utils.http_status(res.status) }, false)
164170
end
165171

166172
if config.get("result").show_headers then
167-
local line_count = vim.api.nvim_buf_line_count(res_bufnr)
168173
-- Headers, e.g. Content-Type: application/json
169-
vim.api.nvim_buf_set_lines(
170-
res_bufnr,
171-
line_count + 1,
172-
line_count + 1 + #header_lines,
173-
false,
174-
header_lines
175-
)
174+
for _, header_block in ipairs(headers) do
175+
utils.write_block(res_bufnr, header_block, true)
176+
end
176177
end
177178

178179
--- Add the curl command results into the created buffer
179180
local formatter = config.get("result").formatters[content_type]
180-
-- formate response body
181+
-- format response body
181182
if type(formatter) == "function" then
182183
local ok, out = pcall(formatter, res.body)
183184
-- check if formatter ran successfully
@@ -220,8 +221,8 @@ local function create_callback(curl_cmd, opts)
220221
buf_content = buf_content .. "\n#+END"
221222

222223
local lines = utils.split(buf_content, "\n")
223-
local line_count = vim.api.nvim_buf_line_count(res_bufnr) - 1
224-
vim.api.nvim_buf_set_lines(res_bufnr, line_count, line_count + #lines, false, lines)
224+
225+
utils.write_block(res_bufnr, lines)
225226

226227
-- Only open a new split if the buffer is not loaded into the current window
227228
if vim.fn.bufwinnr(res_bufnr) == -1 then

lua/rest-nvim/init.lua

+7-5
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ local function load_external_payload(fileimport_string)
8383
end
8484
end
8585

86-
8786
-- @param headers table HTTP headers
8887
-- @param payload table of the form { external = bool, filename_tpl= path, body_tpl = string }
8988
-- with body_tpl an array of lines
@@ -101,7 +100,7 @@ local function splice_body(headers, payload)
101100
else
102101
lines = payload.body_tpl
103102
end
104-
local content_type = headers[utils.key(headers,"content-type")] or ""
103+
local content_type = utils.get_value(headers, "content-type") or ""
105104
local has_json = content_type:find("application/[^ ]*json")
106105

107106
local body = ""
@@ -140,8 +139,9 @@ end
140139
rest.run_request = function(req, opts)
141140
-- TODO rename result to request
142141
local result = req
143-
local curl_raw_args = config.get("skip_ssl_verification") and vim.list_extend(result.raw, { "-k" })
144-
or result.raw
142+
local curl_raw_args = config.get("skip_ssl_verification")
143+
and vim.list_extend(result.raw, { "-k" })
144+
or result.raw
145145
opts = vim.tbl_deep_extend(
146146
"force", -- use value from rightmost map
147147
defaultRequestOpts,
@@ -153,7 +153,9 @@ rest.run_request = function(req, opts)
153153
local spliced_body = nil
154154
if not req.body.inline and req.body.filename_tpl then
155155
curl_raw_args = vim.tbl_extend("force", curl_raw_args, {
156-
'--data-binary', '@'..load_external_payload(req.body.filename_tpl)})
156+
"--data-binary",
157+
"@" .. load_external_payload(req.body.filename_tpl),
158+
})
157159
else
158160
spliced_body = splice_body(result.headers, result.body)
159161
end

lua/rest-nvim/request/init.lua

+19-19
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ local function get_importfile_name(bufnr, start_line, stop_line)
2121
local fileimport_inlined
2222
fileimport_line = vim.api.nvim_buf_get_lines(bufnr, import_line - 1, import_line, false)
2323
-- check second char against '@' (meaning "dont inline")
24-
fileimport_inlined = string.sub(fileimport_line[1], 2, 2) ~= '@'
25-
fileimport_string = string.gsub(fileimport_line[1], "<@?", "", 1):gsub("^%s+", ""):gsub("%s+$", "")
24+
fileimport_inlined = string.sub(fileimport_line[1], 2, 2) ~= "@"
25+
fileimport_string =
26+
string.gsub(fileimport_line[1], "<@?", "", 1):gsub("^%s+", ""):gsub("%s+$", "")
2627
return fileimport_inlined, fileimport_string
27-
2828
end
2929
return nil
3030
end
@@ -42,7 +42,7 @@ local function get_body(bufnr, start_line, stop_line)
4242
local inline, importfile = get_importfile_name(bufnr, start_line, stop_line)
4343
local lines -- an array of strings
4444
if importfile ~= nil then
45-
return { external = true; inline = inline; filename_tpl = importfile }
45+
return { external = true, inline = inline, filename_tpl = importfile }
4646
else
4747
lines = vim.api.nvim_buf_get_lines(bufnr, start_line, stop_line, false)
4848
end
@@ -63,7 +63,7 @@ local function get_body(bufnr, start_line, stop_line)
6363
end
6464
end
6565

66-
return { external = false; inline = false; body_tpl = lines2 }
66+
return { external = false, inline = false, body_tpl = lines2 }
6767
end
6868

6969
local function get_response_script(bufnr, start_line, stop_line)
@@ -285,9 +285,9 @@ M.buf_get_request = function(bufnr, curpos)
285285

286286
local curl_args, body_start = get_curl_args(bufnr, headers_end, end_line)
287287

288-
local host = headers[utils.key(headers,"host")] or ""
288+
local host = utils.get_value(headers, "host") or ""
289289
parsed_url.url = host:gsub("%s+", "") .. parsed_url.url
290-
headers[utils.key(headers,"host")] = nil
290+
headers[utils.key(headers, "host")] = nil
291291

292292
local body = get_body(bufnr, body_start, end_line)
293293

@@ -302,17 +302,17 @@ M.buf_get_request = function(bufnr, curpos)
302302
end
303303

304304
local req = {
305-
method = parsed_url.method,
306-
url = parsed_url.url,
307-
http_version = parsed_url.http_version,
308-
headers = headers,
309-
raw = curl_args,
310-
body = body,
311-
bufnr = bufnr,
312-
start_line = start_line,
313-
end_line = end_line,
314-
script_str = script_str,
315-
}
305+
method = parsed_url.method,
306+
url = parsed_url.url,
307+
http_version = parsed_url.http_version,
308+
headers = headers,
309+
raw = curl_args,
310+
body = body,
311+
bufnr = bufnr,
312+
start_line = start_line,
313+
end_line = end_line,
314+
script_str = script_str,
315+
}
316316

317317
return true, req
318318
end
@@ -393,7 +393,7 @@ M.highlight = function(bufnr, start_line, end_line)
393393
higroup,
394394
{ start_line - 1, 0 },
395395
{ end_line - 1, end_column },
396-
{ regtype = "c"; inclusive = false }
396+
{ regtype = "c", inclusive = false }
397397
)
398398

399399
vim.defer_fn(function()

lua/rest-nvim/utils/init.lua

+102-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ M.get_variables = function()
182182
if variables[name]:match(oname) then
183183
-- Add that into the variable
184184
-- I.E if @url={{path}}:{{port}}/{{source}}
185-
-- Substitue in path, port and source
185+
-- Substitute in path, port and source
186186
variables[name] = variables[name]:gsub("{{" .. oname .. "}}", ovalue)
187187
end
188188
end
@@ -317,6 +317,16 @@ M.key = function(tbl, key)
317317
return key
318318
end
319319

320+
--- Get the table value or nil if not found
321+
---
322+
--- @param tbl (table) Table to iterate over
323+
--- @param key (string) The key to the value case insensitive
324+
---
325+
--- @return any
326+
M.get_value = function(tbl, key)
327+
return tbl[M.key(tbl, key)]
328+
end
329+
320330
-- tbl_to_str recursively converts the provided table into a json string
321331
-- @param tbl Table to convert into a String
322332
-- @param json If the string should use a key:value syntax
@@ -417,6 +427,97 @@ M.contains_comments = function(str)
417427
return str:find("^#") or str:find("^%s+#")
418428
end
419429

430+
--- Filter a table and return filtered copy
431+
---
432+
--- @param tbl table The table to filter
433+
--- @param filter function The filtering function, parameters are value, key and table
434+
--- @param preserve_keys boolean? Should the copied table preserve keys or not, default true
435+
---
436+
--- @return List|table
437+
M.filter = function(tbl, filter, preserve_keys)
438+
local out = {}
439+
440+
preserve_keys = preserve_keys and true
441+
442+
for key, val in ipairs(tbl) do
443+
if filter(val, key, tbl) then
444+
if preserve_keys then
445+
out[key] = val
446+
else
447+
table.insert(out, val)
448+
end
449+
end
450+
end
451+
452+
return out
453+
end
454+
455+
--- Make a copy of the table applying the transformation function to each element.
456+
--- Does not preserve the keys of the original table.
457+
---
458+
--- @param tbl table The table to filter
459+
--- @param transform function The transformation function, parameters are value, key and table
460+
---
461+
--- @return List
462+
M.map = function(tbl, transform)
463+
local out = {}
464+
465+
for key, val in ipairs(tbl) do
466+
table.insert(out, transform(val, key, tbl))
467+
end
468+
469+
return out
470+
end
471+
472+
--- Wrapper around nvim_buf_set_lines
473+
---
474+
--- @param buffer integer The target buffer
475+
--- @param block List The list of lines to write
476+
--- @param newline boolean? Add a newline to the end, default false
477+
---
478+
--- @return nil
479+
M.write_block = function(buffer, block, newline)
480+
local content = vim.api.nvim_buf_get_lines(buffer, 0, -1, false)
481+
local first_line = false
482+
483+
if #content == 1 and content[1] == "" then
484+
first_line = true
485+
end
486+
487+
vim.api.nvim_buf_set_lines(buffer, first_line and 0 or -1, -1, false, block)
488+
489+
if newline then
490+
vim.api.nvim_buf_set_lines(buffer, -1, -1, false, { "" })
491+
end
492+
end
493+
494+
--- Split table on the elements where the function returns true
495+
---
496+
--- @param tbl List
497+
--- @param index function
498+
--- @param inclusive boolean? If true the split value is in the first table, default false
499+
---
500+
--- @return List[]
501+
M.split_list = function(tbl, index, inclusive)
502+
local out = { {} }
503+
504+
for key, val in ipairs(tbl) do
505+
if index(val, key, tbl) then
506+
table.insert(out, {})
507+
508+
if inclusive then
509+
table.insert(out[#out - 1], val)
510+
else
511+
table.insert(out[#out], val)
512+
end
513+
else
514+
table.insert(out[#out], val)
515+
end
516+
end
517+
518+
return out
519+
end
520+
420521
-- http_status returns the status code and the meaning, e.g. 200 OK
421522
-- see https://httpstatuses.com/ for reference
422523
-- @param code The request status code

0 commit comments

Comments
 (0)