Skip to content

Commit 751b54c

Browse files
committed
Merge pull request #4 from heilgar/feature/curl-cp
Feature/curl cp
2 parents e5d4ee4 + 5ee6e00 commit 751b54c

File tree

11 files changed

+228
-12
lines changed

11 files changed

+228
-12
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.1.0] 2024-09-17
9+
### Added
10+
- New feature: Generate and display curl command in dry run output
11+
- New command: `:HttpCopyCurl` to copy curl command for the request under cursor
12+
- New keybinding: `<leader>hc` to copy curl command
13+
- Support for comments in .http and .rest files
14+
- Full line comments starting with '#'
15+
- Inline comments from '#' to end of line
16+
17+
818
## [1.0.0] 2024-09-17
919
### Added
1020
- Comprehensive test suite

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ You can adjust these settings to your preferences.
120120
- `:HttpStop`: Stop the currently running HTTP request.
121121
- `:HttpVerbose`: Toggle verbose mode for debugging.
122122
- `:HttpDryRun`: Perform a dry run of the request under the cursor.
123+
- `:HttpCopyCurl`: Copy the curl command for the HTTP request under the cursor.
123124

124125
### Keybindings
125126

@@ -131,6 +132,7 @@ The plugin comes with the following default keybindings:
131132
- `<leader>hx`: Stop running HTTP request
132133
- `<leader>hv`: Toggle verbose mode
133134
- `<leader>hd`: Perform dry run
135+
- `<leader>hc`: Copy curl command for HTTP request under cursor
134136

135137
To customize these keybindings, you can add the following to your Neovim configuration:
136138

doc/http_client.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ COMMANDS *http_client-commands*
4848
:HttpRunAll *:HttpRunAll*
4949
Run all HTTP requests in the current file.
5050

51+
:HttpCopyCurl *:HttpCopyCurl*
52+
Copy the curl command for the HTTP request under the cursor.
53+
5154
------------------------------------------------------------------------------
5255
KEYBINDINGS *http_client-keybindings*
5356

@@ -71,6 +74,9 @@ The plugin comes with the following default keybindings:
7174
<leader>hd *http_client-dry-run*
7275
Perform dry run
7376

77+
<leader>hc *http_client-copy-curl*
78+
Copy curl command for the HTTP request under cursor
79+
7480
To customize these keybindings, you can pass a 'keybindings' table to the
7581
setup function in your Neovim configuration:
7682
>
@@ -254,6 +260,22 @@ Dry runs can be executed even if no environment file is selected. In this case,
254260
a warning will be displayed in the dry run output if environment variables are
255261
needed but not set.
256262

263+
------------------------------------------------------------------------------
264+
COMMENTS *http_client-comments*
265+
266+
The plugin now supports comments in .http and .rest files. Comments can be used
267+
to add explanations or temporarily disable parts of requests.
268+
269+
- Full line comments start with '#' at the beginning of the line
270+
- Inline comments start with '#' and continue to the end of the line
271+
272+
Examples:
273+
274+
# This is a full line comment
275+
GET https://api.example.com/users # This is an inline comment
276+
277+
Comments are ignored when parsing and executing requests.
278+
257279
==============================================================================
258280
vim:ft=help:et:ts=4:sw=4:sts=4:norl:
259281

lua/http_client/commands/init.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ local M = {}
22

33
M.request = require('http_client.commands.request')
44
M.select_env = require('http_client.commands.select_env')
5+
M.utils = require('http_client.commands.utils')
56

67
return M
78

lua/http_client/commands/utils.lua

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
local M = {}
2+
3+
local vvv = require('http_client.utils.verbose')
4+
local parser = require('http_client.core.parser')
5+
local environment = require('http_client.core.environment')
6+
local http_client = require('http_client.core.http_client')
7+
local curl_generator = require('http_client.core.curl_generator')
8+
9+
M.copy_curl = function()
10+
local request = parser.get_request_under_cursor()
11+
if not request then
12+
print('\nNo valid HTTP request found under cursor')
13+
return
14+
end
15+
16+
local env = environment.get_current_env()
17+
request = parser.replace_placeholders(request, env)
18+
19+
local curl_command = curl_generator.generate_curl(request)
20+
vim.fn.setreg('+', curl_command)
21+
print('Curl command copied to clipboard')
22+
end
23+
24+
return M
25+

lua/http_client/config.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ M.defaults = {
1010
run_request = "<leader>hr",
1111
stop_request = "<leader>hx",
1212
dry_run = "<leader>hd",
13-
toggle_verbose = "<leader>hv"
13+
toggle_verbose = "<leader>hv",
14+
copy_curl = "<leader>hc",
1415
},
1516
}
1617

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
local M = {}
2+
3+
local function escape_quotes(str)
4+
return str:gsub('"', '\\"')
5+
end
6+
7+
M.generate_curl = function(request)
8+
local curl_parts = { "curl" }
9+
10+
-- Add method
11+
table.insert(curl_parts, "-X " .. request.method)
12+
13+
-- Add headers
14+
for key, value in pairs(request.headers or {}) do
15+
table.insert(curl_parts, '-H "' .. escape_quotes(key) .. ': ' .. escape_quotes(value) .. '"')
16+
end
17+
18+
-- Add body if present
19+
if request.body then
20+
table.insert(curl_parts, "-d '" .. request.body .. "'")
21+
end
22+
23+
-- Add URL
24+
table.insert(curl_parts, '"' .. escape_quotes(request.url) .. '"')
25+
26+
return table.concat(curl_parts, " ")
27+
end
28+
29+
return M
30+

