@@ -399,18 +399,11 @@ impl WelcomePage {
location: &SerializedWorkspaceLocation,
paths: &PathList,
) -> impl IntoElement {
+ let name = project_name(paths);
+
let (icon, title) = match location {
- SerializedWorkspaceLocation::Local => {
- let path = paths.paths().first().map(|p| p.as_path());
- let name = path
- .and_then(|p| p.file_name())
- .map(|n| n.to_string_lossy().to_string())
- .unwrap_or_else(|| "Untitled".to_string());
- (IconName::Folder, name)
- }
- SerializedWorkspaceLocation::Remote(_) => {
- (IconName::Server, "Remote Project".to_string())
- }
+ SerializedWorkspaceLocation::Local => (IconName::Folder, name),
+ SerializedWorkspaceLocation::Remote(_) => (IconName::Server, name),
};
SectionButton::new(
@@ -661,3 +654,48 @@ mod persistence {
}
}
}
+
+fn project_name(paths: &PathList) -> String {
+ let joined = paths
+ .paths()
+ .iter()
+ .filter_map(|p| p.file_name().map(|n| n.to_string_lossy().to_string()))
+ .collect::<Vec<_>>()
+ .join(", ");
+ if joined.is_empty() {
+ "Untitled".to_string()
+ } else {
+ joined
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_project_name_empty() {
+ let paths = PathList::new::<&str>(&[]);
+ assert_eq!(project_name(&paths), "Untitled");
+ }
+
+ #[test]
+ fn test_project_name_single() {
+ let paths = PathList::new(&["/home/user/my-project"]);
+ assert_eq!(project_name(&paths), "my-project");
+ }
+
+ #[test]
+ fn test_project_name_multiple() {
+ // PathList sorts lexicographically, so filenames appear in alpha order
+ let paths = PathList::new(&["/home/user/zed", "/home/user/api"]);
+ assert_eq!(project_name(&paths), "api, zed");
+ }
+
+ #[test]
+ fn test_project_name_root_path_filtered() {
+ // A bare root "/" has no file_name(), falls back to "Untitled"
+ let paths = PathList::new(&["/"]);
+ assert_eq!(project_name(&paths), "Untitled");
+ }
+}