Coalesce consecutive spaces in new buffer tab titles (#32363)

VS Code has a behavior where it coalesces consecutive spaces in new
buffer tab titles, which I quite like. This presents the content better
and allows more meaningful content to be displayed, as consecutive
spaces don't count towards the 40 character limit.

VS Code

<img width="1013" alt="SCR-20250608-uelt"
src="https://github.com/user-attachments/assets/71a1fd4b-a506-4eab-b6a4-66096a12f1ad"
/>

Zed

<img width="1136" alt="SCR-20250608-ueif"
src="https://github.com/user-attachments/assets/f40fc3c9-0f0f-471d-93ed-be9568fbe778"
/>


Release Notes:

- N/A
This commit is contained in:
Joseph T. Lyons 2025-06-09 02:01:32 -04:00 committed by GitHub
parent 4fe05530b0
commit ebea734515
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 63 additions and 22 deletions

View file

@ -2600,27 +2600,58 @@ impl MultiBuffer {
return title.into();
}
self.as_singleton()
.and_then(|buffer| {
let buffer = buffer.read(cx);
if let Some(buffer) = self.as_singleton() {
let buffer = buffer.read(cx);
if let Some(file) = buffer.file() {
return Some(file.file_name(cx).to_string_lossy());
if let Some(file) = buffer.file() {
return file.file_name(cx).to_string_lossy();
}
if let Some(title) = self.buffer_based_title(buffer) {
return title;
}
};
"untitled".into()
}
fn buffer_based_title(&self, buffer: &Buffer) -> Option<Cow<str>> {
let mut is_leading_whitespace = true;
let mut count = 0;
let mut prev_was_space = false;
let mut title = String::new();
for ch in buffer.snapshot().chars() {
if is_leading_whitespace && ch.is_whitespace() {
continue;
}
is_leading_whitespace = false;
if ch == '\n' || count >= 40 {
break;
}
if ch.is_whitespace() {
if !prev_was_space {
title.push(' ');
count += 1;
prev_was_space = true;
}
} else {
title.push(ch);
count += 1;
prev_was_space = false;
}
}
let title = buffer
.snapshot()
.chars()
.skip_while(|ch| ch.is_whitespace())
.take_while(|&ch| ch != '\n')
.take(40)
.collect::<String>()
.trim_end()
.to_string();
let title = title.trim_end().to_string();
(!title.is_empty()).then(|| title.into())
})
.unwrap_or("untitled".into())
if !title.is_empty() {
return Some(title.into());
}
None
}
pub fn set_title(&mut self, title: String, cx: &mut Context<Self>) {

View file

@ -3686,10 +3686,20 @@ fn test_new_empty_buffer_takes_trimmed_first_line_for_title(cx: &mut App) {
#[gpui::test]
fn test_new_empty_buffer_uses_truncated_first_line_for_title(cx: &mut App) {
let title_after = ["a", "b", "c", "d"]
.map(|letter| letter.repeat(10))
.join("");
let title = format!("{}{}", title_after, "e".repeat(10));
let title = "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeee";
let title_after = "aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd";
let buffer = cx.new(|cx| Buffer::local(title, cx));
let multibuffer = cx.new(|cx| MultiBuffer::singleton(buffer.clone(), cx));
assert_eq!(multibuffer.read(cx).title(cx), title_after);
}
#[gpui::test]
fn test_new_empty_buffer_uses_truncated_first_line_for_title_after_merging_adjacent_spaces(
cx: &mut App,
) {
let title = "aaaaaaaaaabbbbbbbbbb ccccccccccddddddddddeeeeeeeeee";
let title_after = "aaaaaaaaaabbbbbbbbbb ccccccccccddddddddd";
let buffer = cx.new(|cx| Buffer::local(title, cx));
let multibuffer = cx.new(|cx| MultiBuffer::singleton(buffer.clone(), cx));