kjps 0.1.2

A tool to kill a java process
Documentation
use crate::process;
use crate::process::Process;

use std::error::Error;
use std::io::{stdin, stdout, Write};
use termion::event::Key;
use termion::input::TermRead;
use termion::raw::IntoRawMode;

pub fn run() -> Result<(), Box<dyn Error>> {
    let stdin = stdin();
    let mut stdout = stdout().into_raw_mode()?;
    let mut state = State::new()?;

    write!(
        stdout,
        "{}{}{}{}",
        termion::clear::All,
        termion::cursor::Goto(1, 1),
        process::print_processes(&state.processes, state.idx),
        termion::cursor::Hide
    )?;
    stdout.flush()?;

    for c in stdin.keys() {
        write!(
            stdout,
            "{}{}",
            termion::cursor::Goto(1, 1),
            termion::clear::CurrentLine
        )?;
        let key = c?;
        match key {
            Key::Char('q') | Key::Ctrl('c') => break,
            Key::Char('r') => state.refresh()?,
            Key::Up | Key::Char('k') => state.move_up(),
            Key::Down | Key::Char('j') => state.move_down(),
            Key::Backspace | Key::Char('d') => {
                let current_process = state.processes.get(state.idx);
                match current_process {
                    Some(process) => {
                        let res = process::kill_process(process);
                        match res {
                            Ok(_) => state.remove_process(),
                            Err(_) => {}
                        }
                    }
                    None => {}
                }
            }
            _ => {}
        }
        write!(
            stdout,
            "{}{}",
            termion::clear::All,
            process::print_processes(&state.processes, state.idx),
        )?;
        stdout.flush()?;
    }
    write!(stdout, "{}", termion::cursor::Show)?;
    Ok(())
}

#[derive(Debug)]
struct State {
    processes: Vec<Process>,
    idx: usize,
}

impl State {
    fn new() -> Result<State, Box<dyn Error>> {
        let processes = State::get_java_prcess()?;
        Ok(State::init(processes))
    }

    fn init(processes: Vec<Process>) -> State {
        State { processes, idx: 0 }
    }

    fn refresh(&mut self) -> Result<(), Box<dyn Error>> {
        let processes = State::get_java_prcess()?;
        self.processes = processes;
        self.idx = 0;
        Ok(())
    }

    fn get_java_prcess() -> Result<Vec<Process>, Box<dyn Error>> {
        let processes = process::get_all_process()?;
        let java_processes = process::filter_java_process(processes)?;
        Ok(java_processes)
    }

    fn move_down(&mut self) {
        if self.idx + 1 < self.processes.len() {
            self.idx += 1
        };
    }

    fn move_up(&mut self) {
        if self.idx > 0 {
            self.idx -= 1
        };
    }

    fn remove_process(&mut self) {
        self.processes.remove(self.idx);
        if self.idx >= self.processes.len() && self.idx > 0 {
            self.idx = self.processes.len() - 1
        };
    }
}