aboutsummaryrefslogtreecommitdiff
path: root/src/color.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/color.rs')
-rw-r--r--src/color.rs174
1 files changed, 84 insertions, 90 deletions
diff --git a/src/color.rs b/src/color.rs
index 20fbb38..f0ab080 100644
--- a/src/color.rs
+++ b/src/color.rs
@@ -458,81 +458,13 @@ fn ansi_to_rgb(code: u8) -> (u8, u8, u8) {
}
}
-/// Detect the best available color mode for the terminal
-pub fn detect_color_mode() -> ColorMode {
- if std::env::var("NO_COLOR").is_ok() {
- return ColorMode::NoColor;
- }
-
- if let Ok(colorterm) = std::env::var("COLORTERM")
- && (colorterm.contains("truecolor") || colorterm.contains("24bit"))
- {
- return ColorMode::Truecolor;
- }
-
- if let Ok(term) = std::env::var("TERM") {
- if term.contains("256color") {
- return ColorMode::Ansi256;
- }
- if term.contains("color") {
- return ColorMode::Ansi16;
- }
- }
-
- // If running on Windows, try to enable ANSI (virtual terminal processing)
- #[cfg(windows)]
- {
- if enable_windows_ansi() {
- // After enabling ANSI, reuse heuristic
- if let Ok(colorterm) = std::env::var("COLORTERM")
- && (colorterm.contains("truecolor") || colorterm.contains("24bit"))
- {
- return ColorMode::Truecolor;
- }
-
- if let Ok(term) = std::env::var("TERM") {
- if term.contains("256color") {
- return ColorMode::Ansi256;
- }
- if term.contains("color") {
- return ColorMode::Ansi16;
- }
- }
-
- return ColorMode::Ansi16;
- } else {
- // If we couldn't enable ANSI, detect shell and adjust gracefully
- if let Some(shell) = detect_windows_shell() {
- let shell = shell.to_lowercase();
- if shell.contains("cmd.exe") {
- // cmd historically doesn't support ANSI; fallback to Ansi16
- return ColorMode::Ansi16;
- }
- if shell.contains("powershell") || shell.contains("pwsh") {
- // Try to detect term capability
- if let Ok(term) = std::env::var("TERM") {
- if term.contains("256color") {
- return ColorMode::Ansi256;
- }
- }
- // Default to Ansi16 when in older hosts
- return ColorMode::Ansi16;
- }
- }
- // Generic fallback if no shell detected
- return ColorMode::Ansi16;
- }
- }
-
- // Default fallback for non-Windows
- ColorMode::Ansi16
-}
+// (Removed older detect_color_mode to keep a single refactored implementation)
/// Try to enable ANSI (virtual terminal processing) on Windows consoles.
/// Returns true if enabling succeeded or isn't necessary, false otherwise.
#[cfg(windows)]
pub fn enable_windows_ansi() -> bool {
- use std::ptr;
+ // no ptr usage required; removed unused import
use winapi::um::consoleapi::{GetConsoleMode, SetConsoleMode};
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
use winapi::um::processenv::GetStdHandle;
@@ -559,49 +491,95 @@ pub fn enable_windows_ansi() -> bool {
true
}
-/// Detect the parent shell name on Windows, using the sysinfo crate.
+/// Detect the parent shell name on Windows, using environment hints.
#[cfg(windows)]
pub fn detect_windows_shell() -> Option<String> {
// Heuristic checks using common env vars
- // PowerShell sets PSModulePath; pwsh may also set POWERSHELL_* env vars.
if std::env::var("PSModulePath").is_ok() {
return Some("powershell".to_string());
}
-
- if std::env::var("PWshPROFILE").is_ok() || std::env::var("$PWSH_VERSION").is_ok() {
- // Some versions of pwsh may expose env vars; use generic pwsh hint
+ if std::env::var("PWshPROFILE").is_ok() || std::env::var("PWSH_VERSION").is_ok() {
return Some("pwsh".to_string());
}
-
- // COMSPEC usually points to cmd.exe on Windows
if let Ok(comspec) = std::env::var("COMSPEC") {
if comspec.to_lowercase().ends_with("cmd.exe") {
return Some("cmd.exe".to_string());
}
}
-
- // Windows Terminal sets WT_SESSION, but it's not a shell; just return terminal info
if std::env::var("WT_SESSION").is_ok() {
return Some("windows_terminal".to_string());
}
+ None
+}
+#[cfg(not(windows))]
+#[allow(dead_code)]
+pub fn detect_windows_shell() -> Option<String> {
None
}
-/// Linear interpolation between two colors in HSV space
-pub fn lerp_color_hsv(start: &Color, end: &Color, t: f32) -> Color {
- let (h1, s1, v1) = rgb_to_hsv(start.to_rgb());
- let (h2, s2, v2) = rgb_to_hsv(end.to_rgb());
+/// Convert Color to a crossterm Color (helper for use across platforms)
+pub fn to_crossterm_color(color: &Color) -> crossterm::style::Color {
+ let (r, g, b) = color.to_rgb();
+ crossterm::style::Color::Rgb { r, g, b }
+}
- // Handle hue interpolation correctly (shortest path around the color wheel)
- let h_diff = (h2 - h1 + 180.0) % 360.0 - 180.0;
- let h = (h1 + h_diff * t + 360.0) % 360.0;
+/// Detect the parent shell name on Windows, using the sysinfo crate.
+pub fn detect_color_mode() -> ColorMode {
+ if std::env::var("NO_COLOR").is_ok() {
+ return ColorMode::NoColor;
+ }
- let s = s1 + (s2 - s1) * t;
- let v = v1 + (v2 - v1) * t;
+ // Early checks
+ if std::env::var("COLORTERM").is_ok_and(|colorterm| {
+ colorterm.contains("truecolor") || colorterm.contains("24bit")
+ }) {
+ return ColorMode::Truecolor;
+ }
- let (r, g, b) = hsv_to_rgb(h, s, v);
- Color::Truecolor(r, g, b)
+ if std::env::var("TERM").is_ok_and(|term| term.contains("256color")) {
+ return ColorMode::Ansi256;
+ }
+ if std::env::var("TERM").is_ok_and(|term| term.contains("color")) {
+ return ColorMode::Ansi16;
+ }
+
+ // Default fallback
+ let mode = ColorMode::Ansi16;
+
+ // If running on Windows, try to enable ANSI (virtual terminal processing)
+ #[cfg(windows)]
+ {
+ if enable_windows_ansi() {
+ // Re-check for a better mode
+ if let Ok(colorterm) = std::env::var("COLORTERM") {
+ if colorterm.contains("truecolor") || colorterm.contains("24bit") {
+ mode = ColorMode::Truecolor;
+ }
+ }
+ if let Ok(term) = std::env::var("TERM") {
+ if term.contains("256color") {
+ mode = ColorMode::Ansi256;
+ }
+ }
+ } else if let Some(shell) = detect_windows_shell() {
+ let shell = shell.to_lowercase();
+ if shell.contains("cmd.exe") {
+ // cmd historically doesn't support ANSI; use 16 colors fallback
+ mode = ColorMode::Ansi16;
+ } else if shell.contains("powershell") || shell.contains("pwsh") {
+ if let Ok(term) = std::env::var("TERM") {
+ if term.contains("256color") {
+ mode = ColorMode::Ansi256;
+ }
+ }
+ } else {
+ mode = ColorMode::Ansi16;
+ }
+ }
+ }
+
+ mode
}
/// Convert RGB to HSV
@@ -632,6 +610,22 @@ fn rgb_to_hsv((r, g, b): (u8, u8, u8)) -> (f32, f32, f32) {
(h, s, v)
}
+/// Linear interpolation between two colors in HSV space
+pub fn lerp_color_hsv(start: &Color, end: &Color, t: f32) -> Color {
+ let (h1, s1, v1) = rgb_to_hsv(start.to_rgb());
+ let (h2, s2, v2) = rgb_to_hsv(end.to_rgb());
+
+ // Handle hue interpolation correctly (shortest path around the color wheel)
+ let h_diff = (h2 - h1 + 180.0) % 360.0 - 180.0;
+ let h = (h1 + h_diff * t + 360.0) % 360.0;
+
+ let s = s1 + (s2 - s1) * t;
+ let v = v1 + (v2 - v1) * t;
+
+ let (r, g, b) = hsv_to_rgb(h, s, v);
+ Color::Truecolor(r, g, b)
+}
+
/// Convert HSV to RGB
fn hsv_to_rgb(h: f32, s: f32, v: f32) -> (u8, u8, u8) {
let c = v * s;