Better sorting

This commit is contained in:
ef3d0c3e 2024-08-04 08:32:15 +02:00
parent 0982527944
commit cc7bc7169c
3 changed files with 84 additions and 52 deletions

View file

@ -76,34 +76,28 @@ impl NavEntry {
result result
} }
/// Gets the insert index of the entry inside an already sorted entry list
fn sort_entry( fn sort_entry(
title: &String, left: &(String, String, Option<String>),
previous: &Option<String>, right: &(String, String, Option<String>),
entries: &Vec<(String, String, Option<String>)>, ) -> std::cmp::Ordering {
) -> usize { match (&left.2, &right.2) {
let mut insert_at = 0; (Some(_), Some(_)) => left.0.cmp(&right.0),
if let Some(previous) = &previous (Some(lp), None) => {
// Using sort key if &right.0 == lp {
{ std::cmp::Ordering::Greater
for (i, (ent_title, _, _)) in entries.iter().enumerate() { } else {
if ent_title == previous { left.0.cmp(&right.0)
insert_at = i + 1;
break;
} }
} }
(None, Some(rp)) => {
if &left.0 == rp {
std::cmp::Ordering::Less
} else {
left.0.cmp(&right.0)
} }
// 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;
} }
(None, None) => left.0.cmp(&right.0),
insert_at += 1;
} }
insert_at
} }
} }
@ -196,47 +190,49 @@ pub fn create_navigation(docs: &Vec<CompiledDocument>) -> Result<NavEntry, Strin
} }
all_paths.insert(path.clone(), title.clone()); all_paths.insert(path.clone(), title.clone());
pent.entries.insert( pent.entries.push((title.clone(), path.clone(), previous));
NavEntry::sort_entry(title, &previous, &pent.entries),
(title.clone(), path.clone(), previous),
);
} }
// Sort entries
fn sort_entries(nav: &mut NavEntry) {
nav.entries
.sort_unstable_by(|l, r| NavEntry::sort_entry(l, r));
for (_, child) in &mut nav.children {
sort_entries(child);
}
}
sort_entries(&mut nav);
Ok(nav) Ok(nav)
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use rand::rngs::OsRng;
use rand::RngCore;
use super::*; use super::*;
#[test] #[test]
fn sort() { fn sort() {
let entries: Vec<(String, String, Option<String>)> = vec![ let mut entries: Vec<(String, String, Option<String>)> = vec![
("Root".into(), "".into(), None), ("Index".into(), "".into(), None),
("First".into(), "".into(), Some("Root".into())), ("AB".into(), "".into(), Some("Index".into())),
("1".into(), "".into(), Some("First".into())), ("Getting Started".into(), "".into(), Some("Index".into())),
("2".into(), "".into(), Some("First".into())), ("Sections".into(), "".into(), Some("Getting Started".into())),
("Style".into(), "".into(), Some("Getting Started".into())),
]; ];
let mut shuffled = entries.clone();
for _ in 0..10 {
for i in 0..5 {
let pos = OsRng.next_u64() % entries.len() as u64;
shuffled.swap(i, pos as usize);
}
assert_eq!( shuffled.sort_by(|l, r| NavEntry::sort_entry(l, r));
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!( assert_eq!(shuffled, entries);
NavEntry::sort_entry(&"1.1".into(), &Some("First".into()), &entries), }
3
);
assert_eq!(
NavEntry::sort_entry(&"2.1".into(), &Some("First".into()), &entries),
4
);
} }
} }

View file

@ -407,3 +407,40 @@ mod section_style {
impl_elementstyle!(SectionStyle, STYLE_KEY); impl_elementstyle!(SectionStyle, STYLE_KEY);
} }
#[cfg(test)]
mod tests
{
use crate::{parser::{langparser::LangParser, source::SourceFile}, validate_document};
use super::*;
#[test]
fn parser()
{
let source = Rc::new(SourceFile::with_content(
"".to_string(),
r#"
# 1
##+ 2
###* 3
####+* 4
#####*+ 5
######{refname} 6
"#
.to_string(),
None,
));
let parser = LangParser::default();
let doc = parser.parse(source, None);
validate_document!(doc.content().borrow(), 0,
Section { depth == 1, title == "1" };
Section { depth == 2, title == "2", kind == section_kind::NO_TOC };
Section { depth == 3, title == "3", kind == section_kind::NO_NUMBER };
Section { depth == 4, title == "4", kind == section_kind::NO_NUMBER | section_kind::NO_TOC };
Section { depth == 5, title == "5", kind == section_kind::NO_NUMBER | section_kind::NO_TOC };
Section { depth == 6, title == "6", reference == Some("refname".to_string()) };
);
}
}

View file

@ -1,4 +1,3 @@
#![feature(char_indices_offset)]
mod cache; mod cache;
mod compiler; mod compiler;
mod document; mod document;