Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance Variable Management in Hurl.nvim #220

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions lua/hurl/lib/variable_store.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
local M = {}
local utils = require('hurl.utils')

-- Get the path for storing persisted variables
local function get_store_path()
return vim.fn.stdpath('data') .. '/hurl_variables.json'
end

-- Load persisted variables from disk
function M.load_persisted_vars()
local file_path = get_store_path()
local file = io.open(file_path, 'r')
if not file then
return {}
end

local content = file:read('*all')
file:close()

local ok, data = pcall(vim.json.decode, content)
if not ok then
utils.log_error('Failed to parse persisted variables: ' .. data)
return {}
end

return data
end

-- Save variables to disk
function M.save_persisted_vars(vars)
local file_path = get_store_path()
local file = io.open(file_path, 'w')
if not file then
utils.log_error('Failed to open variable store for writing: ' .. file_path)
return false
end

local ok, encoded = pcall(vim.json.encode, vars)
if not ok then
utils.log_error('Failed to encode variables: ' .. encoded)
file:close()
return false
end

file:write(encoded)
file:close()
return true
end

-- Parse variables from env file
function M.parse_env_file(file_path)
local file = io.open(file_path, 'r')
if not file then
return {}
end

local vars = {}
for line in file:lines() do
local name, value = line:match('^([^=]+)=(.+)$')
if name and value then
vars[name:trim()] = value:trim()
end
end
file:close()

return vars
end

return M
112 changes: 86 additions & 26 deletions lua/hurl/main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ local utils = require('hurl.utils')
local http = require('hurl.http_utils')
local hurl_runner = require('hurl.lib.hurl_runner')
local codelens = require('hurl.codelens')
local variable_store = require('hurl.lib.variable_store')

local M = {}

Expand Down Expand Up @@ -243,62 +244,121 @@ function M.setup()
)
end, { nargs = '*', range = true })

