orgize/
headline.rs

1use indextree::NodeId;
2use std::borrow::Cow;
3use std::ops::RangeInclusive;
4use std::usize;
5
6use crate::{
7    config::ParseConfig,
8    elements::{Element, Title},
9    parsers::{parse_container, Container, OwnedArena},
10    validate::{ValidationError, ValidationResult},
11    Org,
12};
13
14/// Represents the document in `Org` struct.
15///
16/// Each `Org` struct only has one `Document`.
17#[derive(Copy, Clone, Debug)]
18pub struct Document {
19    doc_n: NodeId,
20    sec_n: Option<NodeId>,
21}
22
23impl Document {
24    pub(crate) fn from_org(org: &Org) -> Document {
25        let sec_n = org.arena[org.root]
26            .first_child()
27            .and_then(|n| match org[n] {
28                Element::Section => Some(n),
29                Element::Headline { .. } => None,
30                _ => unreachable!("Document should only contains section and headline."),
31            });
32
33        Document {
34            doc_n: org.root,
35            sec_n,
36        }
37    }
38
39    /// Returns the ID of the section element of this document,
40    /// or `None` if it has no section.
41    pub fn section_node(self) -> Option<NodeId> {
42        self.sec_n
43    }
44
45    /// Returns an iterator of this document's children.
46    ///
47    /// ```rust
48    /// # use orgize::Org;
49    /// #
50    /// let mut org = Org::parse(
51    ///     r#"
52    /// ** h1
53    /// ** h2
54    /// *** h2_1
55    /// *** h2_2
56    /// ** h3
57    /// "#,
58    ///     );
59    ///
60    /// let d = org.document();
61    ///
62    /// let mut iter = d.children(&org);
63    ///
64    /// assert_eq!(iter.next().unwrap().title(&org).raw, "h1");
65    /// assert_eq!(iter.next().unwrap().title(&org).raw, "h2");
66    /// assert_eq!(iter.next().unwrap().title(&org).raw, "h3");
67    /// assert!(iter.next().is_none());
68    /// ```
69    pub fn children<'a>(self, org: &'a Org) -> impl Iterator<Item = Headline> + 'a {
70        self.doc_n
71            .children(&org.arena)
72            // skip section if exists
73            .skip(if self.sec_n.is_some() { 1 } else { 0 })
74            .map(move |n| match org[n] {
75                Element::Headline { level } => Headline::from_node(n, level, org),
76                _ => unreachable!(),
77            })
78    }
79
80    /// Returns the first child of this document, or `None` if it has no child.
81    ///
82    /// ```rust
83    /// # use orgize::Org;
84    /// #
85    /// let mut org = Org::parse(
86    ///     r#"
87    /// ** h1
88    /// ** h2
89    /// *** h2_1
90    /// *** h2_2
91    /// ** h3
92    /// "#,
93    ///     );
94    ///
95    /// let d = org.document();
96    ///
97    /// assert_eq!(d.first_child(&org).unwrap().title(&org).raw, "h1");
98    /// ```
99    ///
100    /// ```rust
101    /// # use orgize::Org;
102    /// #
103    /// let org = Org::new();
104    ///
105    /// assert!(org.document().first_child(&org).is_none());
106    /// ```
107    pub fn first_child(self, org: &Org) -> Option<Headline> {
108        self.doc_n
109            .children(&org.arena)
110            // skip section if exists
111            .nth(if self.sec_n.is_some() { 1 } else { 0 })
112            .map(move |n| match org[n] {
113                Element::Headline { level } => Headline::from_node(n, level, org),
114                _ => unreachable!(),
115            })
116    }
117
118    /// Returns the last child of this document, or `None` if it has no child.
119    ///
120    /// ```rust
121    /// # use orgize::Org;
122    /// #
123    /// let mut org = Org::parse(
124    ///     r#"
125    /// ** h1_1
126    /// ** h1_2
127    /// *** h1_2_1
128    /// *** h1_2_2
129    /// ** h1_3
130    /// "#,
131    ///     );
132    ///
133    /// let d = org.document();
134    ///
135    /// assert_eq!(d.last_child(&org).unwrap().title(&org).raw, "h1_3");
136    /// ```
137    ///
138    /// ```rust
139    /// # use orgize::Org;
140    /// #
141    /// let org = Org::new();
142    ///
143    /// assert!(org.document().last_child(&org).is_none());
144    /// ```
145    pub fn last_child(self, org: &Org) -> Option<Headline> {
146        org.arena[self.doc_n]
147            .last_child()
148            .and_then(|n| match org[n] {
149                Element::Headline { level } => Some(Headline::from_node(n, level, org)),
150                Element::Section => None,
151                _ => unreachable!("Document should only contains section and headline."),
152            })
153    }
154
155    /// Changes the section content of this document.
156    ///
157    /// ```rust
158    /// # use orgize::Org;
159    /// #
160    /// let mut org = Org::parse(
161    ///     r#"
162    /// ** h1_1
163    /// ** h1_2
164    /// "#,
165    /// );
166    ///
167    /// let mut d = org.document();
168    ///
169    /// d.set_section_content("s", &mut org);
170    ///
171    /// let mut writer = Vec::new();
172    /// org.write_org(&mut writer).unwrap();
173    /// assert_eq!(
174    ///     String::from_utf8(writer).unwrap(),
175    ///     r#"
176    /// s
177    /// ** h1_1
178    /// ** h1_2
179    /// "#,
180    /// );
181    /// ```
182    pub fn set_section_content<'a, S>(&mut self, content: S, org: &mut Org<'a>)
183    where
184        S: Into<Cow<'a, str>>,
185    {
186        if let Some(sec_n) = self.sec_n {
187            let children: Vec<_> = sec_n.children(&org.arena).collect();
188            for child in children {
189                child.detach(&mut org.arena);
190            }
191        } else {
192            let sec_n = org.arena.new_node(Element::Section);
193            self.sec_n = Some(sec_n);
194            self.doc_n.prepend(sec_n, &mut org.arena);
195        }
196
197        match content.into() {
198            Cow::Borrowed(content) => parse_container(
199                &mut org.arena,
200                Container::Block {
201                    node: self.sec_n.unwrap(),
202                    content,
203                },
204                &ParseConfig::default(),
205            ),
206            Cow::Owned(ref content) => parse_container(
207                &mut OwnedArena::new(&mut org.arena),
208                Container::Block {
209                    node: self.sec_n.unwrap(),
210                    content,
211                },
212                &ParseConfig::default(),
213            ),
214        }
215
216        org.debug_validate();
217    }
218
219    /// Appends a new child to this document.
220    ///
221    /// Returns an error if the given new child was already attached,
222    /// or the given new child didn't meet the requirements.
223    ///
224    /// ```rust
225    /// # use orgize::{elements::Title, Headline, Org};
226    /// #
227    /// let mut org = Org::parse(
228    ///     r#"
229    /// ***** h1
230    /// **** h2
231    /// *** h3
232    /// "#,
233    /// );
234    ///
235    /// let d = org.document();
236    ///
237    /// let mut h4 = Headline::new(
238    ///     Title {
239    ///         raw: "h4".into(),
240    ///         ..Default::default()
241    ///     },
242    ///     &mut org,
243    /// );
244    ///
245    /// // level must be smaller than or equal to 3
246    /// h4.set_level(4, &mut org).unwrap();
247    /// assert!(d.append(h4, &mut org).is_err());
248    ///
249    /// h4.set_level(2, &mut org).unwrap();
250    /// assert!(d.append(h4, &mut org).is_ok());
251    ///
252    /// let mut writer = Vec::new();
253    /// org.write_org(&mut writer).unwrap();
254    /// assert_eq!(
255    ///     String::from_utf8(writer).unwrap(),
256    ///     r#"
257    /// ***** h1
258    /// **** h2
259    /// *** h3
260    /// ** h4
261    /// "#,
262    /// );
263    ///
264    /// // cannot append an attached headline
265    /// assert!(d.append(h4, &mut org).is_err());
266    /// ```
267    pub fn append(self, hdl: Headline, org: &mut Org) -> ValidationResult<()> {
268        hdl.check_detached(org)?;
269
270        if let Some(last) = self.last_child(org) {
271            hdl.check_level(1..=last.lvl)?;
272        } else {
273            hdl.check_level(1..=usize::max_value())?;
274        }
275
276        self.doc_n.append(hdl.hdl_n, &mut org.arena);
277
278        org.debug_validate();
279
280        Ok(())
281    }
282
283    /// Prepends a new child to this document.
284    ///
285    /// Returns an error if the given new child was already attached,
286    /// or the given new child didn't meet the requirements.
287    ///
288    /// ```rust
289    /// # use orgize::{elements::Title, Headline, Org};
290    /// #
291    /// let mut org = Org::parse(
292    ///     r#"
293    /// ** h2
294    /// ** h3
295    /// "#,
296    /// );
297    ///
298    /// let d = org.document();
299    ///
300    /// let mut h1 = Headline::new(
301    ///     Title {
302    ///         raw: "h1".into(),
303    ///         ..Default::default()
304    ///     },
305    ///     &mut org,
306    /// );
307    ///
308    /// // level must be greater than 2
309    /// h1.set_level(1, &mut org).unwrap();
310    /// assert!(d.prepend(h1, &mut org).is_err());
311    ///
312    /// h1.set_level(4, &mut org).unwrap();
313    /// assert!(d.prepend(h1, &mut org).is_ok());
314    ///
315    /// let mut writer = Vec::new();
316    /// org.write_org(&mut writer).unwrap();
317    /// assert_eq!(
318    ///     String::from_utf8(writer).unwrap(),
319    ///     r#"
320    /// **** h1
321    /// ** h2
322    /// ** h3
323    /// "#,
324    /// );
325    ///
326    /// // cannot prepend an attached headline
327    /// assert!(d.prepend(h1, &mut org).is_err());
328    /// ```
329    pub fn prepend(self, hdl: Headline, org: &mut Org) -> ValidationResult<()> {
330        hdl.check_detached(org)?;
331
332        if let Some(first) = self.first_child(org) {
333            hdl.check_level(first.lvl..=usize::MAX)?;
334        } else {
335            hdl.check_level(1..=usize::MAX)?;
336        }
337
338        if let Some(sec_n) = self.sec_n {
339            sec_n.insert_after(hdl.hdl_n, &mut org.arena);
340        } else {
341            self.doc_n.prepend(hdl.hdl_n, &mut org.arena);
342        }
343
344        org.debug_validate();
345
346        Ok(())
347    }
348}
349
350/// Represents a headline in `Org` struct.
351///
352/// Each `Org` has zero or more `Headline`s.
353#[derive(Copy, Clone, Debug)]
354pub struct Headline {
355    lvl: usize,
356    hdl_n: NodeId,
357    ttl_n: NodeId,
358    sec_n: Option<NodeId>,
359}
360
361impl Headline {
362    /// Creates a new detached Headline.
363    pub fn new<'a>(ttl: Title<'a>, org: &mut Org<'a>) -> Headline {
364        let lvl = ttl.level;
365        let hdl_n = org.arena.new_node(Element::Headline { level: ttl.level });
366        let ttl_n = org.arena.new_node(Element::Document { pre_blank: 0 }); // placeholder
367        hdl_n.append(ttl_n, &mut org.arena);
368
369        match ttl.raw {
370            Cow::Borrowed(content) => parse_container(
371                &mut org.arena,
372                Container::Inline {
373                    node: ttl_n,
374                    content,
375                },
376                &ParseConfig::default(),
377            ),
378            Cow::Owned(ref content) => parse_container(
379                &mut OwnedArena::new(&mut org.arena),
380                Container::Inline {
381                    node: ttl_n,
382                    content,
383                },
384                &ParseConfig::default(),
385            ),
386        }
387
388        org[ttl_n] = Element::Title(ttl);
389
390        Headline {
391            lvl,
392            hdl_n,
393            ttl_n,
394            sec_n: None,
395        }
396    }
397
398    pub(crate) fn from_node(hdl_n: NodeId, lvl: usize, org: &Org) -> Headline {
399        let ttl_n = org.arena[hdl_n].first_child().unwrap();
400        let sec_n = org.arena[ttl_n].next_sibling().and_then(|n| match org[n] {
401            Element::Section => Some(n),
402            _ => None,
403        });
404
405        Headline {
406            lvl,
407            hdl_n,
408            ttl_n,
409            sec_n,
410        }
411    }
412
413    /// Returns the level of this headline.
414    pub fn level(self) -> usize {
415        self.lvl
416    }
417
418    /// Returns the ID of the headline element of this headline.
419    pub fn headline_node(self) -> NodeId {
420        self.hdl_n
421    }
422
423    /// Returns the ID of the title element of this headline.
424    pub fn title_node(self) -> NodeId {
425        self.ttl_n
426    }
427
428    /// Returns the ID of the section element of this headline, or `None` if it has no section.
429    pub fn section_node(self) -> Option<NodeId> {
430        self.sec_n
431    }
432
433    /// Returns a reference to the title element of this headline.
434    pub fn title<'a: 'b, 'b>(self, org: &'b Org<'a>) -> &'b Title<'a> {
435        match &org[self.ttl_n] {
436            Element::Title(title) => title,
437            _ => unreachable!(),
438        }
439    }
440
441    /// Returns a mutual reference to the title element of this headline.
442    ///
443    /// Don't change the level and content of the `&mut Titile` directly.
444    /// Alternatively, uses [`Headline::set_level`] and [`Headline::set_title_content`].
445    ///
446    /// [`Headline::set_level`]: #method.set_level
447    /// [`Headline::set_title_content`]: #method.set_title_content
448    ///
449    /// ```rust
450    /// # use orgize::Org;
451    /// #
452    /// let mut org = Org::parse("* h1");
453    ///
454    /// let h1 = org.headlines().nth(0).unwrap();
455    ///
456    /// h1.title_mut(&mut org).priority = Some('A');
457    ///
458    /// let mut writer = Vec::new();
459    /// org.write_org(&mut writer).unwrap();
460    /// assert_eq!(
461    ///     String::from_utf8(writer).unwrap(),
462    ///     "* [#A] h1\n",
463    /// );
464    /// ```
465    pub fn title_mut<'a: 'b, 'b>(self, org: &'b mut Org<'a>) -> &'b mut Title<'a> {
466        match &mut org[self.ttl_n] {
467            Element::Title(title) => title,
468            _ => unreachable!(),
469        }
470    }
471
472    /// Changes the level of this headline.
473    ///
474    /// Returns an error if this headline is attached and the given new level
475    /// doesn't meet the requirements.
476    ///
477    /// ```rust
478    /// # use orgize::{elements::Title, Headline, Org};
479    /// #
480    /// let mut org = Org::parse(
481    ///     r#"
482    /// * h1
483    /// ****** h1_1
484    /// *** h1_2
485    /// ** h1_3
486    /// "#,
487    ///     );
488    ///
489    /// let mut h1_2 = org.headlines().nth(2).unwrap();
490    ///
491    /// // level must be greater than or equal to 2, and smaller than or equal to 6
492    /// assert!(h1_2.set_level(42, &mut org).is_err());
493    ///
494    /// assert!(h1_2.set_level(5, &mut org).is_ok());
495    ///
496    /// let mut writer = Vec::new();
497    /// org.write_org(&mut writer).unwrap();
498    /// assert_eq!(
499    ///     String::from_utf8(writer).unwrap(),
500    ///     r#"
501    /// * h1
502    /// ****** h1_1
503    /// ***** h1_2
504    /// ** h1_3
505    /// "#,
506    /// );
507    ///
508    /// // detached headline's levels can be changed freely
509    /// let mut new_headline = Headline::new(
510    ///     Title {
511    ///         raw: "new".into(),
512    ///         ..Default::default()
513    ///     },
514    ///     &mut org,
515    /// );
516    /// new_headline.set_level(42, &mut org).unwrap();
517    /// ```
518    pub fn set_level(&mut self, lvl: usize, org: &mut Org) -> ValidationResult<()> {
519        if !self.is_detached(org) {
520            let min = self
521                .next(&org)
522                .or_else(|| self.parent(&org))
523                .map(|hdl| hdl.lvl)
524                .unwrap_or(1);
525            let max = self
526                .previous(&org)
527                .map(|hdl| hdl.lvl)
528                .unwrap_or(usize::max_value());
529            if !(min..=max).contains(&lvl) {
530                return Err(ValidationError::HeadlineLevelMismatch {
531                    range: min..=max,
532                    at: self.hdl_n,
533                });
534            }
535        }
536        self.lvl = lvl;
537        self.title_mut(org).level = lvl;
538        if let Element::Headline { level } = &mut org[self.hdl_n] {
539            *level = lvl;
540        }
541        Ok(())
542    }
543
544    /// Changes the title content of this headline.
545    ///
546    /// ```rust
547    /// # use orgize::Org;
548    /// #
549    /// let mut org = Org::parse(
550    ///     r#"
551    /// * h1
552    /// ** h1_1
553    /// "#,
554    ///     );
555    ///
556    /// let h1 = org.headlines().nth(0).unwrap();
557    /// let h1_1 = org.headlines().nth(1).unwrap();
558    ///
559    /// h1.set_title_content("H1", &mut org);
560    /// h1_1.set_title_content(String::from("*H1_1*"), &mut org);
561    ///
562    /// let mut writer = Vec::new();
563    /// org.write_org(&mut writer).unwrap();
564    /// assert_eq!(
565    ///     String::from_utf8(writer).unwrap(),
566    ///     r#"
567    /// * H1
568    /// ** *H1_1*
569    /// "#,
570    /// );
571    /// ```
572    pub fn set_title_content<'a, S>(self, content: S, org: &mut Org<'a>)
573    where
574        S: Into<Cow<'a, str>>,
575    {
576        let content = content.into();
577
578        let children: Vec<_> = self.ttl_n.children(&org.arena).collect();
579        for child in children {
580            child.detach(&mut org.arena);
581        }
582
583        match &content {
584            Cow::Borrowed(content) => parse_container(
585                &mut org.arena,
586                Container::Inline {
587                    node: self.ttl_n,
588                    content,
589                },
590                &ParseConfig::default(),
591            ),
592            Cow::Owned(ref content) => parse_container(
593                &mut OwnedArena::new(&mut org.arena),
594                Container::Inline {
595                    node: self.ttl_n,
596                    content,
597                },
598                &ParseConfig::default(),
599            ),
600        }
601
602        self.title_mut(org).raw = content;
603
604        org.debug_validate();
605    }
606
607    /// Changes the section content of this headline.
608    ///
609    /// ```rust
610    /// # use orgize::Org;
611    /// #
612    /// let mut org = Org::parse(
613    ///     r#"
614    /// * h1
615    /// ** h1_1
616    /// s1_1
617    /// "#,
618    ///     );
619    ///
620    /// let mut h1 = org.headlines().nth(0).unwrap();
621    /// let mut h1_1 = org.headlines().nth(1).unwrap();
622    ///
623    /// h1.set_section_content("s1", &mut org);
624    /// h1_1.set_section_content(String::from("*s1_1*"), &mut org);
625    ///
626    /// let mut writer = Vec::new();
627    /// org.write_org(&mut writer).unwrap();
628    /// assert_eq!(
629    ///     String::from_utf8(writer).unwrap(),
630    ///     r#"
631    /// * h1
632    /// s1
633    /// ** h1_1
634    /// *s1_1*
635    /// "#,
636    /// );
637    /// ```
638    pub fn set_section_content<'a, S>(&mut self, content: S, org: &mut Org<'a>)
639    where
640        S: Into<Cow<'a, str>>,
641    {
642        if let Some(sec_n) = self.sec_n {
643            let children: Vec<_> = sec_n.children(&org.arena).collect();
644            for child in children {
645                child.detach(&mut org.arena);
646            }
647        } else {
648            let sec_n = org.arena.new_node(Element::Section);
649            self.sec_n = Some(sec_n);
650            self.ttl_n.insert_after(sec_n, &mut org.arena);
651        }
652
653        match content.into() {
654            Cow::Borrowed(content) => parse_container(
655                &mut org.arena,
656                Container::Block {
657                    node: self.sec_n.unwrap(),
658                    content,
659                },
660                &ParseConfig::default(),
661            ),
662            Cow::Owned(ref content) => parse_container(
663                &mut OwnedArena::new(&mut org.arena),
664                Container::Block {
665                    node: self.sec_n.unwrap(),
666                    content,
667                },
668                &ParseConfig::default(),
669            ),
670        }
671
672        org.debug_validate();
673    }
674
675    /// Returns the parent of this headline, or `None` if it is detached or attached to the document.
676    ///
677    /// ```rust
678    /// # use orgize::{elements::Title, Headline, Org};
679    /// #
680    /// let mut org = Org::parse(
681    ///     r#"
682    /// * h1
683    /// ** h1_1
684    /// ** h1_2
685    /// *** h1_2_1
686    /// *** h1_2_2
687    /// ** h1_3
688    /// "#,
689    ///     );
690    ///
691    /// let h1 = org.headlines().nth(0).unwrap();
692    /// let h1_1 = org.headlines().nth(1).unwrap();
693    /// let h1_2_1 = org.headlines().nth(3).unwrap();
694    ///
695    /// assert_eq!(h1_1.parent(&org).unwrap().title(&org).raw, "h1");
696    /// assert_eq!(h1_2_1.parent(&org).unwrap().title(&org).raw, "h1_2");
697    ///
698    /// assert!(h1.parent(&org).is_none());
699    ///
700    /// // detached headline have no parent
701    /// assert!(Headline::new(Title::default(), &mut org).parent(&org).is_none());
702    /// ```
703    pub fn parent(self, org: &Org) -> Option<Headline> {
704        org.arena[self.hdl_n].parent().and_then(|n| match org[n] {
705            Element::Headline { level } => Some(Headline::from_node(n, level, org)),
706            Element::Document { .. } => None,
707            _ => unreachable!(),
708        })
709    }
710
711    /// Returns an iterator of this headline's children.
712    ///
713    /// ```rust
714    /// # use orgize::Org;
715    /// #
716    /// let mut org = Org::parse(
717    ///     r#"
718    /// * h1
719    /// ** h1_1
720    /// ** h1_2
721    /// *** h1_2_1
722    /// *** h1_2_2
723    /// ** h1_3
724    /// "#,
725    ///     );
726    ///
727    /// let h1 = org.headlines().nth(0).unwrap();
728    ///
729    /// let mut iter = h1.children(&org);
730    ///
731    /// assert_eq!(iter.next().unwrap().title(&org).raw, "h1_1");
732    /// assert_eq!(iter.next().unwrap().title(&org).raw, "h1_2");
733    /// assert_eq!(iter.next().unwrap().title(&org).raw, "h1_3");
734    /// assert!(iter.next().is_none());
735    /// ```
736    pub fn children<'a>(self, org: &'a Org) -> impl Iterator<Item = Headline> + 'a {
737        self.hdl_n
738            .children(&org.arena)
739            // skip title and section
740            .skip(if self.sec_n.is_some() { 2 } else { 1 })
741            .filter_map(move |n| match org[n] {
742                Element::Headline { level } => Some(Headline::from_node(n, level, org)),
743                _ => unreachable!(),
744            })
745    }
746
747    /// Returns the first child of this headline, or `None` if it has no child.
748    ///
749    /// ```rust
750    /// # use orgize::Org;
751    /// #
752    /// let mut org = Org::parse(
753    ///     r#"
754    /// * h1
755    /// ** h1_1
756    /// ** h1_2
757    /// *** h1_2_1
758    /// *** h1_2_2
759    /// ** h1_3
760    /// "#,
761    ///     );
762    ///
763    /// let h1_1 = org.headlines().nth(1).unwrap();
764    /// let h1_2 = org.headlines().nth(2).unwrap();
765    /// let h1_3 = org.headlines().nth(5).unwrap();
766    ///
767    /// assert_eq!(h1_2.first_child(&org).unwrap().title(&org).raw, "h1_2_1");
768    ///
769    /// assert!(h1_1.first_child(&org).is_none());
770    /// assert!(h1_3.first_child(&org).is_none());
771    /// ```
772    pub fn first_child(self, org: &Org) -> Option<Headline> {
773        self.hdl_n
774            .children(&org.arena)
775            // skip title and section
776            .nth(if self.sec_n.is_some() { 2 } else { 1 })
777            .map(|n| match org[n] {
778                Element::Headline { level } => Headline::from_node(n, level, org),
779                _ => unreachable!(),
780            })
781    }
782
783    /// Returns the last child of this headline, or `None` if it has no child.
784    ///
785    /// ```rust
786    /// # use orgize::Org;
787    /// #
788    /// let mut org = Org::parse(
789    ///     r#"
790    /// * h1
791    /// ** h1_1
792    /// ** h1_2
793    /// *** h1_2_1
794    /// *** h1_2_2
795    /// ** h1_3
796    /// "#,
797    ///     );
798    ///
799    /// let h1_1 = org.headlines().nth(1).unwrap();
800    /// let h1_2 = org.headlines().nth(2).unwrap();
801    /// let h1_3 = org.headlines().nth(5).unwrap();
802    ///
803    /// assert_eq!(h1_2.last_child(&org).unwrap().title(&org).raw, "h1_2_2");
804    ///
805    /// assert!(h1_1.last_child(&org).is_none());
806    /// assert!(h1_3.last_child(&org).is_none());
807    /// ```
808    pub fn last_child(self, org: &Org) -> Option<Headline> {
809        org.arena[self.hdl_n]
810            .last_child()
811            .and_then(|n| match org[n] {
812                Element::Headline { level } => Some(Headline::from_node(n, level, org)),
813                Element::Section | Element::Title(_) => None,
814                _ => unreachable!("Headline should only contains section and headline."),
815            })
816    }
817
818    /// Returns the previous sibling of this headline, or `None` if it is a first child.
819    ///
820    /// ```rust
821    /// # use orgize::Org;
822    /// #
823    /// let mut org = Org::parse(
824    ///     r#"
825    /// * h1
826    /// ** h1_1
827    /// ** h1_2
828    /// *** h1_2_1
829    /// *** h1_2_2
830    /// ** h1_3
831    /// "#,
832    ///     );
833    ///
834    /// let h1_1 = org.headlines().nth(1).unwrap();
835    /// let h1_2 = org.headlines().nth(2).unwrap();
836    /// let h1_2_1 = org.headlines().nth(3).unwrap();
837    ///
838    /// assert_eq!(h1_2.previous(&org).unwrap().title(&org).raw, "h1_1");
839    ///
840    /// assert!(h1_1.previous(&org).is_none());
841    /// assert!(h1_2_1.previous(&org).is_none());
842    /// ```
843    pub fn previous(self, org: &Org) -> Option<Headline> {
844        org.arena[self.hdl_n]
845            .previous_sibling()
846            .and_then(|n| match org[n] {
847                Element::Headline { level } => Some(Headline::from_node(n, level, org)),
848                Element::Title(_) | Element::Section => None,
849                _ => unreachable!(),
850            })
851    }
852
853    /// Returns the next sibling of this headline, or `None` if it is a last child.
854    ///
855    /// ```rust
856    /// # use orgize::Org;
857    /// #
858    /// let mut org = Org::parse(
859    ///     r#"
860    /// * h1
861    /// ** h1_1
862    /// ** h1_2
863    /// *** h1_2_1
864    /// *** h1_2_2
865    /// ** h1_3
866    /// "#,
867    ///     );
868    ///
869    /// let h1_2 = org.headlines().nth(2).unwrap();
870    /// let h1_2_2 = org.headlines().nth(4).unwrap();
871    /// let h1_3 = org.headlines().nth(5).unwrap();
872    ///
873    /// assert_eq!(h1_2.next(&org).unwrap().title(&org).raw, "h1_3");
874    ///
875    /// assert!(h1_3.next(&org).is_none());
876    /// assert!(h1_2_2.next(&org).is_none());
877    /// ```
878    pub fn next(self, org: &Org) -> Option<Headline> {
879        org.arena[self.hdl_n].next_sibling().map(|n| match org[n] {
880            Element::Headline { level } => Headline::from_node(n, level, org),
881            _ => unreachable!(),
882        })
883    }
884
885    /// Detaches this headline from arena.
886    ///
887    /// ```rust
888    /// # use orgize::Org;
889    /// #
890    /// let mut org = Org::parse(
891    ///     r#"
892    /// * h1
893    /// ** h1_1
894    /// ** h1_2
895    /// *** h1_2_1
896    /// *** h1_2_2
897    /// ** h1_3
898    /// "#,
899    ///     );
900    ///
901    /// let h1_2 = org.headlines().nth(2).unwrap();
902    ///
903    /// h1_2.detach(&mut org);
904    ///
905    /// let mut writer = Vec::new();
906    /// org.write_org(&mut writer).unwrap();
907    /// assert_eq!(
908    ///     String::from_utf8(writer).unwrap(),
909    ///     r#"
910    /// * h1
911    /// ** h1_1
912    /// ** h1_3
913    /// "#,
914    /// );
915    /// ```
916    pub fn detach(self, org: &mut Org) {
917        self.hdl_n.detach(&mut org.arena);
918    }
919
920    /// Returns `true` if this headline is detached.
921    pub fn is_detached(self, org: &Org) -> bool {
922        org.arena[self.hdl_n].parent().is_none()
923    }
924
925    /// Appends a new child to this headline.
926    ///
927    /// Returns an error if the given new child was already attached, or
928    /// the given new child didn't meet the requirements.
929    ///
930    /// ```rust
931    /// # use orgize::{elements::Title, Headline, Org};
932    /// #
933    /// let mut org = Org::parse(
934    ///     r#"
935    /// * h1
936    /// ** h1_1
937    /// ***** h1_1_1
938    /// "#,
939    ///     );
940    ///
941    /// let h1_1 = org.headlines().nth(1).unwrap();
942    ///
943    /// let mut h1_1_2 = Headline::new(
944    ///     Title {
945    ///         raw: "h1_1_2".into(),
946    ///         ..Default::default()
947    ///     },
948    ///     &mut org,
949    /// );
950    ///
951    /// // level must be greater than 2, and smaller than or equal to 5
952    /// h1_1_2.set_level(2, &mut org).unwrap();
953    /// assert!(h1_1.append(h1_1_2, &mut org).is_err());
954    /// h1_1_2.set_level(6, &mut org).unwrap();
955    /// assert!(h1_1.append(h1_1_2, &mut org).is_err());
956    ///
957    /// h1_1_2.set_level(4, &mut org).unwrap();
958    /// assert!(h1_1.append(h1_1_2, &mut org).is_ok());
959    ///
960    /// let mut writer = Vec::new();
961    /// org.write_org(&mut writer).unwrap();
962    /// assert_eq!(
963    ///     String::from_utf8(writer).unwrap(),
964    ///     r#"
965    /// * h1
966    /// ** h1_1
967    /// ***** h1_1_1
968    /// **** h1_1_2
969    /// "#,
970    /// );
971    ///
972    /// // cannot append an attached headline
973    /// assert!(h1_1.append(h1_1_2, &mut org).is_err());
974    /// ```
975    pub fn append(self, hdl: Headline, org: &mut Org) -> ValidationResult<()> {
976        hdl.check_detached(org)?;
977
978        if let Some(last) = self.last_child(org) {
979            hdl.check_level(self.lvl + 1..=last.lvl)?;
980        } else {
981            hdl.check_level(self.lvl + 1..=usize::MAX)?;
982        }
983
984        self.hdl_n.append(hdl.hdl_n, &mut org.arena);
985
986        org.debug_validate();
987
988        Ok(())
989    }
990
991    /// Prepends a new child to this headline.
992    ///
993    /// Returns an error if the given new child was already attached, or
994    /// the given new child didn't meet the requirements.
995    ///
996    /// ```rust
997    /// # use orgize::{elements::Title, Headline, Org};
998    /// #
999    /// let mut org = Org::parse(
1000    ///     r#"
1001    /// * h1
1002    /// ** h1_1
1003    /// ***** h1_1_1
1004    /// "#,
1005    ///     );
1006    ///
1007    /// let h1_1 = org.headlines().nth(1).unwrap();
1008    ///
1009    /// let mut h1_1_2 = Headline::new(
1010    ///     Title {
1011    ///         raw: "h1_1_2".into(),
1012    ///         ..Default::default()
1013    ///     },
1014    ///     &mut org,
1015    /// );
1016    ///
1017    /// // level must be greater than or equal to 5
1018    /// h1_1_2.set_level(2, &mut org).unwrap();
1019    /// assert!(h1_1.prepend(h1_1_2, &mut org).is_err());
1020    ///
1021    /// h1_1_2.set_level(5, &mut org).unwrap();
1022    /// assert!(h1_1.prepend(h1_1_2, &mut org).is_ok());
1023    ///
1024    /// // cannot prepend an attached headline
1025    /// assert!(h1_1.prepend(h1_1_2, &mut org).is_err());
1026    /// ```
1027    pub fn prepend(self, hdl: Headline, org: &mut Org) -> ValidationResult<()> {
1028        hdl.check_detached(org)?;
1029
1030        if let Some(first) = self.first_child(org) {
1031            hdl.check_level(first.lvl..=usize::MAX)?;
1032        } else {
1033            hdl.check_level(self.lvl + 1..=usize::MAX)?;
1034        }
1035
1036        self.sec_n
1037            .unwrap_or(self.ttl_n)
1038            .insert_after(hdl.hdl_n, &mut org.arena);
1039
1040        org.debug_validate();
1041
1042        Ok(())
1043    }
1044
1045    /// Inserts a new sibling before this headline.
1046    ///
1047    /// Returns an error if the given new child was already attached, or
1048    /// the given new child didn't meet the requirements.
1049    ///
1050    /// ```rust
1051    /// # use orgize::{elements::Title, Headline, Org};
1052    /// #
1053    /// let mut org = Org::parse(
1054    ///     r#"
1055    /// * h1
1056    /// ** h1_1
1057    /// **** h1_1_1
1058    /// *** h1_1_3
1059    /// "#,
1060    ///     );
1061    ///
1062    /// let h1_1_3 = org.headlines().nth(3).unwrap();
1063    ///
1064    /// let mut h1_1_2 = Headline::new(
1065    ///     Title {
1066    ///         raw: "h1_1_2".into(),
1067    ///         ..Default::default()
1068    ///     },
1069    ///     &mut org,
1070    /// );
1071    ///
1072    /// // level must be greater than or equal to 3, but smaller than or equal to 4
1073    /// h1_1_2.set_level(2, &mut org).unwrap();
1074    /// assert!(h1_1_3.insert_before(h1_1_2, &mut org).is_err());
1075    /// h1_1_2.set_level(5, &mut org).unwrap();
1076    /// assert!(h1_1_3.insert_before(h1_1_2, &mut org).is_err());
1077    ///
1078    /// h1_1_2.set_level(4, &mut org).unwrap();
1079    /// assert!(h1_1_3.insert_before(h1_1_2, &mut org).is_ok());
1080    ///
1081    /// let mut writer = Vec::new();
1082    /// org.write_org(&mut writer).unwrap();
1083    /// assert_eq!(
1084    ///     String::from_utf8(writer).unwrap(),
1085    ///     r#"
1086    /// * h1
1087    /// ** h1_1
1088    /// **** h1_1_1
1089    /// **** h1_1_2
1090    /// *** h1_1_3
1091    /// "#,
1092    /// );
1093    ///
1094    /// // cannot insert an attached headline
1095    /// assert!(h1_1_3.insert_before(h1_1_2, &mut org).is_err());
1096    /// ```
1097    pub fn insert_before(self, hdl: Headline, org: &mut Org) -> ValidationResult<()> {
1098        hdl.check_detached(org)?;
1099
1100        if let Some(previous) = self.previous(org) {
1101            hdl.check_level(self.lvl..=previous.lvl)?;
1102        } else {
1103            hdl.check_level(self.lvl..=usize::MAX)?;
1104        }
1105
1106        self.hdl_n.insert_before(hdl.hdl_n, &mut org.arena);
1107
1108        org.debug_validate();
1109
1110        Ok(())
1111    }
1112
1113    /// Inserts a new sibling after this headline.
1114    ///
1115    /// Returns an error if the given new child was already attached, or
1116    /// the given new child didn't meet the requirements.
1117    ///
1118    /// ```rust
1119    /// # use orgize::{elements::Title, Headline, Org};
1120    /// #
1121    /// let mut org = Org::parse(
1122    ///     r#"
1123    /// * h1
1124    /// ** h1_1
1125    /// **** h1_1_1
1126    /// *** h1_1_3
1127    /// "#,
1128    ///     );
1129    ///
1130    /// let h1_1_1 = org.headlines().nth(2).unwrap();
1131    ///
1132    /// let mut h1_1_2 = Headline::new(
1133    ///     Title {
1134    ///         raw: "h1_1_2".into(),
1135    ///         ..Default::default()
1136    ///     },
1137    ///     &mut org,
1138    /// );
1139    ///
1140    /// // level must be greater than or equal to 3, but smaller than or equal to 4
1141    /// h1_1_2.set_level(2, &mut org).unwrap();
1142    /// assert!(h1_1_1.insert_after(h1_1_2, &mut org).is_err());
1143    /// h1_1_2.set_level(5, &mut org).unwrap();
1144    /// assert!(h1_1_1.insert_after(h1_1_2, &mut org).is_err());
1145    ///
1146    /// h1_1_2.set_level(4, &mut org).unwrap();
1147    /// assert!(h1_1_1.insert_after(h1_1_2, &mut org).is_ok());
1148    ///
1149    /// let mut writer = Vec::new();
1150    /// org.write_org(&mut writer).unwrap();
1151    /// assert_eq!(
1152    ///     String::from_utf8(writer).unwrap(),
1153    ///     r#"
1154    /// * h1
1155    /// ** h1_1
1156    /// **** h1_1_1
1157    /// **** h1_1_2
1158    /// *** h1_1_3
1159    /// "#,
1160    /// );
1161    ///
1162    /// // cannot insert an attached headline
1163    /// assert!(h1_1_1.insert_after(h1_1_2, &mut org).is_err());
1164    /// ```
1165    pub fn insert_after(self, hdl: Headline, org: &mut Org) -> ValidationResult<()> {
1166        hdl.check_detached(org)?;
1167
1168        if let Some(next) = self.next(org) {
1169            hdl.check_level(next.lvl..=self.lvl)?;
1170        } else if let Some(parent) = self.parent(org) {
1171            hdl.check_level(parent.lvl + 1..=self.lvl)?;
1172        } else {
1173            hdl.check_level(1..=self.lvl)?;
1174        }
1175
1176        self.hdl_n.insert_after(hdl.hdl_n, &mut org.arena);
1177
1178        org.debug_validate();
1179
1180        Ok(())
1181    }
1182
1183    fn check_detached(self, org: &Org) -> ValidationResult<()> {
1184        if !self.is_detached(org) {
1185            Err(ValidationError::ExpectedDetached { at: self.hdl_n })
1186        } else {
1187            Ok(())
1188        }
1189    }
1190
1191    fn check_level(self, range: RangeInclusive<usize>) -> ValidationResult<()> {
1192        if !range.contains(&self.lvl) {
1193            Err(ValidationError::HeadlineLevelMismatch {
1194                range,
1195                at: self.hdl_n,
1196            })
1197        } else {
1198            Ok(())
1199        }
1200    }
1201}
1202
1203impl Org<'_> {
1204    /// Returns the `Document`.
1205    pub fn document(&self) -> Document {
1206        Document::from_org(self)
1207    }
1208
1209    /// Returns an iterator of `Headline`s.
1210    pub fn headlines(&self) -> impl Iterator<Item = Headline> + '_ {
1211        self.root
1212            .descendants(&self.arena)
1213            .skip(1)
1214            .filter_map(move |node| match self[node] {
1215                Element::Headline { level } => Some(Headline::from_node(node, level, self)),
1216                _ => None,
1217            })
1218    }
1219}