use super::super::range::{Position, Range};
use super::super::text_content::TextContent;
use super::super::traits::{AstNode, Container, Visitor, VisualStructure};
use super::annotation::Annotation;
use super::container::VerbatimContainer;
use super::content_item::ContentItem;
use super::data::Data;
use super::typed_content::VerbatimContent;
use std::fmt;
use std::slice;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum VerbatimBlockMode {
Inflow,
Fullwidth,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Verbatim {
pub subject: TextContent,
pub children: VerbatimContainer,
pub closing_data: Data,
pub annotations: Vec<Annotation>,
pub location: Range,
pub mode: VerbatimBlockMode,
additional_groups: Vec<VerbatimGroupItem>,
}
impl Verbatim {
fn default_location() -> Range {
Range::new(0..0, Position::new(0, 0), Position::new(0, 0))
}
pub fn new(
subject: TextContent,
children: Vec<VerbatimContent>,
closing_data: Data,
mode: VerbatimBlockMode,
) -> Self {
Self {
subject,
children: VerbatimContainer::from_typed(children),
closing_data,
annotations: Vec::new(),
location: Self::default_location(),
mode,
additional_groups: Vec::new(),
}
}
pub fn with_subject(subject: String, closing_data: Data) -> Self {
Self {
subject: TextContent::from_string(subject, None),
children: VerbatimContainer::empty(),
closing_data,
annotations: Vec::new(),
location: Self::default_location(),
mode: VerbatimBlockMode::Inflow,
additional_groups: Vec::new(),
}
}
pub fn marker(subject: String, closing_data: Data) -> Self {
Self {
subject: TextContent::from_string(subject, None),
children: VerbatimContainer::empty(),
closing_data,
annotations: Vec::new(),
location: Self::default_location(),
mode: VerbatimBlockMode::Inflow,
additional_groups: Vec::new(),
}
}
pub fn at(mut self, location: Range) -> Self {
self.location = location;
self
}
pub fn with_additional_groups(mut self, groups: Vec<VerbatimGroupItem>) -> Self {
self.additional_groups = groups;
self
}
pub fn additional_groups_mut(&mut self) -> std::slice::IterMut<'_, VerbatimGroupItem> {
self.additional_groups.iter_mut()
}
pub fn annotations(&self) -> &[Annotation] {
&self.annotations
}
pub fn annotations_mut(&mut self) -> &mut Vec<Annotation> {
&mut self.annotations
}
pub fn iter_annotations(&self) -> std::slice::Iter<'_, Annotation> {
self.annotations.iter()
}
pub fn iter_annotation_contents(&self) -> impl Iterator<Item = &ContentItem> {
self.annotations
.iter()
.flat_map(|annotation| annotation.children())
}
pub fn group(&self) -> VerbatimGroupIter<'_> {
VerbatimGroupIter {
first_yielded: false,
verbatim: self,
rest: self.additional_groups.iter(),
}
}
pub fn group_len(&self) -> usize {
1 + self.additional_groups.len()
}
}
impl AstNode for Verbatim {
fn node_type(&self) -> &'static str {
"VerbatimBlock"
}
fn display_label(&self) -> String {
let subject_text = self.subject.as_string();
if subject_text.chars().count() > 50 {
format!("{}…", subject_text.chars().take(50).collect::<String>())
} else {
subject_text.to_string()
}
}
fn range(&self) -> &Range {
&self.location
}
fn accept(&self, visitor: &mut dyn Visitor) {
visitor.visit_verbatim_block(self);
for group in self.group() {
visitor.visit_verbatim_group(&group);
super::super::traits::visit_children(visitor, group.children);
visitor.leave_verbatim_group(&group);
}
visitor.leave_verbatim_block(self);
}
}
impl VisualStructure for Verbatim {
fn is_source_line_node(&self) -> bool {
true
}
fn has_visual_header(&self) -> bool {
true
}
}
impl Container for Verbatim {
fn label(&self) -> &str {
self.subject.as_string()
}
fn children(&self) -> &[ContentItem] {
&self.children
}
fn children_mut(&mut self) -> &mut Vec<ContentItem> {
self.children.as_mut_vec()
}
}
impl fmt::Display for Verbatim {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let group_count = self.group_len();
let group_word = if group_count == 1 { "group" } else { "groups" };
write!(
f,
"VerbatimBlock('{}', {} {}, closing: {})",
self.subject.as_string(),
group_count,
group_word,
self.closing_data.label.value
)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct VerbatimGroupItem {
pub subject: TextContent,
pub children: VerbatimContainer,
}
impl VerbatimGroupItem {
pub fn new(subject: TextContent, children: Vec<VerbatimContent>) -> Self {
Self {
subject,
children: VerbatimContainer::from_typed(children),
}
}
}
#[derive(Debug, Clone)]
pub struct VerbatimGroupItemRef<'a> {
pub subject: &'a TextContent,
pub children: &'a VerbatimContainer,
}
pub struct VerbatimGroupIter<'a> {
first_yielded: bool,
verbatim: &'a Verbatim,
rest: slice::Iter<'a, VerbatimGroupItem>,
}
impl<'a> Iterator for VerbatimGroupIter<'a> {
type Item = VerbatimGroupItemRef<'a>;
fn next(&mut self) -> Option<Self::Item> {
if !self.first_yielded {
self.first_yielded = true;
return Some(VerbatimGroupItemRef {
subject: &self.verbatim.subject,
children: &self.verbatim.children,
});
}
self.rest.next().map(|item| VerbatimGroupItemRef {
subject: &item.subject,
children: &item.children,
})
}
}