pub enum DocEntry { Section(&'static str), Topic(&'static str, &'static str), } use DocEntry::{Section, Topic}; pub const DOCS: &[DocEntry] = &[ // Getting Started Section("Getting Started"), Topic("Welcome", include_str!("../../docs/welcome.md")), Topic("Moving Around", include_str!("../../docs/navigation.md")), Topic( "How Does It Work?", include_str!("../../docs/how_it_works.md"), ), Topic( "Banks & Patterns", include_str!("../../docs/banks_patterns.md"), ), Topic("Stage / Commit", include_str!("../../docs/staging.md")), Topic("Using the Sequencer", include_str!("../../docs/grid.md")), Topic("Editing a Step", include_str!("../../docs/editing.md")), // Forth fundamentals Section("Forth"), Topic("About Forth", include_str!("../../docs/about_forth.md")), Topic("The Dictionary", include_str!("../../docs/dictionary.md")), Topic("The Stack", include_str!("../../docs/stack.md")), Topic("Creating Words", include_str!("../../docs/definitions.md")), Topic("Control Flow", include_str!("../../docs/control_flow.md")), Topic("The Prelude", include_str!("../../docs/prelude.md")), Topic("Oddities", include_str!("../../docs/oddities.md")), // Audio Engine Section("Audio Engine"), Topic("Introduction", include_str!("../../docs/engine_intro.md")), Topic("Settings", include_str!("../../docs/engine_settings.md")), Topic("Sources", include_str!("../../docs/engine_sources.md")), Topic("Samples", include_str!("../../docs/engine_samples.md")), Topic("Wavetables", include_str!("../../docs/engine_wavetable.md")), Topic("Filters", include_str!("../../docs/engine_filters.md")), Topic( "Modulation", include_str!("../../docs/engine_modulation.md"), ), Topic( "Distortion", include_str!("../../docs/engine_distortion.md"), ), Topic("Space & Time", include_str!("../../docs/engine_space.md")), Topic( "Audio-Rate Mod", include_str!("../../docs/engine_audio_modulation.md"), ), Topic("Words & Sounds", include_str!("../../docs/engine_words.md")), // MIDI Section("MIDI"), Topic("Introduction", include_str!("../../docs/midi_intro.md")), Topic("MIDI Output", include_str!("../../docs/midi_output.md")), Topic("MIDI Input", include_str!("../../docs/midi_input.md")), // Tutorials Section("Tutorials"), Topic("Randomness", include_str!("../../docs/tutorial_randomness.md")), Topic( "Notes & Harmony", include_str!("../../docs/tutorial_harmony.md"), ), Topic( "Generators", include_str!("../../docs/tutorial_generators.md"), ), Topic("Timing with at", include_str!("../../docs/tutorial_at.md")), Topic("Using Variables", include_str!("../../docs/tutorial_variables.md")), ]; pub fn topic_count() -> usize { DOCS.iter().filter(|e| matches!(e, Topic(_, _))).count() } pub fn get_topic(index: usize) -> Option<(&'static str, &'static str)> { DOCS.iter() .filter_map(|e| match e { Topic(name, content) => Some((*name, *content)), Section(_) => None, }) .nth(index) } pub fn find_match(query: &str) -> Option<(usize, usize)> { let query = query.to_lowercase(); for (topic_idx, (_, content)) in DOCS .iter() .filter_map(|e| match e { Topic(name, content) => Some((*name, *content)), Section(_) => None, }) .enumerate() { for (line_idx, line) in content.lines().enumerate() { if line.to_lowercase().contains(&query) { return Some((topic_idx, line_idx)); } } } None }