From 8b8d9dadccb6f711c2624d23ffefbe18336da42a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Macio=C5=82ek?= Date: Tue, 14 May 2024 23:37:18 +0200 Subject: [PATCH] scrolling part 2 --- ] | 121 +++++++++++++++++++++++++++++++++++++++++++++++++ src/app.rs | 34 ++++++++++---- src/handler.rs | 55 +++++++++++----------- src/ui.rs | 4 +- 4 files changed, 178 insertions(+), 36 deletions(-) create mode 100644 ] diff --git a/] b/] new file mode 100644 index 0000000..dd46db0 --- /dev/null +++ b/] @@ -0,0 +1,121 @@ +use std::error; + +use ratatui::layout::Rect; + +pub type AppResult = std::result::Result>; + +#[derive(Debug)] +pub struct Direction { + pub x: i8, + pub y: i8, +} + +#[derive(Debug)] +pub struct Position { + pub x: usize, + pub y: usize, +} + +#[derive(Debug)] +pub struct App { + pub running: bool, + pub content: Vec, + pub cursor_position: Position, + pub cursor_offset: Position, + pub opened_filename: String, + pub window_size: Rect, +} + +impl Default for App { + fn default() -> Self { + Self { + running: true, + content: Vec::new(), + cursor_position: Position { x: 0, y: 0 }, + cursor_offset: Position { x: 0, y: 0 }, + opened_filename: String::new(), + window_size: Rect::new(0, 0, 0, 0), + } + } +} + +impl App { + pub fn new() -> Self { + Self::default() + } + + pub fn tick(&self) {} + + pub fn quit(&mut self) { + self.running = false; + } + + pub fn insert_char(&mut self, c: char) { + while self.cursor_position.y >= self.content.len() { + self.content.push(String::new()); + } + self.content[self.cursor_position.y + self.cursor_offset.y] + .insert(self.cursor_position.x + self.cursor_offset.x, c); + self.move_cursor(Direction { x: 1, y: 0 }); + } + + pub fn add_new_line(&mut self) { + self.content.insert( + self.cursor_position.y + self.cursor_offset.y + 1, + String::new(), + ); + self.move_cursor(Direction { x: 0, y: -1 }) + } + + pub fn pop_char(&mut self) { + self.content[self.cursor_position.y].pop(); + + if self.cursor_position.x > 0 { + self.cursor_position.x -= 1; + } + } + + pub fn move_cursor(&mut self, direction: Direction) { + if direction.x < 0 && self.cursor_position.x + self.cursor_offset.x > 0 { + if self.cursor_position.x == 0 { + self.cursor_offset.x -= 1; + } else { + self.cursor_position.x -= 1; + } + } else if direction.x > 0 { + if let Some(line) = self.content.get(self.cursor_position.y) { + if line.len() > self.cursor_position.x + self.cursor_offset.x { + if self.window_size.width.saturating_sub(1) > self.cursor_position.x as u16 { + self.cursor_position.x += 1; + } else { + self.cursor_offset.x += 1; + } + } + } + } + + if direction.y > 0 && self.cursor_position.y + self.cursor_offset.y > 0 { + if self.cursor_position.y == 0 { + self.cursor_offset.y -= 1; + } else { + self.cursor_position.y -= 1; + } + + if self.cursor_position.x > self.content[self.cursor_position.y].len() { + self.cursor_position.x = self.content[self.cursor_position.y].len(); + } + } else if direction.y < 0 + && self.cursor_position.y + self.cursor_offset.y < self.content.len().saturating_sub(1) + { + if self.window_size.height.saturating_sub(4) > self.cursor_position.y as u16 { + self.cursor_position.y += 1; + } else { + self.cursor_offset.y += 1; + } + + if self.cursor_position.x > self.content[self.cursor_position.y].len() { + self.cursor_position.x = self.content[self.cursor_position.y].len(); + } + } + } +} diff --git a/src/app.rs b/src/app.rs index 9dedd7a..f958f9d 100644 --- a/src/app.rs +++ b/src/app.rs @@ -54,23 +54,39 @@ impl App { while self.cursor_position.y >= self.content.len() { self.content.push(String::new()); } + self.content[self.cursor_position.y + self.cursor_offset.y] .insert(self.cursor_position.x + self.cursor_offset.x, c); - self.cursor_position.x += 1; + self.move_cursor(Direction { x: 1, y: 0 }); } pub fn add_new_line(&mut self) { - self.content - .insert(self.cursor_position.y + self.cursor_offset.y, String::new()); - self.cursor_position.y += 1; - self.cursor_position.x = 0; + while self.cursor_position.y >= self.content.len() { + self.content.push(String::new()); + } + + self.content.insert( + self.cursor_position.y + self.cursor_offset.y + 1, + String::new(), + ); + self.move_cursor(Direction { x: 0, y: -1 }); } pub fn pop_char(&mut self) { - self.content[self.cursor_position.y].pop(); + if self.content.len() == 0 { + return; + } + + if self.content[self.cursor_position.y + self.cursor_offset.y].len() == 0 { + self.content + .remove(self.cursor_position.y + self.cursor_offset.y); + + self.move_cursor(Direction { x: 0, y: 1 }); + } else { + self.content[self.cursor_position.y + self.cursor_offset.y] + .remove(self.cursor_position.x + self.cursor_offset.x - 1); - if self.cursor_position.x > 0 { - self.cursor_position.x -= 1; + self.move_cursor(Direction { x: -1, y: 0 }); } } @@ -102,6 +118,7 @@ impl App { if self.cursor_position.x > self.content[self.cursor_position.y].len() { self.cursor_position.x = self.content[self.cursor_position.y].len(); + self.cursor_offset.x = 0; } } else if direction.y < 0 && self.cursor_position.y + self.cursor_offset.y < self.content.len().saturating_sub(1) @@ -114,6 +131,7 @@ impl App { if self.cursor_position.x > self.content[self.cursor_position.y].len() { self.cursor_position.x = self.content[self.cursor_position.y].len(); + self.cursor_offset.x = 0; } } } diff --git a/src/handler.rs b/src/handler.rs index 39c0195..2df3a92 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -2,35 +2,38 @@ use crate::app::{App, AppResult, Direction}; use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> { - match key_event.code { - KeyCode::Char('c') | KeyCode::Char('C') => { - if key_event.modifiers == KeyModifiers::CONTROL { + match key_event.modifiers { + KeyModifiers::CONTROL => { + if key_event.code == KeyCode::Char('c') || key_event.code == KeyCode::Char('C') { app.quit(); } } - KeyCode::Enter => { - app.add_new_line(); - } - KeyCode::Backspace => { - app.pop_char(); - } - KeyCode::Left => { - app.move_cursor(Direction { x: -1, y: 0 }); - } - KeyCode::Right => { - app.move_cursor(Direction { x: 1, y: 0 }); - } - KeyCode::Up => { - app.move_cursor(Direction { x: 0, y: 1 }); - } - KeyCode::Down => { - app.move_cursor(Direction { x: 0, y: -1 }); - } - _ => { - if let KeyCode::Char(c) = key_event.code { - app.insert_char(c) + _ => match key_event.code { + KeyCode::Enter => { + app.add_new_line(); } - } - } + KeyCode::Backspace => { + app.pop_char(); + } + KeyCode::Left => { + app.move_cursor(Direction { x: -1, y: 0 }); + } + KeyCode::Right => { + app.move_cursor(Direction { x: 1, y: 0 }); + } + KeyCode::Up => { + app.move_cursor(Direction { x: 0, y: 1 }); + } + KeyCode::Down => { + app.move_cursor(Direction { x: 0, y: -1 }); + } + _ => { + if let KeyCode::Char(c) = key_event.code { + app.insert_char(c) + } + } + }, + }; + Ok(()) } diff --git a/src/ui.rs b/src/ui.rs index 7f91857..3906cfe 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -17,8 +17,8 @@ pub fn render(app: &mut App, frame: &mut Frame) { let cursor_position_status = Line::from(format!( " {:>2}:{:<2} ", - app.cursor_position.y + 1, - app.cursor_position.x + 1, + app.cursor_position.y + app.cursor_offset.y + 1, + app.cursor_position.x + app.cursor_offset.x + 1, )) .right_aligned() .style(Style::default().bg(Color::Rgb(128, 192, 255)).bold());