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}