vim-flavor 0.0.4 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. data/.rspec +1 -0
  2. data/.travis.yml +4 -0
  3. data/README.md +3 -174
  4. data/Rakefile +10 -0
  5. data/features/.nav +12 -0
  6. data/features/README.md +17 -0
  7. data/features/caching.feature +50 -0
  8. data/features/command_line/README.md +9 -0
  9. data/features/command_line/progress_messages.feature +44 -0
  10. data/features/flavorfile/README.md +9 -0
  11. data/features/flavorfile/comments.feature +24 -0
  12. data/features/flavorfile/repository_name.feature +53 -0
  13. data/features/flavorfile/version_constraint.feature +52 -0
  14. data/features/install_vim_flavor.md +42 -0
  15. data/features/philosophy.md +90 -0
  16. data/features/resolve_dependencies.feature +16 -0
  17. data/features/step_definitions/bootstrap_script_steps.rb +7 -0
  18. data/features/step_definitions/cli_steps.rb +34 -0
  19. data/features/step_definitions/directory_steps.rb +23 -0
  20. data/features/step_definitions/flavor_steps.rb +37 -0
  21. data/features/step_definitions/flavorfile_steps.rb +12 -0
  22. data/features/step_definitions/lockfile_steps.rb +13 -0
  23. data/features/support/env.rb +49 -0
  24. data/features/typical_usage/README.md +63 -0
  25. data/features/typical_usage/deploy_to_arbitrary_place.feature +24 -0
  26. data/features/typical_usage/install_vim_plugins.feature +26 -0
  27. data/features/typical_usage/uninstall_vim_plugins.feature +31 -0
  28. data/features/typical_usage/upgrade_vim_plugins.feature +27 -0
  29. data/features/uninstall_vim_flavor.md +16 -0
  30. data/features/version_lock.feature +26 -0
  31. data/lib/vim-flavor.rb +2 -12
  32. data/lib/vim-flavor/cli.rb +16 -12
  33. data/lib/vim-flavor/enumerableextension.rb +48 -0
  34. data/lib/vim-flavor/facade.rb +65 -102
  35. data/lib/vim-flavor/flavor.rb +70 -63
  36. data/lib/vim-flavor/flavorfile.rb +15 -47
  37. data/lib/vim-flavor/lockfile.rb +27 -44
  38. data/lib/vim-flavor/lockfileparser.rb +65 -0
  39. data/lib/vim-flavor/stringextension.rb +25 -1
  40. data/lib/vim-flavor/version.rb +1 -1
  41. data/lib/vim-flavor/versionconstraint.rb +12 -11
  42. data/spec/enumerableextension_spec.rb +100 -0
  43. data/spec/facade_spec.rb +49 -540
  44. data/spec/flavor_spec.rb +50 -250
  45. data/spec/flavorfile_spec.rb +34 -110
  46. data/spec/lockfile_spec.rb +79 -89
  47. data/spec/spec_helper.rb +0 -65
  48. data/spec/stringextension_spec.rb +10 -6
  49. data/spec/versionconstraint_spec.rb +37 -119
  50. data/vim-flavor.gemspec +3 -1
  51. metadata +135 -46
  52. data/spec/cli_spec.rb +0 -15
