git_bonsai/
interactiveappui.rs

1/*
2 * Copyright 2021 Aurélien Gâteau <mail@agateau.com>
3 *
4 * This file is part of git-bonsai.
5 *
6 * Git-bonsai is free software: you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License as published by the Free
8 * Software Foundation, either version 3 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19use crate::appui::{AppUi, BranchToDeleteInfo};
20use crate::tui;
21
22pub struct InteractiveAppUi;
23
24fn format_branch_info(branch_info: &BranchToDeleteInfo) -> String {
25    let container_str = branch_info
26        .contained_in
27        .iter()
28        .map(|x| format!("      - {}", x))
29        .collect::<Vec<String>>()
30        .join("\n");
31
32    format!("{}, contained in:\n{} \n", branch_info.name, container_str)
33}
34
35impl AppUi for InteractiveAppUi {
36    fn log_info(&self, msg: &str) {
37        tui::log_info(msg);
38    }
39
40    fn log_warning(&self, msg: &str) {
41        tui::log_warning(msg);
42    }
43
44    fn log_error(&self, msg: &str) {
45        tui::log_error(msg);
46    }
47
48    fn select_branches_to_delete(
49        &self,
50        branch_infos: &[BranchToDeleteInfo],
51    ) -> Vec<BranchToDeleteInfo> {
52        let select_items: Vec<String> = branch_infos
53            .iter()
54            .map(format_branch_info)
55            .collect::<Vec<String>>();
56
57        let selections = tui::select("Select branches to delete", &select_items);
58
59        selections
60            .iter()
61            .map(|&x| branch_infos[x].clone())
62            .collect::<Vec<BranchToDeleteInfo>>()
63    }
64
65    fn select_identical_branches_to_delete(&self, branches: &[String]) -> Vec<String> {
66        let mut items = branches.to_vec();
67        items.sort();
68
69        let selections = tui::select(
70            "These branches point to the same commit, which is contained in another branch,\
71            so it is safe to delete them all.\n\
72            Select branches to delete",
73            &items,
74        );
75
76        selections
77            .iter()
78            .map(|&x| items[x].clone())
79            .collect::<Vec<String>>()
80    }
81
82    fn select_identical_branches_to_delete_keep_one(&self, branches: &[String]) -> Vec<String> {
83        let mut items = branches.to_vec();
84        items.sort();
85
86        let mut selections: Vec<usize>;
87        println!(
88            "These branches point to the same commit, but no other branch contains this commit, \
89                so you can delete all of them but one.\n"
90        );
91        loop {
92            selections = tui::select("Select branches to delete", &items);
93            if selections.len() == items.len() {
94                self.log_error("You must leave at least one branch unchecked.");
95            } else {
96                break;
97            }
98        }
99        selections
100            .iter()
101            .map(|&x| items[x].clone())
102            .collect::<Vec<String>>()
103    }
104
105    fn select_default_branch(&self, branches: &[String]) -> Option<String> {
106        let mut items = branches.to_vec();
107        items.sort();
108
109        tui::select_one("Select the branch to use as the default branch", &items)
110            .map(|x| items[x].clone())
111    }
112}