1use std::io::{self, Stdout, Write};
2
3use crossterm::{
4 cursor::{Hide, MoveTo, Show},
5 event::{Event, KeyCode},
6 terminal::{self, Clear, ClearType, EnterAlternateScreen, LeaveAlternateScreen},
7 ExecutableCommand, QueueableCommand,
8};
9
10use crate::smartlog::SmartLog;
11
12pub fn start_ui_and_get_selected_commit<'a>(smartlog: &'a mut SmartLog) -> Option<&'a str> {
13 let mut stdout = io::stdout();
14 terminal::enable_raw_mode().unwrap();
15 stdout.execute(EnterAlternateScreen).unwrap();
16 stdout.execute(Hide).unwrap();
17 render_smartlog(&mut stdout, smartlog);
18
19 let mut commit_hash: Option<&str> = None;
20 'terminal_ui: loop {
21 let input = crossterm::event::read().unwrap();
22 if let Event::Key(key_event) = input {
23 match key_event.code {
24 KeyCode::Char('q') | KeyCode::Esc => break 'terminal_ui,
25 KeyCode::Char('c') => {
26 if key_event
27 .modifiers
28 .contains(crossterm::event::KeyModifiers::CONTROL)
29 {
30 break 'terminal_ui;
31 }
32 }
33 KeyCode::Up => {
34 smartlog.move_up();
35 }
36 KeyCode::Down => {
37 smartlog.move_down();
38 }
39 KeyCode::Char(' ') | KeyCode::Enter => {
40 commit_hash = Some(smartlog.get_selected_commit_hash().unwrap());
41 break 'terminal_ui;
42 }
43 _ => {}
44 }
45 }
46 render_smartlog(&mut stdout, smartlog);
47 }
48
49 stdout.execute(Show).unwrap();
51 stdout.execute(LeaveAlternateScreen).unwrap();
52 terminal::disable_raw_mode().unwrap();
53
54 commit_hash
55}
56
57fn render_smartlog(stdout: &mut Stdout, smartlog: &SmartLog) {
58 stdout.queue(Clear(ClearType::All)).unwrap();
59 for (idx, line) in smartlog.to_string_vec().iter().enumerate() {
60 stdout.queue(MoveTo(0_u16, idx as u16)).unwrap();
61 print!("{}", *line);
62 }
63 stdout.flush().unwrap();
64}