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 {
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()
}
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");
+ }
}
}
}
+use crate::Position;
use std::io::{self, stdout, Write};
use termion::event::Key;
use termion::input::TermRead;
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));
}
io::stdout().flush()
}
+ pub fn cursor_hide() {
+ print!("{}", termion::cursor::Hide);
+ }
+
+ pub fn cursor_show() {
+ print!("{}", termion::cursor::Show);
+ }
+
pub fn read_key() -> Result<Key, std::io::Error> {
loop {
if let Some(key) = io::stdin().lock().keys().next() {