nu-explore: Try to fix a truncation issue in expand view (#10580)

I haven't tested cause can't reproduce, but the issue very likely was
related to a emojies. (I mean I probably could but ....)

Could you try it @fdncred?
 
fix #10560
This commit is contained in:
Maxim Zhiburt 2023-10-07 11:58:26 +00:00 committed by GitHub
parent d51e82f33b
commit eb4fd144eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 446 additions and 417 deletions

813
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -25,4 +25,5 @@ strip-ansi-escapes = "0.2.0"
crossterm = "0.27" crossterm = "0.27"
ratatui = "0.23" ratatui = "0.23"
ansi-str = "0.8" ansi-str = "0.8"
unicode-width = "0.1"
lscolors = { version = "0.15", default-features = false, features = ["nu-ansi-term"] } lscolors = { version = "0.15", default-features = false, features = ["nu-ansi-term"] }

View File

@ -1,6 +1,7 @@
use std::borrow::Cow; use std::borrow::Cow;
use ansi_str::{get_blocks, AnsiStr}; use ansi_str::{get_blocks, AnsiStr};
use nu_table::{string_truncate, string_width};
use ratatui::{ use ratatui::{
layout::Rect, layout::Rect,
style::{Color, Modifier, Style}, style::{Color, Modifier, Style},
@ -18,14 +19,15 @@ impl<'a> ColoredTextW<'a> {
} }
pub fn what(&self, area: Rect) -> String { pub fn what(&self, area: Rect) -> String {
let text = cut_string(self.text, area, self.col); cut_string(self.text, self.col, area.width as usize)
text.ansi_strip().into_owned() .ansi_strip()
.into_owned()
} }
} }
impl Widget for ColoredTextW<'_> { impl Widget for ColoredTextW<'_> {
fn render(self, area: Rect, buf: &mut ratatui::buffer::Buffer) { fn render(self, area: Rect, buf: &mut ratatui::buffer::Buffer) {
let text = cut_string(self.text, area, self.col); let text = cut_string(self.text, self.col, area.width as usize);
let mut offset = 0; let mut offset = 0;
for block in get_blocks(&text) { for block in get_blocks(&text) {
@ -40,30 +42,39 @@ impl Widget for ColoredTextW<'_> {
} }
} }
fn cut_string(text: &str, area: Rect, skip: usize) -> Cow<'_, str> { fn cut_string(source: &str, skip: usize, width: usize) -> Cow<'_, str> {
let mut text = Cow::Borrowed(text); if source.is_empty() {
return Cow::Borrowed(source);
}
let mut text = Cow::Borrowed(source);
if skip > 0 { if skip > 0 {
let n = text let skip_chars = source
.ansi_strip() .ansi_strip()
.chars() .chars()
.map(|c| c.len_utf8()) .scan((0usize, 0usize), |acc, c| {
.take(skip) acc.0 += unicode_width::UnicodeWidthChar::width(c).unwrap_or(0);
if acc.0 > skip {
return None;
}
acc.1 = c.len_utf8();
Some(*acc)
})
.map(|(_, b)| b)
.sum::<usize>(); .sum::<usize>();
let s = text.ansi_get(n..).expect("must be OK").into_owned(); let cut_text = source
text = Cow::Owned(s); .ansi_get(skip_chars..)
.expect("must be OK")
.into_owned();
text = Cow::Owned(cut_text);
} }
if !text.is_empty() && text.len() > area.width as usize {
let n = text
.ansi_strip()
.chars()
.map(|c| c.len_utf8())
.take(area.width as usize)
.sum::<usize>();
let s = text.ansi_get(..n).expect("must be ok").into_owned(); if string_width(&text) > width {
text = Cow::Owned(s); text = Cow::Owned(string_truncate(&text, width));
} }
text text