mdq/select/
sel_list_item.rs1use crate::md_elem::elem::List;
2use crate::md_elem::{MdContext, MdElem};
3use crate::select::string_matcher::StringMatcher;
4use crate::select::{ListItemMatcher, ListItemTask, TrySelector};
5
6#[derive(Debug, PartialEq)]
7pub struct ListItemSelector {
8 li_type: ListItemType,
9 checkbox: ListItemTask,
10 string_matcher: StringMatcher,
11}
12
13impl From<ListItemMatcher> for ListItemSelector {
14 fn from(value: ListItemMatcher) -> Self {
15 Self {
16 li_type: if value.ordered {
17 ListItemType::Ordered
18 } else {
19 ListItemType::Unordered
20 },
21 checkbox: value.task,
22 string_matcher: value.matcher.into(),
23 }
24 }
25}
26
27#[derive(Debug, PartialEq, Copy, Clone)]
28pub enum ListItemType {
29 Ordered,
30 Unordered,
31}
32
33fn task_matches(matcher: ListItemTask, md_is_checked: Option<bool>) -> bool {
34 match matcher {
35 ListItemTask::Unselected => md_is_checked == Some(false),
36 ListItemTask::Selected => md_is_checked == Some(true),
37 ListItemTask::Either => md_is_checked.is_some(),
38 ListItemTask::None => md_is_checked.is_none(),
39 }
40}
41
42impl TrySelector<List> for ListItemSelector {
43 fn try_select(&self, _: &MdContext, item: List) -> Result<Vec<MdElem>, MdElem> {
44 let List { starting_index, items } = item;
50 match items.as_slice() {
51 [li] => {
52 let matched = self.li_type.matches(&starting_index)
53 && task_matches(self.checkbox, li.checked)
54 && self.string_matcher.matches_any(&li.item);
55 let list = MdElem::List(List { starting_index, items });
56 if matched {
57 Ok(vec![list])
58 } else {
59 Err(list)
60 }
61 }
62 _ => {
63 let mut idx = starting_index;
64 let mut items_doc = Vec::with_capacity(items.len());
65 for item in items {
66 items_doc.push(MdElem::List(List {
67 starting_index: idx,
68 items: vec![item],
69 }));
70 if let Some(idx) = idx.as_mut() {
71 *idx += 1;
72 }
73 }
74 Err(MdElem::Doc(items_doc))
75 }
76 }
77 }
78}
79
80impl ListItemType {
81 fn matches(&self, idx: &Option<u32>) -> bool {
82 match self {
83 ListItemType::Ordered => idx.is_some(),
84 ListItemType::Unordered => idx.is_none(),
85 }
86 }
87}