Docs

lines

Source: crates/lvcs-doc/src/lines.rs.

/// Names the code points `start..end` of `text`.
///
/// A range runs from the line holding `start` to the line holding
/// `end - 1`. An empty range names the line
/// holding the character after it, at the text's end the last line, and in
/// an empty text line 1. `None` when the range ends past the text or
/// before it starts.
#[must_use]
pub fn name(text: &str, start: usize, end: usize) -> Option<LineName> {
    let chars: Vec<char> = text.chars().collect();
    name_chars(&chars, start, end)
}

/// Names `spans` of `text` (code points) as a reader is shown them.
///
/// They are sorted, with spans that touch or overlap (`a.end >= b.start`) joined, and each
/// joined run named as [`name`] does. A run that ends past the text is left
/// out.
#[must_use]
pub fn names(text: &str, spans: &[Range<usize>]) -> Vec<LineName> {
    let chars: Vec<char> = text.chars().collect();
    let mut sorted = spans.to_vec();
    sorted.sort_unstable_by_key(|span| (span.start, span.end));
    let mut runs: Vec<Range<usize>> = Vec::with_capacity(sorted.len());
    for span in sorted {
        match runs.last_mut() {
            Some(run) if run.end >= span.start => run.end = run.end.max(span.end),
            _ => runs.push(span),
        }
    }
    runs.into_iter()
        .filter_map(|run| name_chars(&chars, run.start, run.end))
        .collect()
}