Skip to content

Commit

Permalink
ui: control where prompt messages are written
Browse files Browse the repository at this point in the history
  • Loading branch information
torquestomp committed Sep 25, 2024
1 parent e916c6e commit 8debeae
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 7 deletions.
3 changes: 2 additions & 1 deletion cli/src/git_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ pub fn is_colocated_git_workspace(workspace: &Workspace, repo: &ReadonlyRepo) ->
}

fn terminal_get_username(ui: &Ui, url: &str) -> Option<String> {
ui.prompt(&format!("Username for {url}")).ok()
ui.prompt(&mut ui.stdout(), &format!("Username for {url}"))
.ok()
}

fn terminal_get_pw(ui: &Ui, url: &str) -> Option<String> {
Expand Down
1 change: 1 addition & 0 deletions cli/src/movement_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ fn choose_commit<'a>(
drop(formatter);

let choice = ui.prompt_choice(
&mut ui.stdout(),
"enter the index of the commit you want to target",
&choices,
None,
Expand Down
19 changes: 13 additions & 6 deletions cli/src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,15 +566,15 @@ impl Ui {
.unwrap_or(false)
}

pub fn prompt(&self, prompt: &str) -> io::Result<String> {
pub fn prompt(&self, writer: &mut dyn Write, prompt: &str) -> io::Result<String> {
if !Self::can_prompt() {
return Err(io::Error::new(
io::ErrorKind::Unsupported,
"Cannot prompt for input since the output is not connected to a terminal",
));
}
write!(self.stdout(), "{prompt}: ")?;
self.stdout().flush()?;
write!(writer, "{prompt}: ")?;
writer.flush()?;
let mut buf = String::new();
io::stdin().read_line(&mut buf)?;

Expand All @@ -592,20 +592,21 @@ impl Ui {
/// Repeat the given prompt until the input is one of the specified choices.
pub fn prompt_choice(
&self,
writer: &mut dyn Write,
prompt: &str,
choices: &[impl AsRef<str>],
default: Option<&str>,
) -> io::Result<String> {
if !Self::can_prompt() {
if let Some(default) = default {
// Choose the default automatically without waiting.
writeln!(self.stdout(), "{prompt}: {default}")?;
writeln!(writer, "{prompt}: {default}")?;
return Ok(default.to_owned());
}
}

loop {
let choice = self.prompt(prompt)?.trim().to_owned();
let choice = self.prompt(writer, prompt)?.trim().to_owned();
if choice.is_empty() {
if let Some(default) = default {
return Ok(default.to_owned());
Expand All @@ -620,7 +621,12 @@ impl Ui {
}

/// Prompts for a yes-or-no response, with yes = true and no = false.
pub fn prompt_yes_no(&self, prompt: &str, default: Option<bool>) -> io::Result<bool> {
pub fn prompt_yes_no(
&self,
writer: &mut dyn Write,
prompt: &str,
default: Option<bool>,
) -> io::Result<bool> {
let default_str = match &default {
Some(true) => "(Yn)",
Some(false) => "(yN)",
Expand All @@ -629,6 +635,7 @@ impl Ui {
let default_choice = default.map(|c| if c { "Y" } else { "N" });

let choice = self.prompt_choice(
writer,
&format!("{} {}", prompt, default_str),
&["y", "n", "yes", "no", "Yes", "No", "YES", "NO"],
default_choice,
Expand Down

0 comments on commit 8debeae

Please sign in to comment.