From b73ac6b233915cf025276677238e8564270a4c6b Mon Sep 17 00:00:00 2001 From: Sondre Wold Date: Sun, 21 Apr 2024 11:34:51 +0200 Subject: [PATCH] More navigation commands --- octo/src/editor.rs | 74 +++++++++++++++++++++++++++++++++++++++++--- octo/src/main.rs | 1 + octo/src/terminal.rs | 22 +++++++++++-- 3 files changed, 89 insertions(+), 8 deletions(-) diff --git a/octo/src/editor.rs b/octo/src/editor.rs index bef7795..dc87d89 100644 --- a/octo/src/editor.rs +++ b/octo/src/editor.rs @@ -1,14 +1,22 @@ use crate::Terminal; use termion::event::Key; +const VERSION: &str = env!("CARGO_PKG_VERSION"); + fn die(e: std::io::Error) { Terminal::clear_screen(); panic!("{:?}", e); } +pub struct Position { + pub x: usize, + pub y: usize, +} + pub struct Editor { should_quit: bool, terminal: Terminal, + current_position: Position, } impl Editor { @@ -29,18 +37,21 @@ impl Editor { Self { should_quit: false, terminal: Terminal::default().expect("Failed to create terminal"), + current_position: Position { x: 0, y: 0 }, } } fn refresh_screen(&self) -> Result<(), std::io::Error> { - Terminal::clear_screen(); - Terminal::cursor_position(0, 0); + Terminal::cursor_hide(); + Terminal::cursor_position(&Position { x: 0, y: 0 }); if self.should_quit { + Terminal::clear_screen(); println!("Goodbye.\r"); } else { self.draw_rows(); - Terminal::cursor_position(0, 0); + Terminal::cursor_position(&self.current_position); } + Terminal::cursor_show(); Terminal::flush() } @@ -48,13 +59,66 @@ impl Editor { let pressed_key = Terminal::read_key()?; match pressed_key { Key::Ctrl('q') => self.should_quit = true, + Key::Up + | Key::Down + | Key::Left + | Key::Right + | Key::PageUp + | Key::PageDown + | Key::Home + | Key::End => self.move_cursor(pressed_key), _ => (), }; Ok(()) } + + fn move_cursor(&mut self, key: Key) { + let Position { mut x, mut y } = self.current_position; + let size = self.terminal.size(); + let width = size.width.saturating_sub(1) as usize; + let height = size.height.saturating_sub(1) as usize; + match key { + Key::Up => y = y.saturating_sub(1), + Key::Down => { + if y < height { + y = y.saturating_add(1); + } + } + Key::Left => x = x.saturating_sub(1), + Key::Right => { + if x < width { + x = x.saturating_add(1); + } + } + Key::PageUp => y = 0, + Key::PageDown => y = height, + Key::Home => x = 0, + Key::End => x = width, + _ => (), + } + self.current_position = Position { x, y }; + } + + fn draw_welcome_message(&self) { + let mut welcome_message = format!("OCTO -- version {}", VERSION); + let width = self.terminal.size().width as usize; + let len = welcome_message.len(); + let padding = width.saturating_sub(len) / 2; + let spaces = " ".repeat(padding.saturating_sub(1)); + welcome_message = format!("~{}{}", spaces, welcome_message); + welcome_message.truncate(width); + println!("{}\r", welcome_message); + } + fn draw_rows(&self) { - for _ in 0..self.terminal.size().height { - println!("~\r"); + let height = self.terminal.size().height; + for row in 0..height - 1 { + Terminal::clear_current_line(); + if row == height / 3 { + self.draw_welcome_message(); + } else { + println!("~\r"); + } } } } diff --git a/octo/src/main.rs b/octo/src/main.rs index 0637681..4bc5c57 100644 --- a/octo/src/main.rs +++ b/octo/src/main.rs @@ -3,6 +3,7 @@ mod editor; mod terminal; use editor::Editor; pub use terminal::Terminal; +pub use editor::Position; fn main() { Editor::default().run(); diff --git a/octo/src/terminal.rs b/octo/src/terminal.rs index 599d873..cafbdef 100644 --- a/octo/src/terminal.rs +++ b/octo/src/terminal.rs @@ -1,3 +1,4 @@ +use crate::Position; use std::io::{self, stdout, Write}; use termion::event::Key; use termion::input::TermRead; @@ -32,9 +33,16 @@ impl Terminal { print!("{}", termion::clear::All); } - pub fn cursor_position(x: u16, y: u16) { - let x = x.saturating_add(1); - let y = y.saturating_add(1); + pub fn clear_current_line() { + print!("{}", termion::clear::CurrentLine); + } + + pub fn cursor_position(position: &Position) { + let Position{mut x, mut y} = position; + x = x.saturating_add(1); + y = y.saturating_add(1); + let x = x as u16; + let y = y as u16; print!("{}", termion::cursor::Goto(x, y)); } @@ -42,6 +50,14 @@ impl Terminal { io::stdout().flush() } + pub fn cursor_hide() { + print!("{}", termion::cursor::Hide); + } + + pub fn cursor_show() { + print!("{}", termion::cursor::Show); + } + pub fn read_key() -> Result { loop { if let Some(key) = io::stdin().lock().keys().next() { -- 2.39.5