Add support for "..." in edit_predictions.disabled_globs (#64540)
## Objective Let users and projects add edit prediction exclusion patterns without repeating defaults or inherited patterns. Part of #64399. ## Solution Extend the `"..."` convention from #62769, #64222, #64440, and #64484 to `edit_predictions.disabled_globs` using `SplicingVec`. Inherited patterns are inserted at `"..."`, and duplicates retain their first occurrence. Omitting the marker replaces the list, `[]` clears it, and omitting the setting preserves inheritance. Opening an absent setting now initializes it with `["..."]` instead of clearing inherited patterns, and the selection is located by parsing the JSON instead of a regex, so a commented-out or nested `"disabled_globs"` can no longer capture it. Cursor imports append `"..."` like the `files.exclude` import does, so Zed's sensitive-file defaults survive an import; empty lists and empty or literal `"..."` entries are dropped, matching `enabled_patterns`. ## Testing Tested on macOS with settings merge and loading tests, Cursor import tests, the UI settings update and selection path (including commented-out and nested decoy keys), the new `settings_json` key-path lookup, and Copilot integration coverage. To check manually, configure custom disabled patterns alongside `"..."` and confirm that both custom patterns and inherited sensitive-file patterns remain disabled. Repeat without `"..."` and with `[]` to verify replacement and clearing. Opening the setting when it is absent should preserve inherited patterns. ## Self-Review Checklist: - [x] I’ve reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed’s UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable --- Release Notes: - Added support for `"..."` in `edit_predictions.disabled_globs` so custom patterns can extend inherited exclusions, and fixed "Configure Excluded Files" selecting the wrong list when a commented-out `disabled_globs` precedes it. --------- Co-authored-by: Kirill Bulatov <kirill@zed.dev>
This commit is contained in:
1 parent
0ddd9c9863
commit
3a7b16da5d
12 files changed
+598
-68
No files matched your search
Generated
-1
@@ -5556,7 +5556,6 @@ dependencies = [
|
|||||||
"multi_buffer",
|
"multi_buffer",
|
||||||
"paths",
|
"paths",
|
||||||
"project",
|
"project",
|
||||||
"regex",
|
|
||||||
"settings",
|
"settings",
|
||||||
"telemetry",
|
"telemetry",
|
||||||
"text",
|
"text",
|
||||||
|
|||||||
@@ -586,7 +586,7 @@
|
|||||||
// Whether to show code action buttons in the editor toolbar.
|
// Whether to show code action buttons in the editor toolbar.
|
||||||
"code_actions": false,
|
"code_actions": false,
|
||||||
},
|
},
|
||||||
// Whether to allow windows to tab together based on the user’s tabbing preference (macOS only).
|
// Whether to allow windows to tab together based on the user's tabbing preference (macOS only).
|
||||||
"use_system_window_tabs": false,
|
"use_system_window_tabs": false,
|
||||||
// Which fullscreen mode the `zed::ToggleFullScreen` action enters (macOS only).
|
// Which fullscreen mode the `zed::ToggleFullScreen` action enters (macOS only).
|
||||||
//
|
//
|
||||||
@@ -1873,11 +1873,20 @@
|
|||||||
"edit_predictions": {
|
"edit_predictions": {
|
||||||
// Which edit prediction provider to use.
|
// Which edit prediction provider to use.
|
||||||
"provider": "zed",
|
"provider": "zed",
|
||||||
// A list of globs representing files that edit predictions should be disabled for.
|
// Disable edit predictions for files matching these glob patterns.
|
||||||
// There's a sensible default list of globs already included.
|
//
|
||||||
// Any addition to this list will be merged with the default list.
|
// Use `"..."` to add patterns without repeating Zed's defaults. In project
|
||||||
// Globs are matched relative to the worktree root,
|
// settings, it extends the user or parent configuration value. Omit
|
||||||
// except when starting with a slash (/) or equivalent in Windows.
|
// `"..."` to replace the inherited list.
|
||||||
|
//
|
||||||
|
// Inherited patterns are inserted at `"..."`, and duplicates keep their first
|
||||||
|
// occurrence.
|
||||||
|
//
|
||||||
|
// Set `[]` to clear the inherited list. Omit this setting to inherit it unchanged.
|
||||||
|
//
|
||||||
|
// Relative patterns are matched against paths relative to the worktree root.
|
||||||
|
// Absolute patterns are matched against absolute paths.
|
||||||
|
// A leading `~` is expanded to your home folder.
|
||||||
"disabled_globs": [
|
"disabled_globs": [
|
||||||
"**/.env*",
|
"**/.env*",
|
||||||
"**/*.pem",
|
"**/*.pem",
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ mod tests {
|
|||||||
use lsp::Uri;
|
use lsp::Uri;
|
||||||
use project::Project;
|
use project::Project;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use settings::{AllLanguageSettingsContent, DelayMs, SettingsStore};
|
use settings::{AllLanguageSettingsContent, DelayMs, SettingsStore, SplicingVec};
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use util::{
|
use util::{
|
||||||
path,
|
path,
|
||||||
@@ -979,7 +979,7 @@ mod tests {
|
|||||||
settings
|
settings
|
||||||
.edit_predictions
|
.edit_predictions
|
||||||
.get_or_insert(Default::default())
|
.get_or_insert(Default::default())
|
||||||
.disabled_globs = Some(vec![".env*".to_string()]);
|
.disabled_globs = Some(SplicingVec::from(vec![".env*".to_string()]));
|
||||||
});
|
});
|
||||||
|
|
||||||
let (copilot, copilot_lsp) = Copilot::fake(cx);
|
let (copilot, copilot_lsp) = Copilot::fake(cx);
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ menu.workspace = true
|
|||||||
multi_buffer.workspace = true
|
multi_buffer.workspace = true
|
||||||
paths.workspace = true
|
paths.workspace = true
|
||||||
project.workspace = true
|
project.workspace = true
|
||||||
regex.workspace = true
|
|
||||||
settings.workspace = true
|
settings.workspace = true
|
||||||
telemetry.workspace = true
|
telemetry.workspace = true
|
||||||
text.workspace = true
|
text.workspace = true
|
||||||
|
|||||||
@@ -23,13 +23,11 @@ use language::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use project::{DisableAiSettings, Project};
|
use project::{DisableAiSettings, Project};
|
||||||
use regex::Regex;
|
use settings::{
|
||||||
use settings::{Settings, SettingsStore, update_settings_file};
|
Settings, SettingsContent, SettingsStore, SplicingVec, find_value_range_in_json_text,
|
||||||
use std::{
|
update_settings_file,
|
||||||
rc::Rc,
|
|
||||||
sync::{Arc, LazyLock},
|
|
||||||
time::Duration,
|
|
||||||
};
|
};
|
||||||
|
use std::{ops::Range, rc::Rc, sync::Arc, time::Duration};
|
||||||
use ui::{
|
use ui::{
|
||||||
Clickable, ContextMenu, ContextMenuEntry, DocumentationSide, IconButton, IconButtonShape,
|
Clickable, ContextMenu, ContextMenuEntry, DocumentationSide, IconButton, IconButtonShape,
|
||||||
Indicator, PopoverMenu, PopoverMenuHandle, ProgressBar, Tooltip, prelude::*,
|
Indicator, PopoverMenu, PopoverMenuHandle, ProgressBar, Tooltip, prelude::*,
|
||||||
@@ -1402,6 +1400,25 @@ impl StatusItemView for EditPredictionButton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn initialize_disabled_globs_setting(file: &mut SettingsContent) {
|
||||||
|
file.project
|
||||||
|
.all_languages
|
||||||
|
.edit_predictions
|
||||||
|
.get_or_insert_with(Default::default)
|
||||||
|
.disabled_globs
|
||||||
|
.get_or_insert_with(|| SplicingVec::from(vec![SplicingVec::REST.to_string()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn disabled_globs_content_range(text: &str) -> Option<Range<usize>> {
|
||||||
|
let array_range = find_value_range_in_json_text(text, &["edit_predictions", "disabled_globs"])?;
|
||||||
|
let content = text
|
||||||
|
.get(array_range.clone())?
|
||||||
|
.strip_prefix('[')?
|
||||||
|
.strip_suffix(']')?;
|
||||||
|
let start = array_range.start + 1 + (content.len() - content.trim_start().len());
|
||||||
|
Some(start..start + content.trim().len())
|
||||||
|
}
|
||||||
|
|
||||||
async fn open_disabled_globs_setting_in_editor(
|
async fn open_disabled_globs_setting_in_editor(
|
||||||
workspace: WeakEntity<Workspace>,
|
workspace: WeakEntity<Workspace>,
|
||||||
cx: &mut AsyncWindowContext,
|
cx: &mut AsyncWindowContext,
|
||||||
@@ -1423,16 +1440,8 @@ async fn open_disabled_globs_setting_in_editor(
|
|||||||
|
|
||||||
let settings = cx.global::<SettingsStore>();
|
let settings = cx.global::<SettingsStore>();
|
||||||
|
|
||||||
// Ensure that we always have "edit_predictions { "disabled_globs": [] }"
|
|
||||||
let Some(edits) = settings
|
let Some(edits) = settings
|
||||||
.edits_for_update(&text, |file| {
|
.edits_for_update(&text, initialize_disabled_globs_setting)
|
||||||
file.project
|
|
||||||
.all_languages
|
|
||||||
.edit_predictions
|
|
||||||
.get_or_insert_with(Default::default)
|
|
||||||
.disabled_globs
|
|
||||||
.get_or_insert_with(Vec::new);
|
|
||||||
})
|
|
||||||
.log_err()
|
.log_err()
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
@@ -1449,16 +1458,7 @@ async fn open_disabled_globs_setting_in_editor(
|
|||||||
|
|
||||||
let text = item.buffer().read(cx).snapshot(cx).text();
|
let text = item.buffer().read(cx).snapshot(cx).text();
|
||||||
|
|
||||||
static DISABLED_GLOBS_REGEX: LazyLock<Regex> = LazyLock::new(|| {
|
if let Some(range) = disabled_globs_content_range(&text) {
|
||||||
Regex::new(r#""disabled_globs":\s*\[\s*(?P<content>(?:.|\n)*?)\s*\]"#).unwrap()
|
|
||||||
});
|
|
||||||
// Only capture [...]
|
|
||||||
let range = DISABLED_GLOBS_REGEX.captures(&text).and_then(|captures| {
|
|
||||||
captures
|
|
||||||
.name("content")
|
|
||||||
.map(|inner_match| inner_match.start()..inner_match.end())
|
|
||||||
});
|
|
||||||
if let Some(range) = range {
|
|
||||||
let range = MultiBufferOffset(range.start)..MultiBufferOffset(range.end);
|
let range = MultiBufferOffset(range.start)..MultiBufferOffset(range.end);
|
||||||
item.change_selections(
|
item.change_selections(
|
||||||
SelectionEffects::scroll(Autoscroll::newest()),
|
SelectionEffects::scroll(Autoscroll::newest()),
|
||||||
@@ -1686,7 +1686,118 @@ fn copilot_settings_url(enterprise_uri: Option<&str>) -> Arc<str> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use anyhow::Context as _;
|
||||||
use gpui::TestAppContext;
|
use gpui::TestAppContext;
|
||||||
|
use settings::RootUserSettings;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_disabled_globs_selection_and_replacement() -> Result<()> {
|
||||||
|
for contents in [
|
||||||
|
r#""[.][.][.]""#,
|
||||||
|
r#""**/[ab]/**", "...""#,
|
||||||
|
r#""escaped\"]", "backslash\\", "...""#,
|
||||||
|
r#""escaped\\]", "line\nbreak]", "unicode\u005d""#,
|
||||||
|
"\n \"é[ab]\",\n \"...\"\n ",
|
||||||
|
"// Ignore filenames containing a \" character\n \"**/private/**\"\n",
|
||||||
|
"/* Ignore \" and ] */\n \"**/private/**\"\n",
|
||||||
|
"\"**/private/**\", // Keep \" and ]\n \"...\"\n",
|
||||||
|
r#""**/build/**", "...""#,
|
||||||
|
"",
|
||||||
|
"\n ",
|
||||||
|
] {
|
||||||
|
let mut text = format!(
|
||||||
|
r#"// "disabled_globs": ["commented/**"]
|
||||||
|
{{"languages":{{"Rust":{{"disabled_globs":["nested/**"]}}}},
|
||||||
|
/* "disabled_globs": ["commented/**"] */
|
||||||
|
"edit_predictions":{{"disabled_globs":[{contents}],"mode":"subtle"}}}}"#
|
||||||
|
);
|
||||||
|
let mut expected = SettingsContent::parse_json_with_comments(&text)?;
|
||||||
|
let range = disabled_globs_content_range(&text).context("disabled globs selection")?;
|
||||||
|
assert_eq!(text.get(range.clone()), Some(contents.trim()));
|
||||||
|
|
||||||
|
text.replace_range(range, r#""**/replacement/**", "...""#);
|
||||||
|
expected
|
||||||
|
.project
|
||||||
|
.all_languages
|
||||||
|
.edit_predictions
|
||||||
|
.as_mut()
|
||||||
|
.context("edit prediction settings")?
|
||||||
|
.disabled_globs = Some(SplicingVec::from(vec![
|
||||||
|
"**/replacement/**".to_string(),
|
||||||
|
SplicingVec::REST.to_string(),
|
||||||
|
]));
|
||||||
|
assert_eq!(SettingsContent::parse_json_with_comments(&text)?, expected);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
fn test_initialize_disabled_globs_setting(cx: &mut App) {
|
||||||
|
let store = SettingsStore::new(cx, &settings::default_settings());
|
||||||
|
|
||||||
|
let cases: &[(&str, &[&str])] = &[
|
||||||
|
("", &[SplicingVec::REST]),
|
||||||
|
(r#"{}"#, &[SplicingVec::REST]),
|
||||||
|
(r#"{"edit_predictions":{}}"#, &[SplicingVec::REST]),
|
||||||
|
(
|
||||||
|
r#"{"edit_predictions":{"mode":"subtle"}}"#,
|
||||||
|
&[SplicingVec::REST],
|
||||||
|
),
|
||||||
|
(r#"{"edit_predictions":{"disabled_globs":[]}}"#, &[]),
|
||||||
|
(
|
||||||
|
r#"{"edit_predictions":{"disabled_globs":["**/build/**"]}}"#,
|
||||||
|
&["**/build/**"],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
r#"{"edit_predictions":{"disabled_globs":["...","**/build/**"]}}"#,
|
||||||
|
&[SplicingVec::REST, "**/build/**"],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
r#"{"edit_predictions":{"disabled_globs":["[.][.][.]"]}}"#,
|
||||||
|
&["[.][.][.]"],
|
||||||
|
),
|
||||||
|
];
|
||||||
|
for &(content, expected_globs) in cases {
|
||||||
|
let original = if content.is_empty() { "{}" } else { content };
|
||||||
|
let mut expected_content = SettingsContent::parse_json_with_comments(original)
|
||||||
|
.expect("settings content parses");
|
||||||
|
let original_globs = &mut expected_content
|
||||||
|
.project
|
||||||
|
.all_languages
|
||||||
|
.edit_predictions
|
||||||
|
.get_or_insert_with(Default::default)
|
||||||
|
.disabled_globs;
|
||||||
|
let already_configured = original_globs.is_some();
|
||||||
|
*original_globs = Some(SplicingVec::from(
|
||||||
|
expected_globs
|
||||||
|
.iter()
|
||||||
|
.map(|glob| glob.to_string())
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
));
|
||||||
|
|
||||||
|
let edits = store
|
||||||
|
.edits_for_update(content, initialize_disabled_globs_setting)
|
||||||
|
.expect("settings edits are generated");
|
||||||
|
assert_eq!(edits.is_empty(), already_configured, "{content}");
|
||||||
|
let mut updated = content.to_string();
|
||||||
|
for (range, replacement) in edits {
|
||||||
|
updated.replace_range(range, &replacement);
|
||||||
|
}
|
||||||
|
assert_eq!(
|
||||||
|
SettingsContent::parse_json_with_comments(&updated)
|
||||||
|
.expect("updated settings parse"),
|
||||||
|
expected_content,
|
||||||
|
"{content}",
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
store
|
||||||
|
.edits_for_update(&updated, initialize_disabled_globs_setting)
|
||||||
|
.expect("repeated settings edits are generated")
|
||||||
|
.is_empty(),
|
||||||
|
"{content}",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_copilot_settings_url_with_enterprise_uri(cx: &mut TestAppContext) {
|
async fn test_copilot_settings_url_with_enterprise_uri(cx: &mut TestAppContext) {
|
||||||
|
|||||||
@@ -487,9 +487,28 @@ impl InlayHintSettings {
|
|||||||
pub struct EditPredictionSettings {
|
pub struct EditPredictionSettings {
|
||||||
/// The provider that supplies edit predictions.
|
/// The provider that supplies edit predictions.
|
||||||
pub provider: settings::EditPredictionProvider,
|
pub provider: settings::EditPredictionProvider,
|
||||||
/// A list of globs representing files that edit predictions should be disabled for.
|
/// Disable edit predictions for files matching these glob patterns.
|
||||||
/// This list adds to a pre-existing, sensible default set of globs.
|
///
|
||||||
/// Any additional ones you add are combined with them.
|
/// Use `"..."` to add patterns without repeating Zed's defaults. In project
|
||||||
|
/// settings, it extends the user or parent configuration value. Omit
|
||||||
|
/// `"..."` to replace the inherited list.
|
||||||
|
///
|
||||||
|
/// ```json
|
||||||
|
/// {
|
||||||
|
/// "edit_predictions": {
|
||||||
|
/// "disabled_globs": ["**/build/**", "..."]
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Inherited patterns are inserted at `"..."`, and duplicates keep their first
|
||||||
|
/// occurrence.
|
||||||
|
///
|
||||||
|
/// Set `[]` to clear the inherited list. Omit this setting to inherit it unchanged.
|
||||||
|
///
|
||||||
|
/// Relative patterns are matched against paths relative to the worktree root.
|
||||||
|
/// Absolute patterns are matched against absolute paths. A leading `~` is
|
||||||
|
/// expanded to your home folder.
|
||||||
pub disabled_globs: Vec<DisabledGlob>,
|
pub disabled_globs: Vec<DisabledGlob>,
|
||||||
/// Configures how edit predictions are displayed in the buffer.
|
/// Configures how edit predictions are displayed in the buffer.
|
||||||
pub mode: settings::EditPredictionsMode,
|
pub mode: settings::EditPredictionsMode,
|
||||||
@@ -918,6 +937,7 @@ impl settings::Settings for AllLanguageSettings {
|
|||||||
.disabled_globs
|
.disabled_globs
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
.0
|
||||||
.iter()
|
.iter()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
@@ -1096,6 +1116,210 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
fn test_edit_predictions_disabled_globs_replace_and_clear(cx: &mut App) {
|
||||||
|
let mut store = SettingsStore::new(cx, &settings::default_settings());
|
||||||
|
store.register_setting::<AllLanguageSettings>();
|
||||||
|
|
||||||
|
for (content, sensitive_enabled, custom_enabled) in [
|
||||||
|
(r#"{}"#, false, true),
|
||||||
|
(
|
||||||
|
r#"{"edit_predictions":{"disabled_globs":["**/build/**"]}}"#,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
(r#"{"edit_predictions":{"disabled_globs":[]}}"#, true, true),
|
||||||
|
(r#"{"edit_predictions":{}}"#, false, true),
|
||||||
|
] {
|
||||||
|
store
|
||||||
|
.set_user_settings(content, cx)
|
||||||
|
.expect("user settings should load");
|
||||||
|
let settings = &store.get::<AllLanguageSettings>(None).edit_predictions;
|
||||||
|
for (path, expected_enabled) in [
|
||||||
|
(".env", sensitive_enabled),
|
||||||
|
("build/output.rs", custom_enabled),
|
||||||
|
("certificates/private.pem", sensitive_enabled),
|
||||||
|
("config/secrets.yml", sensitive_enabled),
|
||||||
|
("src/main.rs", true),
|
||||||
|
] {
|
||||||
|
let file: Arc<dyn File> = Arc::new(crate::TestFile {
|
||||||
|
path: rel_path(path).into(),
|
||||||
|
root_name: "project".to_string(),
|
||||||
|
local_root: None,
|
||||||
|
});
|
||||||
|
assert_eq!(
|
||||||
|
settings.enabled_for_file(&file, cx),
|
||||||
|
expected_enabled,
|
||||||
|
"path: {path}, settings: {content}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
fn test_edit_predictions_disabled_globs_inherit_across_settings_files(cx: &mut App) {
|
||||||
|
let mut store = SettingsStore::new(cx, &settings::default_settings());
|
||||||
|
store.register_setting::<AllLanguageSettings>();
|
||||||
|
let worktree_id = WorktreeId::from_usize(1);
|
||||||
|
let root = LocalSettingsPath::InWorktree(rel_path("root").into());
|
||||||
|
let child = LocalSettingsPath::InWorktree(rel_path("root/child").into());
|
||||||
|
|
||||||
|
store
|
||||||
|
.set_user_settings(
|
||||||
|
r#"{"edit_predictions":{"disabled_globs":["**/user/**","..."]}}"#,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
.expect("user settings should load");
|
||||||
|
store
|
||||||
|
.set_local_settings(
|
||||||
|
worktree_id,
|
||||||
|
root,
|
||||||
|
LocalSettingsKind::Settings,
|
||||||
|
Some(r#"{"edit_predictions":{"disabled_globs":["**/project/**","..."]}}"#),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
.expect("project settings should load");
|
||||||
|
|
||||||
|
for (content, inherits, child_enabled) in [
|
||||||
|
(
|
||||||
|
r#"{"edit_predictions":{"disabled_globs":["**/child/**","...","**/.env*","..."]}}"#,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
(r#"{"edit_predictions":{}}"#, true, true),
|
||||||
|
(
|
||||||
|
r#"{"edit_predictions":{"disabled_globs":["**/child/**"]}}"#,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
(r#"{"edit_predictions":{"disabled_globs":[]}}"#, false, true),
|
||||||
|
] {
|
||||||
|
store
|
||||||
|
.set_local_settings(
|
||||||
|
worktree_id,
|
||||||
|
child.clone(),
|
||||||
|
LocalSettingsKind::Settings,
|
||||||
|
Some(content),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
.expect("child settings should load");
|
||||||
|
for (location, expected) in [
|
||||||
|
(None, [false, true, true, false]),
|
||||||
|
(
|
||||||
|
Some(SettingsLocation {
|
||||||
|
worktree_id,
|
||||||
|
path: rel_path("root/file.rs"),
|
||||||
|
}),
|
||||||
|
[false, true, false, false],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Some(SettingsLocation {
|
||||||
|
worktree_id,
|
||||||
|
path: rel_path("root/child/file.rs"),
|
||||||
|
}),
|
||||||
|
[!inherits, child_enabled, !inherits, !inherits],
|
||||||
|
),
|
||||||
|
] {
|
||||||
|
let settings = &store.get::<AllLanguageSettings>(location).edit_predictions;
|
||||||
|
for (path, enabled) in [
|
||||||
|
".env",
|
||||||
|
"child/output.rs",
|
||||||
|
"project/output.rs",
|
||||||
|
"user/output.rs",
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.zip(expected)
|
||||||
|
.chain([("...", true), ("src/main.rs", true)])
|
||||||
|
{
|
||||||
|
let file: Arc<dyn File> = Arc::new(crate::TestFile {
|
||||||
|
path: rel_path(path).into(),
|
||||||
|
root_name: "project".to_string(),
|
||||||
|
local_root: None,
|
||||||
|
});
|
||||||
|
assert_eq!(
|
||||||
|
settings.enabled_for_file(&file, cx),
|
||||||
|
enabled,
|
||||||
|
"path: {path}, settings: {content}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
fn test_edit_predictions_disabled_globs_preserve_matching(cx: &mut App) {
|
||||||
|
let mut store = SettingsStore::new(cx, &settings::default_settings());
|
||||||
|
store.register_setting::<AllLanguageSettings>();
|
||||||
|
let absolute_root = if cfg!(windows) {
|
||||||
|
"C:/absolute"
|
||||||
|
} else {
|
||||||
|
"/absolute"
|
||||||
|
};
|
||||||
|
let absolute_pattern = format!("{absolute_root}/project/**/*.rs");
|
||||||
|
let home = shellexpand::tilde("~").into_owned();
|
||||||
|
for (patterns, path, local_root, enabled) in [
|
||||||
|
(
|
||||||
|
vec!["**/src/**", "..."],
|
||||||
|
"src/main.rs",
|
||||||
|
Some(absolute_root),
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
vec!["**/src/**", "..."],
|
||||||
|
"other/main.rs",
|
||||||
|
Some(absolute_root),
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
vec![absolute_pattern.as_str(), "..."],
|
||||||
|
"src/main.rs",
|
||||||
|
Some(absolute_root),
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
vec![absolute_pattern.as_str(), "..."],
|
||||||
|
"src/main.rs",
|
||||||
|
None,
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
vec!["~/project/**/*.rs", "..."],
|
||||||
|
"src/main.rs",
|
||||||
|
Some(home.as_str()),
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
vec!["[", "**/src/**", "..."],
|
||||||
|
"src/main.rs",
|
||||||
|
Some(absolute_root),
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
(vec!["[", "..."], ".env", Some(absolute_root), false),
|
||||||
|
(vec!["[", "{"], ".env", Some(absolute_root), true),
|
||||||
|
(vec!["[", "{"], "src/main.rs", Some(absolute_root), true),
|
||||||
|
(vec!["[.][.][.]"], "...", Some(absolute_root), false),
|
||||||
|
] {
|
||||||
|
store
|
||||||
|
.set_user_settings(
|
||||||
|
&serde_json::json!({"edit_predictions": {"disabled_globs": patterns}})
|
||||||
|
.to_string(),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
.expect("user settings should load");
|
||||||
|
let file: Arc<dyn File> = Arc::new(crate::TestFile {
|
||||||
|
path: rel_path(path).into(),
|
||||||
|
root_name: "project".to_string(),
|
||||||
|
local_root: local_root.map(std::path::PathBuf::from),
|
||||||
|
});
|
||||||
|
let settings = &store.get::<AllLanguageSettings>(None).edit_predictions;
|
||||||
|
assert_eq!(
|
||||||
|
settings.enabled_for_file(&file, cx),
|
||||||
|
enabled,
|
||||||
|
"path: {path}, patterns: {patterns:?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
fn test_edit_predictions_enabled_for_file(cx: &mut TestAppContext) {
|
fn test_edit_predictions_enabled_for_file(cx: &mut TestAppContext) {
|
||||||
use crate::TestFile;
|
use crate::TestFile;
|
||||||
|
|||||||
@@ -677,19 +677,22 @@ impl VsCodeSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn edit_predictions_settings_content(&self) -> Option<EditPredictionSettingsContent> {
|
fn edit_predictions_settings_content(&self) -> Option<EditPredictionSettingsContent> {
|
||||||
let disabled_globs = self
|
let mut disabled_globs = self
|
||||||
.read_value("cursor.general.globalCursorIgnoreList")?
|
.read_value("cursor.general.globalCursorIgnoreList")?
|
||||||
.as_array()?;
|
.as_array()?
|
||||||
|
.iter()
|
||||||
|
.filter_map(Value::as_str)
|
||||||
|
.filter(|glob| !glob.is_empty() && *glob != SplicingVec::REST)
|
||||||
|
.map(str::to_owned)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
if disabled_globs.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
disabled_globs.push(SplicingVec::REST.to_owned());
|
||||||
|
|
||||||
skip_default(EditPredictionSettingsContent {
|
Some(EditPredictionSettingsContent {
|
||||||
disabled_globs: skip_default(
|
disabled_globs: Some(SplicingVec::from(disabled_globs)),
|
||||||
disabled_globs
|
..EditPredictionSettingsContent::default()
|
||||||
.iter()
|
|
||||||
.filter_map(|glob| glob.as_str())
|
|
||||||
.map(|s| s.to_string())
|
|
||||||
.collect(),
|
|
||||||
),
|
|
||||||
..Default::default()
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1235,6 +1238,88 @@ mod tests {
|
|||||||
.reduce_motion
|
.reduce_motion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_import_disabled_globs_extends_inherited_patterns() -> Result<()> {
|
||||||
|
for (ignore_list, expected_imported, expected_merged) in [
|
||||||
|
(
|
||||||
|
serde_json::json!(["**/build/**", "**/cache/**"]),
|
||||||
|
serde_json::json!(["**/build/**", "**/cache/**", "..."]),
|
||||||
|
serde_json::json!(["**/build/**", "**/cache/**", "**/inherited/**"]),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
serde_json::json!(["**/build/**", "", false, null, 1, {}, []]),
|
||||||
|
serde_json::json!(["**/build/**", "..."]),
|
||||||
|
serde_json::json!(["**/build/**", "**/inherited/**"]),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
serde_json::json!(["...", "**/build/**", false]),
|
||||||
|
serde_json::json!(["**/build/**", "..."]),
|
||||||
|
serde_json::json!(["**/build/**", "**/inherited/**"]),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
serde_json::json!(["**/inherited/**", "**/build/**"]),
|
||||||
|
serde_json::json!(["**/inherited/**", "**/build/**", "..."]),
|
||||||
|
serde_json::json!(["**/inherited/**", "**/build/**"]),
|
||||||
|
),
|
||||||
|
] {
|
||||||
|
let content = serde_json::json!({
|
||||||
|
"cursor.general.globalCursorIgnoreList": ignore_list,
|
||||||
|
});
|
||||||
|
let imported =
|
||||||
|
VsCodeSettings::from_str(&content.to_string(), VsCodeSettingsSource::Cursor)?
|
||||||
|
.settings_content();
|
||||||
|
let imported = imported
|
||||||
|
.project
|
||||||
|
.all_languages
|
||||||
|
.edit_predictions
|
||||||
|
.context("imported edit prediction settings")?;
|
||||||
|
assert_eq!(
|
||||||
|
serde_json::to_value(&imported.disabled_globs)?,
|
||||||
|
expected_imported
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut inherited = EditPredictionSettingsContent {
|
||||||
|
disabled_globs: Some(SplicingVec::from(vec!["**/inherited/**".to_string()])),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
inherited.merge_from(&imported);
|
||||||
|
assert_eq!(
|
||||||
|
serde_json::to_value(&inherited.disabled_globs)?,
|
||||||
|
expected_merged
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_import_disabled_globs_omits_empty_results() -> Result<()> {
|
||||||
|
let inherited = AllLanguageSettingsContent {
|
||||||
|
edit_predictions: Some(EditPredictionSettingsContent {
|
||||||
|
disabled_globs: Some(SplicingVec::from(vec!["**/inherited/**".to_string()])),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
for content in [
|
||||||
|
r#"{"cursor.general.globalCursorIgnoreList": "**/build/**"}"#,
|
||||||
|
r#"{"cursor.general.globalCursorIgnoreList": ["..."]}"#,
|
||||||
|
r#"{"cursor.general.globalCursorIgnoreList": [""]}"#,
|
||||||
|
r#"{"cursor.general.globalCursorIgnoreList": ["...", "", false, null]}"#,
|
||||||
|
r#"{"cursor.general.globalCursorIgnoreList": []}"#,
|
||||||
|
r#"{"cursor.general.globalCursorIgnoreList": [false, null, 1, {}, []]}"#,
|
||||||
|
r#"{"cursor.general.globalCursorIgnoreList": null}"#,
|
||||||
|
r#"{}"#,
|
||||||
|
] {
|
||||||
|
let imported =
|
||||||
|
VsCodeSettings::from_str(content, VsCodeSettingsSource::Cursor)?.settings_content();
|
||||||
|
assert_eq!(imported.project.all_languages.edit_predictions, None);
|
||||||
|
let mut unchanged = inherited.clone();
|
||||||
|
unchanged.merge_from(&imported.project.all_languages);
|
||||||
|
assert_eq!(unchanged.edit_predictions, inherited.edit_predictions);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_import_file_exclusions() -> Result<()> {
|
fn test_import_file_exclusions() -> Result<()> {
|
||||||
let imported = VsCodeSettings::from_str(
|
let imported = VsCodeSettings::from_str(
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ use settings_macros::{MergeFrom, with_fallible_options};
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
DelayMs, DocumentFoldingRanges, DocumentSymbols, ExtendingSet, SemanticTokens, merge_from,
|
DelayMs, DocumentFoldingRanges, DocumentSymbols, ExtendingSet, SemanticTokens, SplicingVec,
|
||||||
|
merge_from,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The state of the modifier keys at some point in time
|
/// The state of the modifier keys at some point in time
|
||||||
@@ -132,10 +133,29 @@ impl EditPredictionProvider {
|
|||||||
pub struct EditPredictionSettingsContent {
|
pub struct EditPredictionSettingsContent {
|
||||||
/// Determines which edit prediction provider to use.
|
/// Determines which edit prediction provider to use.
|
||||||
pub provider: Option<EditPredictionProvider>,
|
pub provider: Option<EditPredictionProvider>,
|
||||||
/// A list of globs representing files that edit predictions should be disabled for.
|
/// Disable edit predictions for files matching these glob patterns.
|
||||||
/// This list adds to a pre-existing, sensible default set of globs.
|
///
|
||||||
/// Any additional ones you add are combined with them.
|
/// Use `"..."` to add patterns without repeating Zed's defaults. In project
|
||||||
pub disabled_globs: Option<Vec<String>>,
|
/// settings, it extends the user or parent configuration value. Omit
|
||||||
|
/// `"..."` to replace the inherited list.
|
||||||
|
///
|
||||||
|
/// ```json
|
||||||
|
/// {
|
||||||
|
/// "edit_predictions": {
|
||||||
|
/// "disabled_globs": ["**/build/**", "..."]
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Inherited patterns are inserted at `"..."`, and duplicates keep their first
|
||||||
|
/// occurrence.
|
||||||
|
///
|
||||||
|
/// Set `[]` to clear the inherited list. Omit this setting to inherit it unchanged.
|
||||||
|
///
|
||||||
|
/// Relative patterns are matched against paths relative to the worktree root.
|
||||||
|
/// Absolute patterns are matched against absolute paths. A leading `~` is
|
||||||
|
/// expanded to your home folder.
|
||||||
|
pub disabled_globs: Option<SplicingVec>,
|
||||||
/// The mode used to display edit predictions in the buffer.
|
/// The mode used to display edit predictions in the buffer.
|
||||||
/// Provider support required.
|
/// Provider support required.
|
||||||
pub mode: Option<EditPredictionsMode>,
|
pub mode: Option<EditPredictionsMode>,
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ pub struct WorktreeSettingsContent {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Use `"..."` to add patterns without repeating Zed’s defaults. In project
|
/// Use `"..."` to add patterns without repeating Zed's defaults. In project
|
||||||
/// settings, it extends the user or parent configuration value. Omit
|
/// settings, it extends the user or parent configuration value. Omit
|
||||||
/// `"..."` to replace the inherited list.
|
/// `"..."` to replace the inherited list.
|
||||||
///
|
///
|
||||||
@@ -177,7 +177,7 @@ pub struct WorktreeSettingsContent {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Use `"..."` to add patterns without repeating Zed’s defaults. In project
|
/// Use `"..."` to add patterns without repeating Zed's defaults. In project
|
||||||
/// settings, it extends the user or parent configuration value. Omit
|
/// settings, it extends the user or parent configuration value. Omit
|
||||||
/// `"..."` to replace the inherited list.
|
/// `"..."` to replace the inherited list.
|
||||||
///
|
///
|
||||||
@@ -224,7 +224,7 @@ pub struct WorktreeSettingsContent {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Use `"..."` to add patterns without repeating Zed’s defaults. In project
|
/// Use `"..."` to add patterns without repeating Zed's defaults. In project
|
||||||
/// settings, it extends the user or parent configuration value. Omit
|
/// settings, it extends the user or parent configuration value. Omit
|
||||||
/// `"..."` to replace the inherited list.
|
/// `"..."` to replace the inherited list.
|
||||||
///
|
///
|
||||||
@@ -253,7 +253,7 @@ pub struct WorktreeSettingsContent {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Use `"..."` to add patterns without repeating Zed’s defaults. In project
|
/// Use `"..."` to add patterns without repeating Zed's defaults. In project
|
||||||
/// settings, it extends the user or parent configuration value. Omit
|
/// settings, it extends the user or parent configuration value. Omit
|
||||||
/// `"..."` to replace the inherited list.
|
/// `"..."` to replace the inherited list.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ pub struct WorkspaceSettingsContent {
|
|||||||
///
|
///
|
||||||
/// Default: false
|
/// Default: false
|
||||||
pub close_on_file_delete: Option<bool>,
|
pub close_on_file_delete: Option<bool>,
|
||||||
/// Whether to allow windows to tab together based on the user’s tabbing preference (macOS only).
|
/// Whether to allow windows to tab together based on the user's tabbing preference (macOS only).
|
||||||
///
|
///
|
||||||
/// Default: false
|
/// Default: false
|
||||||
pub use_system_window_tabs: Option<bool>,
|
pub use_system_window_tabs: Option<bool>,
|
||||||
|
|||||||
@@ -71,6 +71,37 @@ pub fn update_value_in_json_text<'a>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "editing")]
|
||||||
|
pub fn find_value_range_in_json_text<T: AsRef<str>>(
|
||||||
|
text: &str,
|
||||||
|
key_path: &[T],
|
||||||
|
) -> Option<Range<usize>> {
|
||||||
|
let mut parser = tree_sitter::Parser::new();
|
||||||
|
parser
|
||||||
|
.set_language(&tree_sitter_json::LANGUAGE.into())
|
||||||
|
.ok()?;
|
||||||
|
let syntax_tree = parser.parse(text, None)?;
|
||||||
|
let mut node = syntax_tree.root_node();
|
||||||
|
if node.kind() == TS_DOCUMENT_KIND {
|
||||||
|
let mut cursor = node.walk();
|
||||||
|
node = node
|
||||||
|
.named_children(&mut cursor)
|
||||||
|
.find(|child| child.kind() != TS_COMMENT_KIND)?;
|
||||||
|
}
|
||||||
|
for key in key_path {
|
||||||
|
let key_json = serde_json::to_string(key.as_ref()).ok()?;
|
||||||
|
let mut cursor = node.walk();
|
||||||
|
let value = node.named_children(&mut cursor).find_map(|pair| {
|
||||||
|
let key_node = pair.child_by_field_name("key")?;
|
||||||
|
(text.get(key_node.byte_range()) == Some(key_json.as_str()))
|
||||||
|
.then(|| pair.child_by_field_name("value"))
|
||||||
|
.flatten()
|
||||||
|
})?;
|
||||||
|
node = value;
|
||||||
|
}
|
||||||
|
Some(node.byte_range())
|
||||||
|
}
|
||||||
|
|
||||||
/// * `replace_key` - When an exact key match according to `key_path` is found, replace the key with `replace_key` if `Some`.
|
/// * `replace_key` - When an exact key match according to `key_path` is found, replace the key with `replace_key` if `Some`.
|
||||||
#[cfg(feature = "editing")]
|
#[cfg(feature = "editing")]
|
||||||
pub fn replace_value_in_json_text<T: AsRef<str>>(
|
pub fn replace_value_in_json_text<T: AsRef<str>>(
|
||||||
@@ -2700,4 +2731,38 @@ mod tests {
|
|||||||
"#;
|
"#;
|
||||||
parse_json_with_comments::<Vec<Value>>(trailing).unwrap_err();
|
parse_json_with_comments::<Vec<Value>>(trailing).unwrap_err();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_find_value_range_in_json_text() {
|
||||||
|
let text = r#"// "edit_predictions": { "disabled_globs": ["commented/**"] },
|
||||||
|
{
|
||||||
|
// "disabled_globs": ["commented/**"],
|
||||||
|
"languages": { "edit_predictions": { "disabled_globs": ["nested/**"] } },
|
||||||
|
"edit_predictions": {
|
||||||
|
/* "disabled_globs": ["commented/**"], */
|
||||||
|
"mode": "subtle",
|
||||||
|
"disabled_globs": ["live/**", /* ] */ "..."], // ]
|
||||||
|
}
|
||||||
|
}"#;
|
||||||
|
let range = find_value_range_in_json_text(text, &["edit_predictions", "disabled_globs"])
|
||||||
|
.expect("value range");
|
||||||
|
assert_eq!(&text[range], r#"["live/**", /* ] */ "..."]"#);
|
||||||
|
assert_eq!(
|
||||||
|
find_value_range_in_json_text(text, &["edit_predictions", "missing"]),
|
||||||
|
None
|
||||||
|
);
|
||||||
|
assert_eq!(find_value_range_in_json_text(text, &["missing"]), None);
|
||||||
|
assert_eq!(
|
||||||
|
find_value_range_in_json_text("// only a comment", &["edit_predictions"]),
|
||||||
|
None
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
find_value_range_in_json_text("", &["edit_predictions"]),
|
||||||
|
None
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
find_value_range_in_json_text(r#"{"a": 1}"#, &["a", "b"]),
|
||||||
|
None
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -100,7 +100,7 @@ To configure panel sizing, open the Settings Editor and search for “Agent Pane
|
|||||||
|
|
||||||
### Flexible Sizing {#agent-panel-flexible-sizing}
|
### Flexible Sizing {#agent-panel-flexible-sizing}
|
||||||
|
|
||||||
- Description: Whether the agent panel uses flexible (proportional) sizing when docked to the left or right. When enabled, `agent.default_width` does not control the panel width, and double-clicking the panel’s outer resize handle restores the default proportion.
|
- Description: Whether the agent panel uses flexible (proportional) sizing when docked to the left or right. When enabled, `agent.default_width` does not control the panel width, and double-clicking the panel's outer resize handle restores the default proportion.
|
||||||
- Setting: `agent.flexible`
|
- Setting: `agent.flexible`
|
||||||
- Default: `true`
|
- Default: `true`
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ Open the Settings Editor and search for “Threads Sidebar Default Width”. Or
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If you haven’t manually resized the sidebar, its width follows changes to this setting immediately. A manually resized width takes precedence until you double-click the divider to reset it. After resetting, the sidebar follows this setting again.
|
If you haven't manually resized the sidebar, its width follows changes to this setting immediately. A manually resized width takes precedence until you double-click the divider to reset it. After resetting, the sidebar follows this setting again.
|
||||||
|
|
||||||
Widths saved by older versions of Zed are preserved if they differ from the previous default of 300 pixels. A saved width of 300 pixels uses this setting instead.
|
Widths saved by older versions of Zed are preserved if they differ from the previous default of 300 pixels. A saved width of 300 pixels uses this setting instead.
|
||||||
|
|
||||||
@@ -789,6 +789,7 @@ For the case of "open", regular selection behavior can be achieved by holding `a
|
|||||||
- Default:
|
- Default:
|
||||||
|
|
||||||
```json [settings]
|
```json [settings]
|
||||||
|
{
|
||||||
"edit_predictions": {
|
"edit_predictions": {
|
||||||
"disabled_globs": [
|
"disabled_globs": [
|
||||||
"**/.env*",
|
"**/.env*",
|
||||||
@@ -803,6 +804,7 @@ For the case of "open", regular selection behavior can be achieved by holding `a
|
|||||||
"/**/zed/keymap.json"
|
"/**/zed/keymap.json"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Options**
|
**Options**
|
||||||
@@ -847,7 +849,7 @@ For the case of "open", regular selection behavior can be achieved by holding `a
|
|||||||
|
|
||||||
### Disabled Globs
|
### Disabled Globs
|
||||||
|
|
||||||
- Description: A list of globs for which 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.
|
- Description: Disable edit predictions for files matching these glob patterns.
|
||||||
- Setting: `disabled_globs`
|
- Setting: `disabled_globs`
|
||||||
- Default: `["**/.env*", "**/*.pem", "**/*.key", "**/*.cert", "**/*.crt", "**/.dev.vars", "**/secrets.yml", "**/.zed/settings.json", "/**/zed/settings.json", "/**/zed/keymap.json"]`
|
- Default: `["**/.env*", "**/*.pem", "**/*.key", "**/*.cert", "**/*.crt", "**/.dev.vars", "**/secrets.yml", "**/.zed/settings.json", "/**/zed/settings.json", "/**/zed/keymap.json"]`
|
||||||
|
|
||||||
@@ -855,6 +857,22 @@ For the case of "open", regular selection behavior can be achieved by holding `a
|
|||||||
|
|
||||||
List of `string` values.
|
List of `string` values.
|
||||||
|
|
||||||
|
Use `"..."` to add patterns without repeating Zed's defaults. In project settings, it extends the user or parent configuration value. Omit `"..."` to replace the inherited list.
|
||||||
|
|
||||||
|
```json [settings]
|
||||||
|
{
|
||||||
|
"edit_predictions": {
|
||||||
|
"disabled_globs": ["**/build/**", "..."]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Inherited patterns are inserted at `"..."`, and duplicates keep their first occurrence.
|
||||||
|
|
||||||
|
Set `[]` to clear the inherited list. Omit this setting to inherit it unchanged.
|
||||||
|
|
||||||
|
Relative patterns are matched against paths relative to the worktree root. Absolute patterns are matched against absolute paths. A leading `~` is expanded to your home folder.
|
||||||
|
|
||||||
### Prediction Debounce
|
### Prediction Debounce
|
||||||
|
|
||||||
- Description: How long Zed waits after you stop typing before automatically requesting an edit prediction.
|
- Description: How long Zed waits after you stop typing before automatically requesting an edit prediction.
|
||||||
@@ -1878,13 +1896,13 @@ Each option controls displaying of a particular toolbar element. If all elements
|
|||||||
|
|
||||||
## Use System Tabs
|
## Use System Tabs
|
||||||
|
|
||||||
- Description: Whether to allow windows to tab together based on the user’s tabbing preference (macOS only).
|
- Description: Whether to allow windows to tab together based on the user's tabbing preference (macOS only).
|
||||||
- Setting: `use_system_window_tabs`
|
- Setting: `use_system_window_tabs`
|
||||||
- Default: `false`
|
- Default: `false`
|
||||||
|
|
||||||
**Options**
|
**Options**
|
||||||
|
|
||||||
This setting enables integration with macOS’s native window tabbing feature. When set to `true`, Zed windows can be grouped together as tabs in a single macOS window, following the system-wide tabbing preferences set by the user (such as "Always", "In Full Screen", or "Never"). This setting is only available on macOS.
|
This setting enables integration with macOS's native window tabbing feature. When set to `true`, Zed windows can be grouped together as tabs in a single macOS window, following the system-wide tabbing preferences set by the user (such as "Always", "In Full Screen", or "Never"). This setting is only available on macOS.
|
||||||
|
|
||||||
## Fullscreen Mode
|
## Fullscreen Mode
|
||||||
|
|
||||||
@@ -2353,7 +2371,7 @@ The result is still `)))` and not `))))))`, which is what it would be by default
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Use `"..."` to add patterns without repeating Zed’s defaults. In project settings, it extends the user or parent configuration value. Omit `"..."` to replace the inherited list.
|
Use `"..."` to add patterns without repeating Zed's defaults. In project settings, it extends the user or parent configuration value. Omit `"..."` to replace the inherited list.
|
||||||
|
|
||||||
```json [settings]
|
```json [settings]
|
||||||
{
|
{
|
||||||
@@ -2375,7 +2393,7 @@ Inherited patterns are inserted at `"..."`, and duplicates keep their first occu
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Use `"..."` to add patterns without repeating Zed’s defaults. In project settings, it extends the user or parent configuration value. Omit `"..."` to replace the inherited list.
|
Use `"..."` to add patterns without repeating Zed's defaults. In project settings, it extends the user or parent configuration value. Omit `"..."` to replace the inherited list.
|
||||||
|
|
||||||
```json [settings]
|
```json [settings]
|
||||||
{
|
{
|
||||||
@@ -2944,7 +2962,7 @@ Example:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Use `"..."` to add patterns without repeating Zed’s defaults. In project settings, it extends the user or parent configuration value. Omit `"..."` to replace the inherited list.
|
Use `"..."` to add patterns without repeating Zed's defaults. In project settings, it extends the user or parent configuration value. Omit `"..."` to replace the inherited list.
|
||||||
|
|
||||||
```json [settings]
|
```json [settings]
|
||||||
{
|
{
|
||||||
@@ -3908,7 +3926,7 @@ List of `string` glob patterns
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Use `"..."` to add patterns without repeating Zed’s defaults. In project settings, it extends the user or parent configuration value. Omit `"..."` to replace the inherited list.
|
Use `"..."` to add patterns without repeating Zed's defaults. In project settings, it extends the user or parent configuration value. Omit `"..."` to replace the inherited list.
|
||||||
|
|
||||||
```json [settings]
|
```json [settings]
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user