uv-errors 0.0.61

Common error traits for uv.
Documentation
use uv_static::EnvVars;

/// Checks if line wrapping should be enabled.
///
/// Returns `false` if `UV_NO_WRAP` is set.
fn should_wrap_lines() -> bool {
    std::env::var_os(EnvVars::UV_NO_WRAP).is_none()
}

/// Gets the terminal width for wrapping.
///
/// Uses `width_override`, then the `COLUMNS` environment variable, and finally attempts to detect
/// the width from the terminal. Returns `None` if no width is available.
pub(crate) fn get_wrap_width(width_override: Option<usize>) -> Option<usize> {
    if !should_wrap_lines() {
        return None;
    }

    if let Some(width) = width_override {
        return Some(width);
    }

    if let Ok(cols) = std::env::var(EnvVars::COLUMNS) {
        if let Ok(width) = cols.parse::<usize>() {
            return Some(width);
        }
    }

    if let Some((terminal_size::Width(width), _)) = terminal_size::terminal_size() {
        return Some(width as usize);
    }

    None
}

/// Wraps text at word boundaries with proper indentation.
///
/// Based on miette's `wrap()` implementation from:
/// <https://github.com/zkat/miette/blob/v7.2.0/src/handlers/graphical.rs#L876-L909>
pub(crate) fn wrap_text(
    text: &str,
    width: Option<usize>,
    initial_indent: &str,
    subsequent_indent: &str,
    authored_line_indent: &str,
) -> String {
    let options = width.map(|width| {
        textwrap::Options::new(width)
            .initial_indent(initial_indent)
            .subsequent_indent(subsequent_indent)
            .break_words(false)
            .word_separator(textwrap::WordSeparator::AsciiSpace)
            .word_splitter(textwrap::WordSplitter::NoHyphenation)
    });

    let mut wrapped = String::with_capacity(text.len());

    for (index, line) in text.split_terminator('\n').enumerate() {
        if index > 0 {
            wrapped.push('\n');
        }

        if line.is_empty() {
            continue;
        }

        let line_indent = if index == 0 {
            initial_indent
        } else {
            authored_line_indent
        };
        if let Some(options) = &options {
            // Preserve authored line breaks and wrap each line independently. A caller may
            // separately indent authored lines to keep nested diagnostic content aligned.
            wrapped.push_str(&textwrap::fill(
                line,
                options.clone().initial_indent(line_indent),
            ));
        } else {
            wrapped.push_str(line_indent);
            wrapped.push_str(line);
        }
    }

    wrapped
}