Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/ronp001/hygen-create

simplifies creation of hygen templates from existing projects
https://github.com/ronp001/hygen-create

hygen

Last synced: 3 months ago
JSON representation

simplifies creation of hygen templates from existing projects

Awesome Lists containing this project

README

        

[![Build Status](https://travis-ci.org/ronp001/hygen-create.svg?branch=master)](https://travis-ci.org/ronp001/hygen-create)

# hygen-create
Simplifies creation of [hygen](http://www.hygen.io) templates from existing projects

## Why

Because creating templates from existing projects is annoying

## In a nutshell

`hygen-create` takes a set of existing project files and uses them to create
`hygen` template files, replacing a selected word with appropriate placeholders (such as <%= name.toLowerCase() %>, <%= h.inflection.camelize(name, true) %>, etc) entries.

Assuming [hygen](http://www.hygen.io) is installed, the resulting template files can be used as is (using the `hygen new` command). They can also be manually edited and changed as desired before using `hygen` to run them.

## Installation

```
$ yarn global add hygen-create
```

or

```
$ npm install -g hygen-create
```

Note that this does NOT install `hygen`. To use the generators made by hygen-create you must have [hygen](http://www.hygen.io) installed as well.

## Generating a generator

There are several steps to generating a generator:

1. Start a hygen-create session: `hygen-create start `
1. `hygen-create add ...` to select files to be templatized for the generator.
1. `hygen-create usename ` to indicate which word to replace with placeholders (of the <%= name %> family): (Note: it's currently highly recommended to use a CamelCased value - see [limitations](#limitations))
1. (Optionally) `hygen-create status` to view information about replacements to be made
1. (Optionally) [configure](#setting-target-templates-directory) the target ```hygen``` _templates directory
1. `hygen-create generate` to generate the new generator

The result: a new ```hygen``` generator will be created. You can now use ```hygen new --name ``` to use your new generator.

## Example session

Just to give a sense of how `hygen-create` works, let's suppose we have a small project that we'd like to reuse as a starting point for other projects.

Our directory hierarchy is:

```
/projects/hello
|-package.json
|-dist
|-hello.js
```

The contents of `package.json`:

```json
{
"name": "hello",
"version": "1.0.0",
"description": "an application that prints hello",
"scripts" : {
"hello": "node dist/hello.js"
}
}
```

The contents of `dist/hello.js`:

```js
// This is hello.js
console.log("Hello!")
```

Although quite simple (and frankly, useless), this is a fully-functioning package
and we can run the `hello` script by typing `npm run hello`:

```bash
$ npm run hello

> [email protected] hello /example
> node dist/hello.js

Hello!
```

### creating a generator

Let's now use `hygen-create` to generate a `greeter generator` from this project.

We'll first start a `hygen-create` session:
```
$ hygen-create start greeter
created hygen-create.json
```

Now let's add our files:

```
$ hygen-create add package.json dist/hello.js
adding: package.json
adding: dist/hello.js
```

If we take a look at `hygen-create.json`, we'll see the added files are listed there:

```
$ cat hygen-create.json
{
"about": "This is a hygen-create definitions file. The hygen-create utility creates generators that can be executed using hygen.",
"hygen_create_version": "0.2.0",
"name": "greeter",
"files_and_dirs": {
"hygen-create.json": true,
"package.json": true,
"dist/hello.js": true
},
"templatize_using_name": null,
"gen_parent_dir": false
}
```

You might notice that `hygen-create` automatically added `hygen-create.json` even though
we did not add it explicitly. The addition of `hygen-create.json` to the generator
makes it easy to iteratively improve the generator we're creating, as we'll see later on.

Now let's tell `hygen-create` that it should turn the word `Hello` into the `name` parameter
of the generator:

```
$ hygen-create usename Hello
using 'Hello' as templatization word
6 matching lines found in 3 included files
```

We can check the status of the session by typing `hygen-create status`:
```
$ hygen-create status

Using the string "Hello" to templatize files (Change using 'hygen-create usename ')

The following files are included in the generator:
[included] - hygen-create.json [2 lines parameterized]
[included] - package.json [3 lines parameterized]
[included] - dist/hello.js [2 lines parameterized]

No target dir: HYGEN_CREATE_TMPLS not set, HYGEN_TMPLS not set, local dir (./_templates) does not exist

Parent dir generation: OFF (the resulting generator will add content to the current directory)
```

If we'd like to see how our files will be templatized, we can use `hygen-create status -v ` to check that out.

So typing ```$ hygen-create status -v package.json``` will output:
![Alt example](doc/example_status.png)

This shows us what the resulting template file will look like (in [hygen template format](http://www.hygen.io/templates)), including a diff of the lines that undergo parameterization.

You might notice that on line 1, ```hello``` is replaced with ```<%= name.toLowerCase() %>```, while on line 3, ```Hello```
is replaced with ```<%= h.capitalize(name) %>```.

Before we generate the generator, we need to ```export HYGEN_CREATE_TMPLS``` to set the target directory.
For the sake of our example, let's ```export HYGEN_CREATE_TMPLS=/tmp/_templates```.

Our final step is to generate the new `greeter` generator:
```
$ hygen-create generate
target path: /tmp/_templates
generating: /tmp/_templates/greeter/new/hygen-create.json.ejs.t
generating: /tmp/_templates/greeter/new/package.json.ejs.t
generating: /tmp/_templates/greeter/new/dist_hello.js.ejs.t
```

### using the generator

We now have a `hygen` generator called `greeter` that is ready to use. For example, we can run:
```
$ export HYGEN_TMPLS=/tmp/_templates
$ mkdir /tmp/dev/hola-greeter
$ cd /tmp/dev/hola-greeter
$ hygen greeter new --name Hola

Loaded templates: /tmp/_templates
added: dist/hola.js
added: hygen-create.json
added: package.json
```

This will generate a new app for us, this one printing `Hola!` instead of `Hello!`:

```
$ cd hola-greeter
$ npm run hola

> [email protected] hola /private/tmp/dev/hola-greeter
> node dist/hola.js

Hola!
```

The reason this prints Hola! and not Hello! is that dist/hola.js now contains the
updated code:
```
$ cat dist/hola.js
// This is hola.js
console.log("Hola!")
```

You may have noticed that to run this we used `npm run hola` rather than `npm run hello`.
This is because `package.json` created by the `greeter generator` looks like this:

```json
{
"name": "hola",
"version": "1.0.0",
"description": "an application that prints 'Hola!'",
"scripts" : {
"hola": "node dist/hola.js"
}
}
```

### iteratively improving the generator

As you may remember, `hygen-create` automatically included `hygen-create.json` as part of the
generator. As a result, when we used the generator to create the `hola` app, we automatically
got a copy of `hygen-create.json` in our directory:

```
$ ls
dist/ hygen-create.json package.json
```

So if we run `hygen-create status` here, we'll see that the generated files are already
included, and the `hygen-create usename ` value and generator name are already set:

```
$ hygen-create status

Using the string "Hola" to templatize files (Change using 'hygen-create usename ')

The following files are included in the generator:
[included] - hygen-create.json [2 lines parameterized]
[included] - package.json [3 lines parameterized]
[included] - dist/hola.js [2 lines parameterized]

Target dir: /tmp/_templates/greeter

Parent dir generation: OFF (the resulting generator will add content to the current directory)
```

This way we can make changes to the generated project and immediately turn those into an updated
version of the generator. For example, let's make a slight modification to `dist/hola.js`:

```
$ cat dist/hola.js
// This is the improved hola.js
console.log("Hola! Hola!")
```

Test our changes:
```
$ npm run hola

> [email protected] hola /private/tmp/dev/hola-greeter
> node dist/hola.js

Hola! Hola!
```

And run `hygen-create` again - although we'll want to change the name of the created generator by running:
```
$ hygen-create rename greeter2
```

(Note that if we do not manually change the name of the target generator, `hygen-create` will
[automatically rename](#previous-versions-of-generators) the previous version)

Now we can run:
```
$ hygen-create generate
target path: /tmp/_templates
generating: /tmp/_templates/greeter2/new/hygen-create.json.ejs.t
generating: /tmp/_templates/greeter2/new/package.json.ejs.t
generating: /tmp/_templates/greeter2/new/dist_hola.js.ejs.t
```

And if we examine `/tmp/_templates/greeter2/new/dist_hola.js.ejs.t` we'll see that the changes we made
to the project have been reflected in the new `greeter2` generator:

```
$ cat /tmp/_templates/greeter2/new/dist_hola.js.ejs.t
---
to: dist/<%= name.toLowerCase() %>.js
---
// This is the improved <%= name.toLowerCase() %>.js
console.log("<%= h.capitalize(name) %>! <%= h.capitalize(name) %>!")
```

## Previous versions of generators

When the `hygen generate` command executes, it checks if the generator directory already exists.
If it does, and the newly created generator is different from the existing one, it will keep the existing generator but rename it by adding a version suffix.

For example, the first time the command to create a generator called `mygen` is executed, the directory
`/mygen/new` will be created. The next time this command is run, `/mygen/new` will be renamed to `/mygen/new.1`, and a new `/mygen/new` will be created.
If the command is run again, `/mygen/new` will be renamed to `/mygen.2`, and so forth.

Note that a new version will not be created if the generator is identical to the previous one.

## Configuration and options

### Setting target templates directory

`hygen-create` will look for a `hygen` _templates directory in the following order:
1. The `HYGEN_CREATE_TMPLS` environment variable - if set and points to an existing directory
1. The `HYGEN_TMPLS` environment variable - if set and points to an existing directory
1. An existing `_templates` directory in the current dir

Note that `hygen-create` will *not* create a _templates directory, and will abort with an error if no such directory is found.

### Option: parent directory generation

* Turning on: `hygen-create setopt --gen-parent-dir`
* Turning off: `hygen-create setopt --no-parent-dir`
* .json file field: `"gen_parent_dir" (boolean)`
* Default:
* If `hygen-create` session was initiated using `hygen-create v0.1.x`: on
* If `hygen-create` session was initiated using `hygen-create v0.2.0` and up: off

**When turned off**: the resulting generator will create contents in the current directory.

**When turned on**: the resulting generator will create a parent directory for all contents. The name of the parent directory will be the value passed in the `--name` option of the generated `hygen` generator.

Example 1: --no-parent-dir
```bash
# start the session
$ hygen-create start mygen

# add a file
$ hygen-create add file1

# specify name to templatize
$ hygen-create usename xyz

# ensure parent-dir generation is off
$ hygen-create setopt --no-parent-dir

# create the generator
$ hygen-create generate # this creates the generator _templates/mygen

# run the generator
# The result: the resulting generator will create ./file1 (i.e., in the current directory)
$ hygen mygen new --name hi

Loaded templates: _templates
added: file1
```

Example 2: --gen-parent-dir
```bash
# start the session
$ hygen-create start mygen

# add a file
$ hygen-create add file1

# specify name to templatize
$ hygen-create usename xyz

# ensure parent-dir generation is off
$ hygen-create setopt --gen-parent-dir

# create the generator
$ hygen-create generate # this creates the generator _templates/mygen

# run the generator
# The result: the resulting generator will create the dir './hi' and then create ./hi/file1
$ hygen mygen new --name hi

Loaded templates: _templates
added: hi/file1

```

## Limitations

### String format (CamelCase, dash-cased, etc.) for the ```hygen-create usename ``` command

TL;DR: provide a CamelCased ```usename/--name``` value both to ```hygen-create``` and to ```hygen```

* ```hygen-create``` currently works best if you provide a CamelCased string to the ```usename``` command. When provided a CamelCased name, ```hygen-create```
will recognize dash-cased, underscore_cased "Title Cased" and other versions. But this recognition currently doesn't work well when the
value provided to ```usename``` not CamelCased.
* There is currently a tight relationship between the format of the ```usename``` string provided to ```hygen-create``` and the string that needs to be provided to ```hygen new --name ```. This may be changed in the future, but right now you should provide the same
format to both commands.

## List of availble commands:
```
$ hygen-create

Usage: hygen-create [options] [command]

hygen-create - create hygen templates from an existing project

Options:

-V, --version output the version number
-v, --verbose provide more info
-p, --project name of session definitions file (default: hygen-create.json)
-h, --help output usage information

Commands:

start [options] initiate a definition session for the generator
rename change the name of the target generator to
add [file|dir...] add files or directories to be templatized
remove|rm [file|dir...] do not templatize specified files/directories
usename set as the templatization param
setopt [options] configure options for the generator
status|s [options] [file] [files...] show replacements to be made in (all|specified) files
generate|g [options] generate a generator from the added files
```

---

## Copyright
(C) 2018 Ron Perry. [MIT License](LICENSE.txt).