Skip to main content

vimwiki_core/lang/elements/blocks/inline/
mod.rs

1use crate::{
2    lang::elements::{IntoChildren, Located},
3    StrictEq,
4};
5use derive_more::{
6    Constructor, Display, From, Index, IndexMut, Into, IntoIterator,
7};
8use serde::{Deserialize, Serialize};
9use std::{fmt, iter::FromIterator};
10
11mod code;
12pub use code::*;
13mod comments;
14pub use comments::*;
15mod links;
16pub use links::*;
17mod math;
18pub use math::*;
19mod tags;
20pub use tags::*;
21mod typefaces;
22pub use typefaces::*;
23
24/// Represents elements that can be dropped into other elements
25#[derive(
26    Clone, Debug, Display, From, Eq, PartialEq, Hash, Serialize, Deserialize,
27)]
28pub enum InlineElement<'a> {
29    Text(Text<'a>),
30    DecoratedText(DecoratedText<'a>),
31    Keyword(Keyword),
32    Link(Link<'a>),
33    Tags(Tags<'a>),
34    Code(CodeInline<'a>),
35    Math(MathInline<'a>),
36
37    /// Comments exist as inline elements, but do not show up when displaying
38    /// an inline element enum
39    #[display(fmt = "")]
40    Comment(Comment<'a>),
41}
42
43impl InlineElement<'_> {
44    pub fn to_borrowed(&self) -> InlineElement {
45        match self {
46            Self::Text(x) => InlineElement::from(x.as_borrowed()),
47            Self::DecoratedText(x) => InlineElement::from(x.to_borrowed()),
48            Self::Keyword(x) => InlineElement::from(*x),
49            Self::Link(x) => InlineElement::from(x.to_borrowed()),
50            Self::Tags(x) => InlineElement::from(x.to_borrowed()),
51            Self::Code(x) => InlineElement::from(x.as_borrowed()),
52            Self::Math(x) => InlineElement::from(x.as_borrowed()),
53            Self::Comment(x) => InlineElement::from(x.to_borrowed()),
54        }
55    }
56
57    pub fn into_owned(self) -> InlineElement<'static> {
58        match self {
59            Self::Text(x) => InlineElement::from(x.into_owned()),
60            Self::DecoratedText(x) => InlineElement::from(x.into_owned()),
61            Self::Keyword(x) => InlineElement::from(x),
62            Self::Link(x) => InlineElement::from(x.into_owned()),
63            Self::Tags(x) => InlineElement::from(x.into_owned()),
64            Self::Code(x) => InlineElement::from(x.into_owned()),
65            Self::Math(x) => InlineElement::from(x.into_owned()),
66            Self::Comment(x) => InlineElement::from(x.into_owned()),
67        }
68    }
69}
70
71impl<'a> IntoChildren for InlineElement<'a> {
72    type Child = Located<InlineElement<'a>>;
73
74    fn into_children(self) -> Vec<Self::Child> {
75        match self {
76            Self::DecoratedText(x) => x.into_children(),
77            _ => vec![],
78        }
79    }
80}
81
82impl<'a> StrictEq for InlineElement<'a> {
83    /// Performs strict_eq check on matching inner variants
84    fn strict_eq(&self, other: &Self) -> bool {
85        match (self, other) {
86            (Self::Text(x), Self::Text(y)) => x.strict_eq(y),
87            (Self::DecoratedText(x), Self::DecoratedText(y)) => x.strict_eq(y),
88            (Self::Keyword(x), Self::Keyword(y)) => x.strict_eq(y),
89            (Self::Link(x), Self::Link(y)) => x.strict_eq(y),
90            (Self::Tags(x), Self::Tags(y)) => x.strict_eq(y),
91            (Self::Code(x), Self::Code(y)) => x.strict_eq(y),
92            (Self::Math(x), Self::Math(y)) => x.strict_eq(y),
93            (Self::Comment(x), Self::Comment(y)) => x.strict_eq(y),
94            _ => false,
95        }
96    }
97}
98
99/// Represents a convenience wrapper around a series of inline elements
100#[derive(
101    Constructor,
102    Clone,
103    Debug,
104    Index,
105    IndexMut,
106    Into,
107    IntoIterator,
108    Eq,
109    PartialEq,
110    Hash,
111    Serialize,
112    Deserialize,
113)]
114#[into_iterator(owned, ref, ref_mut)]
115pub struct InlineElementContainer<'a>(Vec<Located<InlineElement<'a>>>);
116
117impl<'a> InlineElementContainer<'a> {
118    /// Returns iterator over references to elements
119    pub fn iter(&self) -> impl Iterator<Item = &Located<InlineElement<'a>>> {
120        self.into_iter()
121    }
122
123    /// Returns iterator over mutable references to elements
124    pub fn iter_mut(
125        &mut self,
126    ) -> impl Iterator<Item = &mut Located<InlineElement<'a>>> {
127        self.into_iter()
128    }
129
130    /// Returns total elements contained within container
131    pub fn len(&self) -> usize {
132        self.0.len()
133    }
134
135    /// Returns true if container has no elements
136    pub fn is_empty(&self) -> bool {
137        self.0.is_empty()
138    }
139
140    /// Returns reference to element at specified index, if it exists
141    pub fn get(&self, idx: usize) -> Option<&Located<InlineElement<'a>>> {
142        self.0.get(idx)
143    }
144}
145
146impl InlineElementContainer<'_> {
147    pub fn to_borrowed(&self) -> InlineElementContainer {
148        let elements = self
149            .iter()
150            .map(|x| x.as_ref().map(InlineElement::to_borrowed))
151            .collect();
152
153        InlineElementContainer::new(elements)
154    }
155
156    pub fn into_owned(self) -> InlineElementContainer<'static> {
157        let elements = self
158            .into_iter()
159            .map(|x| x.map(InlineElement::into_owned))
160            .collect();
161
162        InlineElementContainer::new(elements)
163    }
164}
165
166impl<'a> IntoChildren for InlineElementContainer<'a> {
167    type Child = Located<InlineElement<'a>>;
168
169    fn into_children(self) -> Vec<Self::Child> {
170        self.0
171    }
172}
173
174impl<'a> fmt::Display for InlineElementContainer<'a> {
175    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176        for le in self.iter() {
177            write!(f, "{}", le.as_inner().to_string())?;
178        }
179        Ok(())
180    }
181}
182
183impl<'a> FromIterator<Located<InlineElement<'a>>>
184    for InlineElementContainer<'a>
185{
186    fn from_iter<I: IntoIterator<Item = Located<InlineElement<'a>>>>(
187        iter: I,
188    ) -> Self {
189        Self::new(iter.into_iter().collect())
190    }
191}
192
193impl<'a> FromIterator<InlineElementContainer<'a>>
194    for InlineElementContainer<'a>
195{
196    fn from_iter<I: IntoIterator<Item = InlineElementContainer<'a>>>(
197        iter: I,
198    ) -> Self {
199        Self::new(iter.into_iter().flat_map(|c| c.0).collect())
200    }
201}
202
203impl<'a> StrictEq for InlineElementContainer<'a> {
204    /// Performs strict_eq check on inner elements
205    fn strict_eq(&self, other: &Self) -> bool {
206        self.0.strict_eq(&other.0)
207    }
208}