Coder Social home page Coder Social logo

vim-projectionist's Introduction

projectionist.vim

Projectionist provides granular project configuration using "projections". What are projections? Let's start with an example.

Example

A while back I went and made a bunch of plugins for working with rbenv. Here's what a couple of them look like:

~/.rbenv/plugins $ tree
.
├── rbenv-ctags
│   ├── bin
│   │   └── rbenv-ctags
│   └── etc
│       └── rbenv.d
│           └── install
│               └── ctags.bash
└── rbenv-sentience
    └── etc
        └── rbenv.d
            └── install
                └── sentience.bash

As you can see, rbenv plugins have hooks in etc/rbenv.d/ and commands in bin/ matching rbenv-*. Here's a projectionist configuration for that setup:

let g:projectionist_heuristics = {
      \   "etc/rbenv.d/|bin/rbenv-*": {
      \     "bin/rbenv-*": {
      \        "type": "command",
      \        "template": ["#!/usr/bin/env bash"],
      \     },
      \     "etc/rbenv.d/*.bash": {"type": "hook"}
      \   }
      \ }

The key in the outermost dictionary says to activate for any directory containing a subdirectory etc/rbenv.d/ or files matching bin/rbenv-*. The corresponding value contains projection definitions. Here, two projections are defined. The first creates an :Ecommand navigation command and provides boilerplate to pre-populate new files with, and the second creates an :Ehook command.

Features

See :help projectionist for the authoritative documentation. Here are some highlights.

Global and per project projection definitions

In the above example, we used the global g:projectionist_heuristics to declare projections based on requirements in the root directory. If that's not flexible enough, you can use the autocommand based API, or create a .projections.json in the root of the project.

Navigation commands

Navigation commands encapsulate editing filenames matching certain patterns. Here are some examples for this very project:

{
  "plugin/*.vim": {"type": "plugin"},
  "autoload/*.vim": {"type": "autoload"},
  "doc/*.txt": {"type": "doc"},
  "README.markdown": {"type": "doc"}
}

With these in place, you could use :Eplugin projectionist to edit plugin/projectionist.vim and :Edoc projectionist to edit doc/projectionist.txt. If no argument is given, it will edit an alternate file of that type (see below) or a projection without a glob. So in this example :Edoc would default to editing README.markdown.

The E stands for edit. You also get S, V, and T variants that split, vsplit, and tabedit.

Tab complete is smart. Not quite "fuzzy finder" smart but smart nonetheless. (On that note, fuzzy finders are great, but I prefer the navigation command approach when there are multiple categories of similarly named files.)

Alternate files

Projectionist provides :A, :AS, :AV, and :AT to jump to an "alternate" file, based on ye olde convention originally established in a.vim. Here's an example configuration for Maven that allows you to jump between the implementation and test:

{
  "src/main/java/*.java": {"alternate": "src/test/java/{}.java"},
  "src/test/java/*.java": {"alternate": "src/main/java/{}.java"}
}

In addition, the navigation commands (like :Eplugin above) will search alternates when no argument is given to edit a related file of that type.

Bonus feature: :A {filename} edits a file relative to the root of the project.

Buffer configuration

Check out these examples for a minimal Ruby project:

{
  "*": {"make": "rake"},
  "spec/*_spec.rb": {"dispatch": "rspec {file}"}
}

That second one sets the default for dispatch.vim. Plugins can use projections for their own configuration.

Installation

Install using your favorite package manager, or use Vim's built-in package support:

mkdir -p ~/.vim/pack/tpope/start
cd ~/.vim/pack/tpope/start
git clone https://tpope.io/vim/projectionist.git
vim -u NONE -c "helptags projectionist/doc" -c q

FAQ

Why not a clearer filename like .vim_projections.json?

Nothing about the file is Vim specific. See projectionist for an example of another tool that uses it.

License

Copyright © Tim Pope. Distributed under the same terms as Vim itself. See :help license.

vim-projectionist's People

Contributors

