git_iblame/
cli.rs

1use std::{io::stdout, path::Path};
2
3use crate::*;
4use crossterm::{clipboard::CopyToClipboard, execute, terminal};
5use git2::Oid;
6
7pub struct Cli {
8    renderer: BlameRenderer,
9    commit_ids: Vec<Oid>,
10}
11
12impl Cli {
13    pub fn new(path: &Path) -> anyhow::Result<Self> {
14        Ok(Self {
15            renderer: BlameRenderer::new(path)?,
16            commit_ids: vec![],
17        })
18    }
19
20    pub fn run(&mut self) -> anyhow::Result<()> {
21        let renderer = &mut self.renderer;
22        let size = terminal::size()?;
23        renderer.set_size((size.0, size.1 - 1));
24        renderer.read()?;
25        let mut out = stdout();
26        let prompt = String::new();
27        loop {
28            renderer.render(&mut out)?;
29
30            let command = Command::read(renderer.rendered_rows(), &prompt)?;
31            match command {
32                Command::PrevDiff => renderer.move_to_prev_diff(),
33                Command::NextDiff => renderer.move_to_next_diff(),
34                Command::PageUp => renderer.move_to_prev_page(),
35                Command::PageDown => renderer.move_to_next_page(),
36                Command::FirstLine => renderer.move_to_first_line(),
37                Command::LastLine => renderer.move_to_last_line(),
38                Command::LineNumber(number) => renderer.set_current_number(number),
39                Command::Older => {
40                    let id = renderer.newest_commit_id();
41                    renderer.set_newest_commit_id_to_older()?;
42                    self.commit_ids.push(id);
43                }
44                Command::Newer => {
45                    if let Some(id) = self.commit_ids.pop() {
46                        renderer.set_newest_commit_id(id)?;
47                    }
48                }
49                Command::Copy => execute!(
50                    out,
51                    CopyToClipboard::to_clipboard_from(renderer.current_commit_id().to_string())
52                )?,
53                Command::Resize(columns, rows) => renderer.set_size((columns, rows - 1)),
54                Command::Quit => break,
55            }
56        }
57        Ok(())
58    }
59}