78 lines
1.7 KiB
Rust
78 lines
1.7 KiB
Rust
pub mod crypto;
|
||
pub mod editor;
|
||
pub mod formatter;
|
||
pub mod keyring;
|
||
pub mod validators;
|
||
|
||
use anyhow::{Context, Result};
|
||
use colored::Colorize;
|
||
use std::io::{self, Write};
|
||
|
||
/// Print success message
|
||
pub fn print_success(msg: &str) {
|
||
println!("{} {}", "✓".green().bold(), msg);
|
||
}
|
||
|
||
/// Print error message
|
||
pub fn print_error(msg: &str) {
|
||
eprintln!("{} {}", "✗".red().bold(), msg);
|
||
}
|
||
|
||
/// Print warning message
|
||
pub fn print_warning(msg: &str) {
|
||
println!("{} {}", "⚠".yellow().bold(), msg);
|
||
}
|
||
|
||
/// Print info message
|
||
pub fn print_info(msg: &str) {
|
||
println!("{} {}", "ℹ".blue().bold(), msg);
|
||
}
|
||
|
||
/// Confirm action with user
|
||
pub fn confirm(prompt: &str) -> Result<bool> {
|
||
print!("{} [y/N] ", prompt);
|
||
io::stdout().flush()?;
|
||
|
||
let mut input = String::new();
|
||
io::stdin().read_line(&mut input)?;
|
||
|
||
Ok(input.trim().to_lowercase().starts_with('y'))
|
||
}
|
||
|
||
/// Get user input
|
||
pub fn input(prompt: &str) -> Result<String> {
|
||
print!("{}: ", prompt);
|
||
io::stdout().flush()?;
|
||
|
||
let mut input = String::new();
|
||
io::stdin().read_line(&mut input)?;
|
||
|
||
Ok(input.trim().to_string())
|
||
}
|
||
|
||
/// Get password input (hidden)
|
||
pub fn password_input(prompt: &str) -> Result<String> {
|
||
use dialoguer::Password;
|
||
|
||
Password::new()
|
||
.with_prompt(prompt)
|
||
.interact()
|
||
.context("Failed to read password")
|
||
}
|
||
|
||
/// Check if running in a terminal
|
||
pub fn is_terminal() -> bool {
|
||
atty::is(atty::Stream::Stdout)
|
||
}
|
||
|
||
/// Format duration in human-readable format
|
||
pub fn format_duration(secs: u64) -> String {
|
||
if secs < 60 {
|
||
format!("{}s", secs)
|
||
} else if secs < 3600 {
|
||
format!("{}m {}s", secs / 60, secs % 60)
|
||
} else {
|
||
format!("{}h {}m", secs / 3600, (secs % 3600) / 60)
|
||
}
|
||
}
|