Skip to main content

mos_parse/
list.rs

1use crate::parser::Parser;
2use crate::support::{RawListLine, list_marker_at};
3use crate::{Item, ListItem};
4
5impl Parser<'_> {
6    /// Consume a contiguous run of list-marker lines starting at the
7    /// current position and push one or more [`Item::List`] entries
8    /// onto `self.items`.
9    pub(crate) fn parse_list(&mut self) {
10        let raw = self.collect_list_lines();
11        if raw.is_empty() {
12            return;
13        }
14        let mut i = 0;
15        while i < raw.len() {
16            let (item, new_i) = self.build_list_at(&raw, i);
17            self.items.push(item);
18            i = new_i;
19        }
20    }
21
22    fn collect_list_lines(&mut self) -> Vec<RawListLine> {
23        let bytes = self.src.as_bytes();
24        let mut out: Vec<RawListLine> = Vec::new();
25        while self.pos < bytes.len() {
26            if self.at_blank_line() {
27                break;
28            }
29            let Some((indent, ordered, content_start)) = list_marker_at(bytes, self.pos) else {
30                break;
31            };
32            let (line_start, content_end, line_end) = self.current_line_bounds();
33            out.push(RawListLine {
34                indent,
35                ordered,
36                content_start,
37                content_end,
38                line_start,
39            });
40            self.pos = line_end;
41        }
42        out
43    }
44
45    /// Build one list from the run starting at `raw[start]`.
46    fn build_list_at(&mut self, raw: &[RawListLine], start: usize) -> (Item, usize) {
47        let base_indent = raw[start].indent;
48        let base_ordered = raw[start].ordered;
49        let mut items: Vec<ListItem> = Vec::new();
50        let mut last_end = raw[start].content_end;
51        let mut i = start;
52        while i < raw.len() {
53            let cur = &raw[i];
54            if cur.indent != base_indent || cur.ordered != base_ordered {
55                break;
56            }
57            let slice = &self.src[cur.content_start..cur.content_end];
58            let inlines = self.parse_inlines(slice, cur.content_start);
59            let item_span = self.span(cur.line_start, cur.content_end);
60            let mut item = ListItem {
61                inlines,
62                children: Vec::new(),
63                span: item_span,
64            };
65            last_end = last_end.max(cur.content_end);
66            i += 1;
67            while i < raw.len() && raw[i].indent > base_indent {
68                let (nested, new_i) = self.build_list_at(raw, i);
69                if let Item::List { span, .. } = &nested {
70                    last_end = last_end.max(span.end());
71                }
72                item.children.push(nested);
73                i = new_i;
74            }
75            items.push(item);
76        }
77        let span = self.span(raw[start].line_start, last_end);
78        (
79            Item::List {
80                ordered: base_ordered,
81                items,
82                span,
83            },
84            i,
85        )
86    }
87}