yeoman / generator

Rails-inspired generator system that provides scaffolding for your apps
http://yeoman.io
BSD 2-Clause "Simplified" License
1.2k stars 298 forks source link

Better management of dest src and configuration (`.yo-rc`?) #312

Closed SBoudrias closed 11 years ago

SBoudrias commented 11 years ago

Hi, there have been quite some talks around the issues here about saving configurations, determining preferences from sub-settings (notably .editorconfig).

The first problem I see here is that it is currently hard to determine the root of a project. For example, all subgenerator must be called from the root or they won't work as expected.

The second is there's no place for yeoman and the generators to save user configurations options.

Over on generator-bbb, what we've created a .bbb-rc file which is read to get user configurations, and is use to determine the root of a project (so our sub-generator works when called from sub directory). This concept is already used by a multitude of projects (bower: .bowerrc, component.json; NPM: package.json, Grunt: Gruntfile.js).

I think this is really a cornerstone in bringing more "intelligence" in how the generator can work based on the user settings.

I think #285, #277, #139, #138, #135 and #14 could benefits from this type of functionnality.

What do you think? (I could work on a basic implementation and send a PR after we talk a bit about the details)

sindresorhus commented 11 years ago

Even though I don't like the idea of introducing yet another rc file onto the world, it does seem like it could be useful. We have discussed it before https://github.com/yeoman/yeoman/issues/105, but it never went anywhere.

Can you expand on what the file would contain?

On a technical perspective I would prefer it to just be a JS file with an exported object.

.yo-rc.js

module.exports = {
  option: true
};
SBoudrias commented 11 years ago

First and foremost, it usefulness is to allow a generator to determine the root of a project. This is usefull to allow generator to work in subdirectory, and would allow generators to more easily find other configs files (like .editorconfig).

On the content, the file should keep prompt choices for every generator used in a project. After, any generator used in the project could save custom properties to this central file to keep track of some project related configs (in generator-bbb, we save all paths config there - user isn't prompt for them, but it can be manually override).

Having this central "data" store would also allow easier sharing of a project between a team. The configurations, just like .gitignore or Gruntfile.jsare then the same for everyone cloning a project.

Of course the usefulness is mostly targeted at generators using sub-generators (so they can retrieve configurations) and to the yeoman-generator core as it can determine smart configuration to use (dest src, beautification preferences, etc).


About it being a js file. It could be, but JSON is way easier to work with as a dynamic data store (read/write - mostly writing).

addyosmani commented 11 years ago

I would favour it being a JSON file. @SBoudrias would you like to propose a sample outline of the file structure in this form (with prompt choices, related configs, paths config etc)?

SBoudrias commented 11 years ago

In my opinion, I think it should be a centralized, but free to write section. The structure could be on two level, the first one divide the file between every generators used on the project, and inside this a simple key-value store.

{
  "yeoman-generator" : {
    "foo": "bar"
  },
  "generator-bbb" : {
    "test_framework" : "mocha"
  }
}

For an API, I'd like it this way:

this.storage.get("test_framework");
this.storage.set("test_framework", "qunit");
this.storage.set({
  "test_framework": "qunit",
  "module_style": "commonjs"
});
this.storage.getAll(); // returning a hash

I think reading the package.json would be the best way to determine the name of a generator.

sindresorhus commented 11 years ago

If we're going for a declarative storage I would prefer YAML (sub-setted to JSON types) as it's more humanized.

Could even reuse configstore by adding an constructor argument to it to override the default path. And add the ability for .set() to accept an hash.

addyosmani commented 11 years ago

Thanks for the structured example, Simon. I actually quite like both the output and the API. Do we need to think about storage clearance and key/value deletion as well?.

I'm not a massive fan of YAML, but if enough people prefer it over JSON let's go with whats the most comfortable option to work with :)

sindresorhus commented 11 years ago

Do we need to think about storage clearance and key/value deletion as well?

Of cource. .del() and .clear()?

passy commented 11 years ago

I'm not a massive fan of YAML, but if enough people prefer it over JSON let's go with whats the most comfortable option to work with :)

There's one reason I would prefer it over JSON: comments.

sindresorhus commented 11 years ago

^ !!

SBoudrias commented 11 years ago

I'll have to checkout configstore, looks very promising!

addyosmani commented 11 years ago

If Simon and Stephen agree with the YAML path too, lets go for it. configstore looks like a good option for us to experiment with.

On Thursday, July 11, 2013, Simon Boudrias wrote:

I'll have to checkout configstore, looks very promising!

— Reply to this email directly or view it on GitHubhttps://github.com/yeoman/generator/issues/312#issuecomment-20813949 .

Sent from Gmail Mobile

SBoudrias commented 11 years ago

Well, I have nothing per say against YAML, but I'm no big fan either.

configstore use Yaml so, let's go for this!

stephenplusplus commented 11 years ago

configstore makes sense to me!

sindresorhus commented 11 years ago

Alright.

Configstore will need the following:

Anything else?

@SBoudrias you suggested .getAll() method, but configstore already have a getter/setter .all. Does that work for you?

SBoudrias commented 11 years ago

That would work for me. But Configstore will need some adjustment (or a good façade) to work with sub objects. So this is still possible.

I could work on a first implementation this weekend.

addyosmani commented 11 years ago

s/del()/remove()?

On Thursday, July 11, 2013, Simon Boudrias wrote:

That would work for me. But Configstore will need some adjustment (or a good façade) to work with sub objects. So this is still possible.

I could work on a first implementation this weekend.

— Reply to this email directly or view it on GitHubhttps://github.com/yeoman/generator/issues/312#issuecomment-20843491 .

Sent from Gmail Mobile

sindresorhus commented 11 years ago

@SBoudrias awesome. looking forward to what you come up with :)

sindresorhus commented 11 years ago

@addyosmani let's go with .delete() to match the Set API.

addyosmani commented 11 years ago

SGTM.

kevinwolfcr commented 11 years ago

I am actually using a similar approach on all of my projects, take a look: https://github.com/toi-agency/generator-restangular/blob/master/AppConfig.json

I think that is a good idea because we can use multiple generators in our projects which will look for the config file and generate the given scaffold in the given folder.

kevinwolfcr commented 11 years ago

Check this generator: https://github.com/kevin-wolf/generator-angularjs i've implemented this.