Ability to update JSON arrays (#38087)

Closes #ISSUE

Adds the ability to our JSON updating code to update arrays within other
objects. Previously updating of arrays was limited to just top level
arrays (i.e. `keymap.json`) however this PR makes it so nested arrays
are supported as well using `#{index}` syntax as a key.

This PR also fixes an issue with the array updating code that meant that
updating empty json values `""` or an empty `keymap.json` file in the
case of the Keymap Editor would fail instead of creating a new array.

Release Notes:

- Fixed an issue where keybindings would fail to save in the Keymap
Editor if the `keymap.json` file was completely empty
This commit is contained in:
Ben Kunkle
2025-09-14 12:36:26 -04:00
committed by GitHub
parent 1c27a6dbc2
commit 99b71677c6
2 changed files with 898 additions and 86 deletions
+34 -43
View File
@@ -678,8 +678,7 @@ impl KeymapFile {
None,
index,
tab_size,
)
.context("Failed to remove keybinding")?;
);
keymap_contents.replace_range(replace_range, &replace_value);
return Ok(keymap_contents);
}
@@ -699,16 +698,14 @@ impl KeymapFile {
// if we are only changing the keybinding (common case)
// not the context, etc. Then just update the binding in place
let (replace_range, replace_value) =
replace_top_level_array_value_in_json_text(
&keymap_contents,
&["bindings", keystrokes_str],
Some(&source_action_value),
Some(&source.keystrokes_unparsed()),
index,
tab_size,
)
.context("Failed to replace keybinding")?;
let (replace_range, replace_value) = replace_top_level_array_value_in_json_text(
&keymap_contents,
&["bindings", keystrokes_str],
Some(&source_action_value),
Some(&source.keystrokes_unparsed()),
index,
tab_size,
);
keymap_contents.replace_range(replace_range, &replace_value);
return Ok(keymap_contents);
@@ -721,28 +718,24 @@ impl KeymapFile {
// just update the section in place, updating the context
// and the binding
let (replace_range, replace_value) =
replace_top_level_array_value_in_json_text(
&keymap_contents,
&["bindings", keystrokes_str],
Some(&source_action_value),
Some(&source.keystrokes_unparsed()),
index,
tab_size,
)
.context("Failed to replace keybinding")?;
let (replace_range, replace_value) = replace_top_level_array_value_in_json_text(
&keymap_contents,
&["bindings", keystrokes_str],
Some(&source_action_value),
Some(&source.keystrokes_unparsed()),
index,
tab_size,
);
keymap_contents.replace_range(replace_range, &replace_value);
let (replace_range, replace_value) =
replace_top_level_array_value_in_json_text(
&keymap_contents,
&["context"],
source.context.map(Into::into).as_ref(),
None,
index,
tab_size,
)
.context("Failed to replace keybinding")?;
let (replace_range, replace_value) = replace_top_level_array_value_in_json_text(
&keymap_contents,
&["context"],
source.context.map(Into::into).as_ref(),
None,
index,
tab_size,
);
keymap_contents.replace_range(replace_range, &replace_value);
return Ok(keymap_contents);
} else {
@@ -751,16 +744,14 @@ impl KeymapFile {
// section, then treat this operation as an add operation of the
// new binding with the updated context.
let (replace_range, replace_value) =
replace_top_level_array_value_in_json_text(
&keymap_contents,
&["bindings", keystrokes_str],
None,
None,
index,
tab_size,
)
.context("Failed to replace keybinding")?;
let (replace_range, replace_value) = replace_top_level_array_value_in_json_text(
&keymap_contents,
&["bindings", keystrokes_str],
None,
None,
index,
tab_size,
);
keymap_contents.replace_range(replace_range, &replace_value);
operation = KeybindUpdateOperation::Add {
source,
@@ -811,7 +802,7 @@ impl KeymapFile {
&keymap_contents,
&value.into(),
tab_size,
)?;
);
keymap_contents.replace_range(replace_range, &replace_value);
}
return Ok(keymap_contents);
File diff suppressed because it is too large Load Diff