diff --git a/docs/docs/getting-started/configuration-options.md b/docs/docs/getting-started/configuration-options.md index a9182d33..18daea85 100644 --- a/docs/docs/getting-started/configuration-options.md +++ b/docs/docs/getting-started/configuration-options.md @@ -90,6 +90,9 @@ Here is a full example of setting up the Kulala plugin with the available `opts` -- disable the vim.print output of the scripts -- they will be still written to disk, but not printed immediately disable_script_print_output = false, + -- set scope for environment and request variables + -- possible values: b = buffer, g = global + environment_scope = "b", }, } ``` @@ -511,3 +514,26 @@ Example: }, } ``` +### environment_scope + +While using request variables the results will be stored for later use. +As usual variables they are file relevant and should be stored in the buffer. +If you want to share the variables between buffers you can use the global scope. + +Possible values: + +- `"b"` (buffer) +- `"g"` (global) + +Default: `"b"` + +Example: + +```lua +{ +"mistweaverco/kulala.nvim", + opts = { + environment_scope = "b", + }, +} +``` diff --git a/lua/kulala/config/init.lua b/lua/kulala/config/init.lua index 5a71867c..79590b9f 100644 --- a/lua/kulala/config/init.lua +++ b/lua/kulala/config/init.lua @@ -68,6 +68,9 @@ M.defaults = { -- disable the vim.print output of the scripts -- they will be still written to disk, but not printed immediately disable_script_print_output = false, + -- set scope for environment and request variables + -- possible values: b = buffer, g = global + environment_scope = "b", } M.default_contenttype = { @@ -76,7 +79,7 @@ M.default_contenttype = { pathresolver = nil, } -M.options = {} +M.options = M.defaults M.setup = function(config) M.options = vim.tbl_deep_extend("force", M.defaults, config or {}) diff --git a/lua/kulala/db/init.lua b/lua/kulala/db/init.lua index e7b780db..83566c51 100644 --- a/lua/kulala/db/init.lua +++ b/lua/kulala/db/init.lua @@ -1,10 +1,78 @@ +local CONFIG = require("kulala.config") + local M = {} -M.data = { - selected_env = nil, -- string - name of selected env - http_client_env = nil, -- table of envs from http-client.env.json - http_client_env_base = nil, -- table of base env values which should be applied to all requests - env = {}, -- table of envs from document sources -} +M.data = nil +M.global_data = {} + +local function default_data() + return { + selected_env = nil, -- string - name of selected env + http_client_env = nil, -- table of envs from http-client.env.json + http_client_env_base = nil, -- table of base env values which should be applied to all requests + env = {}, -- table of envs from document sources + scope_nr = nil, -- number - buffer number of the current scope + } +end + +local function get_current_scope_nr() + if CONFIG.get().environment_scope == "b" then + return vim.fn.bufnr() + elseif CONFIG.get().environment_scope == "g" then + return 0 + end +end + +local function load_data() + if CONFIG.get().environment_scope == "b" then + M.data = vim.b.kulala_data or default_data() + elseif CONFIG.get().environment_scope == "g" then + -- keep in lua only + if not M.data then + M.data = default_data() + end + end + M.data.scope_nr = get_current_scope_nr() +end + +local function save_data() + if CONFIG.get().environment_scope == "b" then + if vim.fn.bufexists(M.data.scope_nr) ~= -1 then + vim.b[M.data.scope_nr].kulala_data = M.data + end + elseif CONFIG.get().environment_scope == "g" then + -- keep in lua only + end +end + +M.global_find_many = function() + return M.global_data +end + +M.global_find_unique = function(key) + return M.global_data[key] +end + +M.global_update = function() + return M.global_data +end + +M.find_many = function() + if not M.data or not M.data.scope_nr then + load_data() + elseif M.data.scope_nr ~= get_current_scope_nr() then + save_data() + load_data() + end + return M.data +end + +M.update = function() + return M.find_many() +end + +M.find_unique = function(key) + return M.find_many()[key] +end return M diff --git a/lua/kulala/external_processing/init.lua b/lua/kulala/external_processing/init.lua index 69fe9627..a3f8637f 100644 --- a/lua/kulala/external_processing/init.lua +++ b/lua/kulala/external_processing/init.lua @@ -47,7 +47,7 @@ M.env_stdin_cmd = function(cmdstring, contents) end -- save the result to the environment variable - DB.data.env[env_name] = M.stdin_cmd(cmd_string, contents) + DB.update().env[env_name] = M.stdin_cmd(cmd_string, contents) end return M diff --git a/lua/kulala/internal_processing/init.lua b/lua/kulala/internal_processing/init.lua index 8eca9cd4..d62bbe33 100644 --- a/lua/kulala/internal_processing/init.lua +++ b/lua/kulala/internal_processing/init.lua @@ -106,11 +106,11 @@ M.set_env_for_named_request = function(name, body) cookies = get_cookies_as_table(), }, request = { - headers = DB.data.current_request.headers, - body = DB.data.current_request.body, + headers = DB.find_unique("current_request").headers, + body = DB.find_unique("current_request").body, }, } - DB.data.env[name] = named_request + DB.update().env[name] = named_request end M.env_header_key = function(cmd) @@ -122,7 +122,7 @@ M.env_header_key = function(cmd) if value == nil then vim.notify("env-header-key --> Header not found.", vim.log.levels.ERROR) else - DB.data.env[variable_name] = value + DB.update().env[variable_name] = value end end @@ -151,7 +151,7 @@ M.env_json_key = function(cmd, body) else local kv = vim.split(cmd, " ") local value = get_nested_value(json, kv[2]) - DB.data.env[kv[1]] = value + DB.update().env[kv[1]] = value end end @@ -163,7 +163,7 @@ M.prompt_var = function(metadata_value) if value == nil or value == "" then return false end - DB.data.env[key] = value + DB.update().env[key] = value return true end diff --git a/lua/kulala/parser/env.lua b/lua/kulala/parser/env.lua index 464cc608..12f615e7 100644 --- a/lua/kulala/parser/env.lua +++ b/lua/kulala/parser/env.lua @@ -13,8 +13,8 @@ M.get_env = function() env[key] = value end - DB.data.http_client_env_base = {} - DB.data.http_client_env = {} + DB.update().http_client_env_base = {} + DB.update().http_client_env = {} if Config.get().vscode_rest_client_environmentvars then local vscode_dir = FS.find_file_in_parent_dirs(".vscode") @@ -29,10 +29,11 @@ M.get_env = function() if settings and settings["rest-client.environmentVariables"] then local f = settings["rest-client.environmentVariables"] if f["$shared"] then - DB.data.http_client_env_base = vim.tbl_deep_extend("force", DB.data.http_client_env_base, f["$shared"]) + DB.update().http_client_env_base = + vim.tbl_deep_extend("force", DB.find_unique("http_client_env_base"), f["$shared"]) end f["$shared"] = nil - DB.data.http_client_env = vim.tbl_deep_extend("force", DB.data.http_client_env, f) + DB.update().http_client_env = vim.tbl_deep_extend("force", DB.find_unique("http_client_env"), f) end end end @@ -43,10 +44,11 @@ M.get_env = function() if settings and settings["rest-client.environmentVariables"] then local f = settings["rest-client.environmentVariables"] if f["$shared"] then - DB.data.http_client_env_base = vim.tbl_deep_extend("force", DB.data.http_client_env_base, f["$shared"]) + DB.update().http_client_env_base = + vim.tbl_deep_extend("force", DB.find_unique("http_client_env_base"), f["$shared"]) end f["$shared"] = nil - DB.data.http_client_env = vim.tbl_deep_extend("force", DB.data.http_client_env, f) + DB.update().http_client_env = vim.tbl_deep_extend("force", DB.find_unique("http_client_env"), f) end end end @@ -67,24 +69,26 @@ M.get_env = function() if http_client_env_json then local f = vim.fn.json_decode(vim.fn.readfile(http_client_env_json)) if f._base then - DB.data.http_client_env_base = vim.tbl_deep_extend("force", DB.data.http_client_env_base, f._base) + DB.update().http_client_env_base = vim.tbl_deep_extend("force", DB.find_unique("http_client_env_base"), f._base) end f._base = nil - DB.data.http_client_env = vim.tbl_deep_extend("force", DB.data.http_client_env, f) + DB.update().http_client_env = vim.tbl_deep_extend("force", DB.find_unique("http_client_env"), f) end - for key, value in pairs(DB.data.http_client_env_base) do + local http_client_env_base = DB.find_unique("http_client_env_base") or {} + for key, value in pairs(http_client_env_base) do if key ~= "DEFAULT_HEADERS" then env[key] = value end end - local selected_env = DB.data.http_client_env[vim.g.kulala_selected_env or Config.get().default_env] + local selected_env = DB.find_unique("http_client_env")[vim.g.kulala_selected_env or Config.get().default_env] if selected_env then env = vim.tbl_extend("force", env, selected_env) end - for key, value in pairs(DB.data.env) do + local db_env = DB.find_unique("env") or {} + for key, value in pairs(db_env) do env[key] = value end diff --git a/lua/kulala/parser/init.lua b/lua/kulala/parser/init.lua index 41379577..63375291 100644 --- a/lua/kulala/parser/init.lua +++ b/lua/kulala/parser/init.lua @@ -491,7 +491,7 @@ function M.parse(start_request_linenr) Scripts.javascript.run("pre_request", req.scripts.pre_request) local env = ENV_PARSER.get_env() - DB.data.previous_request = DB.data.current_request + DB.update().previous_request = DB.find_unique("current_request") document_variables = extend_document_variables(document_variables, req) @@ -531,8 +531,8 @@ function M.parse(start_request_linenr) end -- Merge headers from the _base environment if it exists - if DB.data.http_client_env_base then - local default_headers = DB.data.http_client_env_base["DEFAULT_HEADERS"] + if DB.find_unique("http_client_env_base") then + local default_headers = DB.find_unique("http_client_env_base")["DEFAULT_HEADERS"] if default_headers then for key, value in pairs(default_headers) do key = key:lower() @@ -664,7 +664,10 @@ function M.parse(start_request_linenr) if CONFIG.get().debug then FS.write_file(PLUGIN_TMP_DIR .. "/request.txt", table.concat(res.cmd, " "), false) end - DB.data.current_request = res + DB.update().current_request = res + -- Save this to global, + -- so .replay() can be triggered from any buffer or window + DB.global_update().replay = res return res end diff --git a/lua/kulala/parser/request_variables.lua b/lua/kulala/parser/request_variables.lua index c13bbfa1..d6ed6a69 100644 --- a/lua/kulala/parser/request_variables.lua +++ b/lua/kulala/parser/request_variables.lua @@ -43,7 +43,7 @@ local function get_config_contenttype(headers) end local function get_body_value_from_path(name, method, subpath) - local base_table = DB.data.env[name] + local base_table = DB.find_unique("env")[name] if not base_table then return nil end @@ -80,7 +80,7 @@ local function get_body_value_from_path(name, method, subpath) end local function get_header_value_from_path(name, method, subpath) - local base_table = DB.data.env[name] + local base_table = DB.find_unique("env")[name] if not base_table then return nil end @@ -110,7 +110,8 @@ local function get_header_value_from_path(name, method, subpath) end local function get_cookies_value_from_path(name, subpath) - local base_table = DB.data.env[name] + local db_env = DB.find_unique("env") + local base_table = db_env and db_env[name] or nil if not base_table then return nil end diff --git a/lua/kulala/ui/init.lua b/lua/kulala/ui/init.lua index 3db7f114..50c2972c 100644 --- a/lua/kulala/ui/init.lua +++ b/lua/kulala/ui/init.lua @@ -419,7 +419,7 @@ M.show_script_output = function() end M.replay = function() - local result = DB.data.current_request + local result = DB.global_find_unique("replay") if result == nil then vim.notify("No request to replay", vim.log.levels.WARN, { title = "kulala" }) return diff --git a/lua/kulala/ui/selector.lua b/lua/kulala/ui/selector.lua index acbae84a..be05e458 100644 --- a/lua/kulala/ui/selector.lua +++ b/lua/kulala/ui/selector.lua @@ -4,12 +4,13 @@ local FS = require("kulala.utils.fs") local M = {} function M.select_env() - if not DB.data.http_client_env then + local http_client_env = DB.find_unique("http_client_env") + if not http_client_env then return end local envs = {} - for key, _ in pairs(DB.data.http_client_env) do + for key, _ in pairs(http_client_env) do table.insert(envs, key) end diff --git a/lua/telescope/_extensions/kulala.lua b/lua/telescope/_extensions/kulala.lua index a2e9b74e..a8a07597 100644 --- a/lua/telescope/_extensions/kulala.lua +++ b/lua/telescope/_extensions/kulala.lua @@ -45,12 +45,13 @@ local function kulala_search(_) end local function kulala_env_select(_) - if not DB.data.http_client_env then + local http_client_env = DB.find_unique("http_client_env") + if not http_client_env then return end local envs = {} - for key, _ in pairs(DB.data.http_client_env) do + for key, _ in pairs(http_client_env) do table.insert(envs, key) end @@ -74,7 +75,7 @@ local function kulala_env_select(_) previewer = previewers.new_buffer_previewer({ title = "Environment", define_preview = function(self, entry) - local env = DB.data.http_client_env[entry.value] + local env = http_client_env[entry.value] if env == nil then return end diff --git a/tests/db/db_spec.lua b/tests/db/db_spec.lua new file mode 100644 index 00000000..e6d4f476 --- /dev/null +++ b/tests/db/db_spec.lua @@ -0,0 +1,24 @@ +local DB = require("kulala.db") + +describe("db scoped", function() + it("should not leak into other buffers", function() + vim.cmd("new") + local buf1 = vim.api.nvim_get_current_buf() + DB.update().key1 = "value1" + assert.equal(DB.find_unique("key1"), "value1") + + vim.cmd("new") + local buf2 = vim.api.nvim_get_current_buf() + DB.update().key2 = "value2" + assert.equal(DB.find_unique("key1"), nil) + assert.equal(DB.find_unique("key2"), "value2") + + vim.api.nvim_set_current_buf(buf1) + assert.equal(DB.find_unique("key1"), "value1") + assert.equal(DB.find_unique("key2"), nil) + + vim.api.nvim_set_current_buf(buf2) + assert.equal(DB.find_unique("key1"), nil) + assert.equal(DB.find_unique("key2"), "value2") + end) +end)