tpope / vim-projectionist

projectionist.vim: Granular project configuration
https://www.vim.org/scripts/script.php?script_id=4989
1.06k stars 65 forks source link

Support nested folder hierarchies for projections #14

Closed glittershark closed 10 years ago

glittershark commented 10 years ago

Some tools like Zend Framework have a folder hierarchy something like the following:

application/
|   modules/
|   |   mod1/
|   |   |   controllers/
|   |   |   |   MyController.php
|   |   |   |   ...
|   |   mod2/
|   |   |   controllers/
|   |   |   |   MyController.php
|   |   |   |   ...
|   |   ...
|   ...

It'd be nice in projectile if I could define a projection like:

{
    "application/modules/*/controllers/*Controller.php": {
        "command": "controller"
    }
}

so I could EController mod1_my

monokrome commented 10 years ago

Seems like that solved most of the issues, actually. Thank you for clarifying.

Seems like this is one is a working example for anyone that might be confused on a similar project:

{
  "src/**/services/*.coffee": {
    "command": "service",
    "template": [
      "angular.module '{dirname|dot}'",
      "  .service '{dirname|dot}.controllers.{basename|underscore}', [",
      "    '$rootScope'",
      "",
      "  ].concat ($rootScope) ->"
    ]
  }
}
monokrome commented 10 years ago

One lingering issue is that concatenating them together means that I have no context of ** vs directory element in the * glob, but I think that this template usage might be an unusual use case?

There is a common use case in Django apps where models.py gets long and moved to a models package instead, for instance.

tpope commented 10 years ago

I don't understand the question.

monokrome commented 10 years ago

For instance, a user may have a file named src/common/services/twitter/tweet.coffee. Given the previously supplied example .projections.json file, you might try to create a new file based on a template:

:Eservice common/twitter/tweet

The slashes seem really awkward in this situation. It might be nice to allow spaces where globs are separated, but this is quite a digression.

This interface is ambiguous, because a user running the previous command would be attempting to define a module called common.services.twitter.tweet. However, getting this information for the template is impossible because {dirname} will be set to common/twitter and {basename} would be tweet. The template would produce common.twitter.services.tweet instead.

One common example of where this use case would occur is when there is a Django project with a package that defines models as a package instead of a single-file module.

I was specifically asking whether using templates in this way was an intended/supported use case, or if it's something that shouldn't be supported? If this is an intentionally unsupported use case then the current implementation seems to work. If it should be supported then it might make more sense to allow a more powerful use case.

tpope commented 10 years ago

Bigger problem there is that the generated filename would be src/common/twitter/services/tweet.coffee. This is where support for multiple * would help, as the proper pattern would be "src/*/services/**/*.coffee".

Once that's fixed, adding another template expansion or two is a comparatively straightforward process.

monokrome commented 10 years ago

Good point. That definitely seems like the right solution as long as it's possible to reference the separate globs independently in the template!

The other concern that is potentially of interest here is whether having two globs implies an additional argument through the command. Would a user use :Eservice common twitter/tweet as their command?

tpope commented 10 years ago

Not if I can help it.

On Tue, Apr 29, 2014 at 11:37 PM, Brandon R. Stoner < notifications@github.com> wrote:

The other concern that is potentially of interest here is whether having two globs implies an additional argument through the command, as well. IE, would a user then use this command?

:Eservice common twitter/tweet

— Reply to this email directly or view it on GitHubhttps://github.com/tpope/vim-projectionist/issues/14#issuecomment-41757582 .

tommcdo commented 10 years ago

I think two new transformations are in order: one that returns the first component, and one that returns all but the first. These will be necessary for cases where * precedes **.

My use case will involve a lot of modules/*/classes/controller/**/*.php-like patterns, so dirname and basename alone aren't enough.

Actually, with the two transformations I'm proposing (the biggest obstacle for which is what to call them), the **/* could be replaced with a **.

tpope commented 10 years ago

I'd probably just repurpose head and tail. But that's small potatoes compared to enhancing the glob support. Unless a hero steps up I don't see this making it into 1.0.

monokrome commented 10 years ago

Just to note, I've seen projects where not having multiple ** is going to cause issues. This doesn't represent my current use case, but would have in the last project that I worked on. The case there is that there can be nested modules. For instance, these patterns should be possible in this case where I can reference the different paren groupings:

src\/([\w\/\\]+)\/(directives|controllers)\/([\w\/\\]+)\.coffee
src/module/directives/example.coffee
src/module/submodule/directives/example.coffee
src/module/directives/category/example.coffee
src/module/controllers/example.coffee
src/module/directives/category/example.coffee
src/module/submodule/directives/example.coffee

A live view of the expression matches can be seen here. Hovering over each line of text will show a tooltip of expected matches in these cases.

It seems like adding limitations such as allowing only one ** glob might be coming at a cost of flexibility. There will always be some solution where head, tail, etc is not enough in some projects - even with the ability to have multiple * groups.