mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-20 19:08:00 +03:00
Add copilot.disabled_globs setting
This commit is contained in:
parent
dc999f719b
commit
c485fc86a2
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1983,6 +1983,7 @@ dependencies = [
|
|||||||
"futures 0.3.25",
|
"futures 0.3.25",
|
||||||
"fuzzy",
|
"fuzzy",
|
||||||
"git",
|
"git",
|
||||||
|
"glob",
|
||||||
"gpui",
|
"gpui",
|
||||||
"indoc",
|
"indoc",
|
||||||
"itertools",
|
"itertools",
|
||||||
@ -5964,6 +5965,7 @@ dependencies = [
|
|||||||
"collections",
|
"collections",
|
||||||
"fs",
|
"fs",
|
||||||
"futures 0.3.25",
|
"futures 0.3.25",
|
||||||
|
"glob",
|
||||||
"gpui",
|
"gpui",
|
||||||
"json_comments",
|
"json_comments",
|
||||||
"postage",
|
"postage",
|
||||||
|
@ -77,6 +77,7 @@ async-trait = { version = "0.1" }
|
|||||||
ctor = { version = "0.1" }
|
ctor = { version = "0.1" }
|
||||||
env_logger = { version = "0.9" }
|
env_logger = { version = "0.9" }
|
||||||
futures = { version = "0.3" }
|
futures = { version = "0.3" }
|
||||||
|
glob = { version = "0.3.1" }
|
||||||
lazy_static = { version = "1.4.0" }
|
lazy_static = { version = "1.4.0" }
|
||||||
log = { version = "0.4.16", features = ["kv_unstable_serde"] }
|
log = { version = "0.4.16", features = ["kv_unstable_serde"] }
|
||||||
ordered-float = { version = "2.1.1" }
|
ordered-float = { version = "2.1.1" }
|
||||||
|
@ -115,6 +115,13 @@
|
|||||||
// "git_gutter": "hide"
|
// "git_gutter": "hide"
|
||||||
"git_gutter": "tracked_files"
|
"git_gutter": "tracked_files"
|
||||||
},
|
},
|
||||||
|
"copilot": {
|
||||||
|
// The set of glob patterns for which copilot should be disabled
|
||||||
|
// in any matching file.
|
||||||
|
"disabled_globs": [
|
||||||
|
".env"
|
||||||
|
]
|
||||||
|
},
|
||||||
// Settings specific to journaling
|
// Settings specific to journaling
|
||||||
"journal": {
|
"journal": {
|
||||||
// The path of the directory where journal entries are stored
|
// The path of the directory where journal entries are stored
|
||||||
|
@ -79,6 +79,7 @@ workspace = { path = "../workspace", features = ["test-support"] }
|
|||||||
|
|
||||||
ctor.workspace = true
|
ctor.workspace = true
|
||||||
env_logger.workspace = true
|
env_logger.workspace = true
|
||||||
|
glob.workspace = true
|
||||||
rand.workspace = true
|
rand.workspace = true
|
||||||
unindent.workspace = true
|
unindent.workspace = true
|
||||||
tree-sitter = "0.20"
|
tree-sitter = "0.20"
|
||||||
|
@ -2925,11 +2925,7 @@ impl Editor {
|
|||||||
|
|
||||||
let snapshot = self.buffer.read(cx).snapshot(cx);
|
let snapshot = self.buffer.read(cx).snapshot(cx);
|
||||||
let cursor = self.selections.newest_anchor().head();
|
let cursor = self.selections.newest_anchor().head();
|
||||||
let language_name = snapshot.language_at(cursor).map(|language| language.name());
|
if !self.is_copilot_enabled_at(cursor, &snapshot, cx) {
|
||||||
if !cx
|
|
||||||
.global::<Settings>()
|
|
||||||
.show_copilot_suggestions(language_name.as_deref())
|
|
||||||
{
|
|
||||||
self.clear_copilot_suggestions(cx);
|
self.clear_copilot_suggestions(cx);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@ -3080,6 +3076,37 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_copilot_enabled_at(
|
||||||
|
&self,
|
||||||
|
location: Anchor,
|
||||||
|
snapshot: &MultiBufferSnapshot,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) -> bool {
|
||||||
|
let settings = cx.global::<Settings>();
|
||||||
|
|
||||||
|
let language_name = snapshot
|
||||||
|
.language_at(location)
|
||||||
|
.map(|language| language.name());
|
||||||
|
if !settings.show_copilot_suggestions(language_name.as_deref()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let file = snapshot.file_at(location);
|
||||||
|
if let Some(file) = file {
|
||||||
|
let path = file.path();
|
||||||
|
if settings
|
||||||
|
.copilot
|
||||||
|
.disabled_globs
|
||||||
|
.iter()
|
||||||
|
.any(|glob| glob.matches_path(path))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
|
fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
|
||||||
self.display_map.read(cx).has_suggestion()
|
self.display_map.read(cx).has_suggestion()
|
||||||
}
|
}
|
||||||
|
@ -6387,6 +6387,97 @@ async fn test_copilot_multibuffer(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_copilot_disabled_globs(
|
||||||
|
deterministic: Arc<Deterministic>,
|
||||||
|
cx: &mut gpui::TestAppContext,
|
||||||
|
) {
|
||||||
|
let (copilot, copilot_lsp) = Copilot::fake(cx);
|
||||||
|
cx.update(|cx| {
|
||||||
|
let mut settings = Settings::test(cx);
|
||||||
|
settings.copilot.disabled_globs = vec![glob::Pattern::new(".env*").unwrap()];
|
||||||
|
cx.set_global(settings);
|
||||||
|
cx.set_global(copilot)
|
||||||
|
});
|
||||||
|
|
||||||
|
let fs = FakeFs::new(cx.background());
|
||||||
|
fs.insert_tree(
|
||||||
|
"/test",
|
||||||
|
json!({
|
||||||
|
".env": "SECRET=something\n",
|
||||||
|
"README.md": "hello\n"
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
let project = Project::test(fs, ["/test".as_ref()], cx).await;
|
||||||
|
|
||||||
|
let private_buffer = project
|
||||||
|
.update(cx, |project, cx| {
|
||||||
|
project.open_local_buffer("/test/.env", cx)
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let public_buffer = project
|
||||||
|
.update(cx, |project, cx| {
|
||||||
|
project.open_local_buffer("/test/README.md", cx)
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let multibuffer = cx.add_model(|cx| {
|
||||||
|
let mut multibuffer = MultiBuffer::new(0);
|
||||||
|
multibuffer.push_excerpts(
|
||||||
|
private_buffer.clone(),
|
||||||
|
[ExcerptRange {
|
||||||
|
context: Point::new(0, 0)..Point::new(1, 0),
|
||||||
|
primary: None,
|
||||||
|
}],
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
multibuffer.push_excerpts(
|
||||||
|
public_buffer.clone(),
|
||||||
|
[ExcerptRange {
|
||||||
|
context: Point::new(0, 0)..Point::new(1, 0),
|
||||||
|
primary: None,
|
||||||
|
}],
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
multibuffer
|
||||||
|
});
|
||||||
|
let (_, editor) = cx.add_window(|cx| build_editor(multibuffer, cx));
|
||||||
|
|
||||||
|
let mut copilot_requests = copilot_lsp
|
||||||
|
.handle_request::<copilot::request::GetCompletions, _, _>(move |_params, _cx| async move {
|
||||||
|
Ok(copilot::request::GetCompletionsResult {
|
||||||
|
completions: vec![copilot::request::Completion {
|
||||||
|
text: "next line".into(),
|
||||||
|
range: lsp::Range::new(lsp::Position::new(1, 0), lsp::Position::new(1, 0)),
|
||||||
|
..Default::default()
|
||||||
|
}],
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
editor.update(cx, |editor, cx| {
|
||||||
|
editor.change_selections(None, cx, |selections| {
|
||||||
|
selections.select_ranges([Point::new(0, 0)..Point::new(0, 0)])
|
||||||
|
});
|
||||||
|
editor.next_copilot_suggestion(&Default::default(), cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
|
||||||
|
assert!(copilot_requests.try_next().is_err());
|
||||||
|
|
||||||
|
editor.update(cx, |editor, cx| {
|
||||||
|
editor.change_selections(None, cx, |s| {
|
||||||
|
s.select_ranges([Point::new(2, 0)..Point::new(2, 0)])
|
||||||
|
});
|
||||||
|
editor.next_copilot_suggestion(&Default::default(), cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
|
||||||
|
assert!(copilot_requests.try_next().is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
|
fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
|
||||||
let point = DisplayPoint::new(row as u32, column as u32);
|
let point = DisplayPoint::new(row as u32, column as u32);
|
||||||
point..point
|
point..point
|
||||||
|
@ -10,9 +10,9 @@ use gpui::{AppContext, Entity, ModelContext, ModelHandle, Task};
|
|||||||
pub use language::Completion;
|
pub use language::Completion;
|
||||||
use language::{
|
use language::{
|
||||||
char_kind, AutoindentMode, Buffer, BufferChunks, BufferSnapshot, CharKind, Chunk, CursorShape,
|
char_kind, AutoindentMode, Buffer, BufferChunks, BufferSnapshot, CharKind, Chunk, CursorShape,
|
||||||
DiagnosticEntry, IndentSize, Language, LanguageScope, OffsetRangeExt, OffsetUtf16, Outline,
|
DiagnosticEntry, File, IndentSize, Language, LanguageScope, OffsetRangeExt, OffsetUtf16,
|
||||||
OutlineItem, Point, PointUtf16, Selection, TextDimension, ToOffset as _, ToOffsetUtf16 as _,
|
Outline, OutlineItem, Point, PointUtf16, Selection, TextDimension, ToOffset as _,
|
||||||
ToPoint as _, ToPointUtf16 as _, TransactionId, Unclipped,
|
ToOffsetUtf16 as _, ToPoint as _, ToPointUtf16 as _, TransactionId, Unclipped,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
@ -2754,6 +2754,11 @@ impl MultiBufferSnapshot {
|
|||||||
self.trailing_excerpt_update_count
|
self.trailing_excerpt_update_count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn file_at<'a, T: ToOffset>(&'a self, point: T) -> Option<&'a Arc<dyn File>> {
|
||||||
|
self.point_to_buffer_offset(point)
|
||||||
|
.and_then(|(buffer, _)| buffer.file())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn language_at<'a, T: ToOffset>(&'a self, point: T) -> Option<&'a Arc<Language>> {
|
pub fn language_at<'a, T: ToOffset>(&'a self, point: T) -> Option<&'a Arc<Language>> {
|
||||||
self.point_to_buffer_offset(point)
|
self.point_to_buffer_offset(point)
|
||||||
.and_then(|(buffer, offset)| buffer.language_at(offset))
|
.and_then(|(buffer, offset)| buffer.language_at(offset))
|
||||||
|
@ -28,7 +28,6 @@ fs = { path = "../fs" }
|
|||||||
fsevent = { path = "../fsevent" }
|
fsevent = { path = "../fsevent" }
|
||||||
fuzzy = { path = "../fuzzy" }
|
fuzzy = { path = "../fuzzy" }
|
||||||
git = { path = "../git" }
|
git = { path = "../git" }
|
||||||
glob = { version = "0.3.1" }
|
|
||||||
gpui = { path = "../gpui" }
|
gpui = { path = "../gpui" }
|
||||||
language = { path = "../language" }
|
language = { path = "../language" }
|
||||||
lsp = { path = "../lsp" }
|
lsp = { path = "../lsp" }
|
||||||
@ -43,6 +42,7 @@ anyhow.workspace = true
|
|||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
backtrace = "0.3"
|
backtrace = "0.3"
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
|
glob.workspace = true
|
||||||
ignore = "0.4"
|
ignore = "0.4"
|
||||||
lazy_static.workspace = true
|
lazy_static.workspace = true
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
|
@ -23,6 +23,7 @@ theme = { path = "../theme" }
|
|||||||
staff_mode = { path = "../staff_mode" }
|
staff_mode = { path = "../staff_mode" }
|
||||||
util = { path = "../util" }
|
util = { path = "../util" }
|
||||||
|
|
||||||
|
glob.workspace = true
|
||||||
json_comments = "0.2"
|
json_comments = "0.2"
|
||||||
postage.workspace = true
|
postage.workspace = true
|
||||||
schemars = "0.8"
|
schemars = "0.8"
|
||||||
|
@ -47,6 +47,7 @@ pub struct Settings {
|
|||||||
pub editor_overrides: EditorSettings,
|
pub editor_overrides: EditorSettings,
|
||||||
pub git: GitSettings,
|
pub git: GitSettings,
|
||||||
pub git_overrides: GitSettings,
|
pub git_overrides: GitSettings,
|
||||||
|
pub copilot: CopilotSettings,
|
||||||
pub journal_defaults: JournalSettings,
|
pub journal_defaults: JournalSettings,
|
||||||
pub journal_overrides: JournalSettings,
|
pub journal_overrides: JournalSettings,
|
||||||
pub terminal_defaults: TerminalSettings,
|
pub terminal_defaults: TerminalSettings,
|
||||||
@ -61,29 +62,6 @@ pub struct Settings {
|
|||||||
pub base_keymap: BaseKeymap,
|
pub base_keymap: BaseKeymap,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Default)]
|
|
||||||
#[serde(rename_all = "snake_case")]
|
|
||||||
pub enum CopilotSettings {
|
|
||||||
#[default]
|
|
||||||
On,
|
|
||||||
Off,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<CopilotSettings> for bool {
|
|
||||||
fn from(value: CopilotSettings) -> Self {
|
|
||||||
match value {
|
|
||||||
CopilotSettings::On => true,
|
|
||||||
CopilotSettings::Off => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CopilotSettings {
|
|
||||||
pub fn is_on(&self) -> bool {
|
|
||||||
<CopilotSettings as Into<bool>>::into(*self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Default)]
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Default)]
|
||||||
pub enum BaseKeymap {
|
pub enum BaseKeymap {
|
||||||
#[default]
|
#[default]
|
||||||
@ -150,6 +128,29 @@ impl TelemetrySettings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default)]
|
||||||
|
pub struct CopilotSettings {
|
||||||
|
pub disabled_globs: Vec<glob::Pattern>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
|
||||||
|
pub struct CopilotSettingsContent {
|
||||||
|
#[serde(default)]
|
||||||
|
disabled_globs: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CopilotSettingsContent> for CopilotSettings {
|
||||||
|
fn from(value: CopilotSettingsContent) -> Self {
|
||||||
|
Self {
|
||||||
|
disabled_globs: value
|
||||||
|
.disabled_globs
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|p| glob::Pattern::new(&p).ok())
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
|
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
|
||||||
pub struct GitSettings {
|
pub struct GitSettings {
|
||||||
pub git_gutter: Option<GitGutter>,
|
pub git_gutter: Option<GitGutter>,
|
||||||
@ -390,6 +391,8 @@ pub struct SettingsFileContent {
|
|||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub buffer_font_features: Option<fonts::Features>,
|
pub buffer_font_features: Option<fonts::Features>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub copilot: Option<CopilotSettingsContent>,
|
||||||
|
#[serde(default)]
|
||||||
pub active_pane_magnification: Option<f32>,
|
pub active_pane_magnification: Option<f32>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub cursor_blink: Option<bool>,
|
pub cursor_blink: Option<bool>,
|
||||||
@ -438,8 +441,7 @@ pub struct LspSettings {
|
|||||||
pub initialization_options: Option<Value>,
|
pub initialization_options: Option<Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
#[serde(rename_all = "snake_case")]
|
|
||||||
pub struct Features {
|
pub struct Features {
|
||||||
pub copilot: bool,
|
pub copilot: bool,
|
||||||
}
|
}
|
||||||
@ -506,6 +508,7 @@ impl Settings {
|
|||||||
show_copilot_suggestions: required(defaults.editor.show_copilot_suggestions),
|
show_copilot_suggestions: required(defaults.editor.show_copilot_suggestions),
|
||||||
},
|
},
|
||||||
editor_overrides: Default::default(),
|
editor_overrides: Default::default(),
|
||||||
|
copilot: defaults.copilot.unwrap().into(),
|
||||||
git: defaults.git.unwrap(),
|
git: defaults.git.unwrap(),
|
||||||
git_overrides: Default::default(),
|
git_overrides: Default::default(),
|
||||||
journal_defaults: defaults.journal,
|
journal_defaults: defaults.journal,
|
||||||
@ -576,6 +579,9 @@ impl Settings {
|
|||||||
merge(&mut self.base_keymap, data.base_keymap);
|
merge(&mut self.base_keymap, data.base_keymap);
|
||||||
merge(&mut self.features.copilot, data.features.copilot);
|
merge(&mut self.features.copilot, data.features.copilot);
|
||||||
|
|
||||||
|
if let Some(copilot) = data.copilot.map(CopilotSettings::from) {
|
||||||
|
self.copilot = copilot;
|
||||||
|
}
|
||||||
self.editor_overrides = data.editor;
|
self.editor_overrides = data.editor;
|
||||||
self.git_overrides = data.git.unwrap_or_default();
|
self.git_overrides = data.git.unwrap_or_default();
|
||||||
self.journal_overrides = data.journal;
|
self.journal_overrides = data.journal;
|
||||||
@ -751,6 +757,7 @@ impl Settings {
|
|||||||
show_copilot_suggestions: Some(true),
|
show_copilot_suggestions: Some(true),
|
||||||
},
|
},
|
||||||
editor_overrides: Default::default(),
|
editor_overrides: Default::default(),
|
||||||
|
copilot: Default::default(),
|
||||||
journal_defaults: Default::default(),
|
journal_defaults: Default::default(),
|
||||||
journal_overrides: Default::default(),
|
journal_overrides: Default::default(),
|
||||||
terminal_defaults: Default::default(),
|
terminal_defaults: Default::default(),
|
||||||
|
Loading…
Reference in New Issue
Block a user