-- Show all global variables
utils.create_cmd('HurlManageVariable', function()
-- Prepare the lines to display in the popup
-- Load variables from all sources
local all_vars = {}

-- Load persisted variables
local persisted_vars = variable_store.load_persisted_vars()
for name, value in pairs(persisted_vars) do
all_vars[name] = {
value = value,
source = 'persisted',
}
end

-- Load variables from env files
local env_files = _HURL_GLOBAL_CONFIG.find_env_files_in_folders()
for _, env_file in ipairs(env_files) do
if vim.fn.filereadable(env_file.path) == 1 then
local env_vars = variable_store.parse_env_file(env_file.path)
for name, value in pairs(env_vars) do
all_vars[name] = {
value = value,
source = 'env:' .. vim.fn.fnamemodify(env_file.path, ':t'),
}
end
end
end

-- Prepare lines for display
local lines = {}
if not _HURL_GLOBAL_CONFIG.global_vars or vim.tbl_isempty(_HURL_GLOBAL_CONFIG.global_vars) then
utils.log_info('hurl: no global variables set')
utils.notify('hurl: no global variables set', vim.log.levels.INFO)
table.insert(lines, 'No global variables set. Please use :HurlSetVariable to set one.')
if vim.tbl_isempty(all_vars) then
table.insert(lines, 'No variables found. Use :HurlSetVariable to set one.')
else
for var_name, var_value in pairs(_HURL_GLOBAL_CONFIG.global_vars) do
table.insert(lines, var_name .. ' = ' .. var_value)
table.insert(lines, '# Variables')
table.insert(lines, '')
for name, data in vim.spairs(all_vars) do
table.insert(lines, string.format('%s = %s [%s]', name, data.value, data.source))
end
end

local popup = require('hurl.popup')
local text_popup = popup.show_text(
'Hurl.nvim - Global variables',
'Hurl.nvim - Variables',
lines,
"Press 'q' to close, 'e' to edit, or 'n' to create a variable."
"Press 'q' to close, 'e' to edit, 'n' to create, or 'd' to delete"
)

-- Add e key binding to edit the variable
-- Add key bindings for variable management
text_popup:map('n', 'e', function()
local line = vim.api.nvim_get_current_line()
local var_name = line:match('^(.-) =')
local var_name = line:match('^([^=]+) =')
if var_name then
local new_value = vim.fn.input('Enter new value for ' .. var_name .. ': ')
_HURL_GLOBAL_CONFIG.global_vars[var_name] = new_value
vim.api.nvim_set_current_line(var_name .. ' = ' .. new_value)
if new_value and new_value ~= '' then
-- Update persisted variables
local vars = variable_store.load_persisted_vars()
vars[var_name] = new_value
variable_store.save_persisted_vars(vars)

-- Update global vars
_HURL_GLOBAL_CONFIG.global_vars = _HURL_GLOBAL_CONFIG.global_vars or {}
_HURL_GLOBAL_CONFIG.global_vars[var_name] = new_value

-- Update display
vim.api.nvim_set_current_line(string.format('%s = %s [persisted]', var_name, new_value))
end
end
end)

-- Add delete functionality
text_popup:map('n', 'd', function()
local line = vim.api.nvim_get_current_line()
local var_name = line:match('^([^=]+) =')
if var_name then
local vars = variable_store.load_persisted_vars()
vars[var_name] = nil
variable_store.save_persisted_vars(vars)

-- Remove from global vars
if _HURL_GLOBAL_CONFIG.global_vars then
_HURL_GLOBAL_CONFIG.global_vars[var_name] = nil
end

-- Remove line from display
local current_line = vim.api.nvim_win_get_cursor(0)[1]
vim.api.nvim_buf_set_lines(0, current_line - 1, current_line, false, {})
end
end)

-- Add 'n' to create new variable
-- Modify existing 'n' mapping to persist new variables
text_popup:map('n', 'n', function()
local var_name = vim.fn.input('Enter new variable name: ')
if not var_name or var_name == '' then
utils.notify('hurl: variable name cannot be empty', vim.log.levels.INFO)
utils.notify('Variable name cannot be empty', vim.log.levels.INFO)
return
end

local var_value = vim.fn.input('Enter new variable value: ')
if not var_value or var_value == '' then
utils.notify('hurl: variable value cannot be empty', vim.log.levels.INFO)
utils.notify('Variable value cannot be empty', vim.log.levels.INFO)
return
end

local line_position = -1
local first_line = vim.api.nvim_buf_get_lines(0, 0, 1, false)
if first_line[1] == 'No global variables set. Please use :HurlSetVariable to set one.' then
-- Clear the buffer if it's empty
line_position = 0
end
-- Update persisted variables
local vars = variable_store.load_persisted_vars()
vars[var_name] = var_value
variable_store.save_persisted_vars(vars)

-- Update global vars
_HURL_GLOBAL_CONFIG.global_vars = _HURL_GLOBAL_CONFIG.global_vars or {}
_HURL_GLOBAL_CONFIG.global_vars[var_name] = var_value

vim.cmd('HurlSetVariable ' .. var_name .. ' ' .. var_value)
-- Append to the last line
vim.api.nvim_buf_set_lines(0, line_position, -1, false, { var_name .. ' = ' .. var_value })
-- Add to display
vim.api.nvim_buf_set_lines(0, -1, -1, false, {
string.format('%s = %s [persisted]', var_name, var_value),
})
end)
end, {
nargs = '*',
Expand Down
48 changes: 35 additions & 13 deletions test/plugin_spec.lua
Original file line number Diff line number Diff line change
@@ -1,19 +1,41 @@
describe('Hurl.nvim plugin', function()
it('should be able to load', function()
local hurl = require('hurl')
assert.truthy(hurl)
describe('Variable management', function()
local variable_store = require('hurl.lib.variable_store')

assert.are.same('split', _HURL_GLOBAL_CONFIG.mode)
assert.are.same(false, _HURL_GLOBAL_CONFIG.debug)
before_each(function()
-- Clear persisted variables before each test
variable_store.save_persisted_vars({})
end)

it('should be able parse the configuration file', function()
require('hurl').setup({
debug = true,
mode = 'popup',
})
it('should persist variables between sessions', function()
-- Set a variable
local vars = {
test_var = 'test_value',
}
variable_store.save_persisted_vars(vars)

assert.are.same('popup', _HURL_GLOBAL_CONFIG.mode)
assert.are.same(true, _HURL_GLOBAL_CONFIG.debug)
-- Load variables
local loaded_vars = variable_store.load_persisted_vars()
assert.are.same(vars, loaded_vars)
end)

it('should load variables from env file', function()
-- Create a temporary env file
local temp_file = vim.fn.tempname()
local f = io.open(temp_file, 'w')
f:write('TEST_VAR=test_value\n')
f:write('ANOTHER_VAR=another_value\n')
f:close()

-- Parse the env file
local vars = variable_store.parse_env_file(temp_file)

-- Clean up
os.remove(temp_file)

-- Verify variables were loaded
assert.are.same({
TEST_VAR = 'test_value',
ANOTHER_VAR = 'another_value',
}, vars)
end)
end)
Loading