gcd-cli 0.0.1

gcd-cli tools for managing and using GCD. GCD stands for GitChangeDirectory, as it primary goal is to quickly change between git project folders.
Documentation
use std::io;
use console::Key::*;
use console::Term;

pub struct InputHandler {
    pub line: String,
    cursor_position: usize,
    term: Term,
}

impl InputHandler {
    pub fn new(input: &str) -> Self {
        InputHandler {
            line: input.to_string(),
            cursor_position: input.len(),
            term: Term::stdout(),
        }
    }
    pub fn read_key(&mut self) -> io::Result<console::Key> {
        self.term.write_line(&format!("Search >{}", self.line))?;
        self.term.move_cursor_up(1)?;
        self.term.move_cursor_right(self.cursor_position+8)?;
        match self.term.read_key() {
            Ok(key) => {
                match key {
                    Char(c) => self.add_char(c),
                    Backspace => self.backspace_char(),
                    Del => self.del_char(),
                    ArrowLeft => self.move_left(),
                    ArrowRight => self.move_right(),
                    Home => self.move_home(),
                    End => self.move_end(),
                    _ => {}
                };
                Ok(key)
            }
            Err(_) => Ok(Escape),
        }
    }

    fn add_char(&mut self, c: char) {
        if self.cursor_position == self.line.len() {
            self.line.push(c);
            self.cursor_position = self.line.len();
        } else {
            self.line.insert(self.cursor_position, c);
        }
    }

    fn backspace_char(&mut self) {
        if self.cursor_position == self.line.len() {
            self.line.pop();
            self.cursor_position = self.line.len();
        } else {
            self.line.remove(self.cursor_position - 1);
            self.cursor_position -=1;
        }
    }

    fn del_char(&mut self) {
        if self.cursor_position == self.line.len() {
            self.line.pop();
            self.cursor_position = self.line.len();
        } else {
            self.line.remove(self.cursor_position);
        }
    }

    fn move_left(&mut self) {
        if self.cursor_position == 0 {
            self.cursor_position = 0;
        } else {
            self.cursor_position -= 1;
        }
    }
    fn move_right(&mut self) {
        if self.cursor_position < self.line.len() {
            self.cursor_position += 1;
        }
    }

    fn move_home(&mut self) {
        self.cursor_position = 0;
    }

    fn move_end(&mut self) {
        self.cursor_position = self.line.len();
    }

}

#[test]
fn test_input() {
    let mut ih = InputHandler::new("");

    ih.add_char('a');
    assert_eq!("a", ih.line);

    ih.move_home();
    ih.add_char('b');
    assert_eq!("ba", ih.line);

    ih.move_end();
    ih.add_char('c');
    assert_eq!("bac", ih.line);

    ih.move_left();
    ih.backspace_char();
    assert_eq!("bc", ih.line);

    ih.move_left();
    ih.add_char('a');
    assert_eq!("abc", ih.line);

    ih.move_right();
    ih.del_char();
    assert_eq!("ac", ih.line);
}