use crate::error::RexactError;
pub fn locate(chars: &[char], offset: usize) -> (usize, usize) {
let end = offset.min(chars.len());
let mut line = 1;
let mut col = 1;
for &c in &chars[..end] {
if c == '\n' {
line += 1;
col = 1;
} else {
col += 1;
}
}
(line, col)
}
impl RexactError {
pub fn render(&self, source: &str) -> String {
let mut out = self.to_string();
if let Some((line, col)) = self.position {
if let Some(text) = source.split('\n').nth(line - 1) {
out.push_str(&format!("\n {text}\n {}^", " ".repeat(col - 1)));
}
}
out
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::error::ErrorCode;
#[test]
fn locate_counts_scalars_and_lines() {
let c: Vec<char> = "ab\nc😀d".chars().collect();
assert_eq!(locate(&c, 0), (1, 1));
assert_eq!(locate(&c, 2), (1, 3));
assert_eq!(locate(&c, 3), (2, 1));
assert_eq!(locate(&c, 5), (2, 3)); assert_eq!(locate(&c, 99), (2, 4)); }
#[test]
fn caret_sits_under_the_column() {
let mut e = RexactError::new(ErrorCode::P007);
e.position = Some((1, 3));
let r = e.render("ab[");
assert!(r.ends_with("\n ab[\n ^"), "{r}");
}
}