use owo_colors::{OwoColorize, Stream};
use crate::path_display;
fn symbol_for_stream(s: &str, stream: Stream) -> String {
match s {
"✓" => s.if_supports_color(stream, |t| t.green()).to_string(),
"↑" => s.if_supports_color(stream, |t| t.cyan()).to_string(),
"~" => s.if_supports_color(stream, |t| t.yellow()).to_string(),
"!" => s.if_supports_color(stream, |t| t.magenta()).to_string(),
"✗" => s.if_supports_color(stream, |t| t.red()).to_string(),
other => other.to_string(),
}
}
pub fn symbol(s: &str) -> String {
symbol_for_stream(s, Stream::Stdout)
}
pub fn symbol_stderr(s: &str) -> String {
symbol_for_stream(s, Stream::Stderr)
}
pub fn green(s: &str) -> String {
s.if_supports_color(Stream::Stdout, |t| t.green())
.to_string()
}
pub fn yellow(s: &str) -> String {
s.if_supports_color(Stream::Stdout, |t| t.yellow())
.to_string()
}
pub fn yellow_stderr(s: &str) -> String {
s.if_supports_color(Stream::Stderr, |t| t.yellow())
.to_string()
}
pub fn bold_yellow_stderr(s: &str) -> String {
use owo_colors::Style;
s.if_supports_color(Stream::Stderr, |t| t.style(Style::new().bold().yellow()))
.to_string()
}
pub fn cyan_stderr(s: &str) -> String {
s.if_supports_color(Stream::Stderr, |t| t.cyan())
.to_string()
}
pub fn dim_stderr(s: &str) -> String {
s.if_supports_color(Stream::Stderr, |t| t.dimmed())
.to_string()
}
pub fn red(s: &str) -> String {
s.if_supports_color(Stream::Stdout, |t| t.red()).to_string()
}
pub fn bold(s: &str) -> String {
s.if_supports_color(Stream::Stdout, |t| t.bold())
.to_string()
}
pub fn bold_cyan(s: &str) -> String {
use owo_colors::Style;
s.if_supports_color(Stream::Stdout, |t| t.style(Style::new().bold().cyan()))
.to_string()
}
pub fn dim(s: &str) -> String {
s.if_supports_color(Stream::Stdout, |t| t.dimmed())
.to_string()
}
pub fn cyan(s: &str) -> String {
s.if_supports_color(Stream::Stdout, |t| t.cyan())
.to_string()
}
pub fn status_label(s: &str, sym: &str) -> String {
match sym {
"✓" => s
.if_supports_color(Stream::Stdout, |t| t.green())
.to_string(),
"↑" => s
.if_supports_color(Stream::Stdout, |t| t.cyan())
.to_string(),
"~" | "!" => s
.if_supports_color(Stream::Stdout, |t| t.yellow())
.to_string(),
"✗" => s.if_supports_color(Stream::Stdout, |t| t.red()).to_string(),
_ => s.to_string(),
}
}
const PRESETS_NOTE_LABEL_WIDTH: usize = 18;
fn presets_note_value(plain_label: &str, styled_label: &str, value: &str) -> String {
let pad = " ".repeat(PRESETS_NOTE_LABEL_WIDTH.saturating_sub(plain_label.chars().count()) + 2);
format!("{styled_label}{pad}{value}")
}
fn presets_note(plain_label: &str, styled_label: &str, dir: &std::path::Path) -> String {
presets_note_value(plain_label, styled_label, &path_display::format(dir))
}
pub fn presets_source_note(value: &str) -> String {
use owo_colors::Style;
let label = "◈ Preset Source";
let styled = label
.if_supports_color(Stream::Stdout, |t| t.style(Style::new().bold().cyan()))
.to_string();
presets_note_value(label, &styled, value)
}
pub fn external_presets_note(dir: &std::path::Path) -> String {
presets_source_note(&format!("external · {}", path_display::format(dir)))
}
pub fn presets_overlay_note(dir: &std::path::Path) -> String {
use owo_colors::Style;
let label = "◈ Presets Overlay";
let styled = label
.if_supports_color(Stream::Stdout, |t| t.style(Style::new().bold().yellow()))
.to_string();
presets_note(label, &styled, dir)
}
pub fn shell_deployment_note(value: &str) -> String {
let label = "◈ Shell Deployment";
presets_note_value(label, label, value)
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::Path;
#[test]
fn external_presets_note_contains_path() {
let path = Path::new("/home/user/.custom/presets");
let note = external_presets_note(path);
assert!(
note.contains("/home/user/.custom/presets"),
"note should include the path: {note:?}"
);
}
#[test]
fn external_presets_note_uses_shared_source_label() {
let path = Path::new("/some/dir");
let note = external_presets_note(path);
assert!(
note.contains("Preset Source") && note.contains("external"),
"note should use the shared preset-source vocabulary: {note:?}"
);
}
#[test]
fn presets_note_values_use_the_same_column() {
let source = presets_source_note("built-in");
let external = external_presets_note(Path::new("/external"));
let overlay = presets_overlay_note(Path::new("/overlay"));
let deployment = shell_deployment_note("snapshot");
assert_eq!(source.find("built-in"), external.find("external"));
assert_eq!(source.find("built-in"), overlay.find("/overlay"));
assert_eq!(source.find("built-in"), deployment.find("snapshot"));
}
}