summaryrefslogtreecommitdiff
path: root/src/widgets/luaeditor/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/luaeditor/mod.rs')
-rw-r--r--src/widgets/luaeditor/mod.rs132
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);
+ }
+}