aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-symfony-console/src/formatter/output_formatter_style.rs
blob: 2cf85e8e7ea7066f40adc783a7c4f4011b02c0e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
//! ref: composer/vendor/symfony/console/Formatter/OutputFormatterStyle.php

use crate::color::Color;
use crate::formatter::output_formatter_style_interface::OutputFormatterStyleInterface;

/// Formatter style class for defining styles.
#[derive(Debug, Clone)]
pub struct OutputFormatterStyle {
    color: Color,
    foreground: String,
    background: String,
    options: Vec<String>,
    href: Option<String>,
    handles_href_gracefully: Option<bool>,
}

impl OutputFormatterStyle {
    /// Initializes output formatter style.
    pub fn new(foreground: Option<&str>, background: Option<&str>, options: Vec<String>) -> Self {
        let foreground = foreground
            .filter(|s| !s.is_empty())
            .unwrap_or("")
            .to_string();
        let background = background
            .filter(|s| !s.is_empty())
            .unwrap_or("")
            .to_string();
        let color = Color::new(&foreground, &background, &options).unwrap();
        Self {
            color,
            foreground,
            background,
            options,
            href: None,
            handles_href_gracefully: None,
        }
    }

    pub fn set_href(&mut self, url: &str) {
        self.href = Some(url.to_string());
    }
}

impl OutputFormatterStyleInterface for OutputFormatterStyle {
    fn set_foreground(&mut self, color: Option<&str>) {
        self.foreground = color.filter(|s| !s.is_empty()).unwrap_or("").to_string();
        self.color = Color::new(&self.foreground, &self.background, &self.options.clone()).unwrap();
    }

    fn set_background(&mut self, color: Option<&str>) {
        self.background = color.filter(|s| !s.is_empty()).unwrap_or("").to_string();
        self.color = Color::new(&self.foreground, &self.background, &self.options.clone()).unwrap();
    }

    fn set_option(&mut self, option: &str) {
        self.options.push(option.to_string());
        self.color = Color::new(&self.foreground, &self.background, &self.options.clone()).unwrap();
    }

    fn unset_option(&mut self, option: &str) {
        let pos = shirabe_php_shim::array_search_in_vec(option, &self.options);
        if let Some(pos) = pos {
            self.options.remove(pos);
        }

        self.color = Color::new(&self.foreground, &self.background, &self.options.clone()).unwrap();
    }

    fn set_options(&mut self, options: Vec<String>) {
        self.options = options;
        self.color = Color::new(&self.foreground, &self.background, &self.options.clone()).unwrap();
    }

    fn apply(&mut self, text: &str) -> String {
        let mut text = text.to_string();

        if self.handles_href_gracefully.is_none() {
            self.handles_href_gracefully = Some(
                shirabe_php_shim::getenv("TERMINAL_EMULATOR").as_deref()
                    != Some(std::ffi::OsStr::new("JetBrains-JediTerm"))
                    && (shirabe_php_shim::getenv("KONSOLE_VERSION").is_none_or(|v| v.is_empty())
                        || shirabe_php_shim::getenv("KONSOLE_VERSION")
                            .map(|v| v.to_string_lossy().parse::<i64>().unwrap_or(0))
                            .unwrap_or(0)
                            > 201100)
                    && shirabe_php_shim::PHP_SERVER
                        .lock()
                        .unwrap()
                        .get("IDEA_INITIAL_DIRECTORY")
                        .is_none(),
            );
        }

        if let Some(href) = &self.href
            && self.handles_href_gracefully == Some(true)
        {
            text = format!("\x1b]8;;{href}\x1b\\{text}\x1b]8;;\x1b\\");
        }

        self.color.apply(&text)
    }

    fn clone_box(&self) -> Box<dyn OutputFormatterStyleInterface> {
        Box::new(self.clone())
    }
}