1mod input;
4mod progress;
5
6use input::{DefaultPrompt, PasswordPrompt, SelectionPrompt, TextPrompt};
7use progress::{ProgressBarTrait, SpinnerTrait};
8use std::sync::OnceLock;
9
10pub const DOWNLOAD_MESSAGE: &str = "Downloading changes";
12pub const APPLY_MESSAGE: &str = "Applying changes";
13pub const UPLOAD_MESSAGE: &str = "Uploading changes";
14pub const COMPLETE_MESSAGE: &str = "Completing changes";
15pub const OUTPUT_MESSAGE: &str = "Outputting repository";
16
17static INTERACTIVE_CONTEXT: OnceLock<InteractiveContext> = OnceLock::new();
20
21pub fn get_context() -> Result<InteractiveContext, InteractionError> {
23 if let Some(context) = INTERACTIVE_CONTEXT.get() {
24 Ok(*context)
25 } else {
26 Err(InteractionError::NoContext)
27 }
28}
29
30pub fn set_context(value: InteractiveContext) {
32 INTERACTIVE_CONTEXT
34 .set(value)
35 .expect("Interactive context is already set!");
36}
37
38#[derive(Clone, Copy, Debug)]
40#[non_exhaustive]
41pub enum PromptType {
42 Confirm,
43 Input,
44 Select,
45 Password,
46}
47
48impl core::fmt::Display for PromptType {
49 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
50 let name = match *self {
51 Self::Confirm => "confirm",
52 Self::Input => "input",
53 Self::Select => "fuzzy selection",
54 Self::Password => "password",
55 };
56
57 write!(f, "{name}")
58 }
59}
60
61#[derive(thiserror::Error, Debug)]
63#[non_exhaustive]
64pub enum InteractionError {
65 #[error("mode of interactivity not set")]
66 NoContext,
67 #[error("unable to provide interactivity in this context, and no valid default value for {0} prompt `{1}`")]
68 NotInteractive(PromptType, String),
69 #[error("I/O error while interacting with terminal")]
70 IO(#[from] std::io::Error),
71}
72
73#[derive(Clone, Copy, Debug)]
75#[non_exhaustive]
76pub enum InteractiveContext {
77 Terminal,
78 NotInteractive,
79}
80
81pub struct Confirm(Box<dyn DefaultPrompt<bool>>);
83
84pub struct Select(Box<dyn SelectionPrompt<usize>>);
86
87pub struct Input(Box<dyn TextPrompt<String>>);
89
90pub struct Password(Box<dyn PasswordPrompt<String>>);
92
93pub struct ProgressBar(Box<dyn ProgressBarTrait>);
95
96pub struct Spinner(Box<dyn SpinnerTrait>);