Skip to content

Commit

Permalink
Add case conversion filters. (#59)
Browse files Browse the repository at this point in the history
* Add tera-text-filters.

* Add heck filters directly.

* Fix formatting.

* Initial readme update for case conversion filters.
  • Loading branch information
atholbro authored Aug 1, 2023
1 parent df2d817 commit 8c6aec3
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 1 deletion.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ memchr = "2"
regex = "1"
serde = {version = "1", features = ["derive"]}
tera = "1"
heck = "0.4.0"
term = "0.7"
toml = "0.5"
walkdir = "2"
Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Run `kickstart --help` for a full listing of the available commands and their fl
- It can load templates from a local directory or from a Git repository
- It has conditional cleanup to not let irrelevant files in the output directory after generation
- Templates can be made for any kind of projects/languages
- Case conversion filters, e.g. `camelCase` to `CamelCase`

The main drawback compared to cookiecutter is the lack of hook scripts support, which can be mitigated a bit by the conditional cleanup.

Expand Down Expand Up @@ -179,6 +180,18 @@ And three more optional fields:

- [Rust CLI application](https://github.com/Keats/rust-cli-template)

## Case Conversion Filters
Case conversion filters are provided (_via [heck](https://github.com/withoutboats/heck)_):
- `upper_camel_case`: UpperCamelCase
- `camel_case`: lowerCamelCase
- `snake_case`: snake_case
- `kebab_case`: kebab-case
- `shouty_snake_case`: SHOUTY_SNAKE_CASE
- `title_case`: Title Case
- `shouty_kebab_case`: SHOUTY-KEBAB-CASE

You can use these like any other filter, e.g. `{{variable_name | camel_case}}`.

## Changelog

### 0.3.0 (unreleased)
Expand Down
49 changes: 49 additions & 0 deletions src/filters.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use std::collections::HashMap;

use heck::*;
use tera::{to_value, try_get_value, Result, Tera, Value};

pub fn register_all_filters(tera: &mut Tera) {
tera.register_filter("upper_camel_case", upper_camel_case);
tera.register_filter("camel_case", camel_case);
tera.register_filter("snake_case", snake_case);
tera.register_filter("kebab_case", kebab_case);
tera.register_filter("shouty_snake_case", shouty_snake_case);
tera.register_filter("title_case", title_case);
tera.register_filter("shouty_kebab_case", shouty_kebab_case);
}

pub fn upper_camel_case(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
let s = try_get_value!("upper_camel_case", "value", String, value);
Ok(to_value(&s.to_upper_camel_case()).unwrap())
}

pub fn camel_case(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
let s = try_get_value!("camel_case", "value", String, value);
Ok(to_value(&s.to_lower_camel_case()).unwrap())
}

pub fn snake_case(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
let s = try_get_value!("snake_case", "value", String, value);
Ok(to_value(&s.to_snake_case()).unwrap())
}

pub fn kebab_case(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
let s = try_get_value!("kebab_case", "value", String, value);
Ok(to_value(&s.to_kebab_case()).unwrap())
}

pub fn shouty_snake_case(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
let s = try_get_value!("shouty_snake_case", "value", String, value);
Ok(to_value(&s.to_shouty_snake_case()).unwrap())
}

pub fn title_case(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
let s = try_get_value!("title_case", "value", String, value);
Ok(to_value(&s.to_title_case()).unwrap())
}

pub fn shouty_kebab_case(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
let s = try_get_value!("shouty_kebab_case", "value", String, value);
Ok(to_value(&s.to_shouty_kebab_case()).unwrap())
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

mod definition;
pub mod errors;
mod filters;
pub mod generation;
mod prompt;
pub mod terminal;
Expand Down
6 changes: 5 additions & 1 deletion src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::path::{Path, PathBuf};
use memchr::memchr;
use tera::{Context, Tera};

use crate::filters::register_all_filters;
use crate::errors::{map_io_err, new_error, Result, ErrorKind};

#[derive(Debug, Clone, Eq, PartialEq)]
Expand Down Expand Up @@ -53,7 +54,10 @@ pub fn render_one_off_template(
context: &Context,
path: Option<PathBuf>,
) -> Result<String> {
Tera::one_off(content, context, false)
let mut tera = Tera::default();
register_all_filters(&mut tera);

tera.render_str(content, context)
.map_err(|err| new_error(ErrorKind::Tera { err, path }))
}

Expand Down

0 comments on commit 8c6aec3

Please sign in to comment.