gitfetch_rs/cli/
interactive.rs1use anyhow::Result;
2use dialoguer::{Input, Select, theme::Theme};
3use std::fmt;
4
5struct GitfetchTheme;
7
8impl Theme for GitfetchTheme {
9 fn format_prompt(&self, f: &mut dyn fmt::Write, prompt: &str) -> fmt::Result {
10 write!(f, "{}", prompt)
11 }
12
13 fn format_select_prompt_item(
14 &self,
15 f: &mut dyn fmt::Write,
16 text: &str,
17 active: bool,
18 ) -> fmt::Result {
19 let indicator = if active { "●" } else { "○" };
20 write!(f, "{} {}", indicator, text)
21 }
22
23 fn format_input_prompt(
24 &self,
25 f: &mut dyn fmt::Write,
26 prompt: &str,
27 default: Option<&str>,
28 ) -> fmt::Result {
29 match default {
30 Some(default) => write!(f, "{} [{}]: ", prompt, default),
31 None => write!(f, "{}: ", prompt),
32 }
33 }
34
35 fn format_input_prompt_selection(
36 &self,
37 f: &mut dyn fmt::Write,
38 prompt: &str,
39 sel: &str,
40 ) -> fmt::Result {
41 write!(f, "{}: {}", prompt, sel)
42 }
43}
44
45pub fn prompt_provider() -> Result<String> {
46 let providers = vec!["GitHub", "GitLab", "Gitea/Forgejo/Codeberg", "Sourcehut"];
47
48 println!("Choose your git provider:");
49 println!();
50
51 let selection = Select::with_theme(&GitfetchTheme)
52 .items(&providers)
53 .default(0)
54 .interact()?;
55
56 println!();
57 println!("Use ↑/↓ arrows, ● = selected, Enter to confirm");
58
59 let provider = match selection {
60 0 => "github",
61 1 => "gitlab",
62 2 => "gitea",
63 3 => "sourcehut",
64 _ => unreachable!(),
65 };
66
67 Ok(provider.to_string())
68}
69
70pub fn prompt_url(provider: &str) -> Result<String> {
71 Input::new()
72 .with_prompt(format!("Enter {} instance URL", provider))
73 .interact_text()
74 .map_err(Into::into)
75}
76
77pub fn prompt_token(provider: &str) -> Result<String> {
78 Input::with_theme(&GitfetchTheme)
79 .with_prompt(format!(
80 "Enter your {} personal access token (optional, press Enter to skip)",
81 provider
82 ))
83 .allow_empty(true)
84 .interact_text()
85 .map_err(Into::into)
86}
87
88pub fn prompt_cache_expiry() -> Result<usize> {
89 let input: String = Input::with_theme(&GitfetchTheme)
90 .with_prompt("Cache expiry in minutes (default: 15, Enter for default)")
91 .allow_empty(true)
92 .interact_text()?;
93
94 if input.is_empty() {
95 Ok(15)
96 } else {
97 match input.parse::<usize>() {
98 Ok(minutes) if minutes >= 1 => Ok(minutes),
99 _ => {
100 println!("Cache expiry must be >= 1 min. Using default: 15");
101 Ok(15)
102 }
103 }
104 }
105}