Danielle d1070ca213
Initial draft of profile metadata format & CLI (#17)
* Initial draft of profile metadata format

* Remove records, add Clippy to Nix, fix Clippy error

* Work on profile definition

* BREAKING: Make global settings consistent with profile settings

* Add builder methods & format

* Integrate launching with profiles

* Add profile loading

* Launching via profile, API tweaks, and yak shaving

* Incremental update, committing everything due to personal system maintainance

* Prepare for review cycle

* Remove reminents of experimental work

* CLI: allow people to override the non-empty directory check

* Fix mistake in previous commit

* Handle trailing whitespace and newlines in prompts

* Revamp prompt to use dialoguer and support defaults

* Make requested changes
2022-03-28 18:41:35 -07:00

77 lines
2.0 KiB
Rust

use dialoguer::{Confirm, Input, Select};
use eyre::Result;
use std::{borrow::Cow, path::Path};
// TODO: make primarily async to avoid copies
// Prompting helpers
pub fn prompt(prompt: &str, default: Option<String>) -> Result<String> {
let prompt = match default.as_deref() {
Some("") => Cow::Owned(format!("{prompt} (optional)")),
Some(default) => Cow::Owned(format!("{prompt} (default: {default})")),
None => Cow::Borrowed(prompt),
};
print_prompt(&prompt);
let mut input = Input::<String>::new();
input.with_prompt("").show_default(false);
if let Some(default) = default {
input.default(default);
}
Ok(input.interact_text()?.trim().to_owned())
}
pub async fn prompt_async(
text: String,
default: Option<String>,
) -> Result<String> {
tokio::task::spawn_blocking(move || prompt(&text, default)).await?
}
// Selection helpers
pub fn select(prompt: &str, choices: &[&str]) -> Result<usize> {
print_prompt(prompt);
let res = Select::new().items(choices).default(0).interact()?;
eprintln!("> {}", choices[res]);
Ok(res)
}
pub async fn select_async(
prompt: String,
choices: &'static [&'static str],
) -> Result<usize> {
tokio::task::spawn_blocking(move || select(&prompt, choices)).await?
}
// Confirmation helpers
pub fn confirm(prompt: &str, default: bool) -> Result<bool> {
print_prompt(prompt);
Ok(Confirm::new().default(default).interact()?)
}
pub async fn confirm_async(prompt: String, default: bool) -> Result<bool> {
tokio::task::spawn_blocking(move || confirm(&prompt, default)).await?
}
// Table display helpers
pub fn table_path_display(path: &Path) -> String {
let mut res = path.display().to_string();
if let Some(home_dir) = dirs::home_dir() {
res = res.replace(&home_dir.display().to_string(), "~");
}
res
}
// Internal helpers
fn print_prompt(prompt: &str) {
println!(
"{}",
paris::formatter::colorize_string(format!("<yellow>?</> {prompt}:"))
);
}