Skip to main content

SecretPrompt

Struct SecretPrompt 

Source
pub struct SecretPrompt { /* private fields */ }
Expand description

Builder returned by secret().

Implementations§

Source§

impl SecretPrompt

Source

pub fn allow_empty(self, v: bool) -> Self

Allow submitting an empty value (default: false).

Examples found in repository?
examples/prompt.rs (line 118)
17fn main() -> cli_ui::prompt::Result<()> {
18    header!(
19        "prompt",
20        env!("CARGO_PKG_VERSION"),
21        "interactive prompt showcase",
22        "all prompt types"
23    );
24
25    intro("Set up a new project");
26
27    // ── 1. Single select with per-option hints ────────────────────────────────
28    let template = select("How would you like to start your new project?")
29        .option("basic", "A basic, helpful starter project")
30        .option("blog", "Use blog template")
31        .hint("Markdown-based blog with RSS feed support")
32        .option("docs", "Use docs (Starlight) template")
33        .hint("Documentation site with search and sidebar")
34        .option("minimal", "Use minimal (empty) template")
35        .hint("Just a Cargo.toml and src/lib.rs — nothing else")
36        .run()?;
37
38    // ── 2. Text input with validation ─────────────────────────────────────────
39    let dir = text("Where should we create your new project?")
40        .default("./my-app")
41        .placeholder("e.g. ./my-project")
42        .hint("Use a relative or absolute path")
43        .validate(|s| {
44            if s.starts_with('.') || s.starts_with('/') {
45                Ok(())
46            } else {
47                Err("path must start with . or /".into())
48            }
49        })
50        .run()?;
51
52    // ── 3. Multi select with per-option hints ─────────────────────────────────
53    let features = multiselect("Which features would you like to enable?")
54        .option("ts", "TypeScript")
55        .hint("JavaScript with syntax for types")
56        .option("tailwind", "Tailwind CSS")
57        .hint("A utility-first CSS framework")
58        .option("react", "React")
59        .hint("A JavaScript library for building user interfaces")
60        .option("vue", "Vue")
61        .hint("The Progressive JavaScript Framework")
62        .option("eslint", "ESLint")
63        .hint("Find and fix problems in your JavaScript code")
64        .run()?;
65
66    // ── 4. Grouped multiselect ────────────────────────────────────────────────
67    let tools = groupmultiselect("Select development tools:")
68        .group("Frontend")
69        .item("TypeScript")
70        .hint("JavaScript with syntax for types")
71        .item("ESLint")
72        .hint("Find and fix problems in your JS code")
73        .item("Prettier")
74        .hint("An opinionated code formatter")
75        .group("Backend")
76        .item("Node.js")
77        .hint("JavaScript runtime built on V8")
78        .item("Express")
79        .hint("Fast, unopinionated web framework")
80        .item("Prisma")
81        .hint("Next-generation ORM for Node.js")
82        .group("Testing")
83        .item("Jest")
84        .hint("Delightful JavaScript testing framework")
85        .item("Cypress")
86        .hint("End-to-end testing for the modern web")
87        .item("Vitest")
88        .hint("Vite-native unit testing framework")
89        .run()?;
90
91    // ── 5. Autocomplete ───────────────────────────────────────────────────────
92    let pkg = autocomplete("Search for a UI package:")
93        .option("astro", "Astro")
94        .hint("The web framework for content-based sites")
95        .option("react", "React")
96        .hint("A JavaScript library for building user interfaces")
97        .option("vue", "Vue")
98        .hint("The Progressive JavaScript Framework")
99        .option("svelte", "Svelte")
100        .hint("Cybernetically enhanced web apps")
101        .option("angular", "Angular")
102        .hint("Platform for building mobile & desktop web apps")
103        .option("solid", "SolidJS")
104        .hint("Simple and performant reactivity for building UIs")
105        .option("qwik", "Qwik")
106        .hint("HTML-first framework with instant interactivity")
107        .placeholder("Type to search...")
108        .max_items(5)
109        .run()?;
110
111    // ── 6. Confirm ────────────────────────────────────────────────────────────
112    let git = confirm("Initialize a new git repository?")
113        .default(true)
114        .run()?;
115
116    // ── 7. Secret ─────────────────────────────────────────────────────────────
117    let _token = secret("Enter your API token (optional)")
118        .allow_empty(true)
119        .hint("Leave empty to skip — you can set it later in .env")
120        .run()?;
121
122    // ── 8. Single-keypress select ─────────────────────────────────────────────
123    let action = select_key("Apply changes?")
124        .option('y', "Yes, apply")
125        .hint("write to disk")
126        .option('n', "No, abort")
127        .hint("discard everything")
128        .option('d', "Diff first")
129        .hint("preview the changes")
130        .run()?;
131    log::info(format!("you chose: {} ({})", action.key, action.label));
132
133    note(
134        "What happens next",
135        "We'll scaffold your project, install dependencies,\nand initialise git if you opted in.",
136    );
137
138    // ── 9. Spinner + tasks runner ─────────────────────────────────────────────
139    let s = spinner();
140    s.start("Resolving dependencies");
141    std::thread::sleep(std::time::Duration::from_millis(700));
142    s.message("Downloading 42 packages");
143    std::thread::sleep(std::time::Duration::from_millis(700));
144    s.stop("Resolved 42 packages");
145
146    // ── 10. Progress bar ──────────────────────────────────────────────────────
147    // Filled/empty bar rendered inside a spinner line. Advance in a loop
148    // (or from a worker thread) with `.advance(step, Some(message))`.
149    let pb = progress().style(ProgressStyle::Heavy).size(30).max(50);
150    pb.start("Downloading assets");
151    for i in 1..=50 {
152        std::thread::sleep(std::time::Duration::from_millis(30));
153        let msg = format!("asset {i}/50");
154        pb.advance(1, Some(msg));
155    }
156    pb.stop("Downloaded 50 assets");
157
158    tasks(vec![
159        Task::new("Compiling", |s| {
160            std::thread::sleep(std::time::Duration::from_millis(400));
161            s.message("crate cli-ui");
162            std::thread::sleep(std::time::Duration::from_millis(400));
163            Some("Compiled in 0.8s".into())
164        }),
165        Task::new("Running tests", |_| {
166            std::thread::sleep(std::time::Duration::from_millis(500));
167            Some("All 12 tests passed".into())
168        }),
169    ]);
170
171    log::success("Project ready");
172    outro("Happy hacking!");
173
174    let _ = prompt::Result::<()>::Ok(());
175
176    // ── Summary ───────────────────────────────────────────────────────────────
177    let feat_str = if features.is_empty() {
178        paint(DIM, "none")
179    } else {
180        paint(OK, &features.values().join(", "))
181    };
182
183    let tool_str = if tools.is_empty() {
184        paint(DIM, "none")
185    } else {
186        paint(OK, &tools.values().join(", "))
187    };
188
189    summary! {
190        done:        "Project configured",
191        "template"   => paint(CYAN,   template.value()),
192        "directory"  => paint(CYAN,   &dir),
193        section,
194        "features"   => feat_str,
195        "tools"      => tool_str,
196        "ui package" => paint(CYAN,   pkg.value()),
197        section,
198        "git"        => paint(if git { OK } else { DIM }, if git { "yes" } else { "no" }),
199    }
200
201    Ok(())
202}
Source

