use super::theme::*;
use std::{collections::*, io::*, sync::*};
const INDENTATION: &str = " ";
const BRANCH_CONTINUATION_LAST: &str = " ";
const BRANCH_CONTINUATION_ONGOING: &str = "│ ";
const BRANCH_CONTINUATION_ONGOING_THICK: &str = "┃ ";
const BRANCH_CONTINUATION_ONGOING_DOUBLE: &str = "║ ";
const BRANCH_INTO_LAST: &str = "└─";
const BRANCH_INTO_LAST_THICK: &str = "┗━";
const BRANCH_INTO_LAST_DOUBLE: &str = "╚═";
const BRANCH_INTO_ONGOING: &str = "├─";
const BRANCH_INTO_ONGOING_THICK: &str = "┣━";
const BRANCH_INTO_ONGOING_DOUBLE: &str = "╠═";
pub static DEFAULT_DEPICTION_CONTEXT: LazyLock<DepictionContext> =
LazyLock::new(|| DepictionContext::new(&DEFAULT_THEME));
pub static PLAIN_DEPICTION_CONTEXT: LazyLock<DepictionContext> = LazyLock::new(|| DepictionContext::new(&PLAIN_THEME));
#[derive(Clone)]
pub struct DepictionContext<'own> {
pub theme: &'own Theme,
pub inline: bool,
pub separator: bool,
pub indentation: String,
pub configuration: HashMap<String, String>,
}
impl<'own> DepictionContext<'own> {
pub fn new(theme: &'own Theme) -> Self {
Self {
theme,
inline: false,
separator: false,
indentation: Default::default(),
configuration: Default::default(),
}
}
pub fn child(&self) -> Self {
Self {
theme: self.theme,
inline: false,
separator: self.separator,
indentation: self.indentation.clone(),
configuration: self.configuration.clone(),
}
}
pub fn with_theme(mut self, theme: &'own Theme) -> Self {
self.theme = theme;
self
}
pub fn with_inline(mut self, inline: bool) -> Self {
self.inline = inline;
self
}
pub fn with_separator(mut self, separator: bool) -> Self {
self.separator = separator;
self
}
pub fn with_configuration(mut self, key: &str, value: &str) -> Self {
self.configuration.insert(key.into(), value.into());
self
}
pub fn increase_indentation(mut self) -> Self {
self.indentation = self.indentation + INDENTATION;
self
}
pub fn increase_indentation_branch(mut self, last: bool) -> Self {
if last {
self.indentation = self.indentation + BRANCH_CONTINUATION_LAST;
} else {
self.indentation = self.indentation + BRANCH_CONTINUATION_ONGOING;
}
self
}
pub fn increase_indentation_thick_branch(mut self, last: bool) -> Self {
if last {
self.indentation = self.indentation + BRANCH_CONTINUATION_LAST;
} else {
self.indentation = self.indentation + BRANCH_CONTINUATION_ONGOING_THICK;
}
self
}
pub fn increase_indentation_double_branch(mut self, last: bool) -> Self {
if last {
self.indentation = self.indentation + BRANCH_CONTINUATION_LAST;
} else {
self.indentation = self.indentation + BRANCH_CONTINUATION_ONGOING_DOUBLE;
}
self
}
pub fn separate<WriteT>(&self, writer: &mut WriteT) -> Result<()>
where
WriteT: Write,
{
if self.separator { write!(writer, " ") } else { Ok(()) }
}
pub fn indent<WriteT>(&self, writer: &mut WriteT) -> Result<()>
where
WriteT: Write,
{
write!(writer, "\n{}", self.theme.delimiter(&self.indentation))
}
pub fn indent_into<WriteT>(&self, writer: &mut WriteT, delimiter: &str) -> Result<()>
where
WriteT: Write,
{
write!(writer, "\n{}", self.theme.delimiter(format!("{}{}", self.indentation, delimiter)))
}
pub fn indent_into_branch<WriteT>(&self, writer: &mut WriteT, last: bool) -> Result<()>
where
WriteT: Write,
{
if last { self.indent_into(writer, BRANCH_INTO_LAST) } else { self.indent_into(writer, BRANCH_INTO_ONGOING) }
}
pub fn indent_into_thick_branch<WriteT>(&self, writer: &mut WriteT, last: bool) -> Result<()>
where
WriteT: Write,
{
if last {
self.indent_into(writer, BRANCH_INTO_LAST_THICK)
} else {
self.indent_into(writer, BRANCH_INTO_ONGOING_THICK)
}
}
pub fn indent_into_double_branch<WriteT>(&self, writer: &mut WriteT, last: bool) -> Result<()>
where
WriteT: Write,
{
if last {
self.indent_into(writer, BRANCH_INTO_LAST_DOUBLE)
} else {
self.indent_into(writer, BRANCH_INTO_ONGOING_DOUBLE)
}
}
pub fn separate_or_indent<WriteT>(&self, writer: &mut WriteT, first: bool) -> Result<()>
where
WriteT: Write,
{
if first && !self.inline { self.separate(writer) } else { self.indent(writer) }
}
pub fn separate_or_indent_into<WriteT>(&self, writer: &mut WriteT, delimiter: &str, first: bool) -> Result<()>
where
WriteT: Write,
{
if first && !self.inline {
self.separate(writer)?;
self.theme.write_delimiter(writer, delimiter)
} else {
self.indent_into(writer, delimiter)
}
}
}