lua/http_client/core/parser.lua

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ local function extract_test_name(lines)
1212
return ""
1313
end
1414

15+
local function remove_comment(line)
16+
local comment_start = line:find("#")
17+
if comment_start then
18+
return line:sub(1, comment_start - 1):match("^%s*(.-)%s*$") -- Trim and remove comment part
19+
end
20+
return line:match("^%s*(.-)%s*$") -- Trim if no comment
21+
end
22+
1523
M.get_request_under_cursor = function()
1624
local current_line = vim.api.nvim_win_get_cursor(0)[1]
1725
local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
@@ -21,7 +29,7 @@ M.get_request_under_cursor = function()
2129

2230
-- First pass: check if there are any ### separators
2331
for _, line in ipairs(lines) do
24-
if line:match("^###") then
32+
if line:match("^###") and not line:match("^###%s*#") then
2533
has_separators = true
2634
break
2735
end
@@ -30,7 +38,7 @@ M.get_request_under_cursor = function()
3038
if has_separators then
3139
-- Find the request that contains the cursor
3240
for i, line in ipairs(lines) do
33-
if line:match("^###") then
41+
if line:match("^###") and not line:match("^###%s*#") then
3442
if i <= current_line then
3543
request_start = i
3644
else
@@ -49,7 +57,7 @@ M.get_request_under_cursor = function()
4957
if not request_start then
5058
request_start = 1
5159
for i, line in ipairs(lines) do
52-
if line:match("^###") then
60+
if line:match("^###") and not line:match("^###%s*#") then
5361
request_end = i - 1
5462
break
5563
end
@@ -105,6 +113,7 @@ M.parse_request = function(lines)
105113

106114
for _, line in ipairs(lines) do
107115
line = trim(line)
116+
108117
if line:match("^>%s*{%%") then
109118
in_response_handler = true
110119
response_handler = ""
@@ -117,29 +126,34 @@ M.parse_request = function(lines)
117126
stage = "body"
118127
end
119128
elseif stage == "start" then
120-
-- Updated regex to make HTTP version optional
129+
line = remove_comment(line)
121130
local method, url, version = line:match("^(%S+)%s+(.+)%s+(HTTP/%S+)$")
122131
if not method then
123-
-- If no HTTP version, try matching without it
124132
method, url = line:match("^(%S+)%s+(.+)$")
125133
end
126134
if method and url then
127135
request.method = method
128136
request.url = url
129-
request.http_version = version or "HTTP/1.1" -- Default to HTTP/1.1 if not specified
137+
request.http_version = version or "HTTP/1.1"
130138
stage = "headers"
131139
end
132140
elseif stage == "headers" then
141+
line = remove_comment(line)
133142
local key, value = line:match("^([^:]+):%s*(.+)$")
134143
if key and value then
135-
request.headers[trim(key)] = trim(value)
144+
key = trim(key)
145+
value = remove_comment(value)
146+
value = trim(value)
147+
if value ~= "" then
148+
request.headers[key] = value
149+
end
136150
end
137151
elseif stage == "body" then
138-
table.insert(body_lines, line)
152+
table.insert(body_lines, remove_comment(line))
139153
end
140154
end
141155

142-
if #body_lines > 0 then
156+
if #body_lines > 0 and request.method ~= 'GET' then
143157
request.body = table.concat(body_lines, "\n")
144158
end
145159

lua/http_client/init.lua

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ local function set_keybindings()
2727
vim.keymap.set('n', M.config.get('keybindings').stop_request, ':HttpStop<CR>', opts)
2828
vim.keymap.set('n', M.config.get('keybindings').dry_run, ':HttpDryRun<CR>', opts)
2929
vim.keymap.set('n', M.config.get('keybindings').toggle_verbose, ':HttpVerbose<CR>', opts)
30+
vim.keymap.set('n', M.config.get('keybindings').copy_curl, ':HttpCopyCurl<CR>', opts)
3031
end
3132
})
3233
end
@@ -92,6 +93,12 @@ M.setup = function(opts)
9293
desc = 'Perform a dry run of the HTTP request without sending it.'
9394
})
9495

96+
vim.api.nvim_create_user_command('HttpCopyCurl', function()
97+
M.commands.utils.copy_curl()
98+
end, {
99+
desc = 'Copy curl command for the HTTP request under cursor.'
100+
})
101+
95102

96103

97104
setup_docs()

lua/http_client/ui/dry_run.lua

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
local M = {}
22
local environment = require('http_client.core.environment')
3+
local curl_generator = require('http_client.core.curl_generator')
34

45
local function format_headers(headers)
56
local formatted = {}
@@ -34,6 +35,7 @@ M.display_dry_run = function(http_client)
3435
local merged_env_info = vim.inspect(merged_env)
3536
local current_request = vim.inspect(http_client.http_client.get_current_request() or {})
3637

38+
local curl_command = curl_generator.generate_curl(request)
3739

3840
local ui = require('http_client.ui.display')
3941

@@ -50,6 +52,9 @@ Dry Run Information (%s):
5052
# Body:
5153
%s
5254
55+
# Curl command:
56+
%s
57+
5358
Environment Information:
5459
------------------------
5560
Current env file: %s
@@ -69,6 +74,7 @@ Current request:
6974
request.status or "N/A",
7075
format_headers(request.headers),
7176
request.body or "No body",
77+
curl_command,
7278
env_file,
7379
private_env,
7480
merged_env_info,

0 commit comments

Comments
 (0)