1- --- Symbol picker: pick an HTTP request from the current file.
2- --- Uses Snacks.picker when available.
3-
41local 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"
137local 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
2722end
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+
3030local 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 ) .. " …"
3434end
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+
4058local 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
88118-- Snacks picker
89119---- -----------------------------------------------------------------------
90120
91- --- Show requests using Snacks.picker.select.
92121local 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 )
125184-- Public API
126185---- -----------------------------------------------------------------------
127186
128- --- Show symbol picker for the current buffer.
129187function M .show_symbols ()
130188 local bufnr = vim .api .nvim_get_current_buf ()
131189 local requests = collect_requests (bufnr )
0 commit comments