@@ -0,0 +1,42 @@
1
+ ## Required softwares
2
+
3
+ * [Git](http://git-scm.com/) 1.7.9 or later
4
+ * [Ruby](http://www.ruby-lang.org/) 1.9.2 or later
5
+ * Recommendation: Use [RVM](http://beginrescueend.com/) or other tools
6
+ for ease of installation across different envinronments.
7
+ * [Vim](http://www.vim.org/) 7.3 or later
8
+ * Note that Vim should be compiled as normal, big or huge version
9
+ to use most of plugins.
10
+
11
+
12
+
13
+
14
+ ## Supported platforms
15
+
16
+ * Unix-like environments such as Linux, Mac OS X, etc.
17
+ * Though Microsoft Windows is not directly supported,
18
+ it is possible to manage Vim plugins via Cygwin or other environments.
19
+
20
+
21
+
22
+
23
+ ## Installation steps
24
+
25
+ gem install vim-flavor
26
+
27
+ cd $YOUR_REPOSITORY_FOR_DOTFILES
28
+
29
+ # Add the following line into the first line of your vimrc:
30
+ #
31
+ # runtime flavors/bootstrap.vim
32
+ vim vimrc
33
+
34
+ touch VimFlavor VimFlavor.lock
35
+
36
+ git add VimFlavor VimFlavor.lock vimrc
37
+ git commit -m 'Use vim-flavor to manage my favorite Vim plugins'
38
+
39
+
40
+
41
+
42
+ <!-- vim: set expandtab shiftwidth=4 softtabstop=4 textwidth=78 : -->
@@ -0,0 +1,90 @@
1
+ ## Installable plugins
2
+
3
+ Not all Vim plugins can be installed with vim-flavor.
4
+ vim-flavor can install plugins which meet the following conditions:
5
+
6
+ * Plugins must have dedicated Git repositories.
7
+ vim-flavor does not support other version control systems.
8
+ This is an intentional design. Because:
9
+ * [vim-scripts.org](http://vim-scripts.org/) provides
10
+ [comprehensive Git mirrors](https://github.com/vim-scripts) for
11
+ [plugins uploaded to www.vim.org](http://www.vim.org/scripts/index.php).
12
+ * Experimental plugins which are not uploaded to www.vim.org
13
+ are usually found in [GitHub](https://github.com/).
14
+ * Plugins must follow [the versioning pocilies of
15
+ RubyGems](http://docs.rubygems.org/read/chapter/7#page26) and have "version"
16
+ tags in their repositories. For example, if there is the version 1.2.3 of
17
+ a plugin, its repository must have the tag `1.2.3`, and the files of the
18
+ version 1.2.3 can be checked out via the tag `1.2.3`. In other words,
19
+ plugins which do not have proper tags are not installable.
20
+ This is an intentional design. Because:
21
+ * It's not possible to determine whether two versions are compatible or not
22
+ without "version" tags. Compatibility is a big problem to resolve
23
+ dependencies of plugins. For example, if plugin A requires plugin X 1.2.3
24
+ or later while plugin B requires plugin X 2.0 or later, it's not possible
25
+ to use A and B at the same time. Such problems should be detected before
26
+ installing plugins.
27
+ * Git mirrors by vim-scripts.org are tagged with version numbers.
28
+ * Some Git repositories might not have "version" tags.
29
+ Such plugins are not ready to use for everyone.
30
+ So that it should not be installable.
31
+ * Plugins must have proper directory structures.
32
+ For example, directories such as `autoload`, `syntax` etc should exist in
33
+ the roots of plugins.
34
+ This is an intentional design. Because:
35
+ * Git mirrors by vim-scripts.org have proper directory structures even if
36
+ the original plugins are uploaded to www.vim.org without proper directory
37
+ structures. (A good example is
38
+ [a.vim](http://www.vim.org/scripts/script.php?script_id=31) and
39
+ [its mirror](https://github.com/vim-scripts/a.vim).)
40
+ * Other Git repositories might not have proper directory structures.
41
+ Such plugins are not ready to use for everyone.
42
+ So that it should not be installable.
43
+
44
+
45
+
46
+
47
+ ## Why make another management tool?
48
+
49
+ I know that there are several implementations for the same purpose and many
50
+ users love them, but all of them do not meet my taste. That's why I wrote
51
+ vim-flavor. The philosophy on vim-flavor is as follows:
52
+
53
+ Whole configuration including *versions of plugins* should be under a version
54
+ control system. All of existing implementations do not manage versions of
55
+ plugins. This means that *it's not possible to use the same configuration
56
+ across multiple environments* (the only one exception is using
57
+ [pathogen](https://github.com/tpope/vim-pathogen) with Git submodules,
58
+ but you'll find it's painful to manually manage many plugins).
59
+
60
+ There should be a standard way to describe proper dependencies of plugins to
61
+ install dependencies without explicit declarations. Most of existing
62
+ implementations do not resolve dependencies automatically (the only one
63
+ exception is
64
+ [vim-addon-manager](https://github.com/MarcWeber/vim-addon-manager), but it
65
+ doesn't take care about required versions). The configuration file formats of
66
+ vim-flavor are also used to describe dependencies of plugins with required
67
+ versions. This means that vim-flavor installs plugins and their dependencies
68
+ automatically (unfortunately this feature is not implemented yet, but it'll be
69
+ available soon).
70
+
71
+ Any software should have enough and reproducible test cases.
72
+ But existing implementations such as
73
+ [vundle](https://github.com/gmarik/vundle) and
74
+ [neobundle](https://github.com/Shougo/neobundle.vim) are not developed so.
75
+ It's horrible for me.
76
+
77
+ Installation steps should be small, be reproducible, and not affect existing
78
+ environment as less as possible. Most of existing implementations require to
79
+ manually tweak `~/.vim` etc. It's painful to set up such stuffs manually
80
+ because a vimfiles path is varied on each platform.
81
+
82
+ Finally, a tool and files deployed by the tool should be uninstalled easily.
83
+ [Vimana](https://github.com/c9s/Vimana) does not meet this because it directly
84
+ puts files into `~/.vim/colors` etc and it doesn't provide `uninstall`
85
+ command.
86
+
87
+
88
+
89
+
90
+ <!-- vim: set expandtab shiftwidth=4 softtabstop=4 textwidth=78 : -->
@@ -0,0 +1,16 @@
1
+ Feature: Resolve dependencies of Vim plugins
2
+ In order to hide details of dependencies,
3
+ as a lazy Vim user,
4
+ I want to resolve and install dependencies of Vim plugins automatically.
5
+
6
+ # TODO
7
+ Scenario: Resolve 2-level dependencies
8
+
9
+ # TODO
10
+ Scenario: Resolve 3-level dependencies
11
+
12
+ # TODO
13
+ Scenario: Resolve dependencies of a plugin required by two or more plugins
14
+
15
+ # TODO
16
+ Scenario: Resolve dependencies of a plugin required by plugins and user
@@ -0,0 +1,7 @@
1
+ Then /^I get a bootstrap script in '(.+)'$/ do |virtual_path|
2
+ File.should exist(
3
+ expand(virtual_path).
4
+ to_flavors_path.
5
+ to_bootstrap_path
6
+ )
7
+ end
@@ -0,0 +1,34 @@
1
+ When /^I run `vim-flavor(.*)`(?: again)?(?:,? (but))?$/ do |args, mode|
2
+ begin
3
+ original_home = ENV['HOME']
4
+ ENV['HOME'] = expand('$home')
5
+ Dir.chdir(expand('$tmp')) do
6
+ original_stdout = $stdout
7
+ begin
8
+ $stdout = @output = StringIO.new()
9
+ Vim::Flavor::CLI.start(args.strip().split(/\s+/).map {|a| expand(a)})
10
+ rescue RuntimeError => e
11
+ @last_error = e
12
+ ensure
13
+ $stdout = original_stdout
14
+ end
15
+ if mode == 'but'
16
+ raise RuntimeError, 'Command succeeded unexpectedly' if not @last_error
17
+ else
18
+ raise @last_error if @last_error
19
+ end
20
+ end
21
+ ensure
22
+ ENV['HOME'] = original_home
23
+ end
24
+ end
25
+
26
+ Then /^it fails with messages like$/ do |pattern|
27
+ @last_error.should_not be_nil
28
+ @last_error.message.should match Regexp.new(pattern.strip().gsub(/\s+/, '\s+'))
29
+ end
30
+
31
+ Then 'it outputs progress like' do |text|
32
+ # For some reason, Cucumber drops the last newline from every docstring...
33
+ @output.string.should include expand(text + "\n")
34
+ end
@@ -0,0 +1,23 @@
1
+ require 'tmpdir'
2
+
3
+ Given /^a temporary directory called '(.+)'$/ do |name|
4
+ path = Dir.mktmpdir
5
+ at_exit do
6
+ delete_path path
7
+ end
8
+ variable_table[name] = path
9
+ end
10
+
11
+ Given /^a home directory called '(.+)' in '(.+)'$/ do |name, virtual_path|
12
+ actual_path = expand(virtual_path)
13
+ Dir.mkdir actual_path, 0700
14
+ variable_table[name] = actual_path
15
+ end
16
+
17
+ Given /^I don't have a directory called '(.+)'$/ do |virtual_path|
18
+ Dir.should_not exist(expand(virtual_path))
19
+ end
20
+
21
+ Given /^I delete '(.+)'$/ do |virtual_path|
22
+ delete_path expand(virtual_path)
23
+ end
@@ -0,0 +1,37 @@
1
+ Given /^a repository '(.+)' with versions '(.+)'$/ do |basename, versions|
2
+ repository_path = make_repo_path(basename)
3
+ doc_name = basename.split('/').last.sub(/^vim-/, '')
4
+ variable_table["#{basename}_uri"] = make_repo_uri(basename)
5
+ system <<-"END"
6
+ {
7
+ mkdir -p '#{repository_path}' &&
8
+ cd '#{repository_path}' &&
9
+ git init &&
10
+ mkdir doc &&
11
+ for v in #{versions}
12
+ do
13
+ echo "*#{doc_name}* $v" >'doc/#{doc_name}.txt'
14
+ git add doc
15
+ git commit -m "Version $v"
16
+ git tag -m "Version $v" "$v"
17
+ done
18
+ } >/dev/null
19
+ END
20
+ end
21
+
22
+ Given /^I disable network to the original repository of '(.+)'$/ do |basename|
23
+ delete_path make_repo_path(basename)
24
+ end
25
+
26
+ Then /^I get flavor '(.+)' with '(.+)' in '(.+)'$/ do |v_repo_name, version, virtual_path|
27
+ flavor_path = make_flavor_path(expand(virtual_path), expand(v_repo_name))
28
+ basename = expand(v_repo_name).split('/').last.sub(/^vim-/, '')
29
+ File.open("#{flavor_path}/doc/#{basename}.txt", 'r').read().should ==
30
+ "*#{basename}* #{version}\n"
31
+ File.should exist("#{flavor_path}/doc/tags")
32
+ end
33
+
34
+ Then /^I don't have flavor '(.+)' in '(.+)'$/ do |v_repo_name, virtual_path|
35
+ flavor_path = make_flavor_path(expand(virtual_path), expand(v_repo_name))
36
+ Dir.should_not exist(flavor_path)
37
+ end
@@ -0,0 +1,12 @@
1
+ Given 'flavorfile' do |content|
2
+ create_file expand('$tmp').to_flavorfile_path, expand(content)
3
+ end
4
+
5
+ When 'I edit flavorfile as' do |content|
6
+ steps %Q{
7
+ Given flavorfile
8
+ """
9
+ #{content}
10
+ """
11
+ }
12
+ end
@@ -0,0 +1,13 @@
1
+ Given 'lockfile' do |content|
2
+ create_file expand('$tmp').to_lockfile_path, expand(content)
3
+ end
4
+
5
+ Given /^I delete lockfile$/ do
6
+ delete_path expand('$tmp').to_lockfile_path
7
+ end
8
+
9
+ Then 'I get lockfile' do |content|
10
+ # For some reason, Cucumber drops the last newline from every docstring...
11
+ File.open(expand('$tmp').to_lockfile_path, 'r').read().should ==
12
+ (content == '' ? '' : expand(content) + "\n")
13
+ end
@@ -0,0 +1,49 @@
1
+ require 'fileutils'
2
+ require 'vim-flavor'
3
+
4
+ class FakeUserEnvironment
5
+ def initialize()
6
+ env = self
7
+ Vim::Flavor::Flavor.instance_eval do
8
+ @github_repo_uri = lambda {|user, repo|
9
+ "file://#{env.expand('$tmp')}/repos/#{user}/#{repo}"
10
+ }
11
+ end
12
+ end
13
+
14
+ def create_file path, content
15
+ File.open(path, 'w') do |f|
16
+ f.write(content)
17
+ end
18
+ end
19
+
20
+ def delete_path path
21
+ FileUtils.remove_entry_secure(path)
22
+ end
23
+
24
+ def expand(virtual_path)
25
+ virtual_path.gsub(/\$([a-z_]+)/) {
26
+ variable_table[$1]
27
+ }
28
+ end
29
+
30
+ def make_flavor_path(vimfiles_path, repo_name)
31
+ "#{vimfiles_path.to_flavors_path}/#{repo_name.zap}"
32
+ end
33
+
34
+ def make_repo_path(basename)
35
+ "#{expand("$tmp")}/repos/#{basename}"
36
+ end
37
+
38
+ def make_repo_uri(basename)
39
+ "file://#{make_repo_path(basename)}"
40
+ end
41
+
42
+ def variable_table
43
+ @variable_table ||= Hash.new
44
+ end
45
+ end
46
+
47
+ World do
48
+ FakeUserEnvironment.new
49
+ end
@@ -0,0 +1,63 @@
1
+ ## Abstract
2
+
3
+ As a skilled Vim user, it is an exciting time to start using a new plugin,
4
+ but installation is not so, because there are several steps to do like the
5
+ following:
6
+
7
+ 1. Get a package of the plugin.
8
+ 2. Copy source tree in the package into `~/.vim` etc.
9
+ 3. Generate the help tags file for the plugin.
10
+
11
+ It is also exciting to upgrade favorite Vim plugins to the latest version,
12
+ but I don't want to repeat the steps for each plugin. It's boring.
13
+
14
+ Some plugins depend on other plugins, so that I have to install also
15
+ dependencies, but it is easy to forget about dependencies.
16
+ It's sad to see error messages like "E117: Unknown function: foo#bar".
17
+
18
+ It would be better to automate these routine works with a declarative way,
19
+ and `vim-flavor` does it.
20
+
21
+
22
+
23
+
24
+ ## Typical workflow
25
+
26
+ cd $YOUR_REPOSITORY_FOR_DOTFILES
27
+
28
+ # Add, delete or change declarations which versions of Vim plugins to use.
29
+ vim VimFlavor
30
+
31
+ # Install Vim plugins according to VimFlavor.
32
+ vim-flavor install
33
+
34
+ # Record changes to the declarations and locked status.
35
+ git add VimFlavor VimFlavor.lock
36
+ git commit -m '...'
37
+
38
+
39
+
40
+
41
+ ## Flavorfile (`VimFlavor`)
42
+
43
+ `vim-flavor` reads a file `VimFlavor` in the current working directory.
44
+ The file is called a flavorfile. A flavorfile contains zero or more
45
+ declarations about Vim plugins and which versions of Vim plugins to use.
46
+
47
+ See also [Flavorfile details](../flavorfile).
48
+
49
+
50
+
51
+
52
+ ## Lockfile (`VimFlavor.lock`)
53
+
54
+ `vim-flavor` creates a file `VimFlavor.lock` in the current working directory.
55
+ The file is called a lockfile. A lockfile contains details about installed
56
+ Vim plugins to use the same configuration on every machine.
57
+
58
+ You don't have to care about the content of a lockfile.
59
+
60
+
61
+
62
+
63
+ <!-- vim: set expandtab shiftwidth=4 softtabstop=4 textwidth=78 : -->
@@ -0,0 +1,24 @@
1
+ @typical_usage
2
+ Feature: Deploy Vim plugins to a non-standard directory
3
+ In order to provide flexibility,
4
+ as a lazy Vim user,
5
+ I want to deploy Vim plugins to arbitrary place.
6
+
7
+ Background:
8
+ Given a temporary directory called 'tmp'
9
+ And a home directory called 'home' in '$tmp/home'
10
+ And a repository 'foo' with versions '1.0.0 1.0.1 1.0.2'
11
+
12
+ Scenario: Install to specified vimfiles path which does not exist
13
+ Given flavorfile
14
+ """ruby
15
+ flavor '$foo_uri'
16
+ """
17
+ And I don't have a directory called '$tmp/my-vimfiles'
18
+ When I run `vim-flavor install --vimfiles-path=$tmp/my-vimfiles`
19
+ Then I get lockfile
20
+ """
21
+ $foo_uri (1.0.2)
22
+ """
23
+ And I get a bootstrap script in '$tmp/my-vimfiles'
24
+ And I get flavor '$foo_uri' with '1.0.2' in '$tmp/my-vimfiles'
@@ -0,0 +1,26 @@
1
+ @typical_usage
2
+ Feature: Install Vim plugins
3
+ In order to automate boring steps,
4
+ as a lazy Vim user,
5
+ I want to use a declarative way to start using new Vim plugins.
6
+
7
+ Background:
8
+ Given a temporary directory called 'tmp'
9
+ And a home directory called 'home' in '$tmp/home'
10
+ And a repository 'foo' with versions '1.0.0 1.0.1 1.0.2'
11
+
12
+ Scenario: Install from scratch
13
+ Given flavorfile
14
+ """ruby
15
+ """
16
+ When I edit flavorfile as
17
+ """ruby
18
+ flavor '$foo_uri'
19
+ """
20
+ And I run `vim-flavor install`
21
+ Then I get lockfile
22
+ """
23
+ $foo_uri (1.0.2)
24
+ """
25
+ And I get a bootstrap script in '$home/.vim'
26
+ And I get flavor '$foo_uri' with '1.0.2' in '$home/.vim'