cargo-port 0.2.0

A TUI for inspecting and managing Rust projects
use unicode_width::UnicodeWidthChar;

pub(super) fn word_wrap(text: &str, max_width: usize) -> Vec<String> {
    if max_width == 0 {
        return vec![String::new()];
    }
    let mut lines = Vec::new();
    let mut current = String::new();
    let mut current_width = 0;
    for word in text.split_whitespace() {
        let word_width = word.chars().map(|c| c.width().unwrap_or(0)).sum::<usize>();
        if current_width > 0 && current_width + 1 + word_width > max_width {
            lines.push(current);
            current = String::new();
            current_width = 0;
        }
        if current_width > 0 {
            current.push(' ');
            current_width += 1;
        }
        if word_width > max_width {
            let wrapped = hard_wrap(word, max_width);
            for (i, part) in wrapped.into_iter().enumerate() {
                if i == 0 {
                    current.push_str(&part);
                    current_width += part.chars().map(|c| c.width().unwrap_or(0)).sum::<usize>();
                } else {
                    lines.push(current);
                    current = part;
                    current_width = current.chars().map(|c| c.width().unwrap_or(0)).sum();
                }
            }
        } else {
            current.push_str(word);
            current_width += word_width;
        }
    }
    if !current.is_empty() {
        lines.push(current);
    }
    if lines.is_empty() {
        lines.push(String::new());
    }
    lines
}

pub(super) fn hard_wrap(text: &str, max_width: usize) -> Vec<String> {
    if max_width == 0 {
        return vec![String::new()];
    }
    let mut lines = Vec::new();
    let mut current = String::new();
    let mut current_width = 0;
    for ch in text.chars() {
        let width = ch.width().unwrap_or(0);
        if current_width > 0 && current_width + width > max_width {
            lines.push(current);
            current = String::new();
            current_width = 0;
        }
        current.push(ch);
        current_width += width;
    }
    if !current.is_empty() {
        lines.push(current);
    }
    if lines.is_empty() {
        lines.push(String::new());
    }
    lines
}