copilot: Add the option to disable Next Edit Suggestions (#47438)
Adds a new setting to GitHub Copilot to toggle the Next Edit Suggestions feature, it is enabled by default. ## Motivations Due to some current usability issues with this feature, see #46880, and some personal anecdotes of using it, it is currently rough to utilize, so this gives the option to disable it. ## Related - #47071 - #30124 - #44486 ## Release Notes - Adds the ability to disable GitHub Copilot's Next Edit Suggestions feature. ## User Interface  ## Text Example The text example will be adding a `z` variable to a `Point3D` class in TypeScript. ### With Next Edit Suggestions In this example I am able to just press auto-complete (press TAB) 3x. ```ts class Point3D { x: number; y: number; z: number; // <-- Cursor before z: suggested constructor(x: number, y: number , z: number // <-- Next Suggestion ) { this.x = x; this.y = y; this.z = z; // <-- Last Suggestion } } ``` ### Without Next Edit Suggestions ```ts class Point3D { x: number; y: number; z: number; // <-- Cursor before z: the only suggestion constructor(x: number, y: number) { this.x = x; this.y = y; } } ```
This commit is contained in:
1 parent
30ca3ac44e
commit
9db716123d
5 files changed
+122
-62
No files matched your search
@@ -1528,11 +1528,13 @@
|
||||
// "enterprise_uri": "",
|
||||
// "proxy": "",
|
||||
// "proxy_no_verify": false
|
||||
// "enabled_next_edit_suggestions": true
|
||||
// },
|
||||
"copilot": {
|
||||
"enterprise_uri": null,
|
||||
"proxy": null,
|
||||
"proxy_no_verify": null,
|
||||
"enabled_next_edit_suggestions": true,
|
||||
},
|
||||
"codestral": {
|
||||
"api_url": "https://codestral.mistral.ai",
|
||||
|
||||
@@ -9,12 +9,13 @@ use ::fs::Fs;
|
||||
use anyhow::{Context as _, Result, anyhow};
|
||||
use collections::{HashMap, HashSet};
|
||||
use command_palette_hooks::CommandPaletteFilter;
|
||||
use futures::future;
|
||||
use futures::{Future, FutureExt, TryFutureExt, channel::oneshot, future::Shared, select_biased};
|
||||
use gpui::{
|
||||
App, AppContext as _, AsyncApp, Context, Entity, EntityId, EventEmitter, Global, Task,
|
||||
WeakEntity, actions,
|
||||
};
|
||||
use language::language_settings::CopilotSettings;
|
||||
use language::language_settings::{AllLanguageSettings, CopilotSettings};
|
||||
use language::{
|
||||
Anchor, Bias, Buffer, BufferSnapshot, Language, PointUtf16, ToPointUtf16,
|
||||
language_settings::{EditPredictionProvider, all_language_settings},
|
||||
@@ -928,21 +929,63 @@ impl Copilot {
|
||||
let hard_tabs = settings.hard_tabs;
|
||||
drop(settings);
|
||||
|
||||
let nes_enabled = AllLanguageSettings::get_global(cx)
|
||||
.edit_predictions
|
||||
.copilot
|
||||
.enabled_next_edit_suggestions
|
||||
.unwrap_or(true);
|
||||
|
||||
cx.background_spawn(async move {
|
||||
let (version, snapshot) = pending_snapshot.await?;
|
||||
let lsp_position = point_to_lsp(position);
|
||||
|
||||
let nes_request = lsp
|
||||
.request::<NextEditSuggestions>(request::NextEditSuggestionsParams {
|
||||
let nes_fut = if nes_enabled {
|
||||
lsp.request::<NextEditSuggestions>(request::NextEditSuggestionsParams {
|
||||
text_document: lsp::VersionedTextDocumentIdentifier {
|
||||
uri: uri.clone(),
|
||||
version,
|
||||
},
|
||||
position: lsp_position,
|
||||
})
|
||||
.fuse();
|
||||
.map(|resp| {
|
||||
resp.into_response()
|
||||
.ok()
|
||||
.map(|result| {
|
||||
result
|
||||
.edits
|
||||
.into_iter()
|
||||
.map(|completion| {
|
||||
let start = snapshot.clip_point_utf16(
|
||||
point_from_lsp(completion.range.start),
|
||||
Bias::Left,
|
||||
);
|
||||
let end = snapshot.clip_point_utf16(
|
||||
point_from_lsp(completion.range.end),
|
||||
Bias::Left,
|
||||
);
|
||||
CopilotEditPrediction {
|
||||
buffer: buffer_entity.clone(),
|
||||
range: snapshot.anchor_before(start)
|
||||
..snapshot.anchor_after(end),
|
||||
text: completion.text,
|
||||
command: completion.command,
|
||||
snapshot: snapshot.clone(),
|
||||
source: CompletionSource::NextEditSuggestion,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.unwrap_or_default()
|
||||
})
|
||||
.left_future()
|
||||
.fuse()
|
||||
} else {
|
||||
future::ready(Vec::<CopilotEditPrediction>::new())
|
||||
.right_future()
|
||||
.fuse()
|
||||
};
|
||||
|
||||
let inline_request = lsp
|
||||
let inline_fut = lsp
|
||||
.request::<InlineCompletions>(request::InlineCompletionsParams {
|
||||
text_document: lsp::VersionedTextDocumentIdentifier {
|
||||
uri: uri.clone(),
|
||||
@@ -957,74 +1000,56 @@ impl Copilot {
|
||||
insert_spaces: !hard_tabs,
|
||||
}),
|
||||
})
|
||||
.map(|resp| {
|
||||
resp.into_response()
|
||||
.ok()
|
||||
.map(|result| {
|
||||
result
|
||||
.items
|
||||
.into_iter()
|
||||
.map(|item| {
|
||||
let start = snapshot.clip_point_utf16(
|
||||
point_from_lsp(item.range.start),
|
||||
Bias::Left,
|
||||
);
|
||||
let end = snapshot.clip_point_utf16(
|
||||
point_from_lsp(item.range.end),
|
||||
Bias::Left,
|
||||
);
|
||||
CopilotEditPrediction {
|
||||
buffer: buffer_entity.clone(),
|
||||
range: snapshot.anchor_before(start)
|
||||
..snapshot.anchor_after(end),
|
||||
text: item.insert_text,
|
||||
command: item.command,
|
||||
snapshot: snapshot.clone(),
|
||||
source: CompletionSource::InlineCompletion,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.unwrap_or_default()
|
||||
})
|
||||
.fuse();
|
||||
|
||||
futures::pin_mut!(nes_request, inline_request);
|
||||
|
||||
let convert_nes =
|
||||
|result: request::NextEditSuggestionsResult| -> Vec<CopilotEditPrediction> {
|
||||
result
|
||||
.edits
|
||||
.into_iter()
|
||||
.map(|completion| {
|
||||
let start = snapshot.clip_point_utf16(
|
||||
point_from_lsp(completion.range.start),
|
||||
Bias::Left,
|
||||
);
|
||||
let end = snapshot
|
||||
.clip_point_utf16(point_from_lsp(completion.range.end), Bias::Left);
|
||||
CopilotEditPrediction {
|
||||
buffer: buffer_entity.clone(),
|
||||
range: snapshot.anchor_before(start)..snapshot.anchor_after(end),
|
||||
text: completion.text,
|
||||
command: completion.command,
|
||||
snapshot: snapshot.clone(),
|
||||
source: CompletionSource::NextEditSuggestion,
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
|
||||
let convert_inline =
|
||||
|result: request::InlineCompletionsResult| -> Vec<CopilotEditPrediction> {
|
||||
result
|
||||
.items
|
||||
.into_iter()
|
||||
.map(|item| {
|
||||
let start = snapshot
|
||||
.clip_point_utf16(point_from_lsp(item.range.start), Bias::Left);
|
||||
let end = snapshot
|
||||
.clip_point_utf16(point_from_lsp(item.range.end), Bias::Left);
|
||||
CopilotEditPrediction {
|
||||
buffer: buffer_entity.clone(),
|
||||
range: snapshot.anchor_before(start)..snapshot.anchor_after(end),
|
||||
text: item.insert_text,
|
||||
command: item.command,
|
||||
snapshot: snapshot.clone(),
|
||||
source: CompletionSource::InlineCompletion,
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
futures::pin_mut!(nes_fut, inline_fut);
|
||||
|
||||
let mut nes_result: Option<Vec<CopilotEditPrediction>> = None;
|
||||
let mut inline_result: Option<Vec<CopilotEditPrediction>> = None;
|
||||
|
||||
loop {
|
||||
select_biased! {
|
||||
nes = nes_request => {
|
||||
let completions = nes.into_response().ok().map(convert_nes).unwrap_or_default();
|
||||
if !completions.is_empty() {
|
||||
return Ok(completions);
|
||||
nes = nes_fut => {
|
||||
if !nes.is_empty() {
|
||||
return Ok(nes);
|
||||
}
|
||||
nes_result = Some(completions);
|
||||
nes_result = Some(nes);
|
||||
}
|
||||
inline = inline_request => {
|
||||
let completions = inline.into_response().ok().map(convert_inline).unwrap_or_default();
|
||||
if !completions.is_empty() {
|
||||
return Ok(completions);
|
||||
inline = inline_fut => {
|
||||
if !inline.is_empty() {
|
||||
return Ok(inline);
|
||||
}
|
||||
inline_result = Some(completions);
|
||||
inline_result = Some(inline);
|
||||
}
|
||||
complete => break,
|
||||
}
|
||||
|
||||
@@ -942,6 +942,11 @@ impl EditPredictionButton {
|
||||
cx: &mut Context<Self>,
|
||||
) -> Entity<ContextMenu> {
|
||||
let all_language_settings = all_language_settings(None, cx);
|
||||
let next_edit_suggestions = all_language_settings
|
||||
.edit_predictions
|
||||
.copilot
|
||||
.enabled_next_edit_suggestions
|
||||
.unwrap_or(true);
|
||||
let copilot_config = copilot_chat::CopilotChatConfiguration {
|
||||
enterprise_uri: all_language_settings
|
||||
.edit_predictions
|
||||
@@ -957,6 +962,27 @@ impl EditPredictionButton {
|
||||
self.add_provider_switching_section(menu, EditPredictionProvider::Copilot, cx);
|
||||
|
||||
menu.separator()
|
||||
.item(
|
||||
ContextMenuEntry::new("Copilot: Next Edit Suggestions")
|
||||
.toggleable(IconPosition::Start, next_edit_suggestions)
|
||||
.handler({
|
||||
let fs = self.fs.clone();
|
||||
move |_, cx| {
|
||||
update_settings_file(fs.clone(), cx, move |settings, _| {
|
||||
settings
|
||||
.project
|
||||
.all_languages
|
||||
.edit_predictions
|
||||
.get_or_insert_default()
|
||||
.copilot
|
||||
.get_or_insert_default()
|
||||
.enabled_next_edit_suggestions =
|
||||
Some(!next_edit_suggestions);
|
||||
});
|
||||
}
|
||||
}),
|
||||
)
|
||||
.separator()
|
||||
.link(
|
||||
"Go to Copilot Settings",
|
||||
OpenBrowser { url: settings_url }.boxed_clone(),
|
||||
|
||||
@@ -483,6 +483,8 @@ pub struct CopilotSettings {
|
||||
pub proxy_no_verify: Option<bool>,
|
||||
/// Enterprise URI for Copilot.
|
||||
pub enterprise_uri: Option<String>,
|
||||
/// Whether the Copilot Next Edit Suggestions feature is enabled.
|
||||
pub enabled_next_edit_suggestions: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
@@ -741,6 +743,7 @@ impl settings::Settings for AllLanguageSettings {
|
||||
proxy: copilot.proxy,
|
||||
proxy_no_verify: copilot.proxy_no_verify,
|
||||
enterprise_uri: copilot.enterprise_uri,
|
||||
enabled_next_edit_suggestions: copilot.enabled_next_edit_suggestions,
|
||||
};
|
||||
|
||||
let codestral = edit_predictions.codestral.unwrap();
|
||||
|
||||
@@ -210,6 +210,10 @@ pub struct CopilotSettingsContent {
|
||||
///
|
||||
/// Default: none
|
||||
pub enterprise_uri: Option<String>,
|
||||
/// Whether the Copilot Next Edit Suggestions feature is enabled.
|
||||
///
|
||||
/// Default: true
|
||||
pub enabled_next_edit_suggestions: Option<bool>,
|
||||
}
|
||||
|
||||
#[with_fallible_options]
|
||||
|
||||
Reference in new issue
Block a user