pub fn hint(self, v: impl Into<String>) -> Self

One-line hint rendered under the label (gated by settings::Settings::show_hints).

Examples found in repository?
examples/prompt.rs (line 119)
17fn main() -> cli_ui::prompt::Result<()> {
18    header!(
19        "prompt",
20        env!("CARGO_PKG_VERSION"),
21        "interactive prompt showcase",
22        "all prompt types"
23    );
24
25    intro("Set up a new project");
26
27    // ── 1. Single select with per-option hints ────────────────────────────────
28    let template = select("How would you like to start your new project?")
29        .option("basic", "A basic, helpful starter project")
30        .option("blog", "Use blog template")
31        .hint("Markdown-based blog with RSS feed support")
32        .option("docs", "Use docs (Starlight) template")
33        .hint("Documentation site with search and sidebar")
34        .option("minimal", "Use minimal (empty) template")
35        .hint("Just a Cargo.toml and src/lib.rs — nothing else")
36        .run()?;
37
38    // ── 2. Text input with validation ─────────────────────────────────────────
39    let dir = text("Where should we create your new project?")
40        .default("./my-app")
41        .placeholder("e.g. ./my-project")
42        .hint("Use a relative or absolute path")
43        .validate(|s| {
44            if s.starts_with('.') || s.starts_with('/') {
45                Ok(())
46            } else {
47                Err("path must start with . or /".into())
48            }
49        })
50        .run()?;
51
52    // ── 3. Multi select with per-option hints ─────────────────────────────────
53    let features = multiselect("Which features would you like to enable?")
54        .option("ts", "TypeScript")
55        .hint("JavaScript with syntax for types")
56        .option("tailwind", "Tailwind CSS")
57        .hint("A utility-first CSS framework")
58        .option("react", "React")
59        .hint("A JavaScript library for building user interfaces")
60        .option("vue", "Vue")
61        .hint("The Progressive JavaScript Framework")
62        .option("eslint", "ESLint")
63        .hint("Find and fix problems in your JavaScript code")
64        .run()?;
65
66    // ── 4. Grouped multiselect ────────────────────────────────────────────────
67    let tools = groupmultiselect("Select development tools:")
68        .group("Frontend")
69        .item("TypeScript")
70        .hint("JavaScript with syntax for types")
71        .item("ESLint")
72        .hint("Find and fix problems in your JS code")
73        .item("Prettier")
74        .hint("An opinionated code formatter")
75        .group("Backend")
76        .item("Node.js")
77        .hint("JavaScript runtime built on V8")
78        .item("Express")
79        .hint("Fast, unopinionated web framework")
80        .item("Prisma")
81        .hint("Next-generation ORM for Node.js")
82        .group("Testing")
83        .item("Jest")
84        .hint("Delightful JavaScript testing framework")
85        .item("Cypress")
86        .hint("End-to-end testing for the modern web")
87        .item("Vitest")
88        .hint("Vite-native unit testing framework")
89        .run()?;
90
91    // ── 5. Autocomplete ───────────────────────────────────────────────────────
92    let pkg = autocomplete("Search for a UI package:")
93        .option("astro", "Astro")
94        .hint("The web framework for content-based sites")
95        .option("react", "React")
96        .hint("A JavaScript library for building user interfaces")
97        .option("vue", "Vue")
98        .hint("The Progressive JavaScript Framework")
99        .option("svelte", "Svelte")
100        .hint("Cybernetically enhanced web apps")
101        .option("angular", "Angular")
102        .hint("Platform for building mobile & desktop web apps")
103        .option("solid", "SolidJS")
104        .hint("Simple and performant reactivity for building UIs")
105        .option("qwik", "Qwik")
106        .hint("HTML-first framework with instant interactivity")
107        .placeholder("Type to search...")
108        .max_items(5)
109        .run()?;
110
111    // ── 6. Confirm ────────────────────────────────────────────────────────────
112    let git = confirm("Initialize a new git repository?")
113        .default(true)
114        .run()?;
115
116    // ── 7. Secret ─────────────────────────────────────────────────────────────
117    let _token = secret("Enter your API token (optional)")
118        .allow_empty(true)
119        .hint("Leave empty to skip — you can set it later in .env")
120        .run()?;
121
122    // ── 8. Single-keypress select ─────────────────────────────────────────────
123    let action = select_key("Apply changes?")
124        .option('y', "Yes, apply")
125        .hint("write to disk")
126        .option('n', "No, abort")
127        .hint("discard everything")
128        .option('d', "Diff first")
129        .hint("preview the changes")
130        .run()?;
131    log::info(format!("you chose: {} ({})", action.key, action.label));
132
133    note(
134        "What happens next",
135        "We'll scaffold your project, install dependencies,\nand initialise git if you opted in.",
136    );
137
138    // ── 9. Spinner + tasks runner ─────────────────────────────────────────────
139    let s = spinner();
140    s.start("Resolving dependencies");
141    std::thread::sleep(std::time::Duration::from_millis(700));
142    s.message("Downloading 42 packages");
143    std::thread::sleep(std::time::Duration::from_millis(700));
144    s.stop("Resolved 42 packages");
145
146    // ── 10. Progress bar ──────────────────────────────────────────────────────
147    // Filled/empty bar rendered inside a spinner line. Advance in a loop
148    // (or from a worker thread) with `.advance(step, Some(message))`.
149    let pb = progress().style(ProgressStyle::Heavy).size(30).max(50);
150    pb.start("Downloading assets");
151    for i in 1..=50 {
152        std::thread::sleep(std::time::Duration::from_millis(30));
153        let msg = format!("asset {i}/50");
154        pb.advance(1, Some(msg));
155    }
156    pb.stop("Downloaded 50 assets");
157
158    tasks(vec![
159        Task::new("Compiling", |s| {
160            std::thread::sleep(std::time::Duration::from_millis(400));
161            s.message("crate cli-ui");
162            std::thread::sleep(std::time::Duration::from_millis(400));
163            Some("Compiled in 0.8s".into())
164        }),
165        Task::new("Running tests", |_| {
166            std::thread::sleep(std::time::Duration::from_millis(500));
167            Some("All 12 tests passed".into())
168        }),
169    ]);
170
171    log::success("Project ready");
172    outro("Happy hacking!");
173
174    let _ = prompt::Result::<()>::Ok(());
175
176    // ── Summary ───────────────────────────────────────────────────────────────
177    let feat_str = if features.is_empty() {
178        paint(DIM, "none")
179    } else {
180        paint(OK, &features.values().join(", "))
181    };
182
183    let tool_str = if tools.is_empty() {
184        paint(DIM, "none")
185    } else {
186        paint(OK, &tools.values().join(", "))
187    };
188
189    summary! {
190        done:        "Project configured",
191        "template"   => paint(CYAN,   template.value()),
192        "directory"  => paint(CYAN,   &dir),
193        section,
194        "features"   => feat_str,
195        "tools"      => tool_str,
196        "ui package" => paint(CYAN,   pkg.value()),
197        section,
198        "git"        => paint(if git { OK } else { DIM }, if git { "yes" } else { "no" }),
199    }
200
201    Ok(())
202}
Source

