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.
- data/.rspec +1 -0
- data/.travis.yml +4 -0
- data/README.md +3 -174
- data/Rakefile +10 -0
- data/features/.nav +12 -0
- data/features/README.md +17 -0
- data/features/caching.feature +50 -0
- data/features/command_line/README.md +9 -0
- data/features/command_line/progress_messages.feature +44 -0
- data/features/flavorfile/README.md +9 -0
- data/features/flavorfile/comments.feature +24 -0
- data/features/flavorfile/repository_name.feature +53 -0
- data/features/flavorfile/version_constraint.feature +52 -0
- data/features/install_vim_flavor.md +42 -0
- data/features/philosophy.md +90 -0
- data/features/resolve_dependencies.feature +16 -0
- data/features/step_definitions/bootstrap_script_steps.rb +7 -0
- data/features/step_definitions/cli_steps.rb +34 -0
- data/features/step_definitions/directory_steps.rb +23 -0
- data/features/step_definitions/flavor_steps.rb +37 -0
- data/features/step_definitions/flavorfile_steps.rb +12 -0
- data/features/step_definitions/lockfile_steps.rb +13 -0
- data/features/support/env.rb +49 -0
- data/features/typical_usage/README.md +63 -0
- data/features/typical_usage/deploy_to_arbitrary_place.feature +24 -0
- data/features/typical_usage/install_vim_plugins.feature +26 -0
- data/features/typical_usage/uninstall_vim_plugins.feature +31 -0
- data/features/typical_usage/upgrade_vim_plugins.feature +27 -0
- data/features/uninstall_vim_flavor.md +16 -0
- data/features/version_lock.feature +26 -0
- data/lib/vim-flavor.rb +2 -12
- data/lib/vim-flavor/cli.rb +16 -12
- data/lib/vim-flavor/enumerableextension.rb +48 -0
- data/lib/vim-flavor/facade.rb +65 -102
- data/lib/vim-flavor/flavor.rb +70 -63
- data/lib/vim-flavor/flavorfile.rb +15 -47
- data/lib/vim-flavor/lockfile.rb +27 -44
- data/lib/vim-flavor/lockfileparser.rb +65 -0
- data/lib/vim-flavor/stringextension.rb +25 -1
- data/lib/vim-flavor/version.rb +1 -1
- data/lib/vim-flavor/versionconstraint.rb +12 -11
- data/spec/enumerableextension_spec.rb +100 -0
- data/spec/facade_spec.rb +49 -540
- data/spec/flavor_spec.rb +50 -250
- data/spec/flavorfile_spec.rb +34 -110
- data/spec/lockfile_spec.rb +79 -89
- data/spec/spec_helper.rb +0 -65
- data/spec/stringextension_spec.rb +10 -6
- data/spec/versionconstraint_spec.rb +37 -119
- data/vim-flavor.gemspec +3 -1
- metadata +135 -46
- 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,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,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'
|