diff --git a/plugin-dev-workspace.kdl b/plugin-dev-workspace.kdl index 318cd6f..95efd79 100644 --- a/plugin-dev-workspace.kdl +++ b/plugin-dev-workspace.kdl @@ -40,8 +40,8 @@ layout { tab_sync_indicator "S" tab_fullscreen_indicator "FS" tab_display_count "3" - tab_truncate_start_format "#[fg=red,bg=#181825] < ..." - tab_truncate_end_format "#[fg=red,bg=#181825] ...>" + tab_truncate_start_format "#[fg=red,bg=#181825] < +{count} ..." + tab_truncate_end_format "#[fg=red,bg=#181825] ... +{count} >" command_0_command "echo \"平仮名, ひらがな 📦\"" command_0_clickaction "bash -c \"zellij --session zjstatus-dev pipe 'zjstatus::notify::hello world!' -n zjstatus\"" diff --git a/src/widgets/tabs.rs b/src/widgets/tabs.rs index a5bb45a..0ffbb6b 100644 --- a/src/widgets/tabs.rs +++ b/src/widgets/tabs.rs @@ -110,9 +110,15 @@ impl Widget for TabsWidget { let (truncated_start, truncated_end, tabs) = get_tab_window(&state.tabs, self.tab_display_count); - if truncated_start { + if truncated_start > 0 { if let Some(f) = &self.tab_truncate_start_format { - output = format!("{}{output}", f.format_string(&f.content)); + let mut content = f.content.clone(); + + if content.contains("{count}") { + content = content.replace("{count}", (truncated_start).to_string().as_str()); + } + + output = format!("{}{output}", f.format_string(&content)); } } @@ -129,9 +135,15 @@ impl Widget for TabsWidget { } } - if truncated_end { + if truncated_end > 0 { if let Some(f) = &self.tab_truncate_end_format { - output = format!("{output}{}", f.format_string(&f.content)); + let mut content = f.content.clone(); + + if content.contains("{count}") { + content = content.replace("{count}", (truncated_end).to_string().as_str()); + } + + output = format!("{output}{}", f.format_string(&content)); } } @@ -153,9 +165,15 @@ impl Widget for TabsWidget { .position + 1; - if truncated_start { + if truncated_start > 0 { if let Some(f) = &self.tab_truncate_start_format { - offset = console::measure_text_width(&f.format_string(&f.content)); + let mut content = f.content.clone(); + + if content.contains("{count}") { + content = content.replace("{count}", (truncated_end).to_string().as_str()); + } + + offset = console::measure_text_width(&f.format_string(&content)); if pos <= offset { switch_tab_to(active_pos.saturating_sub(1) as u32); @@ -186,9 +204,15 @@ impl Widget for TabsWidget { offset += content_len; } - if truncated_end { + if truncated_end > 0 { if let Some(f) = &self.tab_truncate_end_format { - offset += console::measure_text_width(&f.format_string(&f.content)); + let mut content = f.content.clone(); + + if content.contains("{count}") { + content = content.replace("{count}", (truncated_end).to_string().as_str()); + } + + offset += console::measure_text_width(&f.format_string(&content)); if pos <= offset { switch_tab_to(cmp::min(active_pos + 1, state.tabs.len()) as u32); @@ -312,14 +336,17 @@ impl TabsWidget { } } -pub fn get_tab_window(tabs: &Vec, max_count: Option) -> (bool, bool, Vec) { +pub fn get_tab_window( + tabs: &Vec, + max_count: Option, +) -> (usize, usize, Vec) { let max_count = match max_count { Some(count) => count, - None => return (false, false, tabs.to_vec()), + None => return (0, 0, tabs.to_vec()), }; if tabs.len() <= max_count { - return (false, false, tabs.to_vec()); + return (0, 0, tabs.to_vec()); } let active_index = tabs.iter().position(|t| t.active).expect("no active tab"); @@ -327,8 +354,8 @@ pub fn get_tab_window(tabs: &Vec, max_count: Option) -> (bool, b // active tab is in the last #max_count tabs, so return the last #max_count if active_index > tabs.len().saturating_sub(max_count) { return ( - true, - false, + tabs.len().saturating_sub(max_count), + 0, tabs.iter() .cloned() .rev() @@ -342,12 +369,9 @@ pub fn get_tab_window(tabs: &Vec, max_count: Option) -> (bool, b let first_index = active_index.saturating_sub(1); let last_index = cmp::min(first_index + max_count, tabs.len()); - let truncated_start = first_index > 0; - let truncated_end = last_index < tabs.len(); - return ( - truncated_start, - truncated_end, + first_index, + tabs.len().saturating_sub(last_index), tabs.as_slice()[first_index..last_index].to_vec(), ); } @@ -389,7 +413,7 @@ mod test { }, ], Some(3), - (true, true, vec![ + (1, 1, vec![ TabInfo { active: false, name: "2".to_owned(), @@ -437,7 +461,7 @@ mod test { }, ], Some(3), - (false, true, vec![ + (0, 2, vec![ TabInfo { active: true, name: "1".to_owned(), @@ -485,7 +509,7 @@ mod test { }, ], Some(3), - (false, true, vec![ + (0, 2, vec![ TabInfo { active: false, name: "1".to_owned(), @@ -533,7 +557,7 @@ mod test { }, ], Some(3), - (true, false, vec![ + (2, 0, vec![ TabInfo { active: false, name: "3".to_owned(), @@ -581,7 +605,7 @@ mod test { }, ], Some(3), - (true, false, vec![ + (2, 0, vec![ TabInfo { active: false, name: "3".to_owned(), @@ -629,7 +653,7 @@ mod test { }, ], None, - (false, false, vec![ + (0, 0, vec![ TabInfo { active: false, name: "1".to_owned(), @@ -672,7 +696,7 @@ mod test { }, ], Some(3), - (false, false, vec![ + (0, 0, vec![ TabInfo { active: false, name: "1".to_owned(), @@ -705,7 +729,7 @@ mod test { }, ], Some(3), - (false, false, vec![ + (0, 0, vec![ TabInfo { active: false, name: "1".to_owned(), @@ -727,7 +751,7 @@ mod test { pub fn test_get_tab_window( #[case] tabs: Vec, #[case] max_count: Option, - #[case] expected: (bool, bool, Vec), + #[case] expected: (usize, usize, Vec), ) { let res = get_tab_window(&tabs, max_count);