From 05433c38d069d9ce834d39e99b9afa67715cddf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E9=9B=85=20=C2=B7=20Misaki=20Masa?= Date: Tue, 15 Aug 2023 07:32:15 +0800 Subject: [PATCH] fix: tab name width calculating (#58) --- app/src/header/tabs.rs | 40 +++++++++++++++++++++++----------------- core/src/manager/tab.rs | 20 +++++++++++--------- 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/app/src/header/tabs.rs b/app/src/header/tabs.rs index 414eef59..eeadcd4e 100644 --- a/app/src/header/tabs.rs +++ b/app/src/header/tabs.rs @@ -2,7 +2,7 @@ use std::ops::ControlFlow; use config::THEME; use ratatui::{buffer::Buffer, layout::{Alignment, Rect}, text::{Line, Span}, widgets::{Paragraph, Widget}}; -use unicode_width::UnicodeWidthStr; +use unicode_width::{UnicodeWidthChar, UnicodeWidthStr}; use crate::Ctx; @@ -12,6 +12,25 @@ pub(super) struct Tabs<'a> { impl<'a> Tabs<'a> { pub(super) fn new(cx: &'a Ctx) -> Self { Self { cx } } + + fn truncate(&self, name: &str) -> String { + let mut width = 0; + let flow = + name.chars().try_fold(String::with_capacity(THEME.tab.max_width as usize), |mut s, c| { + width += c.width().unwrap_or(0); + if s.width() < THEME.tab.max_width as usize { + s.push(c); + ControlFlow::Continue(s) + } else { + ControlFlow::Break(s) + } + }); + + match flow { + ControlFlow::Break(s) => s, + ControlFlow::Continue(s) => s, + } + } } impl<'a> Widget for Tabs<'a> { @@ -24,25 +43,12 @@ impl<'a> Widget for Tabs<'a> { .enumerate() .map(|(i, tab)| { let mut text = format!("{}", i + 1); - if let Some(dir_name) = tab.current_name() { + if THEME.tab.max_width >= 3 { text.push(' '); - text.push_str(dir_name); + text.push_str(tab.name()); + text = self.truncate(&text); } - let threshold = THEME.tab.max_width.max(1); - let truncated = text.chars().try_fold(String::with_capacity(threshold), |mut text, c| { - if text.width() > threshold { - ControlFlow::Break(text) - } else { - text.push(c); - ControlFlow::Continue(text) - } - }); - let text = match truncated { - ControlFlow::Break(text) => text, - ControlFlow::Continue(text) => text, - }; - if i == tabs.idx() { Span::styled(format!(" {text} "), THEME.tab.active.get()) } else { diff --git a/core/src/manager/tab.rs b/core/src/manager/tab.rs index c45c337e..98038b4f 100644 --- a/core/src/manager/tab.rs +++ b/core/src/manager/tab.rs @@ -264,21 +264,23 @@ impl Tab { }; true } - - pub fn current_name(&self) -> Option<&str> { - self - .current - .cwd - .file_name() - .and_then(|name| name.to_str()) - .or_else(|| self.current.cwd.to_str()) - } } impl Tab { #[inline] pub fn mode(&self) -> &Mode { &self.mode } + #[inline] + pub fn name(&self) -> &str { + self + .current + .cwd + .file_name() + .and_then(|n| n.to_str()) + .or_else(|| self.current.cwd.to_str()) + .unwrap_or_default() + } + #[inline] pub fn history(&self, path: &Path) -> Option<&Folder> { self.history.get(path) }