use crate::error_mod::{Error, Result};
use crate::public_api_mod::{RED, RESET, YELLOW};
use crate::utils_mod::*;
use lazy_static::lazy_static;
lazy_static! {
static ref REGEX_MD_LINK: regex::Regex = regex::Regex::new(
r#".+\[.+\]\((.+)\).+"#
).expect("regex new");
}
pub fn auto_playground_run_code() -> Result<()> {
println!(" {YELLOW}Running auto_playground{RESET}");
let path = std::env::current_dir()?;
let files = crate::utils_mod::traverse_dir_with_exclude_dir(
&path,
"/*.md",
&["/.git".to_string(), "/target".to_string(), "/docs".to_string(), "/pkg".to_string()],
)?;
for md_filename in files {
let md_filename = camino::Utf8Path::new(&md_filename);
let mut is_changed = false;
let md_old = std::fs::read_to_string(md_filename)?;
if md_old.contains("\r\n") {
return Err(Error::ErrorFromString(format!(
"{RED}Error: {md_filename} has CRLF line endings instead of LF. Correct the file! {RESET}"
)));
}
let mut iteration_start_pos = 0;
let mut md_new = String::new();
while let Ok(marker_start) =
find_pos_start_data_after_delimiter(&md_old, iteration_start_pos, "\n[//]: # (auto_playground start)\n")
{
let Ok(code_start) = find_pos_start_data_after_delimiter(&md_old, marker_start, "\n```") else {
return Ok(());
};
let Ok(code_start) = find_pos_start_data_after_delimiter(&md_old, code_start, "\n") else {
return Ok(());
};
let Ok(code_end) = find_pos_end_data_before_delimiter(&md_old, code_start + 3, "\n```\n") else {
return Ok(());
};
let Ok(marker_end) = find_pos_end_data_before_delimiter(&md_old, marker_start, "\n[//]: # (auto_playground end)\n") else {
return Ok(());
};
let rust_code = &md_old[code_start..code_end];
let rust_code_encoded = urlencoding::encode(rust_code).to_string();
let playground_link = format!("https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&code={rust_code_encoded}");
let text_that_has_the_link = &md_old[marker_start..code_start];
let cap_group = REGEX_MD_LINK.captures(text_that_has_the_link).ok_or_else(|| {
Error::ErrorFromString(format!(
"{RED}Error: The old link '{text_that_has_the_link}' is NOT in this format '[Rust playground](https:...)'{RESET}"
))
})?;
let old_link = &cap_group[1];
let text_that_has_the_link = text_that_has_the_link.replace(old_link, &playground_link);
is_changed = true;
md_new.push_str(&format!(
"{}{}{}",
&md_old[iteration_start_pos..marker_start],
&text_that_has_the_link,
&md_old[code_start..marker_end],
));
iteration_start_pos = marker_end;
}
if is_changed {
println!(" {YELLOW}Code inside {md_filename} has changed. Playground link corrected.{RESET}");
md_new.push_str(&md_old[iteration_start_pos..md_old.len()]);
let bak_filename = md_filename.with_extension("bak");
std::fs::write(&bak_filename, md_old)?;
std::fs::write(md_filename, md_new)?;
}
}
println!(" {YELLOW}Finished auto_playground{RESET}");
Ok(())
}