Better sorting
This commit is contained in:
parent
0982527944
commit
cc7bc7169c
3 changed files with 84 additions and 52 deletions
|
@ -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
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()) };
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#![feature(char_indices_offset)]
|
|
||||||
mod cache;
|
mod cache;
|
||||||
mod compiler;
|
mod compiler;
|
||||||
mod document;
|
mod document;
|
||||||
|
|
Loading…
Reference in a new issue