pub fn validate<F>(self, f: F) -> Self
where F: Fn(&str) -> Result<(), String> + Send + Sync + 'static,

Validate with an ad-hoc closure.

Source

pub fn rule(self, v: Validator) -> Self

Apply a composed Validator from the rules library.

Examples found in repository?
examples/prompt_validate.rs (lines 32-39)
9fn main() {
10    let _ = colors(); // silence unused-import warning if you remove theming below
11
12    intro("Validation playground");
13
14    let abort = "Aborted — nothing was saved.";
15
16    // 12-word seed phrase, composed from primitives.
17    let lowercase_words = Validator::new(|v: &str| {
18        if v.split_whitespace()
19            .all(|w| w.chars().all(|c| c.is_ascii_lowercase()))
20        {
21            Ok(())
22        } else {
23            Err("Words must be lowercase ASCII".into())
24        }
25    });
26    let _seed = text("Recovery phrase")
27        .rule(word_count(12).and(lowercase_words))
28        .run()
29        .or_cancel(abort);
30
31    let _pw = secret("Set a password")
32        .rule(
33            min_chars(12)
34                .and(has_upper())
35                .and(has_lower())
36                .and(has_digit())
37                .and(has_special())
38                .msg("≥12 chars with upper, lower, digit, and a special char"),
39        )
40        .run()
41        .or_cancel(abort);
42
43    let _mail = text("Email")
44        .placeholder("you@example.com")
45        .rule(email())
46        .run()
47        .or_cancel(abort);
48
49    let _port = text("Listen port")
50        .default("8080")
51        .rule(int_between(1024, 65535))
52        .run()
53        .or_cancel(abort);
54
55    let _user = text("Username")
56        .rule(
57            min_chars(3)
58                .and(max_chars(20))
59                .and(alphanumeric())
60                .msg("3–20 alphanumeric characters"),
61        )
62        .run()
63        .or_cancel(abort);
64
65    let _name = text("Display name")
66        .validate(|s: &str| {
67            if s.contains(char::is_whitespace) {
68                Err("No spaces allowed".into())
69            } else {
70                Ok(())
71            }
72        })
73        .run()
74        .or_cancel(abort);
75
76    outro("All validators passed!");
77}
Source

