phink_lib/cli/ui/
configtable.rs

1use crate::cli::{
2    config::Configuration,
3    ui,
4    ui::traits::Paint,
5};
6use ratatui::{
7    layout::{
8        Constraint,
9        Rect,
10    },
11    prelude::{
12        Alignment,
13        Color,
14        Modifier,
15        Style,
16        Stylize,
17    },
18    style::palette::{
19        tailwind,
20        tailwind::Palette,
21    },
22    widgets::{
23        Block,
24        Borders,
25        HighlightSpacing,
26        Row,
27        Table,
28    },
29    Frame,
30};
31use ui::ratatui::CTOR_VALUE;
32
33const PALETTE: Palette = tailwind::RED;
34struct TableColors {
35    buffer_bg: Color,
36    header_bg: Color,
37    header_fg: Color,
38    row_fg: Color,
39    selected_style_fg: Color,
40    normal_row_color: Color,
41    alt_row_color: Color,
42}
43
44impl TableColors {
45    const fn new(color: &Palette) -> Self {
46        Self {
47            buffer_bg: tailwind::SLATE.c950,
48            header_bg: color.c900,
49            header_fg: tailwind::SLATE.c200,
50            row_fg: tailwind::SLATE.c200,
51            selected_style_fg: color.c400,
52            normal_row_color: tailwind::SLATE.c950,
53            alt_row_color: tailwind::SLATE.c900,
54        }
55    }
56}
57
58impl Paint for Configuration {
59    fn render(&self, f: &mut Frame, area: Rect) {
60        // Helper function to format optional fields
61        fn format_option<T: std::fmt::Debug>(option: &Option<T>) -> String {
62            match option {
63                Some(value) => {
64                    format!("{:?}", value)
65                        .trim_matches(|c| c == '"' || c == '(' || c == ')')
66                        .to_string()
67                }
68                None => "-".to_string(),
69            }
70        }
71
72        let colors = TableColors::new(&PALETTE);
73
74        let x = &format_option(&self.instantiate_initial_value);
75        let x1 = &format_option(&self.cores);
76        let x2 = &self.use_honggfuzz.to_string();
77        let x3 = &format_option(&self.deployer_address);
78        let x4 = &format_option(&self.max_messages_per_exec);
79        let x5 = &format_option(&self.report_path);
80        let x6 = &self.fuzz_origin.to_string();
81        let x7 = format!(
82            "ref_time = {} proof_size = {}",
83            &self.default_gas_limit.unwrap_or_default().ref_time(),
84            &self.default_gas_limit.unwrap_or_default().proof_size()
85        );
86        let x8 = &format_option(&self.storage_deposit_limit);
87        let x9 = CTOR_VALUE.get().unwrap().to_string();
88
89        let x10 = &self.verbose.to_string();
90        let ctr = &self.instrumented_contract();
91        let x11 = ctr.to_str().unwrap();
92        let x12 = &format_option(&self.fuzz_output);
93        let x13 = &self.show_ui.to_string();
94        let items = vec![
95            Row::new(vec!["Cores used", x1]),
96            Row::new(vec!["Using Honggfuzz", x2]),
97            Row::new(vec!["Deployer address", x3]),
98            Row::new(vec!["Max messages per exec", x4]),
99            Row::new(vec!["Report path", x5]),
100            Row::new(vec!["Fuzzing origin", x6]),
101            Row::new(vec!["Default gas limit", &x7]),
102            Row::new(vec!["Storage deposit limit", x8]),
103            Row::new(vec!["Instantiate initial value", x]),
104            Row::new(vec!["Constructor payload", &x9]),
105            Row::new(vec!["Verbose mode", x10]),
106            Row::new(vec!["Path to instrumented contract", x11]),
107            Row::new(vec!["Fuzz output folder", x12]),
108            Row::new(vec!["Custom UI", x13]),
109        ];
110
111        let rows = items.iter().enumerate().map(|(i, row)| {
112            let color = match i % 2 {
113                0 => colors.normal_row_color,
114                _ => colors.alt_row_color,
115            };
116            row.clone()
117                .style(Style::new().fg(colors.row_fg).bg(color))
118                .height(1)
119        });
120
121        let selected_style = Style::default()
122            .add_modifier(Modifier::REVERSED)
123            .fg(colors.selected_style_fg);
124        let header_style = Style::default()
125            .fg(colors.header_fg)
126            .bg(colors.header_bg)
127            .bold();
128
129        let table = Table::new(
130            rows,
131            [Constraint::Percentage(50), Constraint::Percentage(50)],
132        )
133        .header(Row::new(vec!["Setting", "Value"]).style(header_style))
134        .block(
135            Block::default()
136                .borders(Borders::ALL)
137                .title("Configuration (phink.toml)")
138                .bold()
139                .title_alignment(Alignment::Center),
140        )
141        .row_highlight_style(selected_style)
142        .widths([Constraint::Percentage(25), Constraint::Percentage(75)])
143        .column_spacing(1)
144        .row_highlight_style(Style::default().add_modifier(Modifier::BOLD))
145        .highlight_symbol("> ")
146        .bg(colors.buffer_bg)
147        .highlight_spacing(HighlightSpacing::Always);
148
149        f.render_widget(table, area);
150    }
151}