use promkit_core::{
ContentPosition, CreatedGraphemes, Widget, WidgetLayout, grapheme::StyledGraphemes,
};
#[path = "text/text.rs"]
mod inner;
pub use inner::Text;
pub mod config;
pub use config::Config;
#[derive(Clone, Default)]
pub struct State {
pub text: Text,
pub config: Config,
}
impl State {
pub fn replace(&mut self, state: Self) {
*self = state;
}
pub fn replace_text(&mut self, text: Vec<StyledGraphemes>) {
self.text.replace_contents(text);
}
}
impl Widget for State {
fn create_graphemes(&self) -> CreatedGraphemes {
let lines = self.text.items().iter().map(|item| {
if let Some(style) = &self.config.style {
item.clone().apply_style(*style)
} else {
item.clone()
}
});
CreatedGraphemes {
graphemes: StyledGraphemes::from_lines(lines),
layout: WidgetLayout {
max_height: self.config.lines,
..Default::default()
},
cursor: self
.text
.current_line()
.map(|current_line| ContentPosition {
row: current_line,
column: 0,
}),
}
}
}
impl State {
pub fn hit_at(&self, position: ContentPosition) -> Option<TextHit> {
self.text
.items()
.get(position.row)
.map(|_| TextHit::Select {
index: position.row,
})
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum TextHit {
Select { index: usize },
}
#[cfg(test)]
mod tests {
use super::*;
mod state {
use super::*;
mod hit_at {
use super::*;
#[test]
fn resolves_line_rows() {
let state = State {
text: Text::from("first\nsecond"),
config: Config::default(),
};
assert_eq!(
state.hit_at(ContentPosition { row: 1, column: 20 }),
Some(TextHit::Select { index: 1 })
);
assert_eq!(state.hit_at(ContentPosition { row: 2, column: 0 }), None);
}
}
}
}