1use std::{iter, str::from_utf8};
4
5use crate::data::{Palette, PaletteColor, PaletteSource, ThemeHue};
6use crate::envs::get_session_name;
7use colorsys::Rgb;
8use strip_ansi_escapes::strip;
9use unicode_width::UnicodeWidthStr;
10
11#[cfg(unix)]
12pub use unix_only::*;
13
14#[cfg(unix)]
15mod unix_only {
16 use std::os::unix::fs::PermissionsExt;
17 use std::path::Path;
18 use std::{fs, io};
19
20 pub fn set_permissions(path: &Path, mode: u32) -> io::Result<()> {
21 let mut permissions = fs::metadata(path)?.permissions();
22 permissions.set_mode(mode);
23 fs::set_permissions(path, permissions)
24 }
25}
26
27#[cfg(not(unix))]
28pub fn set_permissions(_path: &std::path::Path, _mode: u32) -> std::io::Result<()> {
29 Ok(())
30}
31
32pub fn ansi_len(s: &str) -> usize {
33 from_utf8(&strip(s).unwrap()).unwrap().width()
34}
35
36pub fn adjust_to_size(s: &str, rows: usize, columns: usize) -> String {
37 s.lines()
38 .map(|l| {
39 let actual_len = ansi_len(l);
40 if actual_len > columns {
41 let mut line = String::from(l);
42 line.truncate(columns);
43 line
44 } else {
45 [l, &str::repeat(" ", columns - ansi_len(l))].concat()
46 }
47 })
48 .chain(iter::repeat(str::repeat(" ", columns)))
49 .take(rows)
50 .collect::<Vec<_>>()
51 .join("\n\r")
52}
53
54pub fn make_terminal_title(pane_title: &str) -> String {
55 format!(
56 "\u{1b}]0;Zellij {}- {}\u{07}",
57 get_session_name()
58 .map(|n| format!("({}) ", n))
59 .unwrap_or_default(),
60 pane_title,
61 )
62}
63
64pub mod colors {
66 pub const WHITE: u8 = 255;
67 pub const GREEN: u8 = 154;
68 pub const GRAY: u8 = 238;
69 pub const BRIGHT_GRAY: u8 = 245;
70 pub const RED: u8 = 124;
71 pub const ORANGE: u8 = 166;
72 pub const BLACK: u8 = 16;
73 pub const MAGENTA: u8 = 201;
74 pub const CYAN: u8 = 51;
75 pub const YELLOW: u8 = 226;
76 pub const BLUE: u8 = 45;
77 pub const PURPLE: u8 = 99;
78 pub const GOLD: u8 = 136;
79 pub const SILVER: u8 = 245;
80 pub const PINK: u8 = 207;
81 pub const BROWN: u8 = 215;
82}
83
84pub fn _hex_to_rgb(hex: &str) -> (u8, u8, u8) {
85 Rgb::from_hex_str(hex)
86 .expect("The passed argument must be a valid hex color")
87 .into()
88}
89
90pub fn default_palette() -> Palette {
91 Palette {
92 source: PaletteSource::Default,
93 theme_hue: ThemeHue::Dark,
94 fg: PaletteColor::EightBit(colors::BRIGHT_GRAY),
95 bg: PaletteColor::EightBit(colors::GRAY),
96 black: PaletteColor::EightBit(colors::BLACK),
97 red: PaletteColor::EightBit(colors::RED),
98 green: PaletteColor::EightBit(colors::GREEN),
99 yellow: PaletteColor::EightBit(colors::YELLOW),
100 blue: PaletteColor::EightBit(colors::BLUE),
101 magenta: PaletteColor::EightBit(colors::MAGENTA),
102 cyan: PaletteColor::EightBit(colors::CYAN),
103 white: PaletteColor::EightBit(colors::WHITE),
104 orange: PaletteColor::EightBit(colors::ORANGE),
105 gray: PaletteColor::EightBit(colors::GRAY),
106 purple: PaletteColor::EightBit(colors::PURPLE),
107 gold: PaletteColor::EightBit(colors::GOLD),
108 silver: PaletteColor::EightBit(colors::SILVER),
109 pink: PaletteColor::EightBit(colors::PINK),
110 brown: PaletteColor::EightBit(colors::BROWN),
111 }
112}
113
114pub fn detect_theme_hue(bg: PaletteColor) -> ThemeHue {
116 match bg {
117 PaletteColor::Rgb((r, g, b)) => {
118 let hsp: f64 = (0.299 * (r as f64 * r as f64)
120 + 0.587 * (g as f64 * g as f64)
121 + 0.114 * (b as f64 * b as f64))
122 .sqrt();
123 match hsp > 127.5 {
124 true => ThemeHue::Light,
125 false => ThemeHue::Dark,
126 }
127 },
128 _ => ThemeHue::Dark,
129 }
130}
131
132pub fn version_number(mut version: &str) -> usize {
138 if let Some(separator) = version.rfind('-') {
139 version = &version[..separator];
140 }
141
142 let mut version_number = 0;
143
144 let semver_versions = version.split('.');
145 for (i, semver_version) in semver_versions.rev().enumerate() {
146 let semver_number = semver_version.parse::<usize>().unwrap_or(0);
147 version_number += usize::pow(100, i as u32) * semver_number;
148 }
149
150 version_number
151}