Feat: collapsible help

This commit is contained in:
2026-02-16 23:43:25 +01:00
parent 540f59dcf5
commit 524e686b3a
12 changed files with 597 additions and 119 deletions

View File

@@ -11,7 +11,7 @@ use crate::model::docs::{get_topic, DocEntry, DOCS};
use crate::state::HelpFocus;
use crate::theme;
use crate::views::highlight;
use crate::widgets::{render_search_bar, CategoryItem, CategoryList};
use crate::widgets::{render_search_bar, CategoryItem, CategoryList, Selection};
use DocEntry::{Section, Topic};
@@ -105,21 +105,38 @@ fn render_topics(frame: &mut Frame, app: &App, area: Rect) {
let theme = theme::get();
let focused = app.ui.help_focus == HelpFocus::Topics;
let mut section_idx = 0usize;
let items: Vec<CategoryItem> = DOCS
.iter()
.map(|entry| match entry {
Section(name) => CategoryItem {
label: name,
is_section: true,
},
Section(name) => {
let collapsed = app
.ui
.help_collapsed
.get(section_idx)
.copied()
.unwrap_or(false);
section_idx += 1;
CategoryItem {
label: name,
is_section: true,
collapsed,
}
}
Topic(name, _) => CategoryItem {
label: name,
is_section: false,
collapsed: false,
},
})
.collect();
CategoryList::new(&items, app.ui.help_topic)
let selection = match app.ui.help_on_section {
Some(s) => Selection::Section(s),
None => Selection::Item(app.ui.help_topic),
};
CategoryList::new(&items, selection)
.focused(focused)
.title("Topics")
.selected_color(theme.dict.category_selected)
@@ -172,7 +189,8 @@ fn render_content(frame: &mut Frame, app: &App, area: Rect) {
{
let mut cache = app.ui.help_parsed.borrow_mut();
if cache[app.ui.help_topic].is_none() {
cache[app.ui.help_topic] = Some(cagire_markdown::parse(md, &AppTheme, &ForthHighlighter));
cache[app.ui.help_topic] =
Some(cagire_markdown::parse(md, &AppTheme, &ForthHighlighter));
}
}
let cache = app.ui.help_parsed.borrow();
@@ -182,7 +200,12 @@ fn render_content(frame: &mut Frame, app: &App, area: Rect) {
let content_area = if has_search_bar {
let [content, search] =
Layout::vertical([Constraint::Fill(1), Constraint::Length(1)]).areas(md_area);
render_search_bar(frame, search, &app.ui.help_search_query, app.ui.help_search_active);
render_search_bar(
frame,
search,
&app.ui.help_search_query,
app.ui.help_search_active,
);
content
} else {
md_area
@@ -295,4 +318,3 @@ fn highlight_line<'a>(line: RLine<'a>, query: &str) -> RLine<'a> {
fn find_bytes(haystack: &[u8], needle: &[u8]) -> Option<usize> {
haystack.windows(needle.len()).position(|w| w == needle)
}