@@ -6,10 +6,11 @@ local proto = require 'proto'
66local define = require ' proto.define'
77local config = require ' config'
88local converter = require ' proto.converter'
9- local jsonb = require ' json-beautify'
109local await = require ' await'
1110local scope = require ' workspace.scope'
1211local inspect = require ' inspect'
12+ local jsone = require ' json-edit'
13+ local jsonc = require ' jsonc'
1314
1415local m = {}
1516m ._eventList = {}
@@ -203,27 +204,96 @@ end
203204--- @field global ? boolean
204205--- @field uri ? uri
205206
206- --- @param cfg table
207207--- @param uri uri
208208--- @param changes config.change[]
209- --- @return boolean
210- local function applyConfig ( cfg , uri , changes )
209+ --- @return config.change[]
210+ local function getValidChanges ( uri , changes )
211211 local scp = scope .getScope (uri )
212- local ok = false
212+ local newChanges = {}
213213 for _ , change in ipairs (changes ) do
214214 if scp :isChildUri (change .uri )
215215 or scp :isLinkedUri (change .uri ) then
216- local value = config .getRaw (change .uri , change .key )
217- local key = change .key :match (' ^Lua%.(.+)$' )
218- if cfg [key ] then
219- cfg [key ] = value
220- else
221- cfg [change .key ] = value
222- end
223- ok = true
216+ newChanges [# newChanges + 1 ] = change
224217 end
225218 end
226- return ok
219+ return newChanges
220+ end
221+
222+ --- @class json.patch
223+ --- @field op ' add' | ' remove' | ' replace' | ' move' | ' copy' | ' test'
224+ --- @field path string
225+ --- @field data any
226+
227+ --- @param cfg table
228+ --- @param change config.change
229+ --- @return json.patch ?
230+ local function makeConfigPatch (cfg , change )
231+ if change .action == ' add' then
232+ if type (cfg [change .key ]) == ' table' and # cfg [change .key ] > 0 then
233+ return {
234+ op = ' add' ,
235+ path = ' /' .. change .key .. ' /-' ,
236+ data = change .value ,
237+ }
238+ else
239+ return makeConfigPatch (cfg , {
240+ action = ' set' ,
241+ key = change .key ,
242+ value = { change .value },
243+ })
244+ end
245+ elseif change .action == ' set' then
246+ if cfg [change .key ] ~= nil then
247+ return {
248+ op = ' replace' ,
249+ path = ' /' .. change .key ,
250+ data = change .value ,
251+ }
252+ else
253+ return {
254+ op = ' add' ,
255+ path = ' /' .. change .key ,
256+ data = change .value ,
257+ }
258+ end
259+ elseif change .action == ' prop' then
260+ if type (cfg [change .key ]) == ' table' and # cfg [change .key ] == 0 then
261+ return {
262+ op = ' add' ,
263+ path = ' /' .. change .key .. ' /' .. change .prop ,
264+ data = change .value ,
265+ }
266+ else
267+ return makeConfigPatch (cfg , {
268+ action = ' set' ,
269+ key = change .key ,
270+ value = { [change .prop ] = change .value },
271+ })
272+ end
273+ end
274+ return nil
275+ end
276+
277+ --- @param path string
278+ --- @param changes config.change[]
279+ --- @return string ?
280+ local function editConfigJson (path , changes )
281+ local text = util .loadFile (path )
282+ if not text then
283+ return nil
284+ end
285+ local cfg = jsonc .decode_jsonc (text )
286+ if type (cfg ) ~= ' table' then
287+ cfg = {}
288+ end
289+ --- @cast cfg table
290+ for _ , change in ipairs (changes ) do
291+ local patch = makeConfigPatch (cfg , change )
292+ if patch then
293+ text = jsone .edit (text , patch , { indent = ' ' })
294+ end
295+ end
296+ return text
227297end
228298
229299local function tryModifySpecifiedConfig (uri , finalChanges )
@@ -235,15 +305,19 @@ local function tryModifySpecifiedConfig(uri, finalChanges)
235305 if scp :get (' lastLocalType' ) ~= ' json' then
236306 return false
237307 end
238- local suc = applyConfig ( scp : get ( ' lastLocalConfig ' ), uri , finalChanges )
239- if not suc then
308+ local validChanges = getValidChanges ( uri , finalChanges )
309+ if # validChanges == 0 then
240310 return false
241311 end
242312 local path = workspace .getAbsolutePath (uri , CONFIGPATH )
243313 if not path then
244314 return false
245315 end
246- util .saveFile (path , jsonb .beautify (scp :get (' lastLocalConfig' ), { indent = ' ' }))
316+ local newJson = editConfigJson (path , validChanges )
317+ if not newJson then
318+ return false
319+ end
320+ util .saveFile (path , newJson )
247321 return true
248322end
249323
@@ -264,17 +338,15 @@ local function tryModifyRC(uri, finalChanges, create)
264338 if not buf and not create then
265339 return false
266340 end
267- local loader = require ' config.loader'
268- local rc = loader .loadRCConfig (uri , path ) or {
269- [' $schema' ] = lang .id == ' zh-cn'
270- and [[ https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema-zh-cn.json]]
271- or [[ https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json]]
272- }
273- local suc = applyConfig (rc , uri , finalChanges )
274- if not suc then
341+ local validChanges = getValidChanges (uri , finalChanges )
342+ if # validChanges == 0 then
343+ return false
344+ end
345+ local newJson = editConfigJson (path , validChanges )
346+ if not newJson then
275347 return false
276348 end
277- util .saveFile (path , jsonb . beautify ( rc , { indent = ' ' }) )
349+ util .saveFile (path , newJson )
278350 return true
279351end
280352
0 commit comments