Fix task list alignment: use char count not byte count, truncate title
- Use .chars().count() instead of .len() for accurate visual width - Truncate title with … when title + due_text exceeds available width - Compute padding from truncated title width for consistent alignment
This commit is contained in:
+27
-4
@@ -94,9 +94,34 @@ pub fn render_task_list(
|
||||
.map(relative_due_str)
|
||||
.unwrap_or((String::new(), Color::DarkGray));
|
||||
|
||||
let checkbox_str = format!("{} ", checkbox);
|
||||
let checkbox_width = checkbox_str.chars().count();
|
||||
let title_width = task.title.chars().count();
|
||||
let due_width = due_text.chars().count();
|
||||
|
||||
let max_title = content_width.saturating_sub(checkbox_width + due_width);
|
||||
|
||||
let display_title: String = if title_width <= max_title {
|
||||
task.title.to_string()
|
||||
} else if max_title >= 2 {
|
||||
let take = max_title - 1;
|
||||
let mut s: String = task.title.chars().take(take).collect();
|
||||
s.push('…');
|
||||
s
|
||||
} else {
|
||||
task.title.chars().take(max_title).collect()
|
||||
};
|
||||
|
||||
let pad = if due_text.is_empty() {
|
||||
0
|
||||
} else {
|
||||
let used = checkbox_width + display_title.chars().count() + due_width;
|
||||
content_width.saturating_sub(used)
|
||||
};
|
||||
|
||||
let mut spans = vec![
|
||||
Span::styled(
|
||||
format!("{} ", checkbox),
|
||||
checkbox_str,
|
||||
Style::default().fg(if task.status == TaskStatus::Completed {
|
||||
Color::Green
|
||||
} else {
|
||||
@@ -104,7 +129,7 @@ pub fn render_task_list(
|
||||
}),
|
||||
),
|
||||
Span::styled(
|
||||
&task.title,
|
||||
display_title,
|
||||
Style::default().fg(DETAIL_COLOR).add_modifier(
|
||||
if task.status == TaskStatus::Completed {
|
||||
Modifier::CROSSED_OUT
|
||||
@@ -116,8 +141,6 @@ pub fn render_task_list(
|
||||
];
|
||||
|
||||
if !due_text.is_empty() {
|
||||
let left_len: usize = spans.iter().map(|s| s.content.len()).sum();
|
||||
let pad = content_width.saturating_sub(left_len + due_text.len());
|
||||
spans.push(Span::raw(" ".repeat(pad)));
|
||||
spans.push(Span::styled(due_text, Style::default().fg(due_color)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user