Skip to content

Commit 11d49b4

Browse files
author
lex
committed
feat(http): rich symbol picker with run detection, URL stripping, highlights
- Strip query params from URL display - Detect run requests, show "run" method + #target - Align method column with fixed width - Rich highlights via snacks chunks (method/url/name) - Middle ellipsis for long URLs
1 parent c34a894 commit 11d49b4

1 file changed

Lines changed: 85 additions & 27 deletions

File tree

lua/poste/http/symbols.lua

Lines changed: 85 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,60 @@
1-
--- Symbol picker: pick an HTTP request from the current file.
2-
--- Uses Snacks.picker when available.
3-
41
local M = {}
52

63
---------------------------------------------------------------------------
7-
-- Parse requests from buffer
4+
-- Helpers
85
---------------------------------------------------------------------------
96

10-
--- Extract URL path from a request line.
11-
--- e.g., "GET https://api.example.com/users" → "/users"
12-
--- e.g., "GET {{host}}/api/v1/items" → "/api/v1/items"
137
local function extract_url_path(line)
148
if not line then return nil end
15-
-- Match: METHOD <url>
169
local url = line:match("^%s*%u+%s+(.+)")
1710
if not url then return nil end
18-
-- Extract path after host: skip protocol://host or {{var}}/host portion
19-
local path = url:match("://[^/]*(.*)") -- after ://host
11+
local path = url:match("://[^/]*(.*)")
2012
if not path then
21-
path = url:match("}}(.*)") -- after {{var}}
13+
path = url:match("}}(.*)")
2214
end
2315
if not path then
24-
path = url:match("^(/.*)") -- already a path
16+
path = url:match("^(/.*)")
17+
end
18+
if path and path ~= "" then
19+
path = path:gsub("%?.*", "")
2520
end
2621
return path and path ~= "" and path or nil
2722
end
2823

29-
--- Truncate a string with ellipsis if it exceeds max length.
24+
local function truncate_middle(s, max)
25+
if not s or #s <= max then return s or "" end
26+
local half = math.floor((max - 1) / 2)
27+
return s:sub(1, half) .. "" .. s:sub(#s - half + 1)
28+
end
29+
3030
local function truncate(s, max)
3131
if not s then return "" end
3232
if #s <= max then return s end
3333
return s:sub(1, max - 1) .. ""
3434
end
3535

36-
--- Scan buffer and collect all ### request blocks.
37-
--- Delegates outer ### detection to cache.lua block index.
38-
--- @param bufnr number Buffer handle
39-
--- @return table[] List of { name, method, url_path, line }
36+
local function short_name(name)
37+
if not name then return "" end
38+
return name:match("([^%.]+)$") or name
39+
end
40+
41+
local function method_hl(method)
42+
if not method or method == "--" then return "PosteMethodOther" end
43+
if method == "run" then return "PosteRun" end
44+
local m = method:upper()
45+
if m == "GET" then return "PosteMethodGET"
46+
elseif m == "POST" then return "PosteMethodPOST"
47+
elseif m == "PUT" then return "PosteMethodPUT"
48+
elseif m == "DELETE" then return "PosteMethodDELETE"
49+
elseif m == "PATCH" then return "PosteMethodPATCH"
50+
elseif m == "HEAD" then return "PosteMethodHEAD"
51+
else return "PosteMethodOther" end
52+
end
53+
54+
---------------------------------------------------------------------------
55+
-- Parse requests from buffer
56+
---------------------------------------------------------------------------
57+
4058
local function collect_requests(bufnr)
4159
local cache = require("poste.http.cache")
4260
local bc = cache.get_buffer_cache(bufnr)
@@ -70,14 +88,26 @@ local function collect_requests(bufnr)
7088

7189
if not skip then
7290
method = next_line:match("^%s*(%u+)%s")
73-
if method then
91+
if not method then
92+
local run_target = next_line:match("^%s*run%s+(%S+)")
93+
if run_target then
94+
method = "run"
95+
url_path = run_target
96+
end
97+
end
98+
if method and method ~= "run" then
7499
url_path = extract_url_path(next_line)
75100
end
76101
break
77102
end
78103
end
79104

80-
table.insert(requests, { name = name, method = method, url_path = url_path, line = block.start_line })
105+
table.insert(requests, {
106+
name = name,
107+
method = method or "--",
108+
url_path = url_path,
109+
line = block.start_line,
110+
})
81111
end
82112
end
83113

@@ -88,17 +118,37 @@ end
88118
-- Snacks picker
89119
---------------------------------------------------------------------------
90120

91-
--- Show requests using Snacks.picker.select.
92121
local function show_snacks_picker(requests)
122+
local max_method_width = 4
123+
for _, req in ipairs(requests) do
124+
local m = (req.method or "--"):len()
125+
if m > max_method_width then max_method_width = m end
126+
end
127+
93128
local items = {}
94129
for _, req in ipairs(requests) do
95130
local method = req.method or "--"
96-
local text = method .. " " .. truncate(req.name, 40)
97-
local desc = req.url_path and truncate(req.url_path, 45) or ""
131+
local url, short
132+
133+
if method == "run" then
134+
url = "#" .. req.name
135+
short = short_name(req.name)
136+
else
137+
url = req.url_path or ""
138+
short = req.name or ""
139+
end
140+
141+
url = truncate_middle(url, 55)
142+
short = truncate(short, 30)
143+
local pad = string.rep(" ", max_method_width - method:len())
144+
98145
items[#items + 1] = {
99-
text = text,
100-
description = desc,
146+
text = method .. pad .. " " .. url .. " " .. short,
101147
key = req,
148+
_method = method,
149+
_pad = pad,
150+
_url = url,
151+
_short = short,
102152
}
103153
end
104154

@@ -107,8 +157,17 @@ local function show_snacks_picker(requests)
107157
{
108158
prompt = "Requests",
109159
layout = "select",
110-
format_item = function(item)
111-
return item.text .. (item.description ~= "" and " " .. item.description or "")
160+
format_item = function(item, supports_chunks)
161+
if supports_chunks then
162+
return {
163+
{ item._method .. item._pad, method_hl(item._method) },
164+
{ " ", "" },
165+
{ item._url, "String" },
166+
{ " ", "" },
167+
{ item._short, "Comment" },
168+
}
169+
end
170+
return item.text
112171
end,
113172
},
114173
function(item)
@@ -125,7 +184,6 @@ end
125184
-- Public API
126185
---------------------------------------------------------------------------
127186

128-
--- Show symbol picker for the current buffer.
129187
function M.show_symbols()
130188
local bufnr = vim.api.nvim_get_current_buf()
131189
local requests = collect_requests(bufnr)

0 commit comments

Comments
 (0)