Skip to content

Commit

Permalink
refactor to use less clone for better performance
Browse files Browse the repository at this point in the history
  • Loading branch information
pwnxpl0it committed Dec 29, 2024
1 parent 9de9aba commit c992fd8
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 70 deletions.
26 changes: 10 additions & 16 deletions src/core/funcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl Fns {

/// This method finds `functions` in a string based on a Regex pattern that matches keywords
pub fn find(
txt: String,
txt: &str,
keywords: &HashMap<String, String>,
re: &Regex,
) -> Option<IndexMap<String, (String, Self)>> {
Expand All @@ -34,11 +34,11 @@ impl Fns {
let keyword = key.as_str().to_string();

if !keywords.contains_key(&keyword) {
let new_keyword = Keywords::strip(keyword.clone()).trim().to_string();
let new_keyword = Keywords::strip(&keyword).trim().to_string();
let data = new_keyword.split(':').collect::<Vec<_>>();

if data.len() == 2 {
let keyword_name = Keywords::strip(data[0].to_string());
let keyword_name = Keywords::strip(&data[0].to_string());
let func = data[1].trim();

match func {
Expand All @@ -58,7 +58,7 @@ impl Fns {
}
}
} else {
let keyword_name = Keywords::strip(keyword.clone());
let keyword_name = Keywords::strip(&keyword);
found.insert(keyword_name, (keyword, Self::None));
continue;
}
Expand All @@ -84,21 +84,17 @@ impl Fns {
}

pub fn find_and_exec(
txt: String,
mut keywords: HashMap<String, String>,
re: Regex,
json_data: serde_json::Value,
) -> HashMap<String, String> {
txt: &str,
keywords: &mut HashMap<String, String>,
re: &Regex,
json_data: &serde_json::Value,
) {
if let Some(found) = Self::find(txt, &keywords, &re) {
for (keyword_name, (keyword, function)) in found {
//HACK: Just a bit of optimization, if the json_data is null then it doesn't make sense to run jq
// because doing so is every expensive and here we are dealing with dynamic queries
if !json_data.is_null() && keyword_name.contains(".") {
//TODO: This is not very performant but it works for now UwU
let output = jq_rs::run(&keyword_name, &json_data.to_string());

if let Ok(value) = output {
//NOTE: This will also replace any quotes in the value
if let Ok(value) = jq_rs::run(&keyword_name, &json_data.to_string()) {
keywords.insert(keyword, value.replace("\"", ""));
}
continue;
Expand All @@ -123,7 +119,5 @@ impl Fns {
}
}
}

keywords
}
}
4 changes: 2 additions & 2 deletions src/core/keywords.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ impl Keywords {
}
}

pub fn strip(keyword: String) -> String {
pub fn strip(keyword: &String) -> String {
keyword.replace("{{$", "").replace("}}", "")
}

Expand Down Expand Up @@ -77,7 +77,7 @@ impl Keywords {
keywords
}

pub fn replace_keywords(keywords: HashMap<String, String>, mut data: String) -> String {
pub fn replace_keywords(keywords: &HashMap<String, String>, mut data: String) -> String {
for (key, value) in keywords.iter() {
data = data.replace(key, value);
}
Expand Down
105 changes: 59 additions & 46 deletions src/core/templates/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,54 +83,67 @@ impl Template {
.unwrap()
}

fn handle_project_name(
keywords: &mut HashMap<String, String>,
options: &mut Options,
file: &File,
) -> Result<String, String> {
let trimmed_content = file.content.trim();
let trimmed_path = file.path.trim();
let trimmed_project_root = options.project_root.trim();

if trimmed_content.contains("{{$PROJECTNAME}}")
|| trimmed_path.contains("{{$PROJECTNAME}}")
|| trimmed_project_root.contains("{{$PROJECTNAME}}")
{
let project_name: String = prompt("Project name")
.map_err(|_| format!("{}", "Project name not set.".red().bold()))?;

keywords.insert("{{$PROJECTNAME}}".to_string(), project_name.clone());
options.set_project_root(&project_name);
Ok(project_name)
} else {
Ok(String::new())
}
}

pub fn extract(mut self, keywords: &mut HashMap<String, String>) {
let mut project = String::from("");
let mut output = String::from("");
let re = Regex::new(KEYWORDS_REGEX).unwrap();
let files = self.files.clone().expect("No files table");
let re = Regex::new(KEYWORDS_REGEX).expect("Invalid keywords regex");
let mut options = self.dump_options().unwrap_or_default();

files.into_iter().for_each(|file| {
*keywords = Fns::find_and_exec(
file.content.clone(),
keywords.clone(),
re.clone(),
options.json_data.clone().unwrap_or(serde_json::Value::Null),
);

*keywords = Fns::find_and_exec(
file.path.clone(),
keywords.clone(),
re.clone(),
options.json_data.clone().unwrap_or(serde_json::Value::Null),
);

if (file.path.contains("{{$PROJECTNAME}}")
|| file.content.contains("{{$PROJECTNAME}}")
|| options.project_root.contains("{{$PROJECTNAME}}"))
&& project.is_empty()
{
project = prompt("Project name").unwrap();
options.set_project_root(&project);
keywords.insert("{{$PROJECTNAME}}".to_string(), project.to_owned());
}

let dir = file.path.split('/').collect::<Vec<_>>();
let path = Keywords::replace_keywords(keywords.to_owned(), file.path.to_owned());

if dir.len() > 1 {
create_dirs(&shellexpand::tilde(&Keywords::replace_keywords(
keywords.to_owned(),
file.path.to_owned().replace(dir[dir.len() - 1], ""),
)))
}

output = Keywords::replace_keywords(keywords.to_owned(), file.content);

let liquified = Self::liquify(&output);

write_content(&shellexpand::tilde(&path), liquified)
});
let json_data = options.json_data.clone().unwrap_or(serde_json::Value::Null);
let mut project = String::new();

self.files
.expect("No files table")
.into_iter()
.for_each(|file| {
Fns::find_and_exec(&file.content, keywords, &re, &json_data);
Fns::find_and_exec(&file.path, keywords, &re, &json_data);

if project.is_empty() {
project = match Self::handle_project_name(keywords, &mut options, &file) {
Ok(name) => name,
Err(e) => {
eprintln!("Error handling project name: {}", e);
return;
}
};
}

let dir_path = file.path.split('/').collect::<Vec<_>>();
if dir_path.len() > 1 {
create_dirs(&shellexpand::tilde(&Keywords::replace_keywords(
keywords,
file.path.replace(dir_path.last().unwrap(), ""),
)));
}

let output = Keywords::replace_keywords(keywords, file.content);
let liquified = Self::liquify(&output);
let path = Keywords::replace_keywords(keywords, file.path);

write_content(&shellexpand::tilde(&path), liquified);
});

options.handle();
}
Expand Down
7 changes: 6 additions & 1 deletion src/core/templates/options/git/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub fn check_git() -> Result<(), String> {
Ok(())
}

pub fn git_init(project_root: &str) {
pub fn init(project_root: &str) {

if let Err(e) = check_git() {
eprintln!("{}: {}", "error".red().bold(), e.red().bold());
Expand All @@ -24,6 +24,11 @@ pub fn git_init(project_root: &str) {
return;
}

//if std::path::Path::new(".git").exists() {
//println!("{}", "\n✅ Git is already initialized.".yellow().bold());
//return;
//}

let cmd = Command::new("git")
.arg("init") //TODO: maybe add git arguments? that can be a bit risky..
.stderr(std::process::Stdio::null()) // hide hints and errors
Expand Down
10 changes: 5 additions & 5 deletions src/core/templates/options/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ impl Options {
pub fn handle(self) {
if self.git {
if self.project_root.is_empty() {
println!(
"{}: {}",
"error".red().bold(),
"Please specify a project root.".red().bold()
eprintln!(
"\n{}: {}",
"error".to_string().red(),
"Project root is not set".yellow()
);
return;
}
Expand All @@ -41,7 +41,7 @@ impl Options {
self.project_root.blue()
);

git::git_init(&self.project_root);
git::init(&self.project_root);
}
}
}

0 comments on commit c992fd8

Please sign in to comment.