aliou avatar andrewradev avatar blueyed avatar camilledejoye avatar dradtke avatar ejones avatar gabesoft avatar genki-s avatar mattjbray avatar mboughaba avatar mmcclimon avatar rwstauner avatar svilenb avatar teoljungberg avatar tommcdo avatar tpope avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vim-projectionist's Issues

Setting to ignore directories

I'm using a build tool that makes a copy of the working directory into _build/. So for example, a rule that matches */src/*.ml ends up picking up stuff in _build/ that is undesirable.

Would it be possible to somehow ignore that directory in projectionist results? Just as nice would be to limit the results as to what is available through git ls-files.

Allowing plugins to load additional projections

We have many developers now interesting in Elixir and Phoenix. We have a set of shared projections for Elixir projects but the process of having people add the .projections.json file to each of their projects and then update them when we make improvements to the projections isn't great.

I'd love to have a vim plugin named phoenix-projections that would merge in our phoenix projections on load without clobbering what's already in the global projections variable.

I looked at rails.vim to see how it loads projections and it has some custom code to merge the rails.vim provided projections with the projections that are already loaded. Would this make sense as public API for vim-projectionist instead? Plugins could call a merge_projections function to add their own projections.

This would make it much easier to ship easily-updatable projections. I don't think that's possible right now outside of doing all the work Rails.vim is currently doing, unless I'm missing something.

Allow `path` to be relative

Have you considered an option for allowing path to be relative?

I want to use "path": ["./shared", "./"] in a project where a file is looked for relative to the file doing the import (not relative to the project root).

I've currently hacked this into my own vimrc by putting a fake protocol in front of the value
and then stripping it off after a projectionist event.

This gets me what I want, but I also want to share this with the other members of my team.
Would you be open to some sort of configuration option or string prefix that would leave a leading "./" and not prefix it with the project root?

Sharing source libraries between projects

Hi I'm not sure if I'm missing something important here, sorry if that's the case. I use some source libraries (in their own directory) shared between all my projects that I'd like to easily browse via projectionist. How can I achieve that? All configuration examples I've seen are related to a single directory. Thank you!

PD. I've tried "set path" in .vimrc to include the desired directory but seem to be useless.

Consider using `<nomodeline>` with `doautocmd User`

I've just noticed a performance issue regarding doautocmd User, which triggers (re-)executing the buffer's modeline, even if there are no events registered (junegunn/vim-oblique#30 (comment)).

This can be skipped using doautocmd <nomodeline> User ... (added/fixed in Vim 7.3.442).

For invocations/hooks where the buffer is not supposed / expected to re-apply
buffer-local settings this seems to make sense.

There are two places in vim-projectionist (and more in your other plugins):

autoload/projectionist.vim
382:  silent doautocmd User ProjectionistActivate

plugin/projectionist.vim
58:    silent doautocmd User ProjectionistDetect

I think this can provide a nice performance boost for large files / expensive modelines.

Another possibility to address this for the common case of no user-defined events, an if exists('#User#Foo') could be wrapped around it, but then it won't help for the case where an user event is defined.

Suggested on vim_dev: https://groups.google.com/forum/m/#!topic/vim_dev/DidKMDAsppw

Request: When opening a file, use its path relative to current directory

When opening files, it seems that the command being invoked uses the absolute path, or perhaps the path relative to your home directory. This results in ugly pathnames in the buffer list. It's fixed by issuing :lcd . -- I guess because it reinterprets the current buffer relative to the new (albeit totally unchanged) path.

Anyway, this could conceivably be fixed using the :. filename modifier with fnamemodify(). From the documentation:

    :.      Reduce file name to be relative to current directory, if
            possible.  File name is unmodified if it is not below the
            current directory.

Here's a quick asciicast of what's going on:

https://asciinema.org/a/10590

Transformation from CamelCase to under_score

I have the following .projections.json file for android apps:

{
  "src/com/andrewradev/android_app/*Activity.java": {
    "command":   "activity",
    "alternate": "res/layout/{underscore}.xml",
    "template":  [
      "public class {} extends Activity",
      "{",
      "   @Override public void onCreate(Bundle savedInstanceState) {",
      "   {",
      "       super.onCreate(savedInstanceState);",
      "       setContentView(R.layout.{underscore});",
      "   }",
      "}"
    ]
  },
}

In a project like this, the class names are camelcased, so the command would work like :Eactivity FooBar, resulting in a FooBarActivity.java. I'd like the layout file to be underscored, but I can't figure out a way to do it. I have the same problem with creating a new file for the transformations in the template.

The {underscore} transformation only turns / into _, and doesn't care about camelcased words. If it were modified to transform camelcasedness, that could help. Or, it could be a separate transformation, something like {camelcase_underscore}.

(I also like {camelscore}, but the mirror {undercase} seems silly. Also might be confusing.)

Alternately, maybe I could enter an underscored entity name like foo_bar and have a substitution in the pattern itself: src/com/andrewradev/android_app/{camelcase}Activity.java.

Is there some other (possibly existing) way that I'm missing? What do you think about either of these ideas?

Multiple alternate files

Is it possible to define multiple alternate files for the same buffer? For example, those cases where one of my library files is related to multiple tests (unit, integration, feature...)

Currently I get a list of possible alternate files (which will be created) if there is none for the current buffer, but I have not found a way to get a similar window if multiple alternate files are available.

Template only populates first line

I have this:

  "app/assets/javascripts/application/controllers/*.js" : {
    "command": "acontroller",
    "template": [
      "angular.module('myapp').controller('%SCtrl', ['$scope', function($scope) {",
      "}]);"
    ]
  },

But when I create a new file using the template, only the first line appears. Messing around a bit, I think it’s the } in the second line that breaks it.

