use crate::{
errors::TektonError,
models::{
friendly::{FriendlySnippets, Table},
snipmate::Snipmate,
},
};
use regex::{bytes::RegexSetBuilder, Regex};
pub fn compose_snipmate_snippets(friendlies: FriendlySnippets) -> Result<String, TektonError> {
let snippets = create_snipmate_structs_from_json(friendlies)?;
let snipmate_string = build_snipmate_string(snippets)?;
Ok(snipmate_string)
}
pub fn build_snipmate_string(snippets: Vec<Snipmate>) -> Result<String, TektonError> {
match snippets.len() {
0 => Err(TektonError::Reason("No snippets to convert".to_string())),
_ => {
let mut snipmate_string = String::from("");
for snip in snippets {
snipmate_string = snipmate_string + &snip.display();
}
Ok(snipmate_string)
}
}
}
pub fn create_snipmate_structs_from_json(
friendlies: FriendlySnippets,
) -> Result<Vec<Snipmate>, TektonError> {
let table: Table = friendlies.snippets;
if table.is_empty() {
return Err(TektonError::Reason("No snippets to convert".to_string()));
}
let target = table.len();
let mut count: usize = 0;
let mut snipmate_snippets: Vec<Snipmate> = Vec::new();
for (_name, v) in table {
if let Some(prefix) = v.prefix {
let snip: Snipmate = Snipmate {
prefix,
body: v.body,
description: v.description,
};
count += 1;
snipmate_snippets.push(snip)
}
}
println!("Count: {} || Target: {}", count, target);
match count == target {
true => Ok(snipmate_snippets),
false => Err(TektonError::Reason(
"Missing snippets in count, conversion aborted.".to_string(),
)),
}
}
pub fn build_snippets_from_file(lines: Vec<String>) -> Vec<Snipmate> {
let mut snippets: Vec<Snipmate> = Vec::new();
let tab = String::from("\\t");
let tab_regex = Regex::new(&tab).unwrap();
let set = RegexSetBuilder::new([r#"snippet ([a-zA-Z0-9]*)"#])
.case_insensitive(true)
.build()
.expect("failed");
let re = Regex::new(r##"\\""##).unwrap();
for line in lines.iter() {
if set.is_match(line.as_bytes()) {
let mut s = line.split_whitespace();
s.next();
let name = s.next().unwrap_or("").to_string();
let mut desc = s.collect::<Vec<&str>>().join(" ");
desc = re.replace_all(&desc, "").to_string();
desc = desc.replace('\"', "");
let description: Option<String> = match desc.len() {
0 => None,
_ => Some(desc),
};
snippets.push(Snipmate::new(name, Vec::new(), description));
}
else {
let index = snippets.len() - 1;
let handle = snippets.get_mut(index).unwrap();
handle
.body
.push(tab_regex.replace_all(&line.to_string(), " ").to_string());
}
}
snippets
}
#[cfg(test)]
mod tests {
use crate::models::friendly::FriendlySnippetBody;
use super::*;
#[test]
fn test_building_snipmate_on_empty_string() {
let input: Vec<String> = vec![];
let snippets = build_snippets_from_file(input);
assert_eq!(snippets.len(), 0);
}
#[test]
fn test_building_snippets_from_file() {
let input: Vec<String> = vec![
"snippet test".to_string(),
" test snippet".to_string(),
"snippet test2 an epic description".to_string(),
" a second snippet".to_string(),
" with several".to_string(),
" lines.".to_string(),
];
let snippets = build_snippets_from_file(input);
assert_eq!(snippets.len(), 2);
let snip = snippets.get(0).unwrap();
let snip2 = snippets.get(1).unwrap();
let expected = vec![
Snipmate::new(
"test".to_string(),
vec![" test snippet".to_string()],
None,
),
Snipmate::new(
"test2".to_string(),
vec![
" a second snippet".to_string(),
" with several".to_string(),
" lines.".to_string(),
],
Some("an epic description".to_string()),
),
];
assert_eq!(snip.prefix, expected.get(0).unwrap().prefix);
assert_eq!(snip.body, expected.get(0).unwrap().body);
assert_eq!(snip.description, expected.get(0).unwrap().description);
assert_eq!(snip2.prefix, expected.get(1).unwrap().prefix);
assert_eq!(snip2.body, expected.get(1).unwrap().body);
assert_eq!(snip2.description, expected.get(1).unwrap().description);
}
#[test]
fn test_output_string() {
let input: Vec<String> = vec!["snippet test".to_string(), " test snippet".to_string()];
let snippets = build_snippets_from_file(input);
if let Ok(res) = build_snipmate_string(snippets) {
let spaces = " "; let expected: &str = &("snippet test\n\t".to_string() + spaces + "test snippet\n");
assert_eq!(res, expected);
} else {
assert!(false);
}
}
#[test]
fn test_convert_json_to_snipmate() -> Result<(), TektonError> {
let json = FriendlySnippetBody::new(
Some("None".into()),
vec![
" pub fn testing() {".to_string(),
" ${1}".to_string(),
" }".to_string(),
],
None,
);
let mut friendlies = FriendlySnippets::new();
friendlies.snippets.insert("test".into(), json);
let snipmates = create_snipmate_structs_from_json(friendlies)?;
assert_eq!(snipmates.len(), 1);
let string_rep = build_snipmate_string(snipmates)?;
let expected_string =
"snippet None\n\t pub fn testing() {\n\t ${1}\n\t }\n".to_string();
assert_eq!(string_rep, expected_string);
Ok(())
}
}