summaryrefslogtreecommitdiffstats
path: root/default-plugins/tab-bar/src/tab.rs
blob: a87d040814fa249f3b3de7a352952b5927b33620 (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
107
108
109
110
111
use crate::{line::tab_separator, LinePart};
use ansi_term::{ANSIString, ANSIStrings};
use unicode_width::UnicodeWidthStr;
use zellij_tile::prelude::*;
use zellij_tile_utils::style;

fn cursors(focused_clients: &[ClientId], palette: Palette) -> (Vec<ANSIString>, usize) {
    // cursor section, text length
    let mut len = 0;
    let mut cursors = vec![];
    for client_id in focused_clients.iter() {
        if let Some(color) = client_id_to_colors(*client_id, palette) {
            cursors.push(style!(color.1, color.0).paint(" "));
            len += 1;
        }
    }
    (cursors, len)
}

pub fn render_tab(
    text: String,
    palette: Palette,
    separator: &str,
    focused_clients: &[ClientId],
    active: bool,
    is_alternate_tab: bool,
) -> LinePart {
    let separator_width = separator.width();
    let alternate_tab_color = match palette.theme_hue {
        // TODO: only do this if we don't have the arrow capabilities
        ThemeHue::Dark => palette.white,
        ThemeHue::Light => palette.black,
    };
    let background_color = if active {
        palette.green
    } else if is_alternate_tab {
        alternate_tab_color
    } else {
        palette.fg
    };
    let foreground_color = match palette.theme_hue {
        ThemeHue::Dark => palette.black,
        ThemeHue::Light => palette.white,
    };
    let left_separator = style!(foreground_color, background_color).paint(separator);
    let mut tab_text_len =
        text.width() + (separator_width * 2) + separator_width * (separator_width * 2); // 2 for left and right separators, 2 for the text padding
    let tab_styled_text = style!(foreground_color, background_color)
        .bold()
        .paint(format!(" {} ", text));

    let right_separator = style!(background_color, foreground_color).paint(separator);
    let tab_styled_text = if !focused_clients.is_empty() {
        let (cursor_section, extra_length) = cursors(focused_clients, palette);
        tab_text_len += extra_length;
        let mut s = String::new();
        let cursor_beginning = style!(foreground_color, background_color)
            .bold()
            .paint("[")
            .to_string();
        let cursor_section = ANSIStrings(&cursor_section).to_string();
        let cursor_end = style!(foreground_color, background_color)
            .bold()
            .paint("]")
            .to_string();
        s.push_str(&left_separator.to_string());
        s.push_str(&tab_styled_text.to_string());
        s.push_str(&cursor_beginning);
        s.push_str(&cursor_section);
        s.push_str(&cursor_end);
        s.push_str(&right_separator.to_string());
        s
    } else {
        ANSIStrings(&[left_separator, tab_styled_text, right_separator]).to_string()
    };

    LinePart {
        part: tab_styled_text,
        len: tab_text_len,
    }
}

pub fn tab_style(
    text: String,
    is_active_tab: bool,
    is_alternate_tab: bool,
    is_sync_panes_active: bool,
    palette: Palette,
    capabilities: PluginCapabilities,
    focused_clients: &[ClientId],
) -> LinePart {
    let separator = tab_separator(capabilities);
    let mut tab_text = text;
    if is_sync_panes_active {
        tab_text.push_str(" (Sync)");
    }
    // we only color alternate tabs differently if we can't use the arrow fonts to separate them
    let is_alternate_tab = if !capabilities.arrow_fonts {
        false
    } else {
        is_alternate_tab
    };
    render_tab(
        tab_text,
        palette,
        separator,
        focused_clients,
        is_active_tab,
        is_alternate_tab,
    )
}