@@ 1,6 1,7 @@
extern crate termion;
use crate::termion::cursor::DetectCursorPos;
+use std::fmt::Debug;
use std::fmt::Display;
use std::io::{stdin, stdout, Write};
use termion::event::Key;
@@ 10,6 11,13 @@ use termion::screen::*;
struct Term {
screen: Box<dyn Write>,
+ mode: Mode,
+}
+
+#[derive(Eq, PartialEq, Debug)]
+enum Mode {
+ Normal,
+ Insert,
}
impl Term {
@@ 26,6 34,7 @@ impl Term {
screen.flush().unwrap();
Self {
screen: Box::new(screen),
+ mode: Mode::Normal,
}
}
@@ 33,8 42,12 @@ impl Term {
write!(self.screen, "{}", w);
}
+ pub fn pos(&mut self) -> (u16, u16) {
+ return self.screen.cursor_pos().unwrap();
+ }
+
pub fn write_newline(&mut self) {
- let mut pos = self.screen.cursor_pos().unwrap();
+ let mut pos = self.pos();
pos.0 = 1;
pos.1 += 1;
@@ 48,6 61,20 @@ impl Term {
self.write(&termion::cursor::Left(1));
}
+ pub fn enter_mode(&mut self, m: Mode) {
+ log(format!("Entering mode: {:?}", m));
+ self.mode = m;
+ let term_size = termion::terminal_size().unwrap();
+ let current_pos = self.pos();
+ self.write(&termion::cursor::Goto(1, term_size.1));
+ self.write(&match self.mode {
+ Mode::Normal => "Normal",
+ Mode::Insert => "Insert",
+ });
+ self.write(&termion::cursor::Goto(current_pos.0, current_pos.1));
+ self.flush();
+ }
+
pub fn flush(&mut self) {
self.screen.flush().unwrap();
}
@@ 56,21 83,65 @@ impl Term {
fn main() {
let stdin = stdin();
let mut term = Term::new();
-
+ term.enter_mode(Mode::Normal);
for c in stdin.keys() {
- match c.unwrap() {
- Key::Char('q') => break,
- Key::Char('\n') => term.write_newline(),
- Key::Backspace => term.backspace(),
+ let key = c.unwrap();
+ log(format!("New key event: {:?}", &key));
+ match key {
Key::Left => term.write(&termion::cursor::Left(1)),
Key::Right => term.write(&termion::cursor::Right(1)),
Key::Up => term.write(&termion::cursor::Up(1)),
Key::Down => term.write(&termion::cursor::Down(1)),
- Key::Char(x) => term.write(&x),
- _ => continue,
+ Key::Esc => term.enter_mode(Mode::Normal),
+ _ => {}
};
+ match term.mode {
+ Mode::Normal => {
+ if bindings_normal(&mut term, &key) == false {
+ log("Should quit");
+ break;
+ }
+ }
+ Mode::Insert => bindings_insert(&mut term, &key),
+ };
term.flush();
}
term.write(&termion::cursor::Show);
+ term.enter_mode(Mode::Normal);
+}
+
+/// Returns true if the program should continue running.
+/// If false is returned, the Program should terminate
+fn bindings_normal(term: &mut Term, k: &Key) -> bool {
+ log(format!("Normal Mode binding: {:?}", k));
+ match k {
+ Key::Char('q') => return false,
+ Key::Char('i') => term.enter_mode(Mode::Insert),
+ _ => {}
+ };
+
+ true
+}
+
+fn bindings_insert(term: &mut Term, k: &Key) {
+ log(format!("Insert Mode binding: {:?}", k));
+ match k {
+ Key::Char('\n') => term.write_newline(),
+ Key::Backspace => term.backspace(),
+ Key::Char(x) => term.write(x),
+ _ => {}
+ };
+}
+
+fn log(x: impl Display) {
+ let mut file = std::fs::OpenOptions::new()
+ .write(true)
+ .append(true)
+ .open("log")
+ .unwrap();
+
+ if let Err(e) = writeln!(file, "{}", x) {
+ eprintln!("Couldn't write to file: {}", e);
+ }
}