use crate::state::EditorState;
use crate::view::overlay::OverlayFace;
use crate::view::virtual_text::VirtualTextPosition;
use ratatui::style::Style;
#[derive(Debug, Clone, PartialEq)]
pub enum ViewTokenKind {
Text(String),
Newline,
Space,
VirtualText {
text: String,
style: Style,
position: VirtualTextPosition,
priority: i32,
},
StyleStart(Style),
StyleEnd,
Overlay(OverlayFace),
}
#[derive(Debug, Clone, PartialEq)]
pub struct ViewToken {
pub source_offset: Option<usize>,
pub kind: ViewTokenKind,
}
#[derive(Debug, Clone, Default)]
pub struct ViewStream {
pub tokens: Vec<ViewToken>,
pub source_map: Vec<Option<usize>>,
}
impl ViewStream {
pub fn new() -> Self {
Self {
tokens: Vec::new(),
source_map: Vec::new(),
}
}
pub fn push(&mut self, token: ViewToken) {
self.source_map.push(token.source_offset);
self.tokens.push(token);
}
}
pub fn build_base_stream(state: &mut EditorState, start: usize, end: usize) -> ViewStream {
let mut stream = ViewStream::new();
if start >= end {
return stream;
}
let text = state.get_text_range(start, end);
let mut current_offset = start;
let mut buffer = String::new();
for ch in text.chars() {
if ch == '\n' {
if !buffer.is_empty() {
stream.push(ViewToken {
source_offset: Some(current_offset - buffer.len()),
kind: ViewTokenKind::Text(buffer.clone()),
});
buffer.clear();
}
stream.push(ViewToken {
source_offset: Some(current_offset),
kind: ViewTokenKind::Newline,
});
current_offset += 1;
} else {
buffer.push(ch);
current_offset += ch.len_utf8();
}
}
if !buffer.is_empty() {
stream.push(ViewToken {
source_offset: Some(current_offset - buffer.len()),
kind: ViewTokenKind::Text(buffer),
});
}
stream
}