Restructure markdown highlighter

This commit is contained in:
2025-06-13 22:08:53 +02:00
parent 83ad2068e0
commit 7f93084e64
15 changed files with 683 additions and 600 deletions

83
src/markdown/span.rs Normal file
View File

@ -0,0 +1,83 @@
use std::{
fmt,
ops::{Deref, Range},
};
#[derive(Clone, Eq, PartialEq)]
pub struct Span<'a> {
complete_str: &'a str,
range: Range<usize>,
}
impl<'a> Span<'a> {
pub fn new(complete_str: &'a str) -> Self {
Self {
complete_str,
range: 0..complete_str.len(),
}
}
pub fn get(&self, slice: Range<usize>) -> Option<Self> {
let start = self.range.start.checked_add(slice.start)?;
let end = self.range.start.checked_add(slice.end)?;
if end > self.range.end || end < start {
return None;
}
Some(Self {
complete_str: self.complete_str,
range: Range { start, end },
})
}
pub fn complete_str(&self) -> Self {
Self::new(self.complete_str)
}
pub fn split_at(&self, i: usize) -> Option<(Self, Self)> {
let head = self.get(0..i)?;
let tail = self.get(i..self.range.len())?;
Some((head, tail))
}
/// Try to merge the spans.
///
/// This only works if spans are pointing into the same backing buffer, and are adjacent.
pub fn try_merge(&self, other: &Self) -> Option<Self> {
if self.complete_str.as_ptr() != other.complete_str.as_ptr() {
return None;
}
if self.range.end == other.range.start {
Some(Self {
range: self.range.start..other.range.end,
..*self
})
} else if self.range.start == other.range.end {
Some(Self {
range: other.range.start..self.range.end,
..*self
})
} else {
None
}
}
}
impl Deref for Span<'_> {
type Target = str;
fn deref(&self) -> &Self::Target {
&self.complete_str[self.range.clone()]
}
}
impl<'a> fmt::Debug for Span<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("Span")
.field(&self.range)
.field(&self.deref())
.finish()
}
}