use serde::{Deserialize, Serialize};
use tatara_lisp::DeriveTataraDomain;
#[derive(DeriveTataraDomain, Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
#[serde(rename_all = "camelCase")]
#[tatara(keyword = "deffold")]
pub struct FoldSpec {
#[serde(default)]
pub filetype: String,
#[serde(default)]
pub method: String,
#[serde(default)]
pub queries: Vec<String>,
#[serde(default)]
pub trigger_chars: String,
#[serde(default)]
pub default_level: u32,
#[serde(default)]
pub marker_start: String,
#[serde(default)]
pub marker_end: String,
}
pub const KNOWN_METHODS: &[&str] = &["treesitter", "indent", "marker", "heading", "syntax"];
#[must_use]
pub fn is_known_method(method: &str) -> bool {
KNOWN_METHODS.contains(&method)
}
impl FoldSpec {
#[must_use]
pub fn effective_method(&self) -> &str {
crate::strutil::default_if_empty(&self.method, "treesitter")
}
#[must_use]
pub fn marker_pair_complete(&self) -> bool {
!self.marker_start.is_empty() && !self.marker_end.is_empty()
}
#[must_use]
pub fn query_count(&self) -> usize {
self.queries.len()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn known_methods_match_vim_foldmethod_vocabulary() {
assert_eq!(
KNOWN_METHODS,
&["treesitter", "indent", "marker", "heading", "syntax"],
);
for m in KNOWN_METHODS {
assert!(is_known_method(m));
}
assert!(!is_known_method("origami"));
assert!(!is_known_method(""));
}
#[test]
fn effective_method_falls_back_to_treesitter() {
let s = FoldSpec::default();
assert_eq!(s.effective_method(), "treesitter");
let s = FoldSpec {
method: "indent".into(),
..Default::default()
};
assert_eq!(s.effective_method(), "indent");
}
#[test]
fn marker_pair_complete_requires_both_sides() {
let mut s = FoldSpec {
method: "marker".into(),
..Default::default()
};
assert!(!s.marker_pair_complete(), "neither set");
s.marker_start = "{{{".into();
assert!(!s.marker_pair_complete(), "only start set");
s.marker_end = "}}}".into();
assert!(s.marker_pair_complete(), "both set");
}
#[test]
fn query_count_reports_query_length() {
let s = FoldSpec::default();
assert_eq!(s.query_count(), 0);
let s = FoldSpec {
queries: vec!["(a)".into(), "(b)".into(), "(c)".into()],
..Default::default()
};
assert_eq!(s.query_count(), 3);
}
}