pub fn format_error_with_excerpt(
    message: Option<&str>,
    source_path: &Option<PathBuf>,
    source: &str,
    start_pos: Position,
    end_pos: Position,
) -> String {
    let (excerpt, padding) = {
        let excerpt_lines = source
            .lines()
            .skip((start_pos.line - 1) as usize)
            .take((end_pos.line - start_pos.line + 1) as usize)
            .collect::<Vec<_>>();

        let line_numbers = (start_pos.line..=end_pos.line)
            .map(|n| n.to_string())
            .collect::<Vec<_>>();

        let number_width = line_numbers.iter().max_by_key(|n| n.len()).unwrap().len();

        let padding = " ".repeat(number_width + 2);

        if start_pos.line == end_pos.line {
            let mut excerpt = format!(
                " {:>width$} | {}\n",
                line_numbers.first().unwrap(),
                excerpt_lines.first().unwrap(),
                width = number_width
            );

            excerpt += &format!(
                "{}|{}{}",
                padding,
                " ".repeat(start_pos.column as usize),
                "^".repeat((end_pos.column - start_pos.column) as usize)
            );

            (excerpt, padding)
        } else {
            let mut excerpt = String::new();

            for (excerpt_line, line_number) in excerpt_lines.iter().zip(line_numbers.iter()) {
                excerpt += &format!(
                    " {:>width$} | {}\n",
                    line_number,
                    excerpt_line,
                    width = number_width
                );
            }

            (excerpt, padding)
        }
    };

    let position_info = if let Some(path) = source_path {
        let display_path = if let Ok(current_dir) = std::env::current_dir() {
            if let Ok(stripped) = path.strip_prefix(current_dir) {
                stripped.display()
            } else {
                path.display()
            }
        } else {
            path.display()
        };

        format!("{} - {}:{}", display_path, start_pos.line, start_pos.column)
    } else {
        format!("{}:{}", start_pos.line, start_pos.column)
    };

    format!(
        "{message}\n --- {position_info}\n{padding}|\n{excerpt}",
        message = message.unwrap_or(""),
        position_info = position_info,
        padding = padding,
        excerpt = excerpt,
    )
}
/// Produces a formatted error string with a corresponding source excerpt
Produces a formatted error string with a corresponding source excerpt
Produces a formatted error string with a corresponding source excerpt
pub fn format_error_with_excerpt(
    message: Option<&str>,
    source_path: &Option<PathBuf>,
    source: &str,
    start_pos: Position,
    end_pos: Position,
) -> String {
    let (excerpt, padding) = {
        let excerpt_lines = source
            .lines()
            .skip((start_pos.line - 1) as usize)
            .take((end_pos.line - start_pos.line + 1) as usize)
            .collect::<Vec<_>>();
        let line_numbers = (start_pos.line..=end_pos.line)
            .map(|n| n.to_string())
            .collect::<Vec<_>>();
        let number_width = line_numbers.iter().max_by_key(|n| n.len()).unwrap().len();
        let padding = " ".repeat(number_width + 2);
        if start_pos.line == end_pos.line {
            let mut excerpt = format!(
                " {:>width$} | {}\n",
                line_numbers.first().unwrap(),
                excerpt_lines.first().unwrap(),
                width = number_width
            );
            excerpt += &format!(
                "{}|{}{}",
                padding,
                " ".repeat(start_pos.column as usize),
                "^".repeat((end_pos.column - start_pos.column) as usize)
            );
            (excerpt, padding)
        } else {
            let mut excerpt = String::new();
            for (excerpt_line, line_number) in excerpt_lines.iter().zip(line_numbers.iter()) {
                excerpt += &format!(
                    " {:>width$} | {}\n",
                    line_number,
                    excerpt_line,
                    width = number_width
                );
            }
            (excerpt, padding)
        }
    };
    let position_info = if let Some(path) = source_path {
        let display_path = if let Ok(current_dir) = std::env::current_dir() {
            if let Ok(stripped) = path.strip_prefix(current_dir) {
                stripped.display()
            } else {
                path.display()
            }
        } else {
            path.display()
        };
        format!("{} - {}:{}", display_path, start_pos.line, start_pos.column)
    } else {
        format!("{}:{}", start_pos.line, start_pos.column)
    };
    format!(
        "{message}\n --- {position_info}\n{padding}|\n{excerpt}",
        message = message.unwrap_or(""),
        position_info = position_info,
        padding = padding,
        excerpt = excerpt,
    )
}
pub fn format_error_with_excerpt ( message : Option < & str > , source_path : & Option < PathBuf > , source : & str , start_pos : Position , end_pos : Position , ) -> String { let ( excerpt , padding ) = { let excerpt_lines = source . lines ( ) . skip ( ( start_pos . line - 1 ) as usize ) . take ( ( end_pos . line - start_pos . line + 1 ) as usize ) . collect :: < Vec < _ > > ( ) ; let line_numbers = ( start_pos . line ..= end_pos . line ) . map ( | n | n . to_string ( ) ) . collect :: < Vec < _ > > ( ) ; let number_width = line_numbers . iter ( ) . max_by_key ( | n | n . len ( ) ) . unwrap ( ) . len ( ) ; let padding = " " . repeat ( number_width + 2 ) ; if start_pos . line == end_pos . line { let mut excerpt = format ! ( " \n " line_numbers first ( ) unwrap ( ) excerpt_lines first ( ) unwrap ( ) width number_width ) ; excerpt += & format ! ( " " padding " " repeat ( start_pos column as usize ) " " repeat ( ( end_pos column start_pos column ) as usize ) ) ; ( excerpt , padding ) } else { let mut excerpt = String :: new ( ) ; for ( excerpt_line , line_number ) in excerpt_lines . iter ( ) . zip ( line_numbers . iter ( ) ) { excerpt += & format ! ( " \n " line_number excerpt_line width number_width ) ; } ( excerpt , padding ) } } ; let position_info = if let Some ( path ) = source_path { let display_path = if let Ok ( current_dir ) = std :: env :: current_dir ( ) { if let Ok ( stripped ) = path . strip_prefix ( current_dir ) { stripped . display ( ) } else { path . display ( ) } } else { path . display ( ) } ; format ! ( " " display_path start_pos line start_pos column ) } else { format ! ( " " start_pos line start_pos column ) } ; format ! ( " \n \n \n " message message unwrap_or ( " " ) position_info position_info padding padding excerpt excerpt ) }
Produces a formatted error string with a corresponding source excerpt
Produces a formatted error string with a corresponding source excerpt
message
Option<&str>
source_path
&Option<PathBuf>
source
&str
start_pos
Position
end_pos
Position
message
Option<&str>
source_path
&Option<PathBuf>
source
&str
start_pos
Position
end_pos
Position