Skip to content

Commit

Permalink
almost done
Browse files Browse the repository at this point in the history
  • Loading branch information
JieningYu committed Nov 12, 2023
1 parent 3cb41d0 commit 2342f41
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 21 deletions.
7 changes: 5 additions & 2 deletions core/src/text/content.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use super::visit::{StyledVisit, Visit};
use super::{
visit::{StyledVisit, Visit},
Style,
};

pub trait Content: Visit + StyledVisit {}
pub trait Content: Visit<()> + StyledVisit<Style> {}
53 changes: 52 additions & 1 deletion core/src/text/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ use crate::{

use visit::{ErasedVisit, ErasedVisitStyled};

use self::{content::Content, visit::CharVisitor};
use self::{
content::Content,
visit::{CharVisitor, StyledVisit, Visit},
};

use super::fmt::Formatting;

Expand Down Expand Up @@ -61,6 +64,7 @@ where
}
}

#[derive(Clone)]
pub struct Text {
content: Arc<dyn ErasedContent>,
sibs: Vec<Self>,
Expand Down Expand Up @@ -175,6 +179,53 @@ impl Hash for Text {
}
}

impl Visit<()> for Text {
fn visit<V: visit::Visitor<()>>(&self, mut visitor: V) -> Option<()> {
if visit::ErasedVisit::visit(&*self.content, &mut visitor).is_some() {
Some(())
} else {
self.sibs
.iter()
.find(|text| visit::Visit::visit(*text, &mut visitor).is_some())
.map(|_| ())
}
}
}

impl StyledVisit<Style> for Text {
fn visit<V: visit::StyleVisitor<Style>>(&self, mut visitor: V, style: &Style) -> Option<Style> {
let style2 = self.style.clone().with_parent(style.clone());
if let Some(value) = visit::ErasedVisitStyled::visit(&*self.content, &mut visitor, &style2)
{
Some(value)
} else {
for text in &self.sibs {
if let Some(value) = visit::StyledVisit::visit(text, &mut visitor, &style2) {
return Some(value);
}
}
None
}
}
}

impl Display for Text {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
struct Vis<'a, 'b> {
f: &'a mut std::fmt::Formatter<'b>,
}

impl visit::Visitor<()> for Vis<'_, '_> {
fn accept(&mut self, as_str: &str) -> Option<()> {
self.f.write_str(as_str).err().map(|_| ())
}
}

visit::Visit::visit(self, Vis { f });
Ok(())
}
}

/// The style of a [`Text`], representing cosmetic attributes.
/// It includes font, color, click event, hover event, etc.
///
Expand Down
36 changes: 18 additions & 18 deletions core/src/text/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ use std::borrow::Cow;
use super::Style;

/// Types that can supply strings to a [`Visitor`].
pub trait Visit {
pub trait Visit<T> {
/// Supplies this visitable's literal content to the visitor.
/// Returns `None` if the visit finished, or a terminating
/// result from the visitor.
fn visit<T, V: Visitor<T>>(&self, visitor: V) -> Option<T>;
fn visit<V: Visitor<T>>(&self, visitor: V) -> Option<T>;
}

macro_rules! erased_text_visit {
($($v:vis trait $n:ident, $t:ty => $vi:ty);+) => {
$($v trait $n { fn visit(&self, visitor: $vi) -> Option<$t>; }
impl<T: Visit> $n for T { #[inline] fn visit(&self, visitor: $vi) -> Option<$t> { Visit::visit(self, visitor) } })+
impl<T: Visit<$t>> $n for T { #[inline] fn visit(&self, visitor: $vi) -> Option<$t> { Visit::visit(self, visitor) } })+
};
}

Expand All @@ -28,18 +28,18 @@ pub fn plain(s: &str) -> Plain<'_> {
}

/// Types that can supply strings to a [`StyleVisitor`] with a style context.
pub trait StyledVisit {
pub trait StyledVisit<T> {
/// Supplies this visitable's literal content and contextual style
/// to the visitor.
/// Returns `None` if the visit finished, or a terminating
/// result from the visitor.
fn visit<T, V: StyleVisitor<T>>(&self, visitor: V, style: &Style) -> Option<T>;
fn visit<V: StyleVisitor<T>>(&self, visitor: V, style: &Style) -> Option<T>;
}

macro_rules! erased_text_styled_visit {
($($v:vis trait $n:ident, $t:ty => $vi:ty);+) => {
$($v trait $n { fn visit(&self, visitor: $vi, style: &Style) -> Option<$t>; }
impl<T: StyledVisit> $n for T { #[inline] fn visit(&self, visitor: $vi, style: &Style) -> Option<$t> { StyledVisit::visit(self, visitor, style) } })+
impl<T: StyledVisit<$t>> $n for T { #[inline] fn visit(&self, visitor: $vi, style: &Style) -> Option<$t> { StyledVisit::visit(self, visitor, style) } })+
};
}

Expand All @@ -53,14 +53,14 @@ pub fn styled(s: &str, style: Style) -> Styled<'_> {
Styled(Cow::Borrowed(s), style)
}

impl Visit for () {
fn visit<T, V: Visitor<T>>(&self, _: V) -> Option<T> {
impl<T> Visit<T> for () {
fn visit<V: Visitor<T>>(&self, _: V) -> Option<T> {
None
}
}

impl StyledVisit for () {
fn visit<T, V: StyleVisitor<T>>(&self, _: V, _: &Style) -> Option<T> {
impl<T> StyledVisit<T> for () {
fn visit<V: StyleVisitor<T>>(&self, _: V, _: &Style) -> Option<T> {
None
}
}
Expand Down Expand Up @@ -108,29 +108,29 @@ where
/// The `Visit` returned from [`plain`].
pub struct Plain<'a>(Cow<'a, str>);

impl<'a> Visit for Plain<'a> {
fn visit<T, V: Visitor<T>>(&self, mut visitor: V) -> Option<T> {
impl<'a, T> Visit<T> for Plain<'a> {
fn visit<V: Visitor<T>>(&self, mut visitor: V) -> Option<T> {
visitor.accept(&self.0)
}
}

impl<'a> StyledVisit for Plain<'a> {
fn visit<T, V: StyleVisitor<T>>(&self, mut visitor: V, style: &Style) -> Option<T> {
impl<'a, T> StyledVisit<T> for Plain<'a> {
fn visit<V: StyleVisitor<T>>(&self, mut visitor: V, style: &Style) -> Option<T> {
visitor.accept(style, &self.0)
}
}

/// The `Visit` returned from [`styled`].
pub struct Styled<'a>(Cow<'a, str>, Style);

impl<'a> Visit for Styled<'a> {
fn visit<T, V: Visitor<T>>(&self, mut visitor: V) -> Option<T> {
impl<'a, T> Visit<T> for Styled<'a> {
fn visit<V: Visitor<T>>(&self, mut visitor: V) -> Option<T> {
visitor.accept(&self.0)
}
}

impl<'a> StyledVisit for Styled<'a> {
fn visit<T, V: StyleVisitor<T>>(&self, mut visitor: V, style: &Style) -> Option<T> {
impl<'a, T> StyledVisit<T> for Styled<'a> {
fn visit<V: StyleVisitor<T>>(&self, mut visitor: V, style: &Style) -> Option<T> {
visitor.accept(&self.1.clone().with_parent(style.clone()), &self.0)
}
}
Expand Down

0 comments on commit 2342f41

Please sign in to comment.