1use std::sync::Arc;
9
10use crate::console::{Justify, Overflow};
11use crate::highlighter::ReprHighlighter;
12use crate::panel::Panel;
13use crate::pretty::{Pretty, PrettyValue};
14use crate::table::{Cell, Table};
15use crate::text::Text;
16
17#[derive(Clone, Debug, PartialEq, Eq)]
19pub struct ScopeOptions {
20 pub title: Option<String>,
22 pub sort_keys: bool,
25 pub indent_guides: bool,
27 pub max_length: Option<usize>,
29 pub max_string: Option<usize>,
31 pub max_depth: Option<usize>,
33 pub overflow: Option<Overflow>,
35}
36
37impl Default for ScopeOptions {
38 fn default() -> Self {
39 ScopeOptions {
40 title: None,
41 sort_keys: true,
42 indent_guides: false,
43 max_length: None,
44 max_string: None,
45 max_depth: None,
46 overflow: None,
47 }
48 }
49}
50
51pub fn render_scope<K: Into<String>>(
54 scope: impl IntoIterator<Item = (K, PrettyValue)>,
55 options: &ScopeOptions,
56) -> Panel {
57 let mut items_table = Table::grid().padding(0, 1, 0, 1).expand(false);
58 items_table.add_column_justify("", Justify::Right);
59
60 let mut items: Vec<(String, PrettyValue)> = scope
61 .into_iter()
62 .map(|(key, value)| (key.into(), value))
63 .collect();
64 if options.sort_keys {
65 items.sort_by_cached_key(|(key, _)| (!key.starts_with("__"), key.to_lowercase()));
68 }
69 for (key, value) in items {
70 let key_style = if key.starts_with("__") {
71 "scope.key.special"
72 } else {
73 "scope.key"
74 };
75 let mut key_text = Text::new("");
76 key_text.append(&key, Some(key_style.into()));
77 key_text.append(" =", Some("scope.equals".into()));
78 let pretty = Pretty::from_value(value)
79 .highlighter(ReprHighlighter::new())
80 .indent_guides(options.indent_guides)
81 .max_length(options.max_length)
82 .max_string(options.max_string)
83 .max_depth(options.max_depth)
84 .overflow(options.overflow);
85 items_table.add_row_cells(vec![
86 Cell::Text(key_text),
87 Cell::Renderable(Arc::new(pretty)),
88 ]);
89 }
90 let mut panel = Panel::fit(Box::new(items_table))
91 .border_style("scope.border")
92 .padding((0, 1, 0, 1));
93 if let Some(title) = &options.title {
94 panel = panel.title(title.clone());
95 }
96 panel
97}