|
| 1 | +local async = require('java-core.utils.async').sync |
| 2 | +local get_error_handler = require('java.handlers.error') |
| 3 | +local class = require('java-core.utils.class') |
| 4 | + |
| 5 | +local config_path = vim.fn.stdpath('data') .. '/nvim-java-profiles.json' |
| 6 | + |
| 7 | +--- @class Profile |
| 8 | +--- @field vm_args string |
| 9 | +--- @field prog_args string |
| 10 | +--- @field name string |
| 11 | +--- @field is_active boolean |
| 12 | +local Profile = class() |
| 13 | + |
| 14 | +--- @param vm_args string |
| 15 | +--- @param prog_args string |
| 16 | +--- @param name string |
| 17 | +--- @param is_active boolean |
| 18 | +function Profile:_init(vm_args, prog_args, name, is_active) |
| 19 | + self.vm_args = vm_args |
| 20 | + self.prog_args = prog_args |
| 21 | + self.name = name |
| 22 | + self.is_active = is_active or false |
| 23 | +end |
| 24 | + |
| 25 | +-- palin config structure |
| 26 | +-- { |
| 27 | +-- "roo_dir" : { |
| 28 | +-- "mod1 -> main_class" : [ |
| 29 | +-- { |
| 30 | +-- "vm_args": "-Xmx1024m", |
| 31 | +-- "prog_args": "arg1 arg2", |
| 32 | +-- "name": "profile_name1", |
| 33 | +-- "is_active": true |
| 34 | +-- }, |
| 35 | +-- { |
| 36 | +-- "vm_args": "-Xmx1024m", |
| 37 | +-- "prog_args": "arg1 arg2", |
| 38 | +-- "name": "profile_name2", |
| 39 | +-- "is_active": false |
| 40 | +-- } |
| 41 | +-- ], |
| 42 | +-- "mod2 -> main_class" : [ |
| 43 | +-- ... |
| 44 | +-- ] |
| 45 | +-- } |
| 46 | +-- } |
| 47 | +--- @return table |
| 48 | +local function read_full_config() |
| 49 | + local file = io.open(config_path, 'r') |
| 50 | + if not file then |
| 51 | + return {} |
| 52 | + end |
| 53 | + local data = file:read('*a') |
| 54 | + file:close() |
| 55 | + local ok, config = pcall(vim.fn.json_decode, data) |
| 56 | + if not ok or not config then |
| 57 | + vim.notify('Failed to read config') |
| 58 | + return {} |
| 59 | + end |
| 60 | + return config |
| 61 | +end |
| 62 | + |
| 63 | +local M = {} |
| 64 | + |
| 65 | +-- loaded profiles |
| 66 | +-- { |
| 67 | +-- ['mod1 -> dap_config_name'] = { |
| 68 | +-- profile_name1 = { |
| 69 | +-- vm_args = '-Xmx1024m', |
| 70 | +-- prog_args = 'arg1 arg2', |
| 71 | +-- name = 'profile_name1', |
| 72 | +-- is_active = true, |
| 73 | +-- }, |
| 74 | +-- profile_name2 = { |
| 75 | +-- vm_args = '-Xmx1024m', |
| 76 | +-- prog_args = 'arg1 arg2', |
| 77 | +-- name = 'profile_name2', |
| 78 | +-- is_active = false, |
| 79 | +-- }, |
| 80 | +-- }, |
| 81 | +-- ['mod2 -> dap_config_name'] = { |
| 82 | +-- .... |
| 83 | +-- }, |
| 84 | +-- } |
| 85 | +--- @return table<string, table<string, Profile>> |
| 86 | +function M.load_current_project_profiles() |
| 87 | + local result = {} |
| 88 | + local current = read_full_config()[M.current_project_path] or {} |
| 89 | + for dap_config_name, dap_config_name_val in pairs(current) do |
| 90 | + result[dap_config_name] = {} |
| 91 | + for _, profile in pairs(dap_config_name_val) do |
| 92 | + result[dap_config_name][profile.name] = Profile( |
| 93 | + profile.vm_args, |
| 94 | + profile.prog_args, |
| 95 | + profile.name, |
| 96 | + profile.is_active |
| 97 | + ) |
| 98 | + end |
| 99 | + end |
| 100 | + return result |
| 101 | +end |
| 102 | + |
| 103 | +function M.save() |
| 104 | + return async(function() |
| 105 | + local full_config = read_full_config() |
| 106 | + local updated_profiles = {} |
| 107 | + for dap_config_name, val in pairs(M.project_profiles) do |
| 108 | + updated_profiles[dap_config_name] = {} |
| 109 | + for _, profile in pairs(val) do |
| 110 | + table.insert(updated_profiles[dap_config_name], profile) |
| 111 | + end |
| 112 | + end |
| 113 | + full_config[M.current_project_path] = updated_profiles |
| 114 | + local ok, json = pcall(vim.fn.json_encode, full_config) |
| 115 | + assert(ok, 'Failed to encode json') |
| 116 | + local file = io.open(config_path, 'w') |
| 117 | + assert(file, 'Failed to open file') |
| 118 | + file:write(json) |
| 119 | + file:close() |
| 120 | + end) |
| 121 | + .catch(get_error_handler('Failed to save profile')) |
| 122 | + .run() |
| 123 | +end |
| 124 | +--- @param dap_config_name string |
| 125 | +--- @return Profile|nil |
| 126 | +function M.get_active_profile(dap_config_name) |
| 127 | + if M.project_profiles[dap_config_name] == nil then |
| 128 | + return nil |
| 129 | + end |
| 130 | + local number_of_profiles = 0 |
| 131 | + for _, profile in pairs(M.project_profiles[dap_config_name]) do |
| 132 | + number_of_profiles = number_of_profiles + 1 |
| 133 | + if profile.is_active then |
| 134 | + return profile |
| 135 | + end |
| 136 | + end |
| 137 | + if number_of_profiles > 0 then |
| 138 | + error('No active profile') |
| 139 | + end |
| 140 | +end |
| 141 | + |
| 142 | +--- @param dap_config_name string |
| 143 | +--- @param profile_name string |
| 144 | +--- @return Profile|nil |
| 145 | +function M.get_profile(profile_name, dap_config_name) |
| 146 | + if M.project_profiles[dap_config_name] == nil then |
| 147 | + return nil |
| 148 | + end |
| 149 | + return M.project_profiles[dap_config_name][profile_name] |
| 150 | +end |
| 151 | + |
| 152 | +--- @param dap_config_name_key string |
| 153 | +--- @return table<string, Profile> |
| 154 | +function M.get_all_profiles(dap_config_name) |
| 155 | + return M.project_profiles[dap_config_name] or {} |
| 156 | +end |
| 157 | +--- @param dap_config_name string |
| 158 | +--- @param profile_name string |
| 159 | +function M.set_active_profile(profile_name, dap_config_name) |
| 160 | + for _, profile in pairs(M.project_profiles[dap_config_name]) do |
| 161 | + if profile.is_active then |
| 162 | + profile.is_active = false |
| 163 | + break |
| 164 | + end |
| 165 | + end |
| 166 | + M.project_profiles[dap_config_name][profile_name].is_active = true |
| 167 | + M.save() |
| 168 | +end |
| 169 | + |
| 170 | +--- @param dap_config_name string |
| 171 | +--- @param current_profile_name string|nil |
| 172 | +--- @param new_profile Profile |
| 173 | +function M.add_or_update_profile( |
| 174 | + new_profile, |
| 175 | + current_profile_name, |
| 176 | + dap_config_name |
| 177 | +) |
| 178 | + assert(new_profile.name, 'Profile name is required') |
| 179 | + if current_profile_name then |
| 180 | + M.project_profiles[dap_config_name][current_profile_name] = nil |
| 181 | + end |
| 182 | + assert( |
| 183 | + M.get_profile(new_profile.name, dap_config_name) == nil, |
| 184 | + "Profile with name '" .. new_profile.name .. "' already exists" |
| 185 | + ) |
| 186 | + |
| 187 | + if M.project_profiles[dap_config_name] == nil then |
| 188 | + M.project_profiles[dap_config_name] = {} |
| 189 | + else |
| 190 | + for _, profile in pairs(M.project_profiles[dap_config_name]) do |
| 191 | + profile.is_active = false |
| 192 | + end |
| 193 | + end |
| 194 | + |
| 195 | + new_profile.is_active = true |
| 196 | + M.project_profiles[dap_config_name][new_profile.name] = new_profile |
| 197 | + M.save() |
| 198 | +end |
| 199 | + |
| 200 | +--- @param dap_config_name string |
| 201 | +--- @param profile_name string |
| 202 | +function M.delete_profile(profile_name, dap_config_name) |
| 203 | + M.project_profiles[dap_config_name][profile_name] = nil |
| 204 | + M.save() |
| 205 | +end |
| 206 | + |
| 207 | +--- @type Profile |
| 208 | +M.Profile = Profile |
| 209 | + |
| 210 | +M.setup = function() |
| 211 | + async(function() |
| 212 | + M.current_project_path = vim.fn.getcwd() |
| 213 | + M.project_profiles = M.load_current_project_profiles() |
| 214 | + end) |
| 215 | + .catch(get_error_handler('Failed to read profile config')) |
| 216 | + .run() |
| 217 | +end |
| 218 | + |
| 219 | +return M |
0 commit comments