~garritfra/rim

03f27f67c25aa0ffc3af0a707c6ae2ce9016199c — Garrit Franke 2 years ago d87a5ba
Add modes
2 files changed, 81 insertions(+), 8 deletions(-)

M .gitignore
M src/main.rs
M .gitignore => .gitignore +2 -0
@@ 1,1 1,3 @@
/target
.vscode/
log
\ No newline at end of file

M src/main.rs => src/main.rs +79 -8
@@ 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);
    }
}