aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/net.lua
diff options
context:
space:
mode:
authorTom Ampuero <46233260+tampueroc@users.noreply.github.com>2025-07-13 21:43:11 +0100
committerGitHub <noreply@github.com>2025-07-13 13:43:11 -0700
commit7cd5356a6f89a46d83bbba9b7f6496b67f054629 (patch)
tree04ac6a86e7419297e8ff3e7eb765b4e987a91181 /runtime/lua/vim/net.lua
parent444a8b3ec6375b03f1483a97095a00b067a499ec (diff)
downloadrneovim-7cd5356a6f89a46d83bbba9b7f6496b67f054629.tar.gz
rneovim-7cd5356a6f89a46d83bbba9b7f6496b67f054629.tar.bz2
rneovim-7cd5356a6f89a46d83bbba9b7f6496b67f054629.zip
feat(net): vim.net.request(), :edit [url] #34140
Problem: Nvim depends on netrw to download/request URL contents. Solution: - Add `vim.net.request()` as a thin curl wrapper: - Basic GET with --silent, --show-error, --fail, --location, --retry - Optional `opts.outpath` to save to a file - Operates asynchronously. Pass an `on_response` handler to get the result. - Add integ tests (requires NVIM_TEST_INTEG to be set) to test success and 404 failure. - Health check for missing `curl`. - Handle `:edit https://…` using `vim.net.request()`. API Usage: 1. Asynchronous request: vim.net.request('https://httpbingo.org/get', { retry = 2 }, function(err, response) if err then print('Fetch failed:', err) else print('Got body of length:', #response.body) end end) 2. Download to file: vim.net.request('https://httpbingo.org/get', { outpath = 'out_async.txt' }, function(err) if err then print('Error:', err) end end) 3. Remote :edit integration (in runtime/plugin/net.lua) fetches into buffer: :edit https://httpbingo.org/get
Diffstat (limited to 'runtime/lua/vim/net.lua')
-rw-r--r--runtime/lua/vim/net.lua63
1 files changed, 63 insertions, 0 deletions
diff --git a/runtime/lua/vim/net.lua b/runtime/lua/vim/net.lua
new file mode 100644
index 0000000000..199b115e93
--- /dev/null
+++ b/runtime/lua/vim/net.lua
@@ -0,0 +1,63 @@
+local M = {}
+
+--- Makes an HTTP GET request to the given URL (asynchronous).
+---
+--- This function operates in one mode:
+--- - Asynchronous (non-blocking): Returns immediately and passes the response object to the
+--- provided `on_response` handler on completetion.
+---
+--- @param url string The URL for the request.
+--- @param opts? table Optional parameters:
+--- - `verbose` (boolean|nil): Enables verbose output.
+--- - `retry` (integer|nil): Number of retries on transient failures (default: 3).
+--- - `outpath` (string|nil): File path to save the response body to. If set, the `body` value in the Response Object will be `true` instead of the response body.
+--- @param on_response fun(err?: string, response?: { body: string|boolean }) Callback invoked on request
+--- completetion. The `body` field in the response object contains the raw response data (text or binary).
+--- Called with (err, nil) on failure, or (nil, { body = string|boolean }) on success.
+function M.request(url, opts, on_response)
+ vim.validate({
+ url = { url, 'string' },
+ opts = { opts, 'table', true },
+ on_response = { on_response, 'function' },
+ })
+
+ opts = opts or {}
+ local retry = opts.retry or 3
+
+ -- Build curl command
+ local args = { 'curl' }
+ if opts.verbose then
+ table.insert(args, '--verbose')
+ else
+ vim.list_extend(args, { '--silent', '--show-error', '--fail' })
+ end
+ vim.list_extend(args, { '--location', '--retry', tostring(retry) })
+
+ if opts.outpath then
+ vim.list_extend(args, { '--output', opts.outpath })
+ end
+
+ table.insert(args, url)
+
+ local function on_exit(res)
+ local err_msg = nil
+ local response = nil
+
+ if res.code ~= 0 then
+ err_msg = (res.stderr ~= '' and res.stderr)
+ or string.format('Request failed with exit code %d', res.code)
+ else
+ response = {
+ body = opts.outpath and true or res.stdout,
+ }
+ end
+
+ if on_response then
+ on_response(err_msg, response)
+ end
+ end
+
+ vim.system(args, {}, on_exit)
+end
+
+return M