//! Some general utility functions. use std::{iter, str::from_utf8}; use crate::data::{Palette, PaletteColor, PaletteSource, ThemeHue}; use crate::envs::get_session_name; use colorsys::Rgb; use strip_ansi_escapes::strip; use unicode_width::UnicodeWidthStr; #[cfg(unix)] pub use unix_only::*; #[cfg(unix)] mod unix_only { use std::os::unix::fs::PermissionsExt; use std::path::Path; use std::{fs, io}; pub fn set_permissions(path: &Path, mode: u32) -> io::Result<()> { let mut permissions = fs::metadata(path)?.permissions(); permissions.set_mode(mode); fs::set_permissions(path, permissions) } } #[cfg(not(unix))] pub fn set_permissions(_path: &std::path::Path, _mode: u32) -> std::io::Result<()> { Ok(()) } pub fn ansi_len(s: &str) -> usize { from_utf8(&strip(s).unwrap()).unwrap().width() } pub fn adjust_to_size(s: &str, rows: usize, columns: usize) -> String { s.lines() .map(|l| { let actual_len = ansi_len(l); if actual_len > columns { let mut line = String::from(l); line.truncate(columns); line } else { [l, &str::repeat(" ", columns - ansi_len(l))].concat() } }) .chain(iter::repeat(str::repeat(" ", columns))) .take(rows) .collect::>() .join("\n\r") } pub fn make_terminal_title(pane_title: &str) -> String { format!( "\u{1b}]0;Zellij {}- {}\u{07}", get_session_name() .map(|n| format!("({}) ", n)) .unwrap_or_default(), pane_title, ) } // Colors pub mod colors { pub const WHITE: u8 = 255; pub const GREEN: u8 = 154; pub const GRAY: u8 = 238; pub const BRIGHT_GRAY: u8 = 245; pub const RED: u8 = 124; pub const ORANGE: u8 = 166; pub const BLACK: u8 = 16; pub const MAGENTA: u8 = 201; pub const CYAN: u8 = 51; pub const YELLOW: u8 = 226; pub const BLUE: u8 = 45; pub const PURPLE: u8 = 99; pub const GOLD: u8 = 136; pub const SILVER: u8 = 245; pub const PINK: u8 = 207; pub const BROWN: u8 = 215; } pub fn _hex_to_rgb(hex: &str) -> (u8, u8, u8) { Rgb::from_hex_str(hex) .expect("The passed argument must be a valid hex color") .into() } pub fn default_palette() -> Palette { Palette { source: PaletteSource::Default, theme_hue: ThemeHue::Dark, fg: PaletteColor::EightBit(colors::BRIGHT_GRAY), bg: PaletteColor::EightBit(colors::GRAY), black: PaletteColor::EightBit(colors::BLACK), red: PaletteColor::EightBit(colors::RED), green: PaletteColor::EightBit(colors::GREEN), yellow: PaletteColor::EightBit(colors::YELLOW), blue: PaletteColor::EightBit(colors::BLUE), magenta: PaletteColor::EightBit(colors::MAGENTA), cyan: PaletteColor::EightBit(colors::CYAN), white: PaletteColor::EightBit(colors::WHITE), orange: PaletteColor::EightBit(colors::ORANGE), gray: PaletteColor::EightBit(colors::GRAY), purple: PaletteColor::EightBit(colors::PURPLE), gold: PaletteColor::EightBit(colors::GOLD), silver: PaletteColor::EightBit(colors::SILVER), pink: PaletteColor::EightBit(colors::PINK), brown: PaletteColor::EightBit(colors::BROWN), } } // Dark magic pub fn detect_theme_hue(bg: PaletteColor) -> ThemeHue { match bg { PaletteColor::Rgb((r, g, b)) => { // HSP, P stands for perceived brightness let hsp: f64 = (0.299 * (r as f64 * r as f64) + 0.587 * (g as f64 * g as f64) + 0.114 * (b as f64 * b as f64)) .sqrt(); match hsp > 127.5 { true => ThemeHue::Light, false => ThemeHue::Dark, } }, _ => ThemeHue::Dark, } } // (this was shamelessly copied from alacritty) // // This returns the current terminal version as a unique number based on the // semver version. The different versions are padded to ensure that a higher semver version will // always report a higher version number. pub fn version_number(mut version: &str) -> usize { if let Some(separator) = version.rfind('-') { version = &version[..separator]; } let mut version_number = 0; let semver_versions = version.split('.'); for (i, semver_version) in semver_versions.rev().enumerate() { let semver_number = semver_version.parse::().unwrap_or(0); version_number += usize::pow(100, i as u32) * semver_number; } version_number }