settings: Remove the `project_name` project setting (#54511)

Tom Houlé created

The `project_name` worktree setting was added in #36713 to let users
override the name shown in the window title. Its description ("The
displayed name of this project. If left empty, the root directory name
will be displayed.") suggests broader coverage, and #46440 reports the
reasonable expectation that it should also apply in the project
switcher. In practice the setting has only ever affected
`Workspace::update_window_title`, so everywhere else (recent projects,
the multi-worktree pane, ...) keeps falling back to the worktree root
name.

Rather than plumb the setting through each of those surfaces, I'm
removing it. Having a project-level setting control how your editor
displays the project has downsides. For example it means a checkout can
dictate UI in someone else's Zed. The natural home for a custom display
name is the workspace DB, set from the UI, which is what we should do if
we want this feature back.

If you want this back, the path forward is to store the display name in
`WorkspaceDb`, expose a UI affordance to edit it, and read it from
`update_window_title`, `recent_projects::get_recent_projects` /
`get_open_folders`, and any other places that currently derive a display
name from the worktree root.

Closes #46440

Release Notes:

- Removed the `project_name` project setting. It only ever affected the
OS window title, and the expectation that it would show up in the
project switcher and elsewhere is better served by a future UI-driven,
per-workspace setting stored locally.

Change summary

assets/settings/default.json                           |  3 -
crates/settings/src/vscode_import.rs                   |  1 
crates/settings_content/src/project.rs                 |  6 ---
crates/settings_ui/src/page_data.rs                    | 24 ------------
crates/workspace/src/workspace.rs                      | 12 -----
crates/worktree/src/worktree_settings.rs               |  2 -
crates/worktree/tests/integration/worktree_settings.rs |  1 
7 files changed, 1 insertion(+), 48 deletions(-)

Detailed changes

assets/settings/default.json 🔗

@@ -1,8 +1,5 @@
 {
   "$schema": "zed://schemas/settings",
-  /// The displayed name of this project. If not set or null, the root directory name
-  /// will be displayed.
-  "project_name": null,
   // The name of the Zed theme to use for the UI.
   //
   // `mode` is one of:

crates/settings/src/vscode_import.rs 🔗

@@ -1036,7 +1036,6 @@ impl VsCodeSettings {
 
     fn worktree_settings_content(&self) -> WorktreeSettingsContent {
         WorktreeSettingsContent {
-            project_name: None,
             prevent_sharing_in_public_channels: false,
             file_scan_exclusions: self
                 .read_value("files.watcherExclude")

crates/settings_content/src/project.rs 🔗

@@ -90,12 +90,6 @@ pub struct ProjectSettingsContent {
 #[with_fallible_options]
 #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
 pub struct WorktreeSettingsContent {
-    /// The displayed name of this project. If not set or null, the root directory name
-    /// will be displayed.
-    ///
-    /// Default: null
-    pub project_name: Option<String>,
-
     /// Whether to prevent this project from being shared in public channels.
     ///
     /// Default: false

crates/settings_ui/src/page_data.rs 🔗

@@ -108,30 +108,6 @@ fn general_page(cx: &App) -> SettingsPage {
     fn general_settings_section(_cx: &App) -> Vec<SettingsPageItem> {
         vec![
             SettingsPageItem::SectionHeader("General Settings"),
-            SettingsPageItem::SettingItem(SettingItem {
-                files: PROJECT,
-                title: "Project Name",
-                description: "The displayed name of this project. If left empty, the root directory name will be displayed.",
-                field: Box::new(SettingField {
-                    json_path: Some("project_name"),
-                    pick: |settings_content| {
-                        settings_content
-                            .project
-                            .worktree
-                            .project_name
-                            .as_ref()
-                            .or(DEFAULT_EMPTY_STRING)
-                    },
-                    write: |settings_content, value| {
-                        settings_content.project.worktree.project_name =
-                            value.filter(|name| !name.is_empty());
-                    },
-                }),
-                metadata: Some(Box::new(SettingsFieldMetadata {
-                    placeholder: Some("Project Name"),
-                    ..Default::default()
-                })),
-            }),
             SettingsPageItem::SettingItem(SettingItem {
                 title: "When Closing With No Tabs",
                 description: "What to do when using the 'close active item' action with no tabs.",

crates/workspace/src/workspace.rs 🔗

@@ -5812,18 +5812,8 @@ impl Workspace {
         let mut title = String::new();
 
         for (i, worktree) in project.visible_worktrees(cx).enumerate() {
-            let name = {
-                let settings_location = SettingsLocation {
-                    worktree_id: worktree.read(cx).id(),
-                    path: RelPath::empty(),
-                };
+            let name = worktree.read(cx).root_name_str();
 
-                let settings = WorktreeSettings::get(Some(settings_location), cx);
-                match &settings.project_name {
-                    Some(name) => name.as_str(),
-                    None => worktree.read(cx).root_name_str(),
-                }
-            };
             if i > 0 {
                 title.push_str(", ");
             }

crates/worktree/src/worktree_settings.rs 🔗

@@ -10,7 +10,6 @@ use util::{
 
 #[derive(Clone, PartialEq, Eq, RegisterSetting)]
 pub struct WorktreeSettings {
-    pub project_name: Option<String>,
     /// Whether to prevent this project from being shared in public channels.
     pub prevent_sharing_in_public_channels: bool,
     pub file_scan_exclusions: PathMatcher,
@@ -76,7 +75,6 @@ impl Settings for WorktreeSettings {
             .collect();
 
         Self {
-            project_name: worktree.project_name,
             prevent_sharing_in_public_channels: worktree.prevent_sharing_in_public_channels,
             file_scan_exclusions: path_matchers(file_scan_exclusions, "file_scan_exclusions")
                 .log_err()

crates/worktree/tests/integration/worktree_settings.rs 🔗

@@ -7,7 +7,6 @@ use worktree::*;
 
 fn make_settings_with_read_only(patterns: &[&str]) -> WorktreeSettings {
     WorktreeSettings {
-        project_name: None,
         prevent_sharing_in_public_channels: false,
         file_scan_exclusions: PathMatcher::default(),
         file_scan_inclusions: PathMatcher::default(),