inline_completion_button: Add menu option to toggle "Eager Preview"s for edit predictions (#24685)

Marshall Bowers created

This PR adds a menu option to the edit prediction menu to toggle the
"Eager Preview" behavior:

<img width="252" alt="Screenshot 2025-02-11 at 2 44 52 PM"
src="https://github.com/user-attachments/assets/232e879b-3c11-4edd-a549-f284e2bca391"
/>

Release Notes:

- N/A

Change summary

crates/inline_completion_button/src/inline_completion_button.rs | 47 ++
crates/language/src/language_settings.rs                        |  4 
2 files changed, 42 insertions(+), 9 deletions(-)

Detailed changes

crates/inline_completion_button/src/inline_completion_button.rs 🔗

@@ -438,13 +438,10 @@ impl InlineCompletionButton {
 
         let settings = AllLanguageSettings::get_global(cx);
         let globally_enabled = settings.show_inline_completions(None, cx);
-        menu = menu.toggleable_entry(
-            "All Files",
-            globally_enabled,
-            IconPosition::Start,
-            None,
-            move |_, cx| toggle_inline_completions_globally(fs.clone(), cx),
-        );
+        menu = menu.toggleable_entry("All Files", globally_enabled, IconPosition::Start, None, {
+            let fs = fs.clone();
+            move |_, cx| toggle_inline_completions_globally(fs.clone(), cx)
+        });
         menu = menu.separator().header("Privacy Settings");
 
         if let Some(provider) = &self.edit_prediction_provider {
@@ -554,6 +551,42 @@ impl InlineCompletionButton {
             );
         }
 
+        let is_eager_preview_enabled = match settings.inline_completions_preview_mode() {
+            language::InlineCompletionPreviewMode::Auto => true,
+            language::InlineCompletionPreviewMode::WhenHoldingModifier => false,
+        };
+        menu = menu.separator().toggleable_entry(
+            "Eager Preview",
+            is_eager_preview_enabled,
+            IconPosition::Start,
+            None,
+            {
+                let fs = fs.clone();
+                move |_window, cx| {
+                    update_settings_file::<AllLanguageSettings>(
+                        fs.clone(),
+                        cx,
+                        move |settings, _cx| {
+                            let inline_preview = match is_eager_preview_enabled {
+                                true => language::InlineCompletionPreviewMode::WhenHoldingModifier,
+                                false => language::InlineCompletionPreviewMode::Auto,
+                            };
+
+                            if let Some(edit_predictions) = settings.edit_predictions.as_mut() {
+                                edit_predictions.inline_preview = inline_preview;
+                            } else {
+                                settings.edit_predictions =
+                                    Some(language_settings::EditPredictionSettingsContent {
+                                        inline_preview,
+                                        ..Default::default()
+                                    });
+                            }
+                        },
+                    );
+                }
+            },
+        );
+
         if let Some(editor_focus_handle) = self.editor_focus_handle.clone() {
             menu = menu
                 .separator()

crates/language/src/language_settings.rs 🔗

@@ -250,7 +250,7 @@ pub struct AllLanguageSettingsContent {
     pub features: Option<FeaturesContent>,
     /// The edit prediction settings.
     #[serde(default)]
-    pub edit_predictions: Option<InlineCompletionSettingsContent>,
+    pub edit_predictions: Option<EditPredictionSettingsContent>,
     /// The default language settings.
     #[serde(flatten)]
     pub defaults: LanguageSettingsContent,
@@ -428,7 +428,7 @@ pub struct LanguageSettingsContent {
 
 /// The contents of the edit prediction settings.
 #[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq)]
-pub struct InlineCompletionSettingsContent {
+pub struct EditPredictionSettingsContent {
     /// A list of globs representing files that edit predictions should be disabled for.
     /// This list adds to a pre-existing, sensible default set of globs.
     /// Any additional ones you add are combined with them.