vimwiki_core/lang/elements/blocks/lists/
mod.rs1use crate::{
2 lang::elements::{
3 AsChildrenMutSlice, AsChildrenSlice, Element, InlineBlockElement,
4 InlineElement, InlineElementContainer, IntoChildren, Located,
5 },
6 StrictEq,
7};
8use derive_more::{
9 AsRef, Constructor, Deref, DerefMut, From, Index, IndexMut, Into,
10 IntoIterator,
11};
12use serde::{Deserialize, Serialize};
13use std::iter::FromIterator;
14
15mod item;
16pub use item::*;
17
18#[derive(
20 Constructor,
21 Clone,
22 Debug,
23 From,
24 Eq,
25 PartialEq,
26 Index,
27 IndexMut,
28 IntoIterator,
29 Serialize,
30 Deserialize,
31)]
32pub struct List<'a> {
33 #[index]
35 #[index_mut]
36 #[into_iterator(owned, ref, ref_mut)]
37 pub items: Vec<Located<ListItem<'a>>>,
38}
39
40impl List<'_> {
41 pub fn to_borrowed(&self) -> List {
42 self.into_iter()
43 .map(|x| x.as_ref().map(ListItem::to_borrowed))
44 .collect()
45 }
46
47 pub fn into_owned(self) -> List<'static> {
48 self.into_iter()
49 .map(|x| x.map(ListItem::into_owned))
50 .collect()
51 }
52}
53
54impl<'a> List<'a> {
55 pub fn iter(&self) -> impl Iterator<Item = &Located<ListItem<'a>>> {
57 self.into_iter()
58 }
59
60 pub fn iter_mut(
62 &mut self,
63 ) -> impl Iterator<Item = &mut Located<ListItem<'a>>> {
64 self.into_iter()
65 }
66
67 pub fn len(&self) -> usize {
69 self.items.len()
70 }
71
72 pub fn is_empty(&self) -> bool {
74 self.items.is_empty()
75 }
76
77 pub fn is_ordered(&self) -> bool {
80 self.iter()
81 .next()
82 .map_or(false, |item| item.ty.is_ordered())
83 }
84
85 pub fn is_unordered(&self) -> bool {
88 self.iter()
89 .next()
90 .map_or(false, |item| item.ty.is_unordered())
91 }
92
93 pub(crate) fn normalize(&mut self) -> &mut Self {
111 if let [head, tail @ ..] = &mut self.items[..] {
113 for item in tail {
118 item.ty = head.ty.clone();
119 }
120 }
121
122 self
123 }
124}
125
126impl<'a> AsChildrenSlice for List<'a> {
127 type Child = Located<ListItem<'a>>;
128
129 fn as_children_slice(&self) -> &[Self::Child] {
130 &self.items
131 }
132}
133
134impl<'a> AsChildrenMutSlice for List<'a> {
135 type Child = Located<ListItem<'a>>;
136
137 fn as_children_mut_slice(&mut self) -> &mut [Self::Child] {
138 &mut self.items
139 }
140}
141
142impl<'a> IntoChildren for List<'a> {
143 type Child = Located<InlineBlockElement<'a>>;
144
145 fn into_children(self) -> Vec<Self::Child> {
146 self.into_iter()
147 .map(|x| x.map(InlineBlockElement::from))
148 .collect()
149 }
150}
151
152impl<'a> FromIterator<Located<ListItem<'a>>> for List<'a> {
153 fn from_iter<I: IntoIterator<Item = Located<ListItem<'a>>>>(
154 iter: I,
155 ) -> Self {
156 Self::new(iter.into_iter().collect())
157 }
158}
159
160impl<'a> StrictEq for List<'a> {
161 fn strict_eq(&self, other: &Self) -> bool {
163 self.items.strict_eq(&other.items)
164 }
165}
166
167#[derive(Clone, Debug, From, Eq, PartialEq, Serialize, Deserialize)]
170pub enum ListItemContent<'a> {
171 InlineContent(InlineElementContainer<'a>),
172 List(List<'a>),
173}
174
175impl ListItemContent<'_> {
176 pub fn to_borrowed(&self) -> ListItemContent {
177 match self {
178 Self::InlineContent(ref x) => {
179 ListItemContent::from(x.to_borrowed())
180 }
181 Self::List(ref x) => ListItemContent::from(x.to_borrowed()),
182 }
183 }
184
185 pub fn into_owned(self) -> ListItemContent<'static> {
186 match self {
187 Self::InlineContent(x) => ListItemContent::from(x.into_owned()),
188 Self::List(x) => ListItemContent::from(x.into_owned()),
189 }
190 }
191}
192
193impl<'a> StrictEq for ListItemContent<'a> {
194 fn strict_eq(&self, other: &Self) -> bool {
196 match (self, other) {
197 (Self::InlineContent(x), Self::InlineContent(y)) => x.strict_eq(y),
198 (Self::List(x), Self::List(y)) => x.strict_eq(y),
199 _ => false,
200 }
201 }
202}
203
204#[derive(
206 AsRef,
207 Constructor,
208 Clone,
209 Debug,
210 Default,
211 Deref,
212 DerefMut,
213 Index,
214 IndexMut,
215 Into,
216 IntoIterator,
217 Eq,
218 PartialEq,
219 Serialize,
220 Deserialize,
221)]
222#[as_ref(forward)]
223#[into_iterator(owned, ref, ref_mut)]
224pub struct ListItemContents<'a>(Vec<Located<ListItemContent<'a>>>);
225
226impl ListItemContents<'_> {
227 pub fn to_borrowed(&self) -> ListItemContents {
228 self.iter()
229 .map(|x| x.as_ref().map(ListItemContent::to_borrowed))
230 .collect()
231 }
232
233 pub fn into_owned(self) -> ListItemContents<'static> {
234 self.into_iter()
235 .map(|x| x.map(ListItemContent::into_owned))
236 .collect()
237 }
238}
239
240impl<'a> ListItemContents<'a> {
241 pub fn inline_content_iter(
242 &self,
243 ) -> impl Iterator<Item = &InlineElement> + '_ {
244 self.iter()
245 .filter_map(|c| match c.as_inner() {
246 ListItemContent::InlineContent(x) => {
247 Some(x.iter().map(|y| y.as_inner()))
248 }
249 _ => None,
250 })
251 .flatten()
252 }
253
254 pub fn inline_content_iter_mut(
255 &mut self,
256 ) -> impl Iterator<Item = &mut InlineElement<'a>> + '_ {
257 self.iter_mut()
258 .filter_map(|c| match c.as_mut_inner() {
259 ListItemContent::InlineContent(x) => {
260 Some(x.iter_mut().map(|y| y.as_mut_inner()))
261 }
262 _ => None,
263 })
264 .flatten()
265 }
266
267 pub fn sublist_iter(&self) -> impl Iterator<Item = &List> + '_ {
268 self.iter().flat_map(|c| match c.as_inner() {
269 ListItemContent::List(x) => Some(x),
270 _ => None,
271 })
272 }
273
274 pub fn sublist_iter_mut(
275 &mut self,
276 ) -> impl Iterator<Item = &mut List<'a>> + '_ {
277 self.iter_mut().flat_map(|c| match c.as_mut_inner() {
278 ListItemContent::List(x) => Some(x),
279 _ => None,
280 })
281 }
282}
283
284impl<'a> AsChildrenSlice for ListItemContents<'a> {
285 type Child = Located<ListItemContent<'a>>;
286
287 fn as_children_slice(&self) -> &[Self::Child] {
288 &self.0
289 }
290}
291
292impl<'a> AsChildrenMutSlice for ListItemContents<'a> {
293 type Child = Located<ListItemContent<'a>>;
294
295 fn as_children_mut_slice(&mut self) -> &mut [Self::Child] {
296 &mut self.0
297 }
298}
299
300impl<'a> IntoChildren for ListItemContents<'a> {
301 type Child = Located<Element<'a>>;
302
303 fn into_children(self) -> Vec<Self::Child> {
304 self.into_iter()
305 .flat_map(|x| {
306 let region = x.region();
307 match x.into_inner() {
308 ListItemContent::InlineContent(content) => content
309 .into_children()
310 .into_iter()
311 .map(|x| x.map(Element::from))
312 .collect(),
313 ListItemContent::List(list) => {
314 vec![Located::new(Element::from(list), region)]
315 }
316 }
317 })
318 .collect()
319 }
320}
321
322impl<'a> FromIterator<Located<ListItemContent<'a>>> for ListItemContents<'a> {
323 fn from_iter<I: IntoIterator<Item = Located<ListItemContent<'a>>>>(
324 iter: I,
325 ) -> Self {
326 Self::new(iter.into_iter().collect())
327 }
328}
329
330impl<'a> StrictEq for ListItemContents<'a> {
331 fn strict_eq(&self, other: &Self) -> bool {
333 self.0.strict_eq(&other.0)
334 }
335}