edit predictions: Do not require modifier if in leading space but just accepted a prediction (#24733)

Agus Zubiaga , Antonio Scandurra , as-cii , Danilo Leal , Antonio , and Ben created

This makes the tab tab tab experience smoother

Release Notes:

- N/A

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: as-cii <as-cii@zed.dev>
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
Co-authored-by: Antonio <antonio@zed.dev>
Co-authored-by: Ben <ben@zed.dev>

Change summary

crates/editor/src/editor.rs  | 33 ++++++++++++++++++---------------
crates/editor/src/element.rs |  3 ++-
2 files changed, 20 insertions(+), 16 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -709,11 +709,12 @@ pub struct Editor {
     /// Used to prevent flickering as the user types while the menu is open
     stale_inline_completion_in_menu: Option<InlineCompletionState>,
     edit_prediction_settings: EditPredictionSettings,
-    edit_prediction_cursor_on_leading_whitespace: bool,
     inline_completions_hidden_for_vim_mode: bool,
     show_inline_completions_override: Option<bool>,
     menu_inline_completions_policy: MenuInlineCompletionsPolicy,
     edit_prediction_preview: EditPredictionPreview,
+    edit_prediction_cursor_on_leading_whitespace: bool,
+    edit_prediction_requires_modifier_in_leading_space: bool,
     inlay_hint_cache: InlayHintCache,
     next_inlay_id: usize,
     _subscriptions: Vec<Subscription>,
@@ -1425,6 +1426,7 @@ impl Editor {
             menu_inline_completions_policy: MenuInlineCompletionsPolicy::ByProvider,
             edit_prediction_settings: EditPredictionSettings::Disabled,
             edit_prediction_cursor_on_leading_whitespace: false,
+            edit_prediction_requires_modifier_in_leading_space: true,
             custom_context_menu: None,
             show_git_blame_gutter: false,
             show_git_blame_inline: false,
@@ -1573,7 +1575,7 @@ impl Editor {
                 || self.edit_prediction_requires_modifier()
                 // Require modifier key when the cursor is on leading whitespace, to allow `tab`
                 // bindings to insert tab characters.
-                || self.edit_prediction_cursor_on_leading_whitespace
+                || (self.edit_prediction_requires_modifier_in_leading_space && self.edit_prediction_cursor_on_leading_whitespace)
             {
                 key_context.add(EDIT_PREDICTION_REQUIRES_MODIFIER_KEY_CONTEXT);
             }
@@ -2137,6 +2139,7 @@ impl Editor {
             self.refresh_document_highlights(cx);
             refresh_matching_bracket_highlights(self, window, cx);
             self.update_visible_inline_completion(window, cx);
+            self.edit_prediction_requires_modifier_in_leading_space = true;
             linked_editing_ranges::refresh_linked_ranges(self, window, cx);
             if self.git_blame_inline_enabled {
                 self.start_inline_blame_timer(window, cx);
@@ -5013,6 +5016,8 @@ impl Editor {
                 cx.notify();
             }
         }
+
+        self.edit_prediction_requires_modifier_in_leading_space = false;
     }
 
     pub fn accept_partial_inline_completion(
@@ -5662,19 +5667,17 @@ impl Editor {
             .bg(bg_color)
             .font(theme::ThemeSettings::get_global(cx).buffer_font.clone())
             .text_size(TextSize::XSmall.rems(cx))
-            .when(!self.edit_prediction_preview_is_active(), |parent| {
-                parent.children(ui::render_modifiers(
-                    &accept_keystroke.modifiers,
-                    PlatformStyle::platform(),
-                    Some(if accept_keystroke.modifiers == window.modifiers() {
-                        Color::Accent
-                    } else {
-                        Color::Muted
-                    }),
-                    Some(IconSize::XSmall.rems().into()),
-                    false,
-                ))
-            })
+            .children(ui::render_modifiers(
+                &accept_keystroke.modifiers,
+                PlatformStyle::platform(),
+                Some(if accept_keystroke.modifiers == window.modifiers() {
+                    Color::Accent
+                } else {
+                    Color::Muted
+                }),
+                Some(IconSize::XSmall.rems().into()),
+                false,
+            ))
             .child(accept_keystroke.key.clone())
             .into()
     }

crates/editor/src/element.rs 🔗

@@ -3811,13 +3811,13 @@ impl EditorElement {
 
                 let mut element = v_flex()
                     .items_end()
-                    .shadow_sm()
                     .child(
                         h_flex()
                             .h(ACCEPT_INDICATOR_HEIGHT)
                             .mb(px(-1.))
                             .px_1p5()
                             .gap_1()
+                            .shadow_sm()
                             .bg(Editor::edit_prediction_line_popover_bg_color(cx))
                             .border_1()
                             .border_b_0()
@@ -3829,6 +3829,7 @@ impl EditorElement {
                         div()
                             .bg(cx.theme().colors().editor_background)
                             .border_1()
+                            .shadow_sm()
                             .border_color(cx.theme().colors().border)
                             .rounded_lg()
                             .rounded_tr(Pixels::ZERO)