1use ratatui::{
2 Frame,
3 layout::Rect,
4 text::{Line, Span},
5 widgets::{Block, Borders, Clear, Paragraph},
6};
7
8use crate::theme::Theme;
9
10pub fn render(frame: &mut Frame, theme: &Theme, markdown: bool) {
11 let area = centered(frame.area(), 76, if markdown { 38 } else { 30 });
12 frame.render_widget(Clear, area);
13
14 let mut lines = Vec::new();
15 section(&mut lines, "Navigation", theme);
16 shortcut(&mut lines, "j / ↓", "Scroll down", theme);
17 shortcut(&mut lines, "k / ↑", "Scroll up", theme);
18 shortcut(&mut lines, "h / ←", "Scroll left", theme);
19 shortcut(&mut lines, "l / →", "Scroll right", theme);
20 shortcut(&mut lines, "PgDn / PgUp", "Page down / up", theme);
21 shortcut(&mut lines, "g / G", "Top / bottom", theme);
22
23 section(&mut lines, "Search", theme);
24 shortcut(&mut lines, "/", "Search", theme);
25 shortcut(&mut lines, "n / N", "Next / previous match", theme);
26 shortcut(&mut lines, "Enter", "Accept search", theme);
27 shortcut(&mut lines, "Esc", "Clear search / highlights", theme);
28
29 if markdown {
30 section(&mut lines, "Headings & links", theme);
31 shortcut(&mut lines, "]h / [h", "Next / previous heading", theme);
32 shortcut(&mut lines, "Left click", "Open a link or image", theme);
33 }
34
35 section(&mut lines, "Display & mouse", theme);
36 shortcut(&mut lines, "w", "Toggle prose wrapping", theme);
37 shortcut(&mut lines, "Wheel", "Scroll vertically", theme);
38 shortcut(&mut lines, "Shift+Wheel", "Scroll horizontally", theme);
39 shortcut(
40 &mut lines,
41 "Trackpad",
42 "Scroll vertically / horizontally",
43 theme,
44 );
45
46 section(&mut lines, "General", theme);
47 shortcut(&mut lines, "? / Esc", "Close help", theme);
48 shortcut(&mut lines, "q", "Quit IRIS", theme);
49
50 lines.push(Line::from(""));
51 lines.push(Line::from(Span::styled(
52 "Press ? or Esc to close",
53 theme.status,
54 )));
55
56 let block = Block::default()
57 .title(" IRIS Help ")
58 .borders(Borders::ALL)
59 .border_style(theme.help_border)
60 .style(theme.help);
61 frame.render_widget(Paragraph::new(lines).block(block), area);
62}
63
64fn section(lines: &mut Vec<Line<'static>>, title: &str, theme: &Theme) {
65 if !lines.is_empty() {
66 lines.push(Line::from(""));
67 }
68 lines.push(Line::from(Span::styled(
69 title.to_string(),
70 theme.help_heading,
71 )));
72}
73
74fn shortcut(lines: &mut Vec<Line<'static>>, key: &str, description: &str, theme: &Theme) {
75 lines.push(Line::from(vec![
76 Span::raw(" "),
77 Span::styled(format!("{key:<18}"), theme.help_key),
78 Span::styled(description.to_string(), theme.help),
79 ]));
80}
81
82fn centered(area: Rect, desired_width: u16, desired_height: u16) -> Rect {
83 let width = desired_width.min(area.width.saturating_sub(2)).max(1);
84 let height = desired_height.min(area.height.saturating_sub(2)).max(1);
85 Rect::new(
86 area.x + area.width.saturating_sub(width) / 2,
87 area.y + area.height.saturating_sub(height) / 2,
88 width,
89 height,
90 )
91}