Skip to main content

binocular/ui/
mod.rs

1use crate::app::App;
2use ratatui::Frame;
3
4pub mod help;
5pub mod indicators;
6pub mod layout;
7pub mod preview;
8pub mod search;
9pub mod shortcuts;
10
11pub fn draw(f: &mut Frame, app: &mut App) {
12    let search_view = search::SearchBarView {
13        app_mode: app.ui.mode,
14        search_mode: app.search_session.query.mode,
15        preview_search_active: app.preview_session.preview.state.search_active,
16        preview_search_query: &app.preview_session.preview.state.search_query,
17        preview_search_cursor: app
18            .preview_session
19            .preview
20            .state
21            .search_query
22            .chars()
23            .count(),
24        query_text: &app.search_session.query.text,
25        query_cursor: app.search_session.query.cursor,
26        search_label: app
27            .search_session
28            .settings
29            .mode
30            .display_name(app.runtime.run.stdin),
31        match_mode_label: if app.is_exact_mode() {
32            " Exact "
33        } else {
34            " Fuzzy "
35        },
36    };
37    let results_view = search::SearchResultsView {
38        app_mode: app.ui.mode,
39        query_mode: app.search_session.query.mode,
40        show_preview: app.show_preview(),
41        is_content_mode: app.is_content_mode(),
42        stdin_mode: app.runtime.run.stdin,
43        query_is_empty: app.search_session.query.text.is_empty(),
44        total_matches: app.search_session.search.total_matches,
45        total_items: app.search_session.search.total_items,
46        working: app.search_session.search.working,
47        marked_count: app.search_session.search.marked_items.len(),
48        diff_marked_count: app.search_session.search.diff_marked_items.len(),
49        results: &app.search_session.search.results,
50        marked_items: &app.search_session.search.marked_items,
51        diff_marked_items: &app.search_session.search.diff_marked_items,
52    };
53    let preview_view = preview::PreviewView {
54        app_mode: app.ui.mode,
55        preview_mode: app.preview_session.preview.state.mode,
56        source: app.preview_session.preview.source.as_ref(),
57        status_message: app
58            .preview_session
59            .preview
60            .state
61            .status_message
62            .as_ref()
63            .map(|(msg, time)| (msg.as_str(), *time)),
64        command_buffer: Some(&app.preview_session.preview.state.command_buffer),
65        highlight_line: app.preview_session.preview.state.highlight_line,
66        search_query: &app.preview_session.preview.state.search_query,
67        selection_start: app.preview_session.preview.state.selection_start,
68        cursor_line: app.preview_session.preview.state.cursor_line,
69        cursor_char: app.preview_session.preview.state.cursor_char,
70        scroll: app.preview_session.preview.state.scroll as u16,
71        scroll_char: app.preview_session.preview.state.scroll_char as u16,
72        area_height: f.area().height,
73    };
74
75    // In log mode, the log viewer occupies the entire terminal.
76    if app.runtime.run.log {
77        preview::render_preview(
78            f,
79            &preview_view,
80            app.preview_session.preview.content.as_mut(),
81            f.area(),
82        );
83        return;
84    }
85
86    let areas = layout::split_main_layout(f.area(), app.show_preview(), &app.ui.layout);
87
88    if areas.show_search {
89        search::render_search_results(
90            f,
91            &results_view,
92            &mut app.search_session.search.scroll_state,
93            areas.search_results,
94        );
95        search::render_search_bar(f, &search_view, areas.search_bar);
96    }
97
98    if let Some(preview_area) = areas.preview {
99        let preview_view = preview::PreviewView {
100            area_height: preview_area.height,
101            ..preview_view
102        };
103        preview::render_preview(
104            f,
105            &preview_view,
106            app.preview_session.preview.content.as_mut(),
107            preview_area,
108        );
109    }
110
111    help::render_help_modal(f, app);
112}