diff --git a/assets/keymaps/default-linux.json b/assets/keymaps/default-linux.json index 13ef7be1ca55cf70813135af868cc769c136fa71..10c78ffa1660d81e86b7b2614770c5390bb819a6 100644 --- a/assets/keymaps/default-linux.json +++ b/assets/keymaps/default-linux.json @@ -796,7 +796,7 @@ }, }, { - "context": "Editor && edit_prediction && edit_prediction_mode == eager", + "context": "Editor && edit_prediction && edit_prediction_mode == eager && !showing_completions", "bindings": { "tab": "editor::AcceptEditPrediction", }, diff --git a/assets/keymaps/default-macos.json b/assets/keymaps/default-macos.json index 9d79ac184bba2d9f5b51f4de23b9cc34e342b816..1095c4b82316bf8debac010a9954a962c495ee28 100644 --- a/assets/keymaps/default-macos.json +++ b/assets/keymaps/default-macos.json @@ -858,7 +858,7 @@ }, }, { - "context": "Editor && edit_prediction && edit_prediction_mode == eager", + "context": "Editor && edit_prediction && edit_prediction_mode == eager && !showing_completions", "bindings": { "tab": "editor::AcceptEditPrediction", }, diff --git a/assets/keymaps/default-windows.json b/assets/keymaps/default-windows.json index 07ced12210e85d0e21491990041695d4b040c6aa..02816c1adf48355b9ffada14608e248b29ab9270 100644 --- a/assets/keymaps/default-windows.json +++ b/assets/keymaps/default-windows.json @@ -790,7 +790,7 @@ }, }, { - "context": "Editor && edit_prediction && edit_prediction_mode == eager", + "context": "Editor && edit_prediction && edit_prediction_mode == eager && !showing_completions", "use_key_equivalents": true, "bindings": { "tab": "editor::AcceptEditPrediction", diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index 6d1a0cf278d5eb7598ed92e91b7d4ffad90d9c05..5da15a1c1f304743c55e87ecc208fd6adbdc7cc2 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -1060,7 +1060,7 @@ }, }, { - "context": "Editor && edit_prediction && edit_prediction_mode == eager", + "context": "Editor && edit_prediction && edit_prediction_mode == eager && !showing_completions", "bindings": { // This is identical to the binding in the base keymap, but the vim bindings above to // "vim::Tab" shadow it, so it needs to be bound again. diff --git a/crates/migrator/src/migrations.rs b/crates/migrator/src/migrations.rs index ec33b6a53b3c598842aa29b6e2c31c08c7b11558..2b4a9e6219e009116e313271c17b0eb2dd2b1723 100644 --- a/crates/migrator/src/migrations.rs +++ b/crates/migrator/src/migrations.rs @@ -304,3 +304,9 @@ pub(crate) mod m_2026_02_25 { pub(crate) use settings::migrate_builtin_agent_servers_to_registry; } + +pub(crate) mod m_2026_03_23 { + mod keymap; + + pub(crate) use keymap::KEYMAP_PATTERNS; +} diff --git a/crates/migrator/src/migrations/m_2026_03_23/keymap.rs b/crates/migrator/src/migrations/m_2026_03_23/keymap.rs new file mode 100644 index 0000000000000000000000000000000000000000..8fadc8201a0d2846e66ddf0de80275732d701acd --- /dev/null +++ b/crates/migrator/src/migrations/m_2026_03_23/keymap.rs @@ -0,0 +1,47 @@ +use std::ops::Range; + +use tree_sitter::{Query, QueryMatch}; + +use crate::MigrationPatterns; + +pub const KEYMAP_PATTERNS: MigrationPatterns = + &[(crate::patterns::KEYMAP_CONTEXT_PATTERN, rename_context_key)]; + +fn rename_context_key( + contents: &str, + mat: &QueryMatch, + query: &Query, +) -> Option<(Range, String)> { + let context_predicate_ix = query.capture_index_for_name("context_predicate")?; + let context_predicate_range = mat + .nodes_for_capture_index(context_predicate_ix) + .next()? + .byte_range(); + let old_predicate = contents.get(context_predicate_range.clone())?.to_string(); + let mut new_predicate = old_predicate.clone(); + + const REPLACEMENTS: &[(&str, &str)] = &[ + ( + "edit_prediction_conflict && !showing_completions", + "(edit_prediction && in_leading_whitespace)", + ), + ( + "edit_prediction_conflict && showing_completions", + "(edit_prediction && showing_completions)", + ), + ( + "edit_prediction_conflict", + "(edit_prediction && (showing_completions || in_leading_whitespace))", + ), + ]; + + for (old, new) in REPLACEMENTS { + new_predicate = new_predicate.replace(old, new); + } + + if new_predicate != old_predicate { + Some((context_predicate_range, new_predicate)) + } else { + None + } +} diff --git a/crates/migrator/src/migrator.rs b/crates/migrator/src/migrator.rs index f208faf163aaf425127791f781d4569a737870ff..0f84e3761a63af3d959f6a49b907090cd4376dca 100644 --- a/crates/migrator/src/migrator.rs +++ b/crates/migrator/src/migrator.rs @@ -143,6 +143,10 @@ pub fn migrate_keymap(text: &str) -> Result> { migrations::m_2025_12_08::KEYMAP_PATTERNS, &KEYMAP_QUERY_2025_12_08, ), + MigrationType::TreeSitter( + migrations::m_2026_03_23::KEYMAP_PATTERNS, + &KEYMAP_QUERY_2026_03_23, + ), ]; run_migrations(text, migrations) } @@ -373,6 +377,10 @@ define_query!( SETTINGS_QUERY_2025_12_15, migrations::m_2025_12_15::SETTINGS_PATTERNS ); +define_query!( + KEYMAP_QUERY_2026_03_23, + migrations::m_2026_03_23::KEYMAP_PATTERNS +); // custom query static EDIT_PREDICTION_SETTINGS_MIGRATION_QUERY: LazyLock = LazyLock::new(|| { @@ -400,6 +408,7 @@ mod tests { } } + #[track_caller] fn assert_migrate_keymap(input: &str, output: Option<&str>) { let migrated = migrate_keymap(input).unwrap(); pretty_assertions::assert_eq!(migrated.as_deref(), output); @@ -418,7 +427,7 @@ mod tests { } #[track_caller] - fn assert_migrate_settings_with_migrations( + fn assert_migrate_with_migrations( migrations: &[MigrationType], input: &str, output: Option<&str>, @@ -966,7 +975,7 @@ mod tests { #[test] fn test_mcp_settings_migration() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::TreeSitter( migrations::m_2025_06_16::SETTINGS_PATTERNS, &SETTINGS_QUERY_2025_06_16, @@ -1155,7 +1164,7 @@ mod tests { } } }"#; - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::TreeSitter( migrations::m_2025_06_16::SETTINGS_PATTERNS, &SETTINGS_QUERY_2025_06_16, @@ -1167,7 +1176,7 @@ mod tests { #[test] fn test_custom_agent_server_settings_migration() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::TreeSitter( migrations::m_2025_11_20::SETTINGS_PATTERNS, &SETTINGS_QUERY_2025_11_20, @@ -1383,7 +1392,7 @@ mod tests { #[test] fn test_flatten_code_action_formatters_basic_array() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_01::flatten_code_actions_formatters, )], @@ -1417,7 +1426,7 @@ mod tests { #[test] fn test_flatten_code_action_formatters_basic_object() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_01::flatten_code_actions_formatters, )], @@ -1574,7 +1583,7 @@ mod tests { #[test] fn test_flatten_code_action_formatters_array_with_multiple_action_blocks_in_defaults_and_multiple_languages() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_01::flatten_code_actions_formatters, )], @@ -1700,7 +1709,7 @@ mod tests { #[test] fn test_flatten_code_action_formatters_array_with_format_on_save_and_multiple_languages() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_01::flatten_code_actions_formatters, )], @@ -1887,7 +1896,7 @@ mod tests { #[test] fn test_format_on_save_formatter_migration_basic() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_02::remove_formatters_on_save, )], @@ -1907,7 +1916,7 @@ mod tests { #[test] fn test_format_on_save_formatter_migration_array() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_02::remove_formatters_on_save, )], @@ -1932,7 +1941,7 @@ mod tests { #[test] fn test_format_on_save_on_off_unchanged() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_02::remove_formatters_on_save, )], @@ -1943,7 +1952,7 @@ mod tests { None, ); - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_02::remove_formatters_on_save, )], @@ -1957,7 +1966,7 @@ mod tests { #[test] fn test_format_on_save_formatter_migration_in_languages() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_02::remove_formatters_on_save, )], @@ -1995,7 +2004,7 @@ mod tests { #[test] fn test_format_on_save_formatter_migration_mixed_global_and_languages() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_02::remove_formatters_on_save, )], @@ -2032,7 +2041,7 @@ mod tests { #[test] fn test_format_on_save_no_migration_when_no_format_on_save() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_02::remove_formatters_on_save, )], @@ -2046,7 +2055,7 @@ mod tests { #[test] fn test_restore_code_actions_on_format() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_16::restore_code_actions_on_format, )], @@ -2067,7 +2076,7 @@ mod tests { ), ); - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_16::restore_code_actions_on_format, )], @@ -2081,7 +2090,7 @@ mod tests { None, ); - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_16::restore_code_actions_on_format, )], @@ -2108,7 +2117,7 @@ mod tests { ), ); - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_16::restore_code_actions_on_format, )], @@ -2137,7 +2146,7 @@ mod tests { ), ); - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_16::restore_code_actions_on_format, )], @@ -2155,7 +2164,7 @@ mod tests { #[test] fn test_make_file_finder_include_ignored_an_enum() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_17::make_file_finder_include_ignored_an_enum, )], @@ -2163,7 +2172,7 @@ mod tests { None, ); - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_17::make_file_finder_include_ignored_an_enum, )], @@ -2183,7 +2192,7 @@ mod tests { ), ); - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_17::make_file_finder_include_ignored_an_enum, )], @@ -2203,7 +2212,7 @@ mod tests { ), ); - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_17::make_file_finder_include_ignored_an_enum, )], @@ -2224,7 +2233,7 @@ mod tests { ); // Platform key: settings nested inside "linux" should be migrated - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_17::make_file_finder_include_ignored_an_enum, )], @@ -2253,7 +2262,7 @@ mod tests { ); // Profile: settings nested inside profiles should be migrated - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_17::make_file_finder_include_ignored_an_enum, )], @@ -2288,7 +2297,7 @@ mod tests { #[test] fn test_make_relative_line_numbers_an_enum() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_21::make_relative_line_numbers_an_enum, )], @@ -2296,7 +2305,7 @@ mod tests { None, ); - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_21::make_relative_line_numbers_an_enum, )], @@ -2312,7 +2321,7 @@ mod tests { ), ); - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_21::make_relative_line_numbers_an_enum, )], @@ -2329,7 +2338,7 @@ mod tests { ); // Platform key: settings nested inside "macos" should be migrated - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_21::make_relative_line_numbers_an_enum, )], @@ -2354,7 +2363,7 @@ mod tests { ); // Profile: settings nested inside profiles should be migrated - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_10_21::make_relative_line_numbers_an_enum, )], @@ -2431,7 +2440,7 @@ mod tests { ); // Platform key: settings nested inside "linux" should be migrated - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_11_25::remove_context_server_source, )], @@ -2469,7 +2478,7 @@ mod tests { ); // Profile: settings nested inside profiles should be migrated - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_11_25::remove_context_server_source, )], @@ -2610,7 +2619,7 @@ mod tests { #[test] fn test_make_auto_indent_an_enum() { // Empty settings should not change - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_01_27::make_auto_indent_an_enum, )], @@ -2619,7 +2628,7 @@ mod tests { ); // true should become "syntax_aware" - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_01_27::make_auto_indent_an_enum, )], @@ -2636,7 +2645,7 @@ mod tests { ); // false should become "none" - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_01_27::make_auto_indent_an_enum, )], @@ -2653,7 +2662,7 @@ mod tests { ); // Already valid enum values should not change - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_01_27::make_auto_indent_an_enum, )], @@ -2665,7 +2674,7 @@ mod tests { ); // Should also work inside languages - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2025_01_27::make_auto_indent_an_enum, )], @@ -2694,7 +2703,7 @@ mod tests { #[test] fn test_move_edit_prediction_provider_to_edit_predictions() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_02::move_edit_prediction_provider_to_edit_predictions, )], @@ -2702,7 +2711,7 @@ mod tests { None, ); - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_02::move_edit_prediction_provider_to_edit_predictions, )], @@ -2726,7 +2735,7 @@ mod tests { ), ); - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_02::move_edit_prediction_provider_to_edit_predictions, )], @@ -2754,7 +2763,7 @@ mod tests { ), ); - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_02::move_edit_prediction_provider_to_edit_predictions, )], @@ -2781,7 +2790,7 @@ mod tests { ), ); - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_02::move_edit_prediction_provider_to_edit_predictions, )], @@ -2798,7 +2807,7 @@ mod tests { // Non-object edit_predictions (e.g. true) should gracefully skip // instead of bail!-ing and aborting the entire migration chain. - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_02::move_edit_prediction_provider_to_edit_predictions, )], @@ -2822,7 +2831,7 @@ mod tests { ); // Platform key: settings nested inside "macos" should be migrated - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_02::move_edit_prediction_provider_to_edit_predictions, )], @@ -2851,7 +2860,7 @@ mod tests { ); // Profile: settings nested inside profiles should be migrated - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_02::move_edit_prediction_provider_to_edit_predictions, )], @@ -2884,7 +2893,7 @@ mod tests { ); // Combined: root + platform + profile should all be migrated simultaneously - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_02::move_edit_prediction_provider_to_edit_predictions, )], @@ -2935,7 +2944,7 @@ mod tests { #[test] fn test_migrate_experimental_sweep_mercury() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_03::migrate_experimental_sweep_mercury, )], @@ -2943,7 +2952,7 @@ mod tests { None, ); - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_03::migrate_experimental_sweep_mercury, )], @@ -2969,7 +2978,7 @@ mod tests { ), ); - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_03::migrate_experimental_sweep_mercury, )], @@ -2995,7 +3004,7 @@ mod tests { ), ); - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_03::migrate_experimental_sweep_mercury, )], @@ -3021,7 +3030,7 @@ mod tests { ), ); - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_03::migrate_experimental_sweep_mercury, )], @@ -3036,7 +3045,7 @@ mod tests { None, ); - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_03::migrate_experimental_sweep_mercury, )], @@ -3054,7 +3063,7 @@ mod tests { ); // Platform key: settings nested inside "linux" should be migrated - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_03::migrate_experimental_sweep_mercury, )], @@ -3085,7 +3094,7 @@ mod tests { ); // Profile: settings nested inside profiles should be migrated - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_03::migrate_experimental_sweep_mercury, )], @@ -3120,7 +3129,7 @@ mod tests { ); // Combined: root + platform + profile should all be migrated simultaneously - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_03::migrate_experimental_sweep_mercury, )], @@ -3178,7 +3187,7 @@ mod tests { #[test] fn test_migrate_always_allow_tool_actions_to_default() { // No agent settings - no change - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3187,7 +3196,7 @@ mod tests { ); // always_allow_tool_actions: true -> tool_permissions.default: "allow" - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3214,7 +3223,7 @@ mod tests { ); // always_allow_tool_actions: false -> just remove it - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3233,7 +3242,7 @@ mod tests { ); // Preserve existing tool_permissions.tools when migrating - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3272,7 +3281,7 @@ mod tests { ); // Don't override existing default (and migrate default_mode to default) - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3302,7 +3311,7 @@ mod tests { ); // Migrate existing default_mode to default (no always_allow_tool_actions) - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3331,7 +3340,7 @@ mod tests { ); // No migration needed if already using new format with "default" - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3349,7 +3358,7 @@ mod tests { ); // Migrate default_mode to default in tool-specific rules - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3388,7 +3397,7 @@ mod tests { ); // When tool_permissions is null, replace it so always_allow is preserved - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3416,7 +3425,7 @@ mod tests { ); // Platform-specific agent migration - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3447,7 +3456,7 @@ mod tests { ); // Channel-specific agent migration - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3488,7 +3497,7 @@ mod tests { ); // Profile-level migration - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3526,7 +3535,7 @@ mod tests { ); // Platform-specific agent with profiles - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3571,7 +3580,7 @@ mod tests { ); // Root-level profile with always_allow_tool_actions - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3606,7 +3615,7 @@ mod tests { ); // Root-level profile with default_mode - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3643,7 +3652,7 @@ mod tests { ); // Root-level profile + root-level agent both migrated - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3689,7 +3698,7 @@ mod tests { // Non-boolean always_allow_tool_actions (string "true") is left in place // so the schema validator can report it, rather than silently dropping user data. - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3705,7 +3714,7 @@ mod tests { ); // null always_allow_tool_actions is removed (treated as false) - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3722,7 +3731,7 @@ mod tests { // Project-local settings (.zed/settings.json) with always_allow_tool_actions // These files have no platform/channel overrides or root-level profiles. - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3763,7 +3772,7 @@ mod tests { ); // Project-local settings with only default_mode (no always_allow_tool_actions) - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3792,7 +3801,7 @@ mod tests { ); // Project-local settings with no agent section at all - no change - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3807,7 +3816,7 @@ mod tests { ); // Existing agent_servers are left untouched - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3850,7 +3859,7 @@ mod tests { ); // Existing agent_servers are left untouched even with partial entries - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3887,7 +3896,7 @@ mod tests { ); // always_allow_tool_actions: false leaves agent_servers untouched - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_04::migrate_tool_permission_defaults, )], @@ -3910,7 +3919,7 @@ mod tests { #[test] fn test_migrate_builtin_agent_servers_to_registry_simple() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry, )], @@ -3950,7 +3959,7 @@ mod tests { #[test] fn test_migrate_builtin_agent_servers_empty_entries() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry, )], @@ -3981,7 +3990,7 @@ mod tests { #[test] fn test_migrate_builtin_agent_servers_with_command() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry, )], @@ -4019,7 +4028,7 @@ mod tests { #[test] fn test_migrate_builtin_agent_servers_gemini_with_command() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry, )], @@ -4047,7 +4056,7 @@ mod tests { #[test] fn test_migrate_builtin_agent_servers_gemini_ignore_system_version_false() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry, )], @@ -4075,7 +4084,7 @@ mod tests { #[test] fn test_migrate_builtin_agent_servers_gemini_ignore_system_version_true() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry, )], @@ -4102,7 +4111,7 @@ mod tests { #[test] fn test_migrate_builtin_agent_servers_already_typed_unchanged() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry, )], @@ -4124,7 +4133,7 @@ mod tests { #[test] fn test_migrate_builtin_agent_servers_preserves_custom_entries() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry, )], @@ -4158,7 +4167,7 @@ mod tests { #[test] fn test_migrate_builtin_agent_servers_target_already_exists() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry, )], @@ -4188,7 +4197,7 @@ mod tests { #[test] fn test_migrate_builtin_agent_servers_no_agent_servers_key() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry, )], @@ -4203,7 +4212,7 @@ mod tests { #[test] fn test_migrate_builtin_agent_servers_all_fields() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry, )], @@ -4251,7 +4260,7 @@ mod tests { #[test] fn test_migrate_builtin_agent_servers_codex_with_command() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry, )], @@ -4283,7 +4292,7 @@ mod tests { #[test] fn test_migrate_builtin_agent_servers_mixed_migrated_and_not() { - assert_migrate_settings_with_migrations( + assert_migrate_with_migrations( &[MigrationType::Json( migrations::m_2026_02_25::migrate_builtin_agent_servers_to_registry, )], @@ -4318,4 +4327,149 @@ mod tests { ), ); } + + #[test] + fn test_migrate_edit_prediction_conflict_context() { + assert_migrate_with_migrations( + &[MigrationType::TreeSitter( + migrations::m_2026_03_23::KEYMAP_PATTERNS, + &KEYMAP_QUERY_2026_03_23, + )], + &r#" + [ + { + "context": "Editor && edit_prediction_conflict", + "bindings": { + "ctrl-enter": "editor::AcceptEditPrediction" // Example of a modified keybinding + } + } + ] + "#.unindent(), + Some( + &r#" + [ + { + "context": "Editor && (edit_prediction && (showing_completions || in_leading_whitespace))", + "bindings": { + "ctrl-enter": "editor::AcceptEditPrediction" // Example of a modified keybinding + } + } + ] + "#.unindent(), + ), + ); + + assert_migrate_with_migrations( + &[MigrationType::TreeSitter( + migrations::m_2026_03_23::KEYMAP_PATTERNS, + &KEYMAP_QUERY_2026_03_23, + )], + &r#" + [ + { + "context": "Editor && edit_prediction_conflict && !showing_completions", + "bindings": { + // Here we don't require a modifier unless there's a language server completion + "tab": "editor::AcceptEditPrediction" + } + } + ] + "#.unindent(), + Some( + &r#" + [ + { + "context": "Editor && (edit_prediction && in_leading_whitespace)", + "bindings": { + // Here we don't require a modifier unless there's a language server completion + "tab": "editor::AcceptEditPrediction" + } + } + ] + "#.unindent(), + ), + ); + + assert_migrate_with_migrations( + &[MigrationType::TreeSitter( + migrations::m_2026_03_23::KEYMAP_PATTERNS, + &KEYMAP_QUERY_2026_03_23, + )], + &r#" + [ + { + "context": "Editor && edit_prediction_conflict && showing_completions", + "bindings": { + "tab": "editor::AcceptEditPrediction" + } + } + ] + "# + .unindent(), + Some( + &r#" + [ + { + "context": "Editor && (edit_prediction && showing_completions)", + "bindings": { + "tab": "editor::AcceptEditPrediction" + } + } + ] + "# + .unindent(), + ), + ); + + assert_migrate_with_migrations( + &[MigrationType::TreeSitter( + migrations::m_2026_03_23::KEYMAP_PATTERNS, + &KEYMAP_QUERY_2026_03_23, + )], + &r#" + [ + { + "context": "Editor && edit_prediction", + "bindings": { + "tab": "editor::AcceptEditPrediction", + // Optional: This makes the default `alt-l` binding do nothing. + "alt-l": null + } + }, + { + "context": "Editor && edit_prediction_conflict", + "bindings": { + "alt-tab": "editor::AcceptEditPrediction", + // Optional: This makes the default `alt-l` binding do nothing. + "alt-l": null + } + }, + ] + "# + .unindent(), + Some( + &r#" + [ + { + "context": "Editor && edit_prediction", + "bindings": { + "tab": "editor::AcceptEditPrediction", + // Optional: This makes the default `alt-l` binding do nothing. + "alt-l": null + } + }, + { + "context": "Editor && (edit_prediction && (showing_completions || in_leading_whitespace))", + "bindings": { + "alt-tab": "editor::AcceptEditPrediction", + // Optional: This makes the default `alt-l` binding do nothing. + "alt-l": null + } + }, + ] + "# + .unindent(), + ), + ); + } }