//! Collect info for MDX. use crate::event::{Kind, Name, Point}; use crate::tokenizer::Tokenizer; use crate::util::slice::{Position, Slice}; use alloc::{string::String, vec, vec::Vec}; pub type Location<'a> = (usize, &'a Point); pub struct Result<'a> { pub start: &'a Point, pub value: String, pub locations: Vec>, } pub fn collect<'a>(tokenizer: &'a Tokenizer, from: usize, names: &[Name]) -> Result<'a> { let mut result = Result { start: &tokenizer.events[from].point, value: String::new(), locations: vec![], }; let mut index = from; let mut acc = 0; while index < tokenizer.events.len() { if tokenizer.events[index].kind == Kind::Enter && names.contains(&tokenizer.events[index].name) { // Include virtual spaces. let value = Slice::from_position( tokenizer.parse_state.bytes, &Position { start: &tokenizer.events[index].point, end: &tokenizer.events[index + 1].point, }, ) .serialize(); acc += value.len(); result.locations.push((acc, &tokenizer.events[index].point)); result.value.push_str(&value); } index += 1; } result } // Turn an index of `result.value` into a point in the whole document. pub fn place_to_point(result: &Result, place: usize) -> Point { let mut index = 0; let mut point = result.start; let mut rest = place; while index < result.locations.len() { point = result.locations[index].1; if result.locations[index].0 > place { break; } rest = place - result.locations[index].0; index += 1; } let mut point = point.clone(); point.column += rest; point.index += rest; point }