use crate::{AppendAsLine, RonlogReferences};
use std::collections::HashMap;
use sysexits::{ExitCode, Result};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ExportFormat {
Md,
Ron,
Rst,
}
crate::enum_trait!(ExportFormat {
Md <-> "md",
Ron <-> "ron",
Rst <-> "rst"
});
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct Fragment {
references: RonlogReferences,
changes: HashMap<String, Vec<String>>,
}
impl Fragment {
crate::getters!(@fn @ref
references: RonlogReferences,
changes: HashMap<String, Vec<String>>
);
pub fn merge(&mut self, other: Self) {
for (link, target) in other.references {
self.references
.entry(link)
.and_modify(|t| *t = target.clone())
.or_insert(target);
}
for (category, changes) in other.changes {
self.changes.entry(category.clone()).or_default();
let mut change_list = self.changes[&category].clone();
change_list.append(&mut changes.clone());
self.changes.insert(category, change_list);
}
}
#[must_use]
pub fn move_references(&mut self) -> RonlogReferences {
let result = self.references.clone();
self.references.clear();
result
}
#[must_use]
pub fn new(
references: &RonlogReferences,
changes: &HashMap<String, Vec<String>>,
) -> Self {
Self {
references: references.clone(),
changes: changes.clone(),
}
}
}
impl crate::ToMd for Fragment {
fn to_md(&self, header_level: u8) -> Result<String> {
if (1..=3).contains(&header_level) {
let mut result = String::new();
for (link_name, target) in &self.references {
result.append_as_line(format!("[{link_name}]: {target}"));
}
if !self.references.is_empty() {
result.push('\n');
}
for (category, changes) in &self.changes {
result.append_as_line(format!(
"{} {category}\n",
"#".repeat(header_level.into())
));
for change in changes {
result.append_as_line(format!("- {change}\n"));
}
}
Ok(result)
} else {
Err(ExitCode::DataErr)
}
}
}
impl crate::ToRst for Fragment {
fn to_rst(&self, header_level: u8) -> Result<String> {
if (1..=3).contains(&header_level) {
let mut result = String::new();
for (link_name, target) in &self.references {
result.append_as_line(format!(".. _{link_name}: {target}"));
}
if !self.references.is_empty() {
result.push('\n');
}
for (category, changes) in &self.changes {
result.append_as_line(format!(
"{category}\n{}\n",
match header_level {
1 => "=",
2 => "-",
3 => ".",
_ => unreachable!(),
}
.repeat(category.len())
));
for change in changes {
result.append_as_line(format!("- {change}\n"));
}
}
Ok(result)
} else {
Err(ExitCode::DataErr)
}
}
}
impl Default for Fragment {
fn default() -> Self {
Self::new(&RonlogReferences::new(), &HashMap::new())
}
}