68 lines
2.3 KiB
Rust
68 lines
2.3 KiB
Rust
use rnix::ParseError;
|
|
use std::{env, fs};
|
|
|
|
fn main() {
|
|
let file = match env::args().nth(1) {
|
|
Some(file) => file,
|
|
None => {
|
|
eprintln!("Usage: error-report <file>");
|
|
return;
|
|
}
|
|
};
|
|
let content = match fs::read_to_string(&file) {
|
|
Ok(content) => content,
|
|
Err(err) => {
|
|
eprintln!("error reading file: {}", err);
|
|
return;
|
|
}
|
|
};
|
|
let ast = rnix::Root::parse(&content);
|
|
for error in ast.errors() {
|
|
let range = match error {
|
|
ParseError::Unexpected(range) => range,
|
|
ParseError::UnexpectedExtra(range) => range,
|
|
ParseError::UnexpectedWanted(_, range, _) => range,
|
|
ParseError::UnexpectedDoubleBind(range) => range,
|
|
ParseError::DuplicatedArgs(range, _) => range,
|
|
err => {
|
|
eprintln!("error: {}", err);
|
|
continue;
|
|
}
|
|
};
|
|
eprintln!("----- ERROR -----");
|
|
eprintln!("{}", error);
|
|
let start = usize::from(range.start());
|
|
let start_row = content[..start].lines().count() - 1;
|
|
let start_line = content[..start].rfind('\n').map(|i| i + 1).unwrap_or(0);
|
|
let start_col = content[start_line..start].chars().count();
|
|
let end = usize::from(range.end());
|
|
let end_row = content[..end].lines().count() - 1;
|
|
let end_line = content[..end].rfind('\n').map(|i| i + 1).unwrap_or(0);
|
|
let end_col = content[end_line..end].chars().count();
|
|
|
|
let mut line_len = 1;
|
|
let mut line = end_row;
|
|
while line >= 10 {
|
|
line /= 10;
|
|
line_len += 1;
|
|
}
|
|
|
|
let i = start_row.saturating_sub(1);
|
|
for (i, line) in content.lines().enumerate().skip(i).take(end_row - i + 1) {
|
|
println!("{:line_len$} {}", i + 1, line, line_len = line_len);
|
|
if i >= start_row && i <= end_row {
|
|
print!("{:line_len$} ", "", line_len = line_len);
|
|
let mut end_col = if i == end_row { end_col } else { line.chars().count() };
|
|
if i == start_row {
|
|
print!("{:indent$}", "", indent = start_col);
|
|
end_col -= start_col;
|
|
}
|
|
for _ in 0..end_col {
|
|
print!("^");
|
|
}
|
|
println!();
|
|
}
|
|
}
|
|
}
|
|
}
|