From 76e07d5c9ac38930d051c153b21eeb57ba71cbb4 Mon Sep 17 00:00:00 2001 From: Chris Biscardi Date: Mon, 29 Jun 2026 00:57:58 -0700 Subject: [PATCH] Disable format-on-save by default (#59710) # Objective Prevent the unexpected modification of files which do not have established formatting conventions. Enabling format-on-save by default can cause changes in ecosystems that don't have established official formatting conventions, or when the formatting conventions came later through new tools (like JavaScript). fixes #59427 ## Solution This PR inverts the default, choosing to disable format-on-save by default, and allowing it to be enabled by users at a global or language level for any language which has an official formatter. However, any ecosystem which has an official formatter has been left enabled. This means languages like Rust, Go, and Zig have `format_on_save` enabled because they come with official formatting tools, while JavaScript, C/C++, and Markdown have it disabled by default. For existing users, this means their custom configurations will stay, but any values that were previously "default" will be updated. ## Testing - open a file for the language being tested (ex: `python`) - formatting should only be enabled if the default for the *language* is enabled - formatting can be enabled or disabled at the language level or the global level in the settings ## 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: - Disable format-on-save by default, except for languages with official formatters --- assets/settings/default.json | 18 +++++++++++++----- .../remote_editing_collaboration_tests.rs | 4 ++++ crates/settings/src/settings_file.rs | 2 ++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/assets/settings/default.json b/assets/settings/default.json index 8637d3d1b23..e4051ee8f02 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -1463,7 +1463,7 @@ "line_ending": "detect", // Whether or not to perform a buffer format before saving: [on, off] // Keep in mind, if the autosave with delay is enabled, format_on_save will be ignored - "format_on_save": "on", + "format_on_save": "off", // How to perform a buffer format. This setting can take multiple values: // // 1. Default. Format files using Zed's Prettier integration (if applicable), @@ -2170,6 +2170,7 @@ // Different settings for specific languages. "languages": { "Astro": { + "format_on_save": "on", "language_servers": ["astro-language-server", "..."], "prettier": { "allowed": true, @@ -2182,14 +2183,12 @@ }, }, "C": { - "format_on_save": "off", "use_on_type_format": false, "prettier": { "allowed": false, }, }, "C++": { - "format_on_save": "off", "use_on_type_format": false, "prettier": { "allowed": false, @@ -2204,6 +2203,7 @@ }, }, "Dart": { + "format_on_save": "on", "tab_size": 2, }, "Diff": { @@ -2212,12 +2212,15 @@ "ensure_final_newline_on_save": false, }, "EEx": { + "format_on_save": "on", "language_servers": ["elixir-ls", "!expert", "!dexter", "!next-ls", "!lexical", "..."], }, "Elixir": { + "format_on_save": "on", "language_servers": ["elixir-ls", "!expert", "!dexter", "!next-ls", "!lexical", "!emmet-language-server", "..."], }, "Elm": { + "format_on_save": "on", "tab_size": 4, }, "Erlang": { @@ -2229,6 +2232,7 @@ "preferred_line_length": 72, }, "Go": { + "format_on_save": "on", "hard_tabs": true, "code_actions_on_format": { "source.organizeImports": true, @@ -2236,11 +2240,13 @@ "debuggers": ["Delve"], }, "GraphQL": { + "format_on_save": "on", "prettier": { "allowed": true, }, }, "HEEx": { + "format_on_save": "on", "language_servers": ["elixir-ls", "!expert", "!dexter", "!next-ls", "!lexical", "..."], }, "HTML": { @@ -2277,6 +2283,7 @@ "language_servers": ["!ruby-lsp", "..."], }, "Kotlin": { + "format_on_save": "on", "language_servers": ["!kotlin-language-server", "kotlin-lsp", "..."], }, "LaTeX": { @@ -2288,7 +2295,6 @@ }, }, "Markdown": { - "format_on_save": "off", "use_on_type_format": false, "remove_trailing_whitespace_on_save": false, "allow_rewrap": "anywhere", @@ -2343,6 +2349,7 @@ ], }, "Rust": { + "format_on_save": "on", "debuggers": ["CodeLLDB"], }, "SCSS": { @@ -2351,6 +2358,7 @@ }, }, "Starlark": { + "format_on_save": "on", "language_servers": ["starpls", "!buck2-lsp", "!tilt", "..."], }, "Svelte": { @@ -2378,7 +2386,6 @@ }, }, "SystemVerilog": { - "format_on_save": "off", "language_servers": ["!slang", "..."], "use_on_type_format": false, }, @@ -2403,6 +2410,7 @@ "language_servers": ["!ruby-lsp", "..."], }, "Zig": { + "format_on_save": "on", "language_servers": ["zls", "..."], }, }, diff --git a/crates/collab/tests/integration/remote_editing_collaboration_tests.rs b/crates/collab/tests/integration/remote_editing_collaboration_tests.rs index 87784b63281..d5552c5f11d 100644 --- a/crates/collab/tests/integration/remote_editing_collaboration_tests.rs +++ b/crates/collab/tests/integration/remote_editing_collaboration_tests.rs @@ -752,6 +752,8 @@ async fn test_ssh_collaboration_formatting_with_prettier( cx_a.update(|cx| { SettingsStore::update_global(cx, |store, cx| { store.update_user_settings(cx, |file| { + file.project.all_languages.defaults.format_on_save = + Some(settings::FormatOnSave::On); file.project.all_languages.defaults.formatter = Some(FormatterList::default()); file.project.all_languages.defaults.prettier = Some(PrettierSettingsContent { allowed: Some(true), @@ -763,6 +765,8 @@ async fn test_ssh_collaboration_formatting_with_prettier( cx_b.update(|cx| { SettingsStore::update_global(cx, |store, cx| { store.update_user_settings(cx, |file| { + file.project.all_languages.defaults.format_on_save = + Some(settings::FormatOnSave::On); file.project.all_languages.defaults.formatter = Some(FormatterList::Single( Formatter::LanguageServer(LanguageServerFormatterSpecifier::Current), )); diff --git a/crates/settings/src/settings_file.rs b/crates/settings/src/settings_file.rs index 2ac94c99318..f1c190cb9c3 100644 --- a/crates/settings/src/settings_file.rs +++ b/crates/settings/src/settings_file.rs @@ -133,6 +133,7 @@ pub fn test_settings() -> &'static str { #[cfg(not(target_os = "windows"))] util::merge_non_null_json_value_into( serde_json::json!({ + "format_on_save": "on", "ui_font_family": "Courier", "ui_font_features": {}, "ui_font_size": 14, @@ -148,6 +149,7 @@ pub fn test_settings() -> &'static str { #[cfg(target_os = "windows")] util::merge_non_null_json_value_into( serde_json::json!({ + "format_on_save": "on", "ui_font_family": "Courier New", "ui_font_features": {}, "ui_font_size": 14,