@@ -6,10 +6,11 @@ local proto = require 'proto'
6
6
local define = require ' proto.define'
7
7
local config = require ' config'
8
8
local converter = require ' proto.converter'
9
- local jsonb = require ' json-beautify'
10
9
local await = require ' await'
11
10
local scope = require ' workspace.scope'
12
11
local inspect = require ' inspect'
12
+ local jsone = require ' json-edit'
13
+ local jsonc = require ' jsonc'
13
14
14
15
local m = {}
15
16
m ._eventList = {}
@@ -203,27 +204,96 @@ end
203
204
--- @field global ? boolean
204
205
--- @field uri ? uri
205
206
206
- --- @param cfg table
207
207
--- @param uri uri
208
208
--- @param changes config.change[]
209
- --- @return boolean
210
- local function applyConfig ( cfg , uri , changes )
209
+ --- @return config.change[]
210
+ local function getValidChanges ( uri , changes )
211
211
local scp = scope .getScope (uri )
212
- local ok = false
212
+ local newChanges = {}
213
213
for _ , change in ipairs (changes ) do
214
214
if scp :isChildUri (change .uri )
215
215
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
224
217
end
225
218
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
227
297
end
228
298
229
299
local function tryModifySpecifiedConfig (uri , finalChanges )
@@ -235,15 +305,19 @@ local function tryModifySpecifiedConfig(uri, finalChanges)
235
305
if scp :get (' lastLocalType' ) ~= ' json' then
236
306
return false
237
307
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
240
310
return false
241
311
end
242
312
local path = workspace .getAbsolutePath (uri , CONFIGPATH )
243
313
if not path then
244
314
return false
245
315
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 )
247
321
return true
248
322
end
249
323
@@ -264,17 +338,15 @@ local function tryModifyRC(uri, finalChanges, create)
264
338
if not buf and not create then
265
339
return false
266
340
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
275
347
return false
276
348
end
277
- util .saveFile (path , jsonb . beautify ( rc , { indent = ' ' }) )
349
+ util .saveFile (path , newJson )
278
350
return true
279
351
end
280
352
0 commit comments