Using as a project/file-type detection mechanism for other plug-ins

Projectionist.vim gets me most of the way towards easily detecting the framework my project uses and allowing me to use that information in other plug-ins. For example, I work on some projects that use the Kohana PHP framework, some that are WordPress sites, etc.

To give you some concreat examples of what I'd like to accomplish based on the "project type":

  • Use templates and snippets that intelligently adhere to the current framework's style (e.g., Kohana uses snake case method names, whereas Laravel uses camel case).
  • Load extra UltiSnips snippets for a given framework or project.
  • Derive a class name (such as the parent class's name) from the current file's path. This may depend on the framework and cannot always be derived directly from a string in the path itself.

These are things that are beyond the scope of Projectionist's template functionality, which is fine, and can only partially be accomplished using settings (as in #28).

Here's what I think I'm looking for:

  1. A way to hook into the ProjectionistActivate autocommand, and query Projectile for the type of the current buffer (e.g., class, test) via a buffer-local variable.

  2. A way to hook into the ProjectionistActivate autocommand, and query Projectile for the type of the current project or projection (e.g., kohana, wordpress) via a buffer-local variable. This is a tough one, as top-level entries in g:projectionist_heuristics don't have keys suitable for this purpose.

  3. (Maybe a better alternative to 2) A way to set the filetype from a projection (related to #28), so that I could do something like:

    let g:projectionist_heuristics = {
        \ "application/bootstrap.php": {
        \   "*.php": { "filetype": "php.kohana" },
        \ }}
    

I looked at how Rake.vim handles activation, but it looks like you sort of inverted the responsibility of detecting a "rake project" such that Rake.vim does the detection and then tells Projectionist about it. Essentially, I'd rather offload the responsibility of activating my own plug-ins to Projectionist, since it's already doing all the work.

Support for case transformations in placeholders

In some of my projects, I have lowercase filenames mapped to mixed case class names. So, for example, the class Foo_Bar is defined in classes/foo/bar.php.

In addition to the placeholders like %u, it would be nice to have a corresponding placeholder like %U that would transform foo/bar into Foo_Bar.

Disable heuristics for a particular project

I have a project with a specific .projections.json but that is also triggering some projections from my global heuristics. Is there a way to disable heuristics for a particular project?

Get the list of files for a type

I'd like to use Shougo's Unite as a front-end for Vim-Projectionist, I think it could be awesome!
But to do so, I would need to query the list of existing types, and the list of file for a given type.

In term of code, it would need something like this:

:call projectionist#queryTypes()
" returns ['model', 'controller', 'views']
:call projectionist#queryType('Model')
" returns ['User', 'Article', 'Comment']

I have tried to play with projectionist#query(), but it seems to be scoped to the current buffer.

Broken globbing when directories have/do not have subdirectories

I have the following configuration:

{  
  "features/support/lib/pages/**/regions/*_region.rb": {"type": "region"}
}

And the directory/file structure:

├── platform
│   ├── regions
│   │   ├── activity
│   │   │   └── activity_region.rb
│   │   ├── jobs
│   │   │   ├── assign_developer_region.rb
│   │   │   ├── candidates_region.rb
│   │   │   ├── # etc in subdirectories
├── public
│   ├── regions
│   │   ├── authors_region.rb
│   │   ├── blog_subscribe_region.rb
│   │   ├── # etc with no subdirectories

Projections for region type are populated only from public/ directory. Docs say nothing about this case so I'm not sure how to configure it to include files from both platform/ and public/ dirs.

Projectile detection doesn't include newly-started files

I have a projectile for vim plugins: 'plugin/*.vim|autoload/**/*.vim|addon-info.json'. I also created a template for addon-info.json. The projectile matches any directory that contains an addon-info.json file, but if I create a new directory and run vim newdir/addon-info.json, the projectile doesn't match and the template isn't used.

Projectiles should be triggered when first starting to edit a file that matches the projectile pattern, even if the file hasn't been saved yet.

Any chance of adding Afoo for multiple alternates

From the the source file in src/main/java/file.java I'd like to be able to type:

  • :Atest and go the test file (src/test/java/file.java)
  • :Aheader and go the header file (src/headers/java/file.java)

.projections.json

{
  "src/main/java/*.java": [
    {
        "alternate": "src/test/java/{}.java",
        "type": "test"
    },
    {
        "alternate": "src/headers/java/{}.java",
        "type": "header"
    }
  ]
}

Allow projectionist to work without buffers

During the work I keep cleaning Vim buffers by using bd *<C-A><Cr>. However, when there are no buffers loaded, all commands (defined in .projections.json) no longer work (e.g. E492: Not an editor command: Efeature)

Invalid argument in glob completion

Emod *.ml...
Error detected while processing function <SNR>216_projection_complete..projectionist#completion_filter:
line    2:
E121: Undefined variable: a:A
E116: Invalid arguments for function s:gsub(a:A, '\*', '.*')
E15: Invalid expression: s:gsub(a:A, '\*', '.*')
:Emod *.ml

Vim version:

VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Jul 20 2015 11:21:53)
MacOS X (unix) version
Included patches: 1-789
Compiled by Homebrew

Higher precedence than rake.vim

If I'm in a ruby-gem that has a different project implementation => test file-structure than normally. But I still want to use :A to flip between the two, but it seems to fallback to using rake.vim's structure

Example project minitest

my .projections.json file looks like this

{
  "lib/minitest/*.rb": { "alternate": "test/minitest/test_minitest_%s.rb" },
  "test/minitest/test_minitest_*.rb": { "alternate": "lib/minitest/%s.rb" },
}

Can't insert braces in template

Using something like function () {} in the template property will replace the braces with the globbed name, and {\n} results in an empty file without an error. Escaping with a backslash doesn't seem to work, and even \u007b gets treated the same ;-)

E216: No such group or event: <nomodeline> User ProjectileDetect

After installing vim-projectile (via Vundle), I receive the following error whenever opening vim:

Error detected while processing function ProjectileDetect:
line   28:
E216: No such group or event: <nomodeline> User ProjectileDetect
Press ENTER or type command to continue

I haven't added any custom projections (neither through g:projectiles, autocommands, nor .projections.json). I don't know vimscript, so I'm at a loss.

vim --version info (vim 7.3)

Number as Part of Property

I have seen this on the type property, not sure about anything else. Basically, when you have a number as part of the property value, projectionist seems to use it as part of the name. For example, with this configuration:

{
    "*.e2e.js": {
        "alternate": "{}.js",
        "type": "e2e"
    }
}

and the file structure

(base folder)
|
|
|_____app/app.js
|
|
|_____app/app.e2e.js

then when I run :Ee2e app/app, vim edits the file 2e.e2e.js. However, with the same file structure, if I instead have the configuration

{
    "*.e2e.js": {
        "alternate": "{}.js",
        "type": "etoe"
    }
}

with type etoe instead of e2e, then run Eetoe app/app, vim correctly edits the file app/app.e2e.js.

This indicates that there is something wrong with either the path parsing or the configuration parsing when there is a number in the property value. It seems to put the number and whatever is left of the type value and stick it in front of the file it tries to edit, and then puts a dot between that and the file extension, completely ignoring the name you gave, file and folder.

For reference, the same file, 2e.e2e.js, is edited/created when I use the configuration:

{
    "app/*.e2e.js": {
        "alternate": "app/{}.js",
        "type": "e2e"
    }
}

and then run Ee2e app.

:A creates a new file if it does not exist

In rails project (using rails.vim), when in lib/my_class.rb and I hit :A, I'll see an error if there's no spec file for my_class.rb.

I was surprised to discover that this project's :A creates a new buffer if the file does not exist!
Is this behavior different by accident? Or there's going to be a new "default"?

Personally, I'd prefer to get an error if the file does not exist, and then bang :A! to create it.

Btw. fantastic plugin, just what I need - love it!

Global settings via projectionist_heuristics

I am wondering if and how global settings are supported.

The following seems to work, but it is unclear if that's the way to go:

let g:projectionist_heuristics = {
    …
    \ "*": {
    \   "*.c": { "alternate": "{}.h" },
    \ },
    \ }

It would be nice to have this documented (in case it is supported).
I can prepare a PR in that case.

Vim(while):E712: Argument of get() must be a List or Dictionary

I've got the following message when I try to use the Start command.

Vim(while):E712: Argument of get() must be a List or Dictionary`

{
  "*": {
    "dispatch": ["zeus", "rspec", "spec/"],
    "start": ["zeus", "console"]
  }
}

Vim version:

VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Apr 28 2014 07:43:17)
MacOS X (unix) version
Included patches: 1-253
Compiled by Homebrew

Stop tab completion at glob boundary

I'm not even sure if this is possible with vim's support for tab completion, but it'd be cool if a multi-glob projection as added in #14 stopped tab completion at the boundary between those globs, like tab-completion for pathnames in shells works.

Renaming a buffer breaks :A

I use http://www.vim.org/scripts/script.php?script_id=1928 to rename things sometimes. I just renamed a buffer (:Rename foo/bar/baz/biff.txt) and then used :A to try to create the related file, and it created the related file for the old name.

My guess is that this is due to a missing hook, but I'm not the expert in vimscript. Hope this helps and thanks for all the plugins.

alternate alternates

I'm trying to create a general-purpose g:projectiles that searches multiple locations for the alternate file if the first location doesn't succeed. For example, some C projects have header files in include/, others in src/. I have this:

let g:projectiles = {
       \  '/*.c|src/*.c': {
       \    '*.c': {'alternate': '../include/{}.h|{}.h'},
       \  },
       \}

If I open src/foo.c, projectile reports "No alternate file". If I remove |{}.h, then projectile correctly finds ../include.h.

FWIW, I'm trying to replace fswitch (or a.vim as mentioned in projectile's readme).

Support command-complete command completion. Amirite?

One of Vim's command-complete options is command completion. I'm not sure I've made that very clear.

I'm referring to this, from the docs:

-complete=command              Ex command (with arguments)

So, one can define a command that completes using other commands including their arguments. In my case, I've made a command that takes some arbitrary command that edits a file and then adds that file to the arglist and moves to it. It looks like this:

command! -nargs=* -complete=command ArgCmd execute "<args>" | argadd % | next

That works with the commands defined by projectile.vim. I can run :ArgCmd Emodel user and it will happily edit my user model and add it to my arguments list. The problem is that it projectile vomits if I try to use completion for :Emodel arguments.

If the completion function used by custom or customlist is set up with this in mind, things can run smoothly. I got it working with a simple command of my own, but after looking into projectile.vim's source I figured this might be better left to you. The basic idea I used was to chop off everything before the actual command name in the CmdLine argument.

Autocomplete doesn't find valid matches

Autocomplete works a bit weird for me.

I enter :Efeature opera and hit <Tab> and the only result I get is other/operational_issue.
However, when I enter :Efeature operafil, I get search/operational_issues/filter_by_type in results.

Why doesn't autocomplete for opera doesn't match search/operational_issues/filter_by_type?

Exclude pattern

I'm trying to setup projectionist for the Feedjira gem:

$ ls lib/feedjira/parser/*.rb
lib/feedjira/parser/atom.rb
lib/feedjira/parser/atom_entry.rb
lib/feedjira/parser/atom_feed_burner.rb
lib/feedjira/parser/atom_feed_burner_entry.rb
lib/feedjira/parser/google_docs_atom.rb
lib/feedjira/parser/google_docs_atom_entry.rb
lib/feedjira/parser/itunes_rss.rb
lib/feedjira/parser/itunes_rss_item.rb
lib/feedjira/parser/itunes_rss_owner.rb
lib/feedjira/parser/rss.rb
lib/feedjira/parser/rss_entry.rb
lib/feedjira/parser/rss_feed_burner.rb
lib/feedjira/parser/rss_feed_burner_entry.rb

Here's my .projections.json file:

{
  "lib/feedjira/parser/*_entry.rb": { "type": "entry" },
  "lib/feedjira/parser/!(*_entry).rb": { "type": "parser" }
}

So, I think I should be able to do :Eparser atom (for example) and have lib/feedjira/parser/atom.rb open, but my pattern isn't working. When I do :Eparser plus a tab nothing is found.

I think my pattern is right because:

$ ls lib/feedjira/parser/!(*_entry).rb
lib/feedjira/parser/atom.rb
lib/feedjira/parser/atom_feed_burner.rb
lib/feedjira/parser/google_docs_atom.rb
lib/feedjira/parser/itunes_rss.rb
lib/feedjira/parser/itunes_rss_item.rb
lib/feedjira/parser/itunes_rss_owner.rb
lib/feedjira/parser/rss.rb
lib/feedjira/parser/rss_feed_burner.rb

But maybe I goofed something? Are exclude patterns not supported?

Undefined variable b:projectionist with vim-ags plugin

It looks like the vim-ags plugin is causing some trouble with projectionist and its ".agsv" file. Having just vim-projectionist and vim-ags installed results in this when I try to use the :Ags command:

"search-results.agsv" [New File]
Error detected while processing BufNewFile Auto commands for "*":
E121: Undefined variable: b:projectionist
E116: Invalid arguments for function empty(b:projectionist) |   call projectionist#apply_template() | endif
E15: Invalid expression: !empty(b:projectionist) |   call projectionist#apply_template() | endif
Press ENTER or type command to continue

Maybe a duplicate of #23? Could I just fix this with a blacklist setting I'm not clever enough to figure out? :)

Support for **/ in paths

Would appreciate the ability to define something like this in .projections.json:

{
  "app/views/**/*.html": { "command": "view" }
}

As it stands, it doesn't look like projectile plays nice with **/.

Alternate doesn't work in some cases

I've set up the following configuration in .projections.json

{
  "features/support/factories/*_factory.rb": {
    "type": "ffactory",
    "alternate": "features/support/spec/factories/{}_factory_spec.rb"
  }
}

I can open file correctly with :Effactory admin, but when I try to :A on it, features directory is opened in buffer.

Both files are present:

$ ls features/support/factories/ | grep admin
admin_factory.rb
$ ls features/support/spec/factories/ | grep admin
admin_factory_spec.rb

Alternate alternates to aid in explicit alternate auto-creation?

Tim mentioned in one of the several 'auto-create alternates' threads that Rubyists - as one example - may have a complex set of alternate file needs, including "test/unit/foo_test.rb, test/models/foo_test.rb, or spec/models/foo_spec.rb". What if we could explicitly define user-customizable suffixes to :A and its friends? Example:

"*.rb": {"alternate": ["ut:test/unit/{}_test.rb!",
                     \ "mt:test/models/{}_test.rb",
                     \ "s:spec/models/{}_spec.rb"]}

Those could be expressed any number of ways, e.g. as a map, or delimited string:

"*.rb": {"alternate": "ut:test/unit/{}_test.rb!;mt:test/models/{}_test.rb;s:spec/models/{}_spec.rb"}

but the practical upshot would be from a *.rb file, :Aut would edit the unit test file, :Amt would edit the model test file, and :As would edit the spec file. The current way it works wouldn't be affected - you could still just have "alternate": "foo", but if you wanted, you could grow it out to an explicit set of alternate alternates via explicit suffixes. I have my own hacked-together functions that allow for tests, notes, demo files, etc. They'd fit easily into this (:Au, :An, :Ad). You could also leave one of your alternate alternates non-prefixed, and that would become the default :A alternate.

I think as long as there can be many alternate files, you'll never find a concrete, automatic solution.

Oh, and the trailing ! at the end of the unit test alternate was a thought about some sugar for specifying that you want auto-creation of that particular alternate file (including any missing folders leading to it). With my Python unit test files, e.g., I will always want the file to be created. If it's empty, I either start working and save it at some point, or I decide not to make tests just now and close it, and it's never saved, so I didn't create anything.

My only fear with this is that some prefix, like :Ast would already exist as a command, but projectionist could also just pop up an error on-load to tell you that one or more of your particular alternate suffixes is clashing with something else that exists, and not create that command, and have you fix it yourself, with a side-effect being you might discover and learn about a command on your system you weren't aware of. I suppose it would have to be an after/ thing to allow it to introspect existing commands.

Validate .projection.json

I installed projectionist using pathogen. I have defined a .projections.json file for javascript as shown below:

{
  "libs/js/*.js" : {alternate: "test/{}.js"}
}

Please note that the alternate key did not have the enclosing quotes ("alternate"). On starting up vim, received no errors, and when I tried :A , I got an error E464: Ambiguous use of user-defined command. Was clueless and was about to open an issue for this, and in the process , corrected the quoting mistake. Will it be possible to throw an error when the json file is invalid as in the case.

`E121: Undefined variable: b:projectionist` with `vim foo.txt` (new file)

vim foo.txt (where foo.txt does not exist) throws this error:

"foo.txt" [New File]
Error detected while processing BufNewFile Auto commands for "*":
E121: Undefined variable: b:projectionist
E116: Invalid arguments for function empty(b:projectionist) |   call projectionist#apply_template() | end
if
E15: Invalid expression: !empty(b:projectionist) |   call projectionist#apply_template() | endif

This does not happen for foo - a file extension is required to trigger it.

Support nested folder hierarchies for projections

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

argument optional for file globs with only one match

It's great the exact-match filenames don't require arguments. (i.e. "README.md": { command: "readme" } )

It would also be cool if a file glob that only matched a single file would similarly default to that file and make arguments optional. For instance, readme files are common without extensions and with various file extensions: (.md, .markdown, .txt, .rtf) but there is rarely more than a single readme. It would be nice if a glob could be specified, but executed without an argument if the glob only matches a single file.

Wildcards in `g:projectiles`?

I was hoping to set g:projectiles up to detect certain kinds of projects. Imagine a projection that works for a Ruby gem project. It would look for a gemspec in the root directory and know that things were good. So, like, this works OK:

let g:projectiles = {
  \   "*.gemspec": {
  \     "spec/*": { "command": "spec" },
  \     "spec/spec_helper.rb": { "command": "spec" }
  \   }
  \ }

I can't seem to get the lib directory to work the way I want. I kind of want this, if this makes any sense (where the %s ends up being the name of the gem):

let g:projectiles = {
  \   "*.gemspec": {
  \     "lib/%s/*": { "command": "lib" },
  \     "lib/%s.rb": { "command": "lib" }
  \   }
  \ }

But putting that in and running :Elib gives Invalid number of arguments and :Elib some_file_name (the file exists) gives this:

Error detected while processing function <SNR>89_open_projection:
line   11:
E766: Insufficient arguments for printf()

Is this possible to do so that I don't have to write a bunch of project-specific projection configs that are all the same except the name of the gem? Like... am I just missing something obvious, here? Or is this something that could be added (not necessarily by @tpope)?

Support multiple globs

I'm trying to use projectionist on an ansible project. Ansible likes roles structured mostly like this:

roles
└── {rolename}
    ├── defaults
    ├── files
    ├── handlers
    │   └── {name}.yml
    ├── meta
    ├── tasks
    │   └── {name}.yml
    ├── templates
    │   └── {name}.j2
    └── vars

I'd like to do a command like :Etask nptd main (or, since I'm asking for ponies right now, :Etask nptd and have "main" defaulted from configuration.) This may be possible and I've come down with a case of the dumb, but here's what I'm trying:

{
    "roles/*/tasks/*.yml": {
        "type": "task"
    }
}

can not goback to the main file!

{
"src/main/java/.java": {"alternate": "src/test/java/{}Test.java"},
"src/test/java/
.java": {"alternate": "src/main/java/{}.java"}
}
here is my setting for my javaweb app
when i edit an file in main dir
for example src/main/java/com/wsdjeg/App.java
,i use :A will change to src/test/java/com/wsdjeg/AppTest.java
but how could i goback to src/main/java/com/wsdjeg/App.java

How to achieve this function?

here is the example you show me in the readme.
{
"src/main/java/.java": {"alternate": "src/test/java/{}.java"},
"src/test/java/
.java": {"alternate": "src/main/java/{}.java"}
}

but i want
{
"src/main/java//.java": {"alternate": "src/test/java/{}/Test{}.java"},
"src/test/java//Test.java": {"alternate": "src/main/java/{}/{}.java"}
}
but it does not work

Add prj CLI to README

So I just went back to my non-rails project after a really long time and remembered I had written this. Any qualms about adding it to the README for this repo?

Projectionist doesn't work until you open a file

Maybe I'm weird, but my workflow tends to be:

  1. Open Vim
  2. :cd ~/code/some-project
  3. :Emodel foo

Unfortunately step 3 won't work until I open some file in that project first.

(As a side note, I think this applies to Fugitive too, but I rarely start with a :Ggrep, though it has happened)

Creating the alternate file if it does not exist

Topic. My workflow stumbles when I just created a new module and run :A to go to the test file and it just aborts. Could we make an option to create the file if it does not exist or something of the sort?

Support for local settings

It would be nice if projectionist allowed users to define settings for specific patterns. For instance, the following configuration might exist:

{
    "project/templates/**.html": {
        "settings": { "filetype": "djangohtml" }
    }
}

I considered just having a filetype setting as well, but it seems like this is a more flexible way to solve the problem. I'm wondering if you think that this is useful or out-of-scope before I tried to write it and send over a pull request.

Is this better than just setting up 'path' & using find ?

Hi,

I used to use projections in rails quite a bit, spent quite sometime configuring it as well on quite a few projects but then I found path. I just use a combination of set exrc, a project local ~/.vimrc where I then setup path and it works pretty well, for edge cases where class names are different than file names, we can just modify includeexpr.

So my question is, how do you think projections is better than something like what I described ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.