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
This commit is contained in:
Chris Biscardi 2026-06-29 00:57:58 -07:00 committed by GitHub
parent 480796c168
commit 76e07d5c9a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 19 additions and 5 deletions

View file

@ -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", "..."],
},
},

View file

@ -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),
));

View file

@ -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,