use std::fmt::Display;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Clone, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct CodeSpan(pub String);
impl CodeSpan {
pub fn new<Body: Into<String>>(body: Body) -> Self {
CodeSpan(body.into())
}
}
impl Display for CodeSpan {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.0.is_empty() {
return Ok(());
}
write!(
f,
"`{}`",
self.0
.replace("\\", "\\\\")
.replace("`", "\\`")
.replace("\n\n", "\\\n\n")
)
}
}
impl From<String> for CodeSpan {
fn from(value: String) -> Self {
CodeSpan(value)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn code_span() {
let code_span: CodeSpan = "anything even EOL\ncan be it".to_string().into();
assert_eq!(code_span.to_string(), "`anything even EOL\ncan be it`");
}
#[test]
fn code_span_with_backtick() {
let code_span = CodeSpan::new("anything even EOL\ncan `be` it");
assert_eq!(
code_span.to_string(),
"`anything even EOL\ncan \\`be\\` it`"
);
}
#[test]
fn code_span_with_terminator() {
let code_span = CodeSpan::new("anything even EOL\n\ncan be it\n");
assert_eq!(
code_span.to_string(),
"`anything even EOL\\\n\ncan be it\n`"
);
}
}