diff options
Diffstat (limited to 'src/widgets/luaeditor/mod.rs')
| -rw-r--r-- | src/widgets/luaeditor/mod.rs | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/widgets/luaeditor/mod.rs b/src/widgets/luaeditor/mod.rs new file mode 100644 index 0000000..723d8b5 --- /dev/null +++ b/src/widgets/luaeditor/mod.rs @@ -0,0 +1,132 @@ +use std::str::FromStr; + +use ratatui::{ + crossterm::event::{KeyCode, KeyEvent}, + prelude::BlockExt, + style::Stylize, + text::ToSpan, + widgets::{Block, Widget}, +}; + +pub mod buffer; +pub mod cursor; + +use buffer::Buffer; + +use self::cursor::CursorMove; + +#[derive(Debug)] +pub struct LuaEditor<'a> { + block: Option<Block<'a>>, + scroll: usize, + buffer: Buffer, +} + +impl<'a> LuaEditor<'a> { + pub fn new<S>(content: S) -> Self + where + S: AsRef<str>, + { + Self { + block: None, + scroll: 0, + buffer: Buffer::from_str(content.as_ref()).unwrap(), + } + } + + pub fn block(mut self, block: Option<Block<'a>>) -> Self { + self.block = block; + self + } + + pub fn handle_key_event(&mut self, event: KeyEvent) { + match event.code { + KeyCode::Char(c) => self.buffer.insert(c), + KeyCode::Backspace => { + self.buffer.delete(); + } + KeyCode::Enter => { + self.buffer.insert('\n'); + } + KeyCode::Left => self.buffer.move_cursor(CursorMove::Left(1)), + KeyCode::Right => self.buffer.move_cursor(CursorMove::Right(1)), + KeyCode::Up => self.buffer.move_cursor(CursorMove::Up(1)), + KeyCode::Down => self.buffer.move_cursor(CursorMove::Down(1)), + KeyCode::Home => {} + KeyCode::End => {} + KeyCode::PageUp => {} + KeyCode::PageDown => {} + KeyCode::Tab => self.buffer.insert('\t'), + KeyCode::BackTab => {} + KeyCode::Delete => {} + KeyCode::Insert => {} + KeyCode::F(_) => {} + KeyCode::Null => {} + KeyCode::Esc => {} + KeyCode::CapsLock => {} + KeyCode::ScrollLock => {} + KeyCode::NumLock => {} + KeyCode::PrintScreen => {} + KeyCode::Pause => {} + KeyCode::Menu => {} + KeyCode::KeypadBegin => {} + KeyCode::Media(_) => {} + KeyCode::Modifier(_) => {} + } + } + + pub fn text(&self) -> String { + self.buffer.lines().join("\n") + } +} + +impl Widget for &mut LuaEditor<'_> { + fn render(self, area: ratatui::prelude::Rect, buf: &mut ratatui::prelude::Buffer) + where + Self: Sized, + { + self.block.render(area, buf); + let inner_area = self.block.inner_if_some(area); + + for (i, line) in self.buffer.lines().iter().enumerate().skip(self.scroll) { + let replace = &line.replace('\t', " "); + let span = replace.to_span(); + let mut span_area = inner_area.clone(); + span_area.height = 1; + span_area.y += i as u16; + + if !inner_area.contains(span_area.into()) { + break; + } + + span.render(span_area, buf) + } + + let mut cursor_area = inner_area.clone(); + cursor_area.width = 1; + cursor_area.height = 1; + cursor_area.y += self.buffer.cursor().y() as u16; + cursor_area.x += self.buffer.cursor().x() as u16; + + let (first, _) = self + .buffer + .current_line() + .split_at(self.buffer.cursor().x() as usize); + + for c in first.chars() { + if c == '\t' { + cursor_area.x += 1; + } + } + + self.buffer + .current_line() + .chars() + .nth(self.buffer.cursor().x() as usize) + .map(|c| if c == '\t' { ' ' } else { c }) + .unwrap_or(' ') + .to_span() + .reversed() + .render(cursor_area, buf); + } +} |