Bunch of changes inspired by r00k

This commit is contained in:
2013-07-07 17:25:47 -04:00
parent c5a1ed1258
commit cf3eea13fb
141 changed files with 22472 additions and 519 deletions

1
vim/bundle/vim-bundler/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/doc/tags

View File

@@ -0,0 +1,2 @@
See the contribution guidelines for
[rails.vim](https://github.com/tpope/vim-rails/blob/HEAD/CONTRIBUTING.markdown).

View File

@@ -0,0 +1,55 @@
# bundler.vim
This is a lightweight bag of Vim goodies for
[Bundler](http://gembundler.com), best accompanied by
[rake.vim](https://github.com/tpope/vim-rake) and/or
[rails.vim](https://github.com/tpope/vim-rails). Features:
* `:Bundle`, which wraps `bundle`.
* An internalized version of `bundle open`: `:Bopen` (and `:Bsplit`,
`:Btabedit`, etc.).
* `'path'` and `'tags'` are automatically altered to include all gems
from your bundle. (Generate those tags with
[gem-ctags](https://github.com/tpope/gem-ctags)!)
* Highlight Bundler keywords in `Gemfile`.
* Support for `gf` in `Gemfile.lock`, plus syntax highlighting that
distinguishes between installed and missing gems.
## Installation
If you don't have a preferred installation method, I recommend
installing [pathogen.vim](https://github.com/tpope/vim-pathogen), and
then simply copy and paste:
cd ~/.vim/bundle
git clone git://github.com/tpope/vim-bundler.git
Once help tags have been generated, you can view the manual with
`:help bundler`.
## FAQ
> I installed the plugin and started Vim. Why don't any of the commands
> exist?
This plugin cares about the current file, not the current working
directory. Edit a file that's covered by a `Gemfile`.
> I opened a new tab. Why don't any of the commands exist?
This plugin cares about the current file, not the current working
directory. Edit a file that's covered by a `Gemfile`.
## Self-Promotion
Like bundler.vim? Follow the repository on
[GitHub](https://github.com/tpope/vim-bundler) and vote for it on
[vim.org](http://www.vim.org/scripts/script.php?script_id=4280). And if
you're feeling especially charitable, follow [tpope](http://tpo.pe/) on
[Twitter](http://twitter.com/tpope) and
[GitHub](https://github.com/tpope).
## License
Copyright (c) Tim Pope. Distributed under the same terms as Vim itself.
See `:help license`.

View File

@@ -0,0 +1,26 @@
" Vim compiler file
if exists("current_compiler")
finish
endif
let current_compiler = "bundler"
let s:cpo_save = &cpo
set cpo-=C
CompilerSet makeprg=bundle
CompilerSet errorformat=
\%+E%f:%l:\ parse\ error,
\%W%f:%l:\ warning:\ %m,
\%E%f:%l:in\ %*[^:]:\ %m,
\%E%f:%l:\ %m,
\%-C%\tfrom\ %f:%l:in\ %.%#,
\%-Z%\tfrom\ %f:%l,
\%-Z%p^,
\%-G%.%#
let &cpo = s:cpo_save
unlet s:cpo_save
" vim: sw=2:

View File

@@ -0,0 +1,68 @@
*bundler.txt* Support for Ruby's Bundler
Author: Tim Pope <http://tpo.pe/>
License: Same terms as Vim itself (see |license|)
This plugin is only available if 'compatible' is not set.
INTRODUCTION *bundler*
This lightweight companion to rails.vim and rake.vim provides support for
Bundler. In addition to the below commands, it also syntax highlights
Gemfile and Gemfile.lock, and alters 'path' and 'tags' to include bundled
gems. I recommend gem-ctags for generating tags for your gems.
COMMANDS *bundler-commands*
*bundler-:Bundle*
:Bundle[!] [args] Invoke `bundle` via |:make|.
*bundler-:Bopen*
:Bopen[!] [gem] With no argument, edits the Gemfile. Otherwise,
effectively does a `bundle open` of a gem inside of
Vim, including an |:lcd| to the gem's root directory.
Add ! to discard the current buffer's changes.
*bundler-:Bedit*
:Bedit[!] [gem] Like |:Bopen|, but don't |:lcd| afterwards.
*bundler-:Bsplit*
:Bsplit[!] [gem] Like |:Bopen|, but horizontally split. Add ! to
suppress the |:lcd|.
*bundler-:Bvsplit*
:Bvsplit[!] [gem] Like |:Bopen|, but vertically split. Add ! to
suppress the |:lcd|.
*bundler-:Btabedit*
:Btabedit[!] [gem] Like |:Bopen|, but use a new tab. Add ! to
suppress the |:lcd|.
*bundler-:Bpedit*
:Bpedit[!] [gem] Like |:Bopen|, but use a preview window. Add ! to
suppress the |:lcd|.
API *bundler-api*
Use bundler#project(root) to retrieve an object for the project at the given
root path. If no path is given, the current buffer's project root is used.
An empty object is returned if no project is found. Use |empty()| to check
for that.
On the bundler#project() object, versions() returns a dictionary mapping
between gem names and their locked versions, paths() returns a dictionary
mapping between gem names and their installation path (omitting gems which
aren't installed), and has(gem) returns true if the given gem name is in the
bundle (regardless of whether or not it is installed).
The original data structures are returned for performance reasons. Do not
mutate.
ABOUT *bundler-about*
Grab the latest version or report a bug on GitHub:
http://github.com/tpope/vim-bundler
vim:tw=78:et:ft=help:norl:

View File

@@ -0,0 +1,581 @@
" bundler.vim - Support for Ruby's Bundler
" Maintainer: Tim Pope <http://tpo.pe/>
" Version: 2.0
if exists('g:loaded_bundler') || &cp || v:version < 700
finish
endif
let g:loaded_bundler = 1
" Utility {{{1
function! s:function(name) abort
return function(substitute(a:name,'^s:',matchstr(expand('<sfile>'), '<SNR>\d\+_'),''))
endfunction
function! s:sub(str,pat,rep) abort
return substitute(a:str,'\v\C'.a:pat,a:rep,'')
endfunction
function! s:gsub(str,pat,rep) abort
return substitute(a:str,'\v\C'.a:pat,a:rep,'g')
endfunction
function! s:shellesc(arg) abort
if a:arg =~ '^[A-Za-z0-9_/.-]\+$'
return a:arg
else
return shellescape(a:arg)
endif
endfunction
function! s:fnameescape(file) abort
if exists('*fnameescape')
return fnameescape(a:file)
else
return escape(a:file," \t\n*?[{`$\\%#'\"|!<")
endif
endfunction
function! s:shellslash(path)
if exists('+shellslash') && !&shellslash
return s:gsub(a:path,'\\','/')
else
return a:path
endif
endfunction
function! s:completion_filter(results,A)
let results = sort(copy(a:results))
call filter(results,'v:val !~# "\\~$"')
let filtered = filter(copy(results),'v:val[0:strlen(a:A)-1] ==# a:A')
if !empty(filtered) | return filtered | endif
let regex = s:gsub(a:A,'[^/:]','[&].*')
let filtered = filter(copy(results),'v:val =~# "^".regex')
if !empty(filtered) | return filtered | endif
let filtered = filter(copy(results),'"/".v:val =~# "[/:]".regex')
if !empty(filtered) | return filtered | endif
let regex = s:gsub(a:A,'.','[&].*')
let filtered = filter(copy(results),'"/".v:val =~# regex')
return filtered
endfunction
function! s:throw(string) abort
let v:errmsg = 'bundler: '.a:string
throw v:errmsg
endfunction
function! s:warn(str)
echohl WarningMsg
echomsg a:str
echohl None
let v:warningmsg = a:str
endfunction
function! s:add_methods(namespace, method_names) abort
for name in a:method_names
let s:{a:namespace}_prototype[name] = s:function('s:'.a:namespace.'_'.name)
endfor
endfunction
let s:commands = []
function! s:command(definition) abort
let s:commands += [a:definition]
endfunction
function! s:define_commands()
for command in s:commands
exe 'command! -buffer '.command
endfor
endfunction
augroup bundler_utility
autocmd!
autocmd User Bundler call s:define_commands()
augroup END
let s:abstract_prototype = {}
" }}}1
" Syntax highlighting {{{1
function! s:syntaxfile()
syntax keyword rubyGemfileMethod gemspec gem source path git group platforms env ruby
hi def link rubyGemfileMethod Function
endfunction
function! s:syntaxlock()
setlocal iskeyword+=-,.
syn match gemfilelockHeading '^[[:upper:]]\+$'
syn match gemfilelockKey '^\s\+\zs\S\+:'he=e-1 skipwhite nextgroup=gemfilelockRevision
syn match gemfilelockKey 'remote:'he=e-1 skipwhite nextgroup=gemfilelockRemote
syn match gemfilelockRemote '\S\+' contained
syn match gemfilelockRevision '[[:alnum:]._-]\+$' contained
syn match gemfilelockGem '^\s\+\zs[[:alnum:]._-]\+\%([ !]\|$\)\@=' contains=gemfilelockFound,gemfilelockMissing skipwhite nextgroup=gemfilelockVersions,gemfilelockBang
syn match gemfilelockVersions '([^()]*)' contained contains=gemfilelockVersion
syn match gemfilelockVersion '[^,()]*' contained
syn match gemfilelockBang '!' contained
if !empty(bundler#project())
exe 'syn match gemfilelockFound "\<\%(bundler\|' . join(keys(s:project().paths()), '\|') . '\)\>" contained'
exe 'syn match gemfilelockMissing "\<\%(' . join(keys(filter(s:project().versions(), '!has_key(s:project().paths(), v:key)')), '\|') . '\)\>" contained'
else
exe 'syn match gemfilelockFound "\<\%(\S*\)\>" contained'
endif
syn match gemfilelockHeading '^PLATFORMS$' nextgroup=gemfilelockPlatform skipnl skipwhite
syn match gemfilelockPlatform '^ \zs[[:alnum:]._-]\+$' contained nextgroup=gemfilelockPlatform skipnl skipwhite
hi def link gemfilelockHeading PreProc
hi def link gemfilelockPlatform Typedef
hi def link gemfilelockKey Identifier
hi def link gemfilelockRemote String
hi def link gemfilelockRevision Number
hi def link gemfilelockFound Statement
hi def link gemfilelockMissing Error
hi def link gemfilelockVersion Type
hi def link gemfilelockBang Special
endfunction
function! s:setuplock()
nnoremap <silent><buffer> gf :Bopen <C-R><C-F><CR>
nnoremap <silent><buffer> <C-W>f :Bsplit <C-R><C-F><CR>
nnoremap <silent><buffer> <C-W><C-F> :Bsplit <C-R><C-F><CR>
nnoremap <silent><buffer> <C-W>gf :Btabedit <C-R><C-F><CR>
endfunction
augroup bundler_syntax
autocmd!
autocmd BufNewFile,BufRead */.bundle/config set filetype=yaml
autocmd BufNewFile,BufRead Gemfile set filetype=ruby
autocmd Syntax ruby if expand('<afile>:t') ==? 'gemfile' | call s:syntaxfile() | endif
autocmd BufNewFile,BufRead [Gg]emfile.lock setf gemfilelock
autocmd FileType gemfilelock set suffixesadd=.rb
autocmd Syntax gemfilelock call s:syntaxlock()
autocmd FileType gemfilelock call s:setuplock()
autocmd User Rails/Gemfile.lock call s:setuplock()
augroup END
" }}}1
" Initialization {{{1
function! s:FindBundlerRoot(path) abort
let path = s:shellslash(a:path)
let fn = fnamemodify(path,':s?[\/]$??')
let ofn = ""
let nfn = fn
while fn != ofn
if filereadable(fn.'/Gemfile')
return s:sub(simplify(fnamemodify(fn,':p')),'[\\/]$','')
endif
let ofn = fn
let fn = fnamemodify(ofn,':h')
endwhile
return ''
endfunction
function! s:Detect(path)
if !exists('b:bundler_root')
let dir = s:FindBundlerRoot(a:path)
if dir != ''
let b:bundler_root = dir
endif
endif
if exists('b:bundler_root')
silent doautocmd User Bundler
endif
endfunction
augroup bundler
autocmd!
autocmd FileType * call s:Detect(expand('<afile>:p'))
autocmd BufNewFile,BufReadPost *
\ if empty(&filetype) |
\ call s:Detect(expand('<afile>:p')) |
\ endif
autocmd VimEnter * if expand('<amatch>')==''|call s:Detect(getcwd())|endif
augroup END
" }}}1
" Project {{{1
let s:project_prototype = {}
let s:projects = {}
function! bundler#project(...) abort
let dir = a:0 ? a:1 : (exists('b:bundler_root') && b:bundler_root !=# '' ? b:bundler_root : s:FindBundlerRoot(expand('%:p')))
if dir !=# ''
if has_key(s:projects,dir)
let project = get(s:projects,dir)
else
let project = {'root': dir}
let s:projects[dir] = project
endif
return extend(extend(project,s:project_prototype,'keep'),s:abstract_prototype,'keep')
endif
return {}
endfunction
function! s:project(...) abort
let project = a:0 ? bundler#project(a:1) : bundler#project()
if empty(project)
call s:throw('not a Bundler project: '.(a:0 ? a:1 : expand('%')))
else
return project
endif
endfunction
function! s:project_path(...) dict abort
return join([self.root]+a:000,'/')
endfunction
call s:add_methods('project',['path'])
function! s:project_locked() dict abort
let lock_file = self.path('Gemfile.lock')
let time = getftime(lock_file)
if time != -1 && time != get(self,'_lock_time',-1)
let self._locked = {'git': [], 'gem': [], 'path': []}
let self._versions = {}
for line in readfile(lock_file)
if line =~# '^\S'
let properties = {'versions': {}}
if has_key(self._locked, tolower(line))
call extend(self._locked[tolower(line)], [properties])
endif
elseif line =~# '^ \w\+: '
let properties[matchstr(line, '\w\+')] = matchstr(line, ': \zs.*')
elseif line =~# '^ [a-zA-Z0-9._-]\+\s\+(\d\+'
let name = split(line, ' ')[0]
let ver = substitute(line, '.*(\|).*', '', 'g')
let properties.versions[name] = ver
let self._versions[name] = ver
endif
endfor
let self._lock_time = time
endif
return get(self, '_locked', {})
endfunction
function! s:project_paths(...) dict abort
call self.locked()
let time = get(self, '_lock_time', -1)
if a:0 && a:1 ==# 'refresh' || time != -1 && time != get(self, '_path_time', -1)
let paths = {}
let chdir = exists("*haslocaldir") && haslocaldir() ? "lchdir" : "chdir"
let cwd = getcwd()
" Explicitly setting $PATH means /etc/zshenv on OS X can't touch it.
if executable('env')
let prefix = 'env PATH='.s:shellesc($PATH).' '
else
let prefix = ''
endif
let gem_paths = []
if exists('$GEM_PATH')
let gem_paths = split($GEM_PATH, has('win32') ? ';' : ':')
else
try
exe chdir s:fnameescape(self.path())
let gem_paths = split(system(prefix.'ruby -rubygems -e "print Gem.path.join(%(;))"'), ';')
finally
exe chdir s:fnameescape(cwd)
endtry
endif
let abi_version = matchstr(get(gem_paths, 0, '1.9.1'), '[0-9.]\+$')
for config in [expand('~/.bundle/config'), self.path('.bundle/config')]
if filereadable(config)
let body = join(readfile(config), "\n")
let bundle_path = matchstr(body, "\\C\\<BUNDLE_PATH: \\zs[^\n]*")
if !empty(bundle_path)
if body =~# '\C\<BUNDLE_DISABLE_SHARED_GEMS:'
let gem_paths = [self.path(bundle_path, 'ruby', abi_version)]
else
let gem_paths = [self.path(bundle_path)]
endif
endif
endif
endfor
for source in self._locked.git
for [name, ver] in items(source.versions)
for path in gem_paths
let dir = path . '/bundler/gems/' . matchstr(source.remote, '.*/\zs.\{-\}\ze\%(\.git\)\=$') . '-' . source.revision[0:11]
if isdirectory(dir)
let files = split(glob(dir . '/*/' . name . '.gemspec'), "\n")
if empty(files)
let paths[name] = dir
else
let paths[name] = files[0][0 : -10-strlen(name)]
endif
break
endif
endfor
endfor
endfor
for source in self._locked.path
for [name, ver] in items(source.versions)
if source.remote !~# '^/'
let local = simplify(self.path(source.remote))
else
let local = source.remote
endif
let files = split(glob(local . '/*/' . name . '.gemspec'), "\n")
if empty(files)
let paths[name] = local
else
let paths[name] = files[0][0 : -10-strlen(name)]
endif
endfor
endfor
for source in self._locked.gem
for [name, ver] in items(source.versions)
for path in gem_paths
let dir = path . '/gems/' . name . '-' . ver
if isdirectory(dir)
let paths[name] = dir
break
endif
endfor
if !has_key(paths, name)
for path in gem_paths
let dir = glob(path . '/gems/' . name . '-' . ver . '-*')
if isdirectory(dir)
let paths[name] = dir
break
endif
endfor
endif
endfor
endfor
let self._path_time = time
let self._paths = paths
let self._sorted = sort(values(paths))
let index = index(self._sorted, self.path())
if index > 0
call insert(self._sorted, remove(self._sorted,index))
endif
call self.alter_buffer_paths()
return paths
endif
return get(self,'_paths',{})
endfunction
function! s:project_sorted() dict abort
call self.paths()
return get(self, '_sorted', [])
endfunction
function! s:project_gems() dict abort
return self.paths()
endfunction
function! s:project_versions() dict abort
call self.locked()
return get(self, '_versions', {})
endfunction
function! s:project_has(gem) dict abort
call self.locked()
return has_key(self.versions(), a:gem)
endfunction
call s:add_methods('project', ['locked', 'gems', 'paths', 'sorted', 'versions', 'has'])
" }}}1
" Buffer {{{1
let s:buffer_prototype = {}
function! s:buffer(...) abort
let buffer = {'#': bufnr(a:0 ? a:1 : '%')}
let g:buffer = buffer
call extend(extend(buffer,s:buffer_prototype,'keep'),s:abstract_prototype,'keep')
if buffer.getvar('bundler_root') !=# ''
return buffer
endif
call s:throw('not a Bundler project: '.(a:0 ? a:1 : expand('%')))
endfunction
function! bundler#buffer(...) abort
return s:buffer(a:0 ? a:1 : '%')
endfunction
function! s:buffer_getvar(var) dict abort
return getbufvar(self['#'],a:var)
endfunction
function! s:buffer_setvar(var,value) dict abort
return setbufvar(self['#'],a:var,a:value)
endfunction
function! s:buffer_project() dict abort
return s:project(self.getvar('bundler_root'))
endfunction
call s:add_methods('buffer',['getvar','setvar','project'])
" }}}1
" Bundle {{{1
function! s:push_chdir()
if !exists("s:command_stack") | let s:command_stack = [] | endif
let chdir = exists("*haslocaldir") && haslocaldir() ? "lchdir " : "chdir "
call add(s:command_stack,chdir.s:fnameescape(getcwd()))
exe chdir.'`=s:project().path()`'
endfunction
function! s:pop_command()
if exists("s:command_stack") && len(s:command_stack) > 0
exe remove(s:command_stack,-1)
endif
endfunction
function! s:Bundle(bang,arg)
let old_makeprg = &l:makeprg
let old_errorformat = &l:errorformat
let old_compiler = get(b:, 'current_compiler', '')
try
compiler bundler
execute 'make! '.a:arg
if a:bang ==# ''
return 'if !empty(getqflist()) | cfirst | endif'
else
return ''
endif
finally
let &l:errorformat = old_errorformat
let &l:makeprg = old_makeprg
let b:current_compiler = old_compiler
if empty(b:current_compiler)
unlet b:current_compiler
endif
endtry
endfunction
function! s:BundleComplete(A,L,P)
if a:L =~# '^\S\+\s\+\%(show\|update\) '
return s:completion_filter(keys(s:project().paths()),a:A)
endif
return s:completion_filter(['install','update','exec','package','config','check','list','show','outdated','console','viz','benchmark'],a:A)
endfunction
function! s:SetupMake() abort
compiler bundler
endfunction
call s:command("-bar -bang -nargs=? -complete=customlist,s:BundleComplete Bundle :execute s:Bundle('<bang>',<q-args>)")
augroup bundler_make
autocmd FileType gemfilelock call s:SetupMake()
autocmd FileType ruby
\ if expand('<afile>:t') ==? 'gemfile' |
\ call s:SetupMake() |
\ endif
autocmd QuickFixCmdPre make,lmake
\ if &makeprg =~# '^bundle' && exists('b:bundler_root') |
\ call s:push_chdir() |
\ endif
autocmd QuickFixCmdPost make,lmake
\ if &makeprg =~# '^bundle' && exists('b:bundler_root') |
\ call s:pop_command() |
\ call s:project().paths("refresh") |
\ endif
augroup END
" }}}1
" Bopen {{{1
function! s:Open(cmd,gem,lcd)
if a:gem ==# '' && a:lcd
return a:cmd.' `=bundler#buffer().project().path("Gemfile")`'
elseif a:gem ==# ''
return a:cmd.' `=bundler#buffer().project().path("Gemfile.lock")`'
else
if !has_key(s:project().paths(), a:gem)
call s:project().paths('refresh')
endif
if !has_key(s:project().paths(), a:gem)
if has_key(s:project().versions(), a:gem)
let v:errmsg = "Gem \"".a:gem."\" is in bundle but not installed"
else
let v:errmsg = "Gem \"".a:gem."\" is not in bundle"
endif
return 'echoerr v:errmsg'
endif
let path = fnameescape(bundler#buffer().project().paths()[a:gem])
let exec = a:cmd.' '.path
if a:cmd =~# '^pedit' && a:lcd
let exec .= '|wincmd P|lcd '.path.'|wincmd p'
elseif a:lcd
let exec .= '|lcd '.path
endif
return exec
endif
endfunction
function! s:OpenComplete(A,L,P)
return s:completion_filter(keys(s:project().paths()),a:A)
endfunction
call s:command("-bar -bang -nargs=? -complete=customlist,s:OpenComplete Bopen :execute s:Open('edit<bang>',<q-args>,1)")
call s:command("-bar -bang -nargs=? -complete=customlist,s:OpenComplete Bedit :execute s:Open('edit<bang>',<q-args>,0)")
call s:command("-bar -bang -nargs=? -complete=customlist,s:OpenComplete Bsplit :execute s:Open('split',<q-args>,<bang>1)")
call s:command("-bar -bang -nargs=? -complete=customlist,s:OpenComplete Bvsplit :execute s:Open('vsplit',<q-args>,<bang>1)")
call s:command("-bar -bang -nargs=? -complete=customlist,s:OpenComplete Btabedit :execute s:Open('tabedit',<q-args>,<bang>1)")
call s:command("-bar -bang -nargs=? -complete=customlist,s:OpenComplete Bpedit :execute s:Open('pedit',<q-args>,<bang>1)")
" }}}1
" Paths {{{1
function! s:build_path_option(paths,suffix) abort
return join(map(copy(a:paths),'",".escape(s:shellslash(v:val."/".a:suffix),", ")'),'')
endfunction
function! s:buffer_alter_paths() dict abort
if self.getvar('&suffixesadd') =~# '\.rb\>'
let new = self.project().sorted()
let old = type(self.getvar('bundler_paths')) == type([]) ? self.getvar('bundler_paths') : []
for [option, suffix] in [['path', 'lib'], ['tags', 'tags']]
let value = self.getvar('&'.option)
if !empty(old)
let drop = s:build_path_option(old,suffix)
let index = stridx(value,drop)
if index > 0
let value = value[0:index-1] . value[index+strlen(drop):-1]
endif
endif
call self.setvar('&'.option,value.s:build_path_option(new,suffix))
endfor
call self.setvar('bundler_paths',new)
endif
endfunction
call s:add_methods('buffer',['alter_paths'])
function! s:project_alter_buffer_paths() dict abort
for bufnr in range(1,bufnr('$'))
if getbufvar(bufnr,'bundler_root') ==# self.path()
let vim_parsing_quirk = s:buffer(bufnr).alter_paths()
endif
if getbufvar(bufnr, '&syntax') ==# 'gemfilelock'
call setbufvar(bufnr, '&syntax', 'gemfilelock')
endif
endfor
endfunction
call s:add_methods('project',['alter_buffer_paths'])
augroup bundler_path
autocmd!
autocmd User Bundler call s:buffer().alter_paths()
augroup END
" }}}1
" vim:set sw=2 sts=2: