From 098252794440736be008f91f979bf7207a944791 Mon Sep 17 00:00:00 2001 From: ef3d0c3e Date: Sat, 3 Aug 2024 18:43:54 +0200 Subject: [PATCH] WIP Navigation sorting --- docs/template.nml | 5 ++ src/compiler/navigation.rs | 99 ++++++++++++++++++++++++++++++++++++-- src/elements/reference.rs | 2 +- src/elements/section.rs | 33 +++++++------ src/lsp/parser.rs | 12 ++++- 5 files changed, 131 insertions(+), 20 deletions(-) diff --git a/docs/template.nml b/docs/template.nml index 3848b46..bb19ec4 100644 --- a/docs/template.nml +++ b/docs/template.nml @@ -25,3 +25,8 @@ function make_doc(categories, title, page_title) nml.variable.insert("compiler.output", page_title .. ".html") end >@ + +@@style.section = { + "link_pos": "Before", + "link": ["", "๐Ÿ”— ", " "] +} diff --git a/src/compiler/navigation.rs b/src/compiler/navigation.rs index 723597d..7d92f8d 100644 --- a/src/compiler/navigation.rs +++ b/src/compiler/navigation.rs @@ -7,7 +7,7 @@ use super::compiler::Target; #[derive(Debug, Default)] pub struct NavEntry { - pub(self) entries: Vec<(String, String)>, + pub(self) entries: Vec<(String, String, Option)>, pub(self) children: HashMap, } @@ -34,7 +34,7 @@ impl NavEntry { depth: usize, ) { // Orphans = Links - for (title, path) in &entry.entries { + for (title, path, _) in &entry.entries { result.push_str( format!( r#"
  • {}
  • "#, @@ -75,6 +75,36 @@ impl NavEntry { } result } + + /// Gets the insert index of the entry inside an already sorted entry list + fn sort_entry( + title: &String, + previous: &Option, + entries: &Vec<(String, String, Option)>, + ) -> usize { + let mut insert_at = 0; + if let Some(previous) = &previous + // Using sort key + { + for (i, (ent_title, _, _)) in entries.iter().enumerate() { + if ent_title == previous { + insert_at = i + 1; + break; + } + } + } + + // Then sort alphabetically + for (ent_title, _, ent_previous) in entries.iter().skip(insert_at) { + if (previous.is_some() && ent_previous != previous) || ent_title > title { + break; + } + + insert_at += 1; + } + + insert_at + } } pub fn create_navigation(docs: &Vec) -> Result { @@ -83,12 +113,16 @@ pub fn create_navigation(docs: &Vec) -> Result) -> Result>() + .join(", ") + )); + } + } + + // Find duplicate paths + if let Some(dup_title) = all_paths.get(path) { + return Err(format!("Conflicting paths: `{path}`. Previously used for entry: `{dup_title}`, conflicting use in `{title}`")); + } + all_paths.insert(path.clone(), title.clone()); + + pent.entries.insert( + NavEntry::sort_entry(title, &previous, &pent.entries), + (title.clone(), path.clone(), previous), + ); } Ok(nav) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn sort() { + let entries: Vec<(String, String, Option)> = vec![ + ("Root".into(), "".into(), None), + ("First".into(), "".into(), Some("Root".into())), + ("1".into(), "".into(), Some("First".into())), + ("2".into(), "".into(), Some("First".into())), + ]; + + assert_eq!( + NavEntry::sort_entry(&"E".into(), &Some("Root".into()), &entries), + 1 + ); + assert_eq!( + NavEntry::sort_entry(&"G".into(), &Some("Root".into()), &entries), + 2 + ); + // Orphans + assert_eq!(NavEntry::sort_entry(&"Q".into(), &None, &entries), 0); + assert_eq!(NavEntry::sort_entry(&"S".into(), &None, &entries), 4); + + assert_eq!( + NavEntry::sort_entry(&"1.1".into(), &Some("First".into()), &entries), + 3 + ); + assert_eq!( + NavEntry::sort_entry(&"2.1".into(), &Some("First".into()), &entries), + 4 + ); + } +} diff --git a/src/elements/reference.rs b/src/elements/reference.rs index d0288b5..e41601a 100644 --- a/src/elements/reference.rs +++ b/src/elements/reference.rs @@ -81,7 +81,7 @@ impl ReferenceRule { ), ); Self { - re: [Regex::new(r"ยง\{(.*)\}(\[((?:\\.|[^\\\\])*?)\])?").unwrap()], + re: [Regex::new(r"ยง\{(.*?)\}(\[((?:\\.|[^\\\\])*?)\])?").unwrap()], properties: PropertyParser{ properties: props }, } } diff --git a/src/elements/section.rs b/src/elements/section.rs index b59f469..1116282 100644 --- a/src/elements/section.rs +++ b/src/elements/section.rs @@ -46,16 +46,17 @@ impl Element for Section { match compiler.target() { Target::HTML => { // Section numbering - let number = if (self.kind & section_kind::NO_NUMBER) == section_kind::NO_NUMBER { + let number = if (self.kind & section_kind::NO_NUMBER) != section_kind::NO_NUMBER { let numbering = compiler.section_counter(self.depth); - let number = " ".to_string() - + numbering - .iter() - .map(|n| n.to_string()) - .collect::>() - .join(".") - .as_str(); - number + + let mut result = String::new(); + for num in numbering.iter() + { + result = result + num.to_string().as_str() + "."; + } + result += " "; + + result } else { String::new() }; @@ -71,8 +72,10 @@ impl Element for Section { let refname = Compiler::refname(compiler.target(), self.title.as_str()); let link = format!( - "{}", - Compiler::sanitize(compiler.target(), self.style.link.as_str()) + "{}{}{}", + Compiler::sanitize(compiler.target(), self.style.link[0].as_str()), + Compiler::sanitize(compiler.target(), self.style.link[1].as_str()), + Compiler::sanitize(compiler.target(), self.style.link[2].as_str()) ); if self.style.link_pos == SectionLinkPos::After { @@ -123,7 +126,7 @@ impl ReferenceableElement for Section { ); Ok(format!( - "{caption}", + "{caption}", Compiler::refname(compiler.target(), self.title.as_str()) )) } @@ -390,14 +393,14 @@ mod section_style { #[derive(Debug, Serialize, Deserialize)] pub struct SectionStyle { pub link_pos: SectionLinkPos, - pub link: String, + pub link: [String; 3], } impl Default for SectionStyle { fn default() -> Self { Self { - link_pos: SectionLinkPos::After, - link: "๐Ÿ”—".to_string(), + link_pos: SectionLinkPos::Before, + link: ["".into(), "๐Ÿ”—".into(), " ".into()], } } } diff --git a/src/lsp/parser.rs b/src/lsp/parser.rs index 2eecb3d..489a6b5 100644 --- a/src/lsp/parser.rs +++ b/src/lsp/parser.rs @@ -1,6 +1,6 @@ use std::{cell::{RefCell, RefMut}, collections::HashMap, rc::Rc}; -use crate::{document::{document::Document, element::Element}, lua::kernel::{Kernel, KernelHolder}, parser::{parser::{Parser, ReportColors}, rule::Rule, source::{Cursor, Source}, state::StateHolder}}; +use crate::{document::{document::Document, element::Element, style::{ElementStyle, StyleHolder}}, lua::kernel::{Kernel, KernelHolder}, parser::{parser::{Parser, ReportColors}, rule::Rule, source::{Cursor, Source}, state::StateHolder}}; #[derive(Debug, Clone)] pub struct LineCursor @@ -146,3 +146,13 @@ impl KernelHolder for LsParser self.get_kernel(name.as_str()).unwrap() } } + +impl StyleHolder for LsParser { + fn styles(&self) -> std::cell::Ref<'_, HashMap>> { + todo!() + } + + fn styles_mut(&self) -> RefMut<'_, HashMap>> { + todo!() + } +}