From e8a329be5d081f7a90f05aa8362742f75b6f16cf Mon Sep 17 00:00:00 2001 From: cophilot <philxsb@gmail.com> Date: Mon, 12 Feb 2024 23:04:32 +0100 Subject: [PATCH] v0.4.0 --- .gitignore | 3 +- .phil-project | 2 +- CHANGELOG.md | 11 +++++++ Cargo.lock | 73 +++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 3 +- README.md | 11 +++++-- src/command_storage.rs | 4 +++ src/commands.rs | 25 ++++++++++----- src/data.rs | 7 ++-- src/utils.rs | 55 ++++++++++++++++++++++++++++--- 10 files changed, 172 insertions(+), 22 deletions(-) diff --git a/.gitignore b/.gitignore index e6d0486..4e54f55 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ ideas.md .templify .templates templify-example -install2 \ No newline at end of file +install2 +dev/ \ No newline at end of file diff --git a/.phil-project b/.phil-project index da1396e..64ea341 100644 --- a/.phil-project +++ b/.phil-project @@ -1,4 +1,4 @@ logo:assets/logo.png logo_small:assets/logo.png description_translate:de -version:0.3.1 +version:0.4.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 83a8715..742aafc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ --- +## [v0.4.0](https://github.com/cophilot/templify/tree/0.4.0) (2024-2-12) + +- `.templify` file is now optional +- Added `-blank` flag for the `init` command +- Added placeholder `$$year$$` +- Added placeholder `$$month$$` +- Added placeholder `$$day$$` +- Added placeholder `$$git-name$$` + +--- + ## [v0.3.1](https://github.com/cophilot/templify/tree/0.3.1) (2024-2-9) - Added `-dry-run` flag for the `generate` command diff --git a/Cargo.lock b/Cargo.lock index e4e5286..b2c99ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,21 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -83,6 +98,20 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.0", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -325,6 +354,29 @@ dependencies = [ "tokio-native-tls", ] +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "idna" version = "0.5.0" @@ -449,6 +501,15 @@ dependencies = [ "tempfile", ] +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", +] + [[package]] name = "num_cpus" version = "1.16.0" @@ -784,8 +845,9 @@ dependencies = [ [[package]] name = "templify" -version = "0.3.1" +version = "0.4.0" dependencies = [ + "chrono", "reqwest", "self-replace", "serde_json", @@ -1006,6 +1068,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index a6b08e6..dd82925 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "templify" -version = "0.3.1" +version = "0.4.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -9,3 +9,4 @@ edition = "2021" reqwest = { version = "0.11", features = ["blocking", "json"] } self-replace = "1.3.6" serde_json = "1.0.1" +chrono = "0.4.19" diff --git a/README.md b/README.md index 7df6ced..252ef82 100644 --- a/README.md +++ b/README.md @@ -213,9 +213,14 @@ tpy load https://github.com/cophilot/templify-vault/tree/main/React-ts ## [Release Notes](https://github.com/cophilot/templify/blob/master/CHANGELOG.md) -### [v0.3.1](https://github.com/cophilot/templify/tree/0.3.1) - -- Added `-dry-run` flag for the `generate` command +### [v0.4.0](https://github.com/cophilot/templify/tree/0.4.0) + +- `.templify` file is now optional +- Added `-blank` flag for the `init` command +- Added placeholder `$$year$$` +- Added placeholder `$$month$$` +- Added placeholder `$$day$$` +- Added placeholder `$$git-name$$` --- diff --git a/src/command_storage.rs b/src/command_storage.rs index 5349c20..6cf93cc 100644 --- a/src/command_storage.rs +++ b/src/command_storage.rs @@ -59,6 +59,10 @@ pub fn get_all_commands() -> Vec<Command> { vec!["offline".to_string(), "o".to_string()], "Do not fetch the example template from the internet.".to_string(), )); + init_com.add_flag(Flag::new_bool_flag( + vec!["blank".to_string(), "b".to_string()], + "Initialize only a blank .templates folder.".to_string(), + )); commands.push(init_com); diff --git a/src/commands.rs b/src/commands.rs index 6aa4a9c..27d5524 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1,9 +1,9 @@ -use std::fs::read_dir; - use crate::{ types::{Command, Status}, utils, version_control, }; +use chrono::{self, Datelike}; +use std::fs::read_dir; pub fn list(_command: &Command) -> Status { let st = utils::check_if_templify_initialized(); @@ -115,10 +115,15 @@ pub fn generate(command: &Command) -> Status { println!("Generating new files from template {}...", template_name); - let new_path = utils::parse_templify_file(&format!(".templates/{}/.templify", template_name)) - ["path"] - .clone() - .replace("$$name$$", given_name.as_str()); + let mut new_path = + utils::parse_templify_file(&format!(".templates/{}/.templify", template_name))["path"] + .clone(); + + new_path = new_path.replace("$$name$$", given_name.as_str()); + new_path = new_path.replace("$$year$$", chrono::Local::now().year().to_string().as_str()); + new_path = new_path.replace("$$month$$", &chrono::Local::now().month().to_string()); + new_path = new_path.replace("$$day$$", &chrono::Local::now().day().to_string()); + new_path = new_path.replace("$$git-name$$", &utils::get_git_name()); // create dir and all subdirs if they don't exist if !dry_run { @@ -205,11 +210,15 @@ pub fn init(command: &Command) -> Status { // check if .templates folder exists if std::path::Path::new(".templates").exists() { - println!("templify is already initialized in this project."); - return Status::ok(); + return Status::error("templify is already initialized in this project.".to_string()); } std::fs::create_dir(".templates").unwrap(); + + if command.get_bool_flag("blank") { + println!("templify initialized successfully."); + return Status::ok(); + } std::fs::write( ".templates/README.md", crate::data::get_init_readme_content(), diff --git a/src/data.rs b/src/data.rs index 15bb685..21e978f 100644 --- a/src/data.rs +++ b/src/data.rs @@ -2,7 +2,8 @@ pub fn templify_file_blank(description: String, path: String) -> String { let content = format!("# This file is used by templify to generate new files from this template. # You can use the following variables in this file: # description:The description of the template -# path:The path of the template based on the project root (You can also use the placeholder $$name$$ to use the name of the template for the path) +# path: The path where the file should be generated based on the project root (you can also use placeholders like $$name$$) + description:{} path:{} ", description, path); @@ -25,13 +26,13 @@ templify is a command line tool that helps you manage your project templates. --- -To learn more about templify, please visit the [GitHub repository](https://github.com/cophilot/templify). +To learn more about templify, please visit [templify.philipp-bonin.com](https://templify.philipp-bonin.com/). --- ## How to use templify? -When you can see this file, you have already initialized templify in this folder. You can now create your own templates and generate new files from them. +When you can see this file, you have already initialized templify in this project. You can now create your own templates and generate new files from them. ### Create a new template diff --git a/src/utils.rs b/src/utils.rs index e080d1b..d1be59c 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,3 +1,4 @@ +use chrono::{self, Datelike}; use std::{io::Write, path::Path}; use crate::types::Status; @@ -8,7 +9,25 @@ pub fn parse_templify_file(file_path: &str) -> std::collections::HashMap<String, map.insert("description".to_string(), "".to_string()); map.insert("path".to_string(), ".".to_string()); - let file_content = std::fs::read_to_string(file_path).unwrap(); + let file_content = std::fs::read_to_string(file_path); + if file_content.is_err() { + return map; + } + let file_content = file_content.unwrap(); + + let mut divider = ":".to_string(); + + let first_line = file_content.lines().next(); + if first_line.is_none() { + return map; + } + + let first_line = first_line.unwrap().replace(" ", ""); + if first_line.starts_with("#!") { + let new_divider = first_line.clone().replace("#!", ""); + + divider = new_divider.to_string(); + } for line in file_content.lines() { let line = line.trim(); @@ -16,7 +35,7 @@ pub fn parse_templify_file(file_path: &str) -> std::collections::HashMap<String, continue; } - let parts: Vec<&str> = line.split(":").collect(); + let parts: Vec<&str> = line.split(divider.as_str()).collect(); if parts.len() < 2 { continue; } @@ -114,7 +133,13 @@ pub fn generate_template_dir(path: &str, new_path: &str, given_name: &str, dry_r continue; } - let new_file_name = file_name.replace("$$name$$", given_name); + let mut new_file_name = file_name.replace("$$name$$", given_name); + new_file_name = + new_file_name.replace("$$year$$", chrono::Local::now().year().to_string().as_str()); + new_file_name = + new_file_name.replace("$$month$$", &chrono::Local::now().month().to_string()); + new_file_name = new_file_name.replace("$$day$$", &chrono::Local::now().day().to_string()); + new_file_name = new_file_name.replace("$$git-name$$", &crate::utils::get_git_name()); let new_path = format!("{}/{}", new_path, new_file_name); // check if new_path already exists @@ -139,7 +164,12 @@ pub fn generate_template_dir(path: &str, new_path: &str, given_name: &str, dry_r pub fn generate_template_file(path: &str, new_path: &str, given_name: &str, dry_run: bool) -> bool { let file_content = std::fs::read_to_string(path).unwrap(); - let file_content = file_content.replace("$$name$$", given_name); + let mut file_content = file_content.replace("$$name$$", given_name); + file_content = + file_content.replace("$$year$$", chrono::Local::now().year().to_string().as_str()); + file_content = file_content.replace("$$month$$", &chrono::Local::now().month().to_string()); + file_content = file_content.replace("$$day$$", &chrono::Local::now().day().to_string()); + file_content = file_content.replace("$$git-name$$", &crate::utils::get_git_name()); if Path::new(new_path).exists() { println!("File {} already exists.", new_path); @@ -177,3 +207,20 @@ pub fn check_internet_connection() -> bool { } return false; } + +pub fn get_git_name() -> String { + let output = std::process::Command::new("git") + .arg("config") + .arg("user.name") + .output(); + if output.is_err() { + return "unknown".to_string(); + } + let output = output.unwrap(); + let output = String::from_utf8_lossy(&output.stdout); + let mut name = output.trim().to_string(); + if name.is_empty() { + name = "unknown".to_string(); + } + return name; +}