返回 CodeWhale
mod.rs
1 //! Every component with fixture data, for `examples/gallery.rs` and the
2 //! snapshot tests. The fixtures double as usage examples: the mode and
3 //! status-line pickers here are the engine's `/mode` and `/statusline`
4 //! pickers rebuilt from kit parts.
5 //!
6 //! One file per area, each exposing `pub(crate) fn entries() -> Vec<Entry>`.
7 //! [`entries`] concatenates them, so a package edits only its own file:
8 //!
9 //! | File | Holds |
10 //! |---|---|
11 //! | `hints`, `status`, `surface`, `picker`, `toast`, `icons`, `spinner`, `whale` | the components that exist |
12 //! | `input` | package Input: text input and form |
13 //! | `lists` | package Lists: list, fuzzy picker, empty state |
14 //! | `chrome` | package Chrome: heading, tabs, toggle, segmented, keymap |
15 //! | `display` | package Display: receipt, diff, tree, progress |
16 //! | `approval` | package Approval: approval card |
17 //! | `motion` | package Motion |
18 //! | `workspace` | messages, composer, tool and agent cards, fleets |
19 //! | `settings` | values, source, locks, apply timing and defaults |
20 //! | `atmosphere` | one workspace scene in each of the five ombre palettes |
21
22 use crossterm::event::KeyCode;
23 use ratatui::{buffer::Buffer, layout::Rect};
24
25 use crate::{
26 Role, Theme,
27 keys::{Platform, pair_label},
28 };
29
30 mod approval;
31 mod artifacts;
32 mod atmosphere;
33 mod attention;
34 mod chrome;
35 mod display;
36 mod habitat;
37 mod hints;
38 mod icons;
39 mod input;
40 mod lists;
41 mod motion;
42 mod native_chrome;
43 mod native_views;
44 mod ocean;
45 mod pending_input;
46 mod picker;
47 mod posture;
48 mod scenes;
49 mod settings;
50 pub mod showcase;
51 mod spinner;
52 mod status;
53 mod surface;
54 mod toast;
55 mod transcript;
56 mod tui_palettes;
57 mod verification;
58 mod whale;
59 mod workbar;
60 mod workbench;
61 mod workspace;
62
63 /// One gallery entry: a name, the size it is drawn at by default, and a
64 /// function that paints it. `draw` must paint inside the `Rect` it is given
65 /// (the gallery draws it at other widths too) and use only the `Theme`.
66 pub struct Entry {
67 pub name: &'static str,
68 pub width: u16,
69 pub height: u16,
70 pub draw: fn(Rect, &mut Buffer, &Theme),
71 }
72
73 /// `↑↓`, or `Up/Down` where marks are ASCII-safe: one spelling for the
74 /// gallery's key hints.
75 fn arrows(theme: &Theme) -> String {
76 pair_label(KeyCode::Up, KeyCode::Down, Platform::current(theme.ascii()))
77 }
78
79 /// Every entry, in gallery order.
80 #[must_use]
81 pub fn entries() -> Vec<Entry> {
82 [
83 native_views::entries(),
84 native_chrome::entries(),
85 posture::entries(),
86 workbar::entries(),
87 tui_palettes::entries(),
88 scenes::entries(),
89 showcase::entries(),
90 workbench::entries(),
91 attention::entries(),
92 artifacts::entries(),
93 habitat::entries(),
94 hints::entries(),
95 status::entries(),
96 surface::entries(),
97 picker::entries(),
98 toast::entries(),
99 icons::entries(),
100 spinner::entries(),
101 verification::entries(),
102 whale::entries(),
103 input::entries(),
104 lists::entries(),
105 chrome::entries(),
106 display::entries(),
107 approval::entries(),
108 motion::entries(),
109 workspace::entries(),
110 settings::entries(),
111 atmosphere::entries(),
112 ocean::entries(),
113 pending_input::entries(),
114 transcript::entries(),
115 ]
116 .into_iter()
117 .flatten()
118 .collect()
119 }
120
121 /// Resolve the source palette used by a native preview. Named presets keep
122 /// their own background; terminal fallbacks still follow the input capabilities.
123 #[must_use]
124 pub fn theme_for(entry: &Entry, theme: &Theme) -> Theme {
125 if let Some(palette) = tui_palettes::palette_for_name(entry.name) {
126 return tui_palettes::theme_for(palette, theme);
127 }
128 if entry.name.starts_with("view-")
129 || entry.name == "instrument-surface"
130 || entry.name == "session-list"
131 || entry.name.starts_with("native-")
132 || entry.name.starts_with("workbar-")
133 || entry.name.starts_with("workflow-")
134 || entry.name.starts_with("posture-")
135 || entry.name.starts_with("metrics-")
136 || entry.name.starts_with("showcase-")
137 {
138 return theme.tui();
139 }
140 *theme
141 }
142
143 /// Render one entry for one theme at its own size.
144 #[must_use]
145 pub fn render(entry: &Entry, theme: &Theme) -> Buffer {
146 render_at(entry, theme, entry.width, entry.height)
147 }
148
149 /// Render one entry for one theme at another size, on the theme's
150 /// `Background` as the gallery paints it.
151 #[must_use]
152 pub fn render_at(entry: &Entry, theme: &Theme, width: u16, height: u16) -> Buffer {
153 let theme = theme_for(entry, theme);
154 crate::testing::render(width, height, |area, buf| {
155 buf.set_style(area, theme.bg(Role::Background));
156 (entry.draw)(area, buf, &theme);
157 })
158 }
159
159 lines RUST