Skip to content

Commit 091d160

Browse files
feat: initial statistics implementation
1 parent 0d22f4a commit 091d160

File tree

5 files changed

+141
-1
lines changed

5 files changed

+141
-1
lines changed

README.md

+14-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ have to leave Neovim!
4848

4949
- System-wide
5050
- curl
51-
- Optional [can be changed, see config bellow]
51+
- Optional [can be changed, see config below]
5252
- jq (to format JSON output)
5353
- tidy (to format HTML output)
5454
- Other plugins
@@ -83,6 +83,9 @@ use {
8383
show_curl_command = false,
8484
show_http_info = true,
8585
show_headers = true,
86+
-- table of curl `--write-out` variables or false if disabled
87+
-- for more granular control see Statistics Spec
88+
show_statistics = false,
8689
-- executables or functions for formatting response body [optional]
8790
-- set them to false if you want to disable them
8891
formatters = {
@@ -154,6 +157,16 @@ To run `rest.nvim` you should map the following commands:
154157
- `custom_dynamic_variables` allows to extend or overwrite built-in dynamic variable functions
155158
(default: {})
156159

160+
### Statistics Spec
161+
162+
| Property | Type | Description |
163+
| :------- | :-------------- | :----------------------------------------------------- |
164+
| [1] | string | `--write-out` variable name, see `man curl`. Required. |
165+
| title | string | Replaces the variable name in the output if defined. |
166+
| type | string|function | Specifies type transformation for the output value.
167+
Default transformers are `time` and `byte`. Can also be a function which takes the
168+
value as a parameter and returns a string. |
169+
157170
## Usage
158171

159172
Create a new http file or open an existing one and place the cursor over the

lua/rest-nvim/config/init.lua

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ local config = {
1414
show_url = true,
1515
show_http_info = true,
1616
show_headers = true,
17+
show_statistics = false,
1718
formatters = {
1819
json = "jq",
1920
html = function(body)

lua/rest-nvim/curl/init.lua

+9
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,15 @@ local function create_callback(curl_cmd, opts)
175175
end
176176
end
177177

178+
if config.get("result").show_statistics then
179+
-- Statistics, e.g. Total Time: 123.4 ms
180+
local statistics
181+
182+
res.body, statistics = utils.parse_statistics(res.body)
183+
184+
utils.write_block(res_bufnr, statistics, true)
185+
end
186+
178187
--- Add the curl command results into the created buffer
179188
local formatter = config.get("result").formatters[content_type]
180189
-- format response body

lua/rest-nvim/init.lua

+17
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,23 @@ rest.run_request = function(req, opts)
158158
spliced_body = splice_body(result.headers, result.body)
159159
end
160160

161+
if config.get("result").show_statistics then
162+
local statistics_line = {}
163+
164+
for _, tbl in ipairs(config.get("result").show_statistics) do
165+
if type(tbl) == "string" then
166+
tbl = { tbl }
167+
end
168+
169+
table.insert(statistics_line, tbl[1] .. "=%{" .. tbl[1] .. "}")
170+
end
171+
172+
curl_raw_args = vim.tbl_extend("force", curl_raw_args, {
173+
"--write-out",
174+
"\\n" .. table.concat(statistics_line, "&"),
175+
})
176+
end
177+
161178
Opts = {
162179
request_id = vim.loop.now(), -- request id used to correlate RestStartRequest and RestStopRequest events
163180
method = result.method:lower(),

lua/rest-nvim/utils/init.lua

+100
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,106 @@ M.split_list = function(tbl, index, inclusive)
508508
return out
509509
end
510510

511+
--- Default transformers for statistics
512+
local transform = {
513+
time = function(time)
514+
time = tonumber(time)
515+
516+
if time >= 60 then
517+
time = string.format("%.2f", time / 60)
518+
519+
return time .. " min"
520+
end
521+
522+
local units = { "s", "ms", "µs", "ns" }
523+
local unit = 1
524+
525+
while time < 1 and unit <= #units do
526+
time = time * 1000
527+
unit = unit + 1
528+
end
529+
530+
time = string.format("%.2f", time)
531+
532+
return time .. " " .. units[unit]
533+
end,
534+
535+
byte = function(bytes)
536+
bytes = tonumber(bytes)
537+
538+
local units = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB" }
539+
local unit = 1
540+
541+
while bytes >= 1024 and unit <= #units do
542+
bytes = bytes / 1024
543+
unit = unit + 1
544+
end
545+
546+
bytes = string.format("%.2f", bytes)
547+
548+
return bytes .. " " .. units[unit]
549+
end,
550+
}
551+
552+
--- Parse statistics line to a table with key, value pairs
553+
---
554+
--- @param statistics_line string The statistics line from body
555+
---
556+
--- @return string[] statistics
557+
local get_parsed_statistics = function(statistics_line)
558+
local out = {}
559+
560+
for _, statistics_pair in ipairs(M.split(statistics_line, "&")) do
561+
local value = M.split(statistics_pair, "=", 1)
562+
563+
if #value == 1 then
564+
table.insert(out, value[1])
565+
else
566+
out[value[1]] = value[2]
567+
end
568+
end
569+
570+
return out
571+
end
572+
573+
--- Parse and transform statistics line to a table of strings to be output.
574+
--- Returns the body without statistics line and a table of statistics lines.
575+
---
576+
--- @param body string Response body
577+
---
578+
--- @return string body, string[] statistics
579+
M.parse_statistics = function(body)
580+
local _, _, statistics = string.find(body, "[%c%s]+([^%c]*)$")
581+
local config_statistics = config.get("result").show_statistics
582+
583+
body = string.gsub(body, "[%c%s]+([^%c]*)$", "")
584+
local out = {}
585+
586+
statistics = get_parsed_statistics(statistics)
587+
588+
for _, tbl in ipairs(config_statistics) do
589+
if type(tbl) == "string" then
590+
tbl = { tbl }
591+
end
592+
593+
local value = statistics[tbl[1]]
594+
595+
if tbl.type then
596+
if type(tbl.type) == "string" then
597+
value = transform[tbl.type](value)
598+
end
599+
600+
if type(tbl.type) == "function" then
601+
value = tbl.type(value)
602+
end
603+
end
604+
605+
table.insert(out, (tbl.title or (tbl[1] .. " ")) .. value)
606+
end
607+
608+
return body, out
609+
end
610+
511611
-- http_status returns the status code and the meaning, e.g. 200 OK
512612
-- see https://httpstatuses.com/ for reference
513613
-- @param code The request status code

0 commit comments

Comments
 (0)