pub fn validate_with(self, v: Validator) -> Self

👎Deprecated since 0.1.0:

use .rule(...) instead

Deprecated alias for rule.

Source

pub fn run(self) -> Result<String>

Run the prompt to completion.

Examples found in repository?
examples/prompt_validate.rs (line 40)
9fn main() {
10    let _ = colors(); // silence unused-import warning if you remove theming below
11
12    intro("Validation playground");
13
14    let abort = "Aborted — nothing was saved.";
15
16    // 12-word seed phrase, composed from primitives.
17    let lowercase_words = Validator::new(|v: &str| {
18        if v.split_whitespace()
19            .all(|w| w.chars().all(|c| c.is_ascii_lowercase()))
20        {
21            Ok(())
22        } else {
23            Err("Words must be lowercase ASCII".into())
24        }
25    });
26    let _seed = text("Recovery phrase")
27        .rule(word_count(12).and(lowercase_words))
28        .run()
29        .or_cancel(abort);
30
31    let _pw = secret("Set a password")
32        .rule(
33            min_chars(12)
34                .and(has_upper())
35                .and(has_lower())
36                .and(has_digit())
37                .and(has_special())
38                .msg("≥12 chars with upper, lower, digit, and a special char"),
39        )
40        .run()
41        .or_cancel(abort);
42
43    let _mail = text("Email")
44        .placeholder("you@example.com")
45        .rule(email())
46        .run()
47        .or_cancel(abort);
48
49    let _port = text("Listen port")
50        .default("8080")
51        .rule(int_between(1024, 65535))
52        .run()
53        .or_cancel(abort);
54
55    let _user = text("Username")
56        .rule(
57            min_chars(3)
58                .and(max_chars(20))
59                .and(alphanumeric())
60                .msg("3–20 alphanumeric characters"),
61        )
62        .run()
63        .or_cancel(abort);
64
65    let _name = text("Display name")
66        .validate(|s: &str| {
67            if s.contains(char::is_whitespace) {
68                Err("No spaces allowed".into())
69            } else {
70                Ok(())
71            }
72        })
73        .run()
74        .or_cancel(abort);
75
76    outro("All validators passed!");
77}
More examples
Hide additional examples
examples/prompt.rs (line 120)
17fn main() -> cli_ui::prompt::Result<()> {
18    header!(
19        "prompt",
20        env!("CARGO_PKG_VERSION"),
21        "interactive prompt showcase",
22        "all prompt types"
23    );
24
25    intro("Set up a new project");
26
27    // ── 1. Single select with per-option hints ────────────────────────────────
28    let template = select("How would you like to start your new project?")
29        .option("basic", "A basic, helpful starter project")
30        .option("blog", "Use blog template")
31        .hint("Markdown-based blog with RSS feed support")
32        .option("docs", "Use docs (Starlight) template")
33        .hint("Documentation site with search and sidebar")
34        .option("minimal", "Use minimal (empty) template")
35        .hint("Just a Cargo.toml and src/lib.rs — nothing else")
36        .run()?;
37
38    // ── 2. Text input with validation ─────────────────────────────────────────
39    let dir = text("Where should we create your new project?")
40        .default("./my-app")
41        .placeholder("e.g. ./my-project")
42        .hint("Use a relative or absolute path")
43        .validate(|s| {
44            if s.starts_with('.') || s.starts_with('/') {
45                Ok(())
46            } else {
47                Err("path must start with . or /".into())
48            }
49        })
50        .run()?;
51
52    // ── 3. Multi select with per-option hints ─────────────────────────────────
53    let features = multiselect("Which features would you like to enable?")
54        .option("ts", "TypeScript")
55        .hint("JavaScript with syntax for types")
56        .option("tailwind", "Tailwind CSS")
57        .hint("A utility-first CSS framework")
58        .option("react", "React")
59        .hint("A JavaScript library for building user interfaces")
60        .option("vue", "Vue")
61        .hint("The Progressive JavaScript Framework")
62        .option("eslint", "ESLint")
63        .hint("Find and fix problems in your JavaScript code")
64        .run()?;
65
66    // ── 4. Grouped multiselect ────────────────────────────────────────────────
67    let tools = groupmultiselect("Select development tools:")
68        .group("Frontend")
69        .item("TypeScript")
70        .hint("JavaScript with syntax for types")
71        .item("ESLint")
72        .hint("Find and fix problems in your JS code")
73        .item("Prettier")
74        .hint("An opinionated code formatter")
75        .group("Backend")
76        .item("Node.js")
77        .hint("JavaScript runtime built on V8")
78        .item("Express")
79        .hint("Fast, unopinionated web framework")
80        .item("Prisma")
81        .hint("Next-generation ORM for Node.js")
82        .group("Testing")
83        .item("Jest")
84        .hint("Delightful JavaScript testing framework")
85        .item("Cypress")
86        .hint("End-to-end testing for the modern web")
87        .item("Vitest")
88        .hint("Vite-native unit testing framework")
89        .run()?;
90
91    // ── 5. Autocomplete ───────────────────────────────────────────────────────
92    let pkg = autocomplete("Search for a UI package:")
93        .option("astro", "Astro")
94        .hint("The web framework for content-based sites")
95        .option("react", "React")
96        .hint("A JavaScript library for building user interfaces")
97        .option("vue", "Vue")
98        .hint("The Progressive JavaScript Framework")
99        .option("svelte", "Svelte")
100        .hint("Cybernetically enhanced web apps")
101        .option("angular", "Angular")
102        .hint("Platform for building mobile & desktop web apps")
103        .option("solid", "SolidJS")
104        .hint("Simple and performant reactivity for building UIs")
105        .option("qwik", "Qwik")
106        .hint("HTML-first framework with instant interactivity")
107        .placeholder("Type to search...")
108        .max_items(5)
109        .run()?;
110
111    // ── 6. Confirm ────────────────────────────────────────────────────────────
112    let git = confirm("Initialize a new git repository?")
113        .default(true)
114        .run()?;
115
116    // ── 7. Secret ─────────────────────────────────────────────────────────────
117    let _token = secret("Enter your API token (optional)")
118        .allow_empty(true)
119        .hint("Leave empty to skip — you can set it later in .env")
120        .run()?;
121
122    // ── 8. Single-keypress select ─────────────────────────────────────────────
123    let action = select_key("Apply changes?")
124        .option('y', "Yes, apply")
125        .hint("write to disk")
126        .option('n', "No, abort")
127        .hint("discard everything")
128        .option('d', "Diff first")
129        .hint("preview the changes")
130        .run()?;
131    log::info(format!("you chose: {} ({})", action.key, action.label));
132
133    note(
134        "What happens next",
135        "We'll scaffold your project, install dependencies,\nand initialise git if you opted in.",
136    );
137
138    // ── 9. Spinner + tasks runner ─────────────────────────────────────────────
139    let s = spinner();
140    s.start("Resolving dependencies");
141    std::thread::sleep(std::time::Duration::from_millis(700));
142    s.message("Downloading 42 packages");
143    std::thread::sleep(std::time::Duration::from_millis(700));
144    s.stop("Resolved 42 packages");
145
146    // ── 10. Progress bar ──────────────────────────────────────────────────────
147    // Filled/empty bar rendered inside a spinner line. Advance in a loop
148    // (or from a worker thread) with `.advance(step, Some(message))`.
149    let pb = progress().style(ProgressStyle::Heavy).size(30).max(50);
150    pb.start("Downloading assets");
151    for i in 1..=50 {
152        std::thread::sleep(std::time::Duration::from_millis(30));
153        let msg = format!("asset {i}/50");
154        pb.advance(1, Some(msg));
155    }
156    pb.stop("Downloaded 50 assets");
157
158    tasks(vec![
159        Task::new("Compiling", |s| {
160            std::thread::sleep(std::time::Duration::from_millis(400));
161            s.message("crate cli-ui");
162            std::thread::sleep(std::time::Duration::from_millis(400));
163            Some("Compiled in 0.8s".into())
164        }),
165        Task::new("Running tests", |_| {
166            std::thread::sleep(std::time::Duration::from_millis(500));
167            Some("All 12 tests passed".into())
168        }),
169    ]);
170
171    log::success("Project ready");
172    outro("Happy hacking!");
173
174    let _ = prompt::Result::<()>::Ok(());
175
176    // ── Summary ───────────────────────────────────────────────────────────────
177    let feat_str = if features.is_empty() {
178        paint(DIM, "none")
179    } else {
180        paint(OK, &features.values().join(", "))
181    };
182
183    let tool_str = if tools.is_empty() {
184        paint(DIM, "none")
185    } else {
186        paint(OK, &tools.values().join(", "))
187    };
188
189    summary! {
190        done:        "Project configured",
191        "template"   => paint(CYAN,   template.value()),
192        "directory"  => paint(CYAN,   &dir),
193        section,
194        "features"   => feat_str,
195        "tools"      => tool_str,
196        "ui package" => paint(CYAN,   pkg.value()),
197        section,
198        "git"        => paint(if git { OK } else { DIM }, if git { "yes" } else { "no" }),
199    }
200
201    Ok(())
202}

Trait Implementations§

Source§

impl Prompt for SecretPrompt

Source§

type Output = String

The value returned to the caller on successful submission.
Source§

fn handle(&mut self, key: Key) -> Step<String>

Apply a key press to the prompt’s internal state. Return: Read more
Source§

fn render(&self, ctx: RenderCtx<'_>) -> Frame

Render the prompt’s current state as one frame (a Vec<String>, one entry per terminal row). The runner takes care of writing the frame and clearing it on the next iteration — prompts never call eprintln! themselves.
Source§

fn render_answered(&self, _value: &String) -> Frame

Render the prompt’s post-submission display. Typically the ◇ question / │ value / │ triple from theme::answered.
Source§

fn run_fallback(self) -> Result<String>

Optional non-interactive fallback for piped/CI environments. The default is to refuse — most prompts override this with a numeric or line-buffered alternative.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.