report: grow the Prompter port and move display_path out of the ui module
Prompter gains interactive(), select() and text() (with the Validator type), and confirm() now propagates cancellation as Err so flows abort instead of silently taking a default when the user hits Ctrl+C. The terminal prompter implements the full port; the port also re-exports the path display helper, which is pure presentation formatting used by events and messages rather than terminal code.
This commit is contained in:
+1
-1
@@ -232,7 +232,7 @@ impl DebUi {
|
||||
if self.shared.enabled && !artifacts.is_empty() {
|
||||
println!("Built in {}s:", elapsed.as_secs());
|
||||
for artifact in artifacts {
|
||||
println!(" {}", crate::ui::display_path(artifact));
|
||||
println!(" {}", crate::report::display_path(artifact));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+31
-8
@@ -12,7 +12,7 @@ use crossterm::{
|
||||
style::{self, Color, Print, SetForegroundColor},
|
||||
terminal,
|
||||
};
|
||||
use std::io::{self, Write};
|
||||
use std::io::{self, IsTerminal, Write};
|
||||
use std::time::Duration;
|
||||
|
||||
/// Why a prompt could not run interactively
|
||||
@@ -32,9 +32,8 @@ impl std::fmt::Display for PromptError {
|
||||
|
||||
impl std::error::Error for PromptError {}
|
||||
|
||||
/// Answer validator of [`text`]: accepts the answer, or explains why it is
|
||||
/// rejected
|
||||
pub type Validator = dyn Fn(&str) -> Result<(), String>;
|
||||
/// Answer validator of [`text`] (re-exported from [`crate::report`])
|
||||
pub use crate::report::Validator;
|
||||
|
||||
/// What a prompt's event loop asks its drawing helper to render; keeping all
|
||||
/// terminal access behind this callback makes the loops pure logic that unit
|
||||
@@ -128,13 +127,37 @@ pub fn confirm(label: &str, default: bool) -> Result<bool, Box<dyn std::error::E
|
||||
}
|
||||
|
||||
/// [`crate::report::Prompter`] answered by the interactive terminal: each
|
||||
/// question runs the matching raw-mode prompt, falling back to the default
|
||||
/// answer when no interactive terminal is attached (CI, piped input).
|
||||
/// question runs the matching raw-mode prompt. Without an interactive
|
||||
/// terminal (CI, piped input) [`Prompter::interactive`] is false — flows
|
||||
/// then take their headless path instead of asking — and a cancel (Ctrl+C)
|
||||
/// propagates as `Err` so flows can abort.
|
||||
pub struct TerminalPrompter;
|
||||
|
||||
impl crate::report::Prompter for TerminalPrompter {
|
||||
fn confirm(&self, question: &str, default: bool) -> bool {
|
||||
confirm(question, default).unwrap_or(default)
|
||||
fn interactive(&self) -> bool {
|
||||
std::io::stdin().is_terminal() && std::io::stdout().is_terminal()
|
||||
}
|
||||
|
||||
fn confirm(&self, question: &str, default: bool) -> Result<bool, Box<dyn std::error::Error>> {
|
||||
confirm(question, default)
|
||||
}
|
||||
|
||||
fn select(
|
||||
&self,
|
||||
label: &str,
|
||||
options: &[String],
|
||||
default: &str,
|
||||
) -> Result<String, Box<dyn std::error::Error>> {
|
||||
select(label, options, default)
|
||||
}
|
||||
|
||||
fn text(
|
||||
&self,
|
||||
label: &str,
|
||||
default: &str,
|
||||
validate: Option<&Validator>,
|
||||
) -> Result<String, Box<dyn std::error::Error>> {
|
||||
text(label, default, validate)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user