summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2024-08-02 18:09:23 +0200
committerNathan Reiner <nathan@nathanreiner.xyz>2024-08-02 18:09:23 +0200
commitde9ad07b2a4737713f1473641fe195d7e3023928 (patch)
tree38f3bdb122b6e94fe45dbfa2264314c7a7f26be8 /src
parent29ab8b40dc6976687ffb8bfbf663314b0ec3c46e (diff)
add tui-cursor handling
Diffstat (limited to 'src')
-rw-r--r--src/app.rs41
-rw-r--r--src/main.rs1
-rw-r--r--src/tui.rs10
-rw-r--r--src/tuicursor.rs15
-rw-r--r--src/widgets/luaeditor/mod.rs52
5 files changed, 67 insertions, 52 deletions
diff --git a/src/app.rs b/src/app.rs
index 89b19dc..e93748f 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -5,11 +5,15 @@ use crate::{
sheet::register::Register,
state::{window::Window, GlobalState},
tui,
+ tuicursor::TuiCursor,
widgets::{logview::LogView, luaeditor::LuaEditor, sheetview::SheetView},
};
use ratatui::{
- crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers},
+ crossterm::{
+ event::{self, Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers},
+ ExecutableCommand,
+ },
prelude::*,
};
@@ -19,6 +23,7 @@ pub struct App {
view: SheetView,
editor: LuaEditor,
logview: LogView,
+ cursor: Option<TuiCursor>,
}
impl App {
@@ -33,10 +38,11 @@ impl App {
view: SheetView::new(),
editor: LuaEditor::new(),
logview: LogView::new(),
+ cursor: None,
}
}
- pub fn run(&mut self, terminal: &mut tui::Tui) -> io::Result<()> {
+ pub fn run(mut self, terminal: &mut tui::Tui) -> io::Result<()> {
if let Err(e) = lua::source(&config::constants::USER_RC_PATH) {
self.exit = true;
tui::restore()?;
@@ -44,7 +50,18 @@ impl App {
}
while !self.exit {
- terminal.draw(|frame| self.render_frame(frame))?;
+ terminal.draw(|frame| {
+ self.render_frame(frame);
+
+ if let Some(cursor) = &self.cursor {
+ frame.set_cursor(cursor.position.1, cursor.position.0);
+ }
+ })?;
+
+ if let Some(cursor) = &self.cursor {
+ terminal.backend_mut().execute(cursor.style)?;
+ }
+
self.handle_events()?;
}
@@ -75,13 +92,11 @@ impl App {
let mut state = GlobalState::instance_mut();
state.log.visible = !state.log.visible;
}
- _ => {
- match focus {
- Window::View => self.view.handle_key_event(key_event),
- Window::Editor => self.editor.handle_key_event(key_event),
- Window::Log => self.logview.handle_key_event(key_event),
- Window::Error => {},
- }
+ _ => match focus {
+ Window::View => self.view.handle_key_event(key_event),
+ Window::Editor => self.editor.handle_key_event(key_event),
+ Window::Log => self.logview.handle_key_event(key_event),
+ Window::Error => {}
},
}
}
@@ -103,7 +118,8 @@ impl App {
}
if state.editor.visible {
- let layout = Layout::horizontal([Constraint::Min(1), Constraint::Length(80)]).split(view);
+ let layout =
+ Layout::horizontal([Constraint::Min(1), Constraint::Length(80)]).split(view);
view = layout[0];
editor = Some(layout[1]);
}
@@ -121,8 +137,11 @@ impl Widget for &mut App {
self.view.render(view, buf);
+ self.cursor = None;
+
if let Some(editor) = editor {
self.editor.render(editor, buf);
+ self.cursor = self.editor.render_cursor().map(|c| c.relative_to(editor));
}
if let Some(log) = log {
diff --git a/src/main.rs b/src/main.rs
index 9228eaf..1a465ca 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -9,6 +9,7 @@ pub mod lua;
pub mod config;
pub mod state;
pub mod cursor;
+pub mod tuicursor;
fn run() -> io::Result<()> {
let mut terminal = tui::init()?;
diff --git a/src/tui.rs b/src/tui.rs
index 5669855..e10f3e1 100644
--- a/src/tui.rs
+++ b/src/tui.rs
@@ -1,7 +1,12 @@
use std::io::{self, stdout, Stdout};
-use ratatui::{backend::CrosstermBackend, crossterm::{terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, ExecutableCommand}, Terminal};
-
+use ratatui::{
+ backend::CrosstermBackend,
+ crossterm::{
+ cursor::SetCursorStyle, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, ExecutableCommand
+ },
+ Terminal,
+};
pub type Tui = Terminal<CrosstermBackend<Stdout>>;
@@ -17,6 +22,7 @@ pub fn init() -> io::Result<Tui> {
pub fn restore() -> io::Result<()> {
stdout().execute(LeaveAlternateScreen)?;
+ stdout().execute(SetCursorStyle::DefaultUserShape)?;
disable_raw_mode()?;
Ok(())
}
diff --git a/src/tuicursor.rs b/src/tuicursor.rs
new file mode 100644
index 0000000..fbb7531
--- /dev/null
+++ b/src/tuicursor.rs
@@ -0,0 +1,15 @@
+use ratatui::{crossterm::cursor::SetCursorStyle, layout::Rect};
+
+pub struct TuiCursor {
+ pub position: (u16, u16),
+ pub style: SetCursorStyle,
+}
+
+impl TuiCursor {
+ pub fn relative_to(self, rect: Rect) -> Self {
+ Self {
+ position: (rect.y + self.position.0, rect.x + self.position.1),
+ style: self.style,
+ }
+ }
+}
diff --git a/src/widgets/luaeditor/mod.rs b/src/widgets/luaeditor/mod.rs
index 3ce9ab5..0bcffc8 100644
--- a/src/widgets/luaeditor/mod.rs
+++ b/src/widgets/luaeditor/mod.rs
@@ -1,12 +1,9 @@
use ratatui::{
- crossterm::event::{KeyCode, KeyEvent, KeyModifiers},
- style::Stylize,
- text::{ToLine, ToSpan},
- widgets::Widget,
+ crossterm::event::{KeyCode, KeyEvent, KeyModifiers}, text::{ToLine, ToSpan}, widgets::Widget
};
use tree_sitter_highlight::HighlightConfiguration;
-use crate::state::{editor::EditorState, window::Window, GlobalState};
+use crate::{state::{editor::EditorState, window::Window, GlobalState}, tuicursor::TuiCursor};
use crate::{cursor::CursorMove, lua};
use super::statusbar::StatusBar;
@@ -83,6 +80,17 @@ impl LuaEditor {
KeyCode::Modifier(_) => {}
}
}
+
+ pub fn render_cursor(&self) -> Option<TuiCursor> {
+ let state = GlobalState::instance();
+ let buffer = &state.editor.buffer;
+ let nr_width = (buffer.lines().len().to_string().len() + 1).max(4) as u16;
+
+ Some(TuiCursor {
+ position: (buffer.cursor().y() as u16, buffer.cursor().x() as u16 + nr_width),
+ style: ratatui::crossterm::cursor::SetCursorStyle::SteadyBar,
+ })
+ }
}
impl Widget for &mut LuaEditor {
@@ -139,40 +147,6 @@ impl Widget for &mut LuaEditor {
(i + 1).to_line().right_aligned().render(nr_area, buf);
}
-
- let mut cursor_area = text_area;
- cursor_area.width = 1;
- cursor_area.height = 1;
- cursor_area.y += buffer.cursor().y() as u16;
- cursor_area.x += buffer.cursor().x() as u16;
-
- let (first, _) = buffer.current_line().split_at(buffer.cursor().x());
-
- for c in first.chars() {
- if c == '\t' {
- cursor_area.x += 1;
- }
- }
-
- if self.scroll > buffer.cursor().y() {
- self.scroll = buffer.cursor().y();
- } else if inner_area.height as usize + self.scroll - 1 < buffer.cursor().y() {
- self.scroll = buffer.cursor().y() - inner_area.height as usize + 1;
- }
-
- cursor_area.y -= self.scroll as u16;
-
- if inner_area.contains(cursor_area.into()) {
- buffer
- .current_line()
- .chars()
- .nth(buffer.cursor().x())
- .map(|c| if c == '\t' { ' ' } else { c })
- .unwrap_or(' ')
- .to_span()
- .reversed()
- .render(cursor_area, buf);
- }
}
}