simplifies creation of hygen templates from existing projects
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
bin
dist
doc
example
example_output
src
.gitignore
.npmignore renamed Hypegen -> hygen-create Feb 22, 2018
.travis.yml
CHANGELOG.md
LICENSE.txt
README.md
WISHLIST.md
hygen-create.json
package.json
tsconfig-prod.json
tsconfig.json
yarn.lock

README.md

Build Status

hygen-create

Simplifies creation of hygen 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 is installed, the resulting template files can be used as is (using the hygen <generator> 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 installed as well.

Generating a generator

There are several steps to generating a generator:

  1. Start a hygen-create session: hygen-create start <generator-name>
  2. hygen-create add <file> ... to select files to be templatized for the generator.
  3. hygen-create usename <name> 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)
  4. (Optionally) hygen-create status to view information about replacements to be made
  5. (Optionally) configure the target hygen _templates directory
  6. hygen-create generate to generate the new generator

The result: a new hygen generator will be created. You can now use hygen <generator-name> new --name <target-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:

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

The contents of dist/hello.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:

$ npm run hello

> hello@1.0.0 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 <name>')

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 <file> to check that out.

So typing $ hygen-create status -v package.json will output: Alt example

This shows us what the resulting template file will look like (in hygen template format), 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

> hola@1.0.0 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:

{
  "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 <string> value and generator name are already set:

$ hygen-create status

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

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

> hola@1.0.0 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 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 <templates-path>/mygen/new will be created. The next time this command is run, <templates-path>/mygen/new will be renamed to <templates-path>/mygen/new.1, and a new <templates-path>/mygen/new will be created. If the command is run again, <templates-path>/mygen/new will be renamed to <templates-path>/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
  2. The HYGEN_TMPLS environment variable - if set and points to an existing directory
  3. 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

# 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

# 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 <name> 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 <generator> new --name <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 <filename>  name of session definitions file (default: hygen-create.json)
    -h, --help                output usage information


  Commands:

    start [options] <generator-name>      initiate a definition session for the generator <generator-name>
    rename <generator-name>               change the name of the target generator to <generator-name>
    add <file|dir> [file|dir...]          add files or directories to be templatized
    remove|rm <file|dir> [file|dir...]    do not templatize specified files/directories
    usename <name>                        set <name> 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.