Swap FuzzyFinder for Command-T.
This commit is contained in:
parent
4cdb6dc777
commit
edb217bc0f
114 changed files with 478043 additions and 9246 deletions
1
vim/vim.symlink/bundle/command-t/.gitattributes
vendored
Normal file
1
vim/vim.symlink/bundle/command-t/.gitattributes
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
data/benchmark.yml export-ignore
|
5
vim/vim.symlink/bundle/command-t/.gitignore
vendored
Normal file
5
vim/vim.symlink/bundle/command-t/.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
.release-notes.txt
|
||||||
|
.ruby-version
|
||||||
|
command-t.recipe
|
||||||
|
/.bundle
|
||||||
|
vendor/bundle
|
9
vim/vim.symlink/bundle/command-t/.gitmodules
vendored
Normal file
9
vim/vim.symlink/bundle/command-t/.gitmodules
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[submodule "vendor/vimball"]
|
||||||
|
path = vendor/vimball
|
||||||
|
url = https://github.com/tomtom/vimball.rb.git
|
||||||
|
[submodule "vendor/vimscriptuploader"]
|
||||||
|
path = vendor/vimscriptuploader
|
||||||
|
url = https://github.com/tomtom/vimscriptuploader.rb.git
|
||||||
|
[submodule "vendor/vroom"]
|
||||||
|
path = vendor/vroom
|
||||||
|
url = https://github.com/google/vroom.git
|
8
vim/vim.symlink/bundle/command-t/.mailmap
Normal file
8
vim/vim.symlink/bundle/command-t/.mailmap
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
Greg Hurrell <greg@hurrell.net> Greg Hurrell <greg@hurrell.net>
|
||||||
|
Greg Hurrell <greg@hurrell.net> Wincent Colaiuta <win@wincent.com>
|
||||||
|
Kevin Webster <webster.kevin@gmail.com> rabidpraxis <webster.kevin@gmail.com>
|
||||||
|
Nicolas Alpi <nicolas.alpi@gmail.com> Spyou <nicolas.alpi@gmail.com>
|
||||||
|
Noon Silk <noonsilk@gmail.com> Noon Silk <noonsilk@gmail.com>
|
||||||
|
Noon Silk <noonsilk@gmail.com> Noon Silk <superhappyfun@gmail.com>
|
||||||
|
Sung Pae <sung@metablu.com> guns <sung@metablu.com>
|
||||||
|
Sung Pae <sung@metablu.com> guns <self@sungpae.com>
|
1
vim/vim.symlink/bundle/command-t/.rspec
Normal file
1
vim/vim.symlink/bundle/command-t/.rspec
Normal file
|
@ -0,0 +1 @@
|
||||||
|
--colour
|
2
vim/vim.symlink/bundle/command-t/.vim_org.yml
Normal file
2
vim/vim.symlink/bundle/command-t/.vim_org.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
--- {}
|
||||||
|
|
7
vim/vim.symlink/bundle/command-t/Gemfile
Normal file
7
vim/vim.symlink/bundle/command-t/Gemfile
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
source 'https://rubygems.org'
|
||||||
|
|
||||||
|
gem 'nokogiri'
|
||||||
|
gem 'mechanize'
|
||||||
|
gem 'rake'
|
||||||
|
gem 'rr'
|
||||||
|
gem 'rspec'
|
48
vim/vim.symlink/bundle/command-t/Gemfile.lock
Normal file
48
vim/vim.symlink/bundle/command-t/Gemfile.lock
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
GEM
|
||||||
|
remote: https://rubygems.org/
|
||||||
|
specs:
|
||||||
|
diff-lcs (1.2.5)
|
||||||
|
domain_name (0.5.15)
|
||||||
|
unf (>= 0.0.5, < 1.0.0)
|
||||||
|
http-cookie (1.0.2)
|
||||||
|
domain_name (~> 0.5)
|
||||||
|
mechanize (2.7.3)
|
||||||
|
domain_name (~> 0.5, >= 0.5.1)
|
||||||
|
http-cookie (~> 1.0)
|
||||||
|
mime-types (~> 2.0)
|
||||||
|
net-http-digest_auth (~> 1.1, >= 1.1.1)
|
||||||
|
net-http-persistent (~> 2.5, >= 2.5.2)
|
||||||
|
nokogiri (~> 1.4)
|
||||||
|
ntlm-http (~> 0.1, >= 0.1.1)
|
||||||
|
webrobots (>= 0.0.9, < 0.2)
|
||||||
|
mime-types (2.1)
|
||||||
|
mini_portile (0.5.2)
|
||||||
|
net-http-digest_auth (1.4)
|
||||||
|
net-http-persistent (2.9.4)
|
||||||
|
nokogiri (1.6.1)
|
||||||
|
mini_portile (~> 0.5.0)
|
||||||
|
ntlm-http (0.1.1)
|
||||||
|
rake (10.1.1)
|
||||||
|
rr (1.1.2)
|
||||||
|
rspec (2.14.1)
|
||||||
|
rspec-core (~> 2.14.0)
|
||||||
|
rspec-expectations (~> 2.14.0)
|
||||||
|
rspec-mocks (~> 2.14.0)
|
||||||
|
rspec-core (2.14.7)
|
||||||
|
rspec-expectations (2.14.5)
|
||||||
|
diff-lcs (>= 1.1.3, < 2.0)
|
||||||
|
rspec-mocks (2.14.5)
|
||||||
|
unf (0.1.3)
|
||||||
|
unf_ext
|
||||||
|
unf_ext (0.0.6)
|
||||||
|
webrobots (0.1.1)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
ruby
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
mechanize
|
||||||
|
nokogiri
|
||||||
|
rake
|
||||||
|
rr
|
||||||
|
rspec
|
22
vim/vim.symlink/bundle/command-t/LICENSE
Normal file
22
vim/vim.symlink/bundle/command-t/LICENSE
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
21
vim/vim.symlink/bundle/command-t/Makefile
Normal file
21
vim/vim.symlink/bundle/command-t/Makefile
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
rubyfiles := $(shell find ruby -name '*.rb')
|
||||||
|
cfiles := $(shell find ruby -name '*.c')
|
||||||
|
cheaders := $(shell find ruby -name '*.h')
|
||||||
|
depends := $(shell find ruby -name depend)
|
||||||
|
txtfiles := $(shell find doc -name '*.txt')
|
||||||
|
vimfiles := $(shell find autoload plugin -name '*.vim')
|
||||||
|
|
||||||
|
vimball: command-t.vba
|
||||||
|
|
||||||
|
command-t.recipe: $(rubyfiles) $(cfiles) $(cheaders) $(depends) $(txtfiles) $(vimfiles)
|
||||||
|
echo "$^" | perl -pe 's/ /\n/g' > $@
|
||||||
|
command-t.vba: command-t.recipe
|
||||||
|
vendor/vimball/vimball.rb -d . -b . vba $^
|
||||||
|
|
||||||
|
.PHONY: spec
|
||||||
|
spec:
|
||||||
|
rspec spec
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -f command-t.vba
|
1
vim/vim.symlink/bundle/command-t/README.txt
Symbolic link
1
vim/vim.symlink/bundle/command-t/README.txt
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
doc/command-t.txt
|
179
vim/vim.symlink/bundle/command-t/Rakefile
Normal file
179
vim/vim.symlink/bundle/command-t/Rakefile
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
|
def bail_on_failure
|
||||||
|
exitstatus = $?.exitstatus
|
||||||
|
if exitstatus != 0
|
||||||
|
err "last command failed with exit status #{exitstatus}"
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def version
|
||||||
|
`git describe`.chomp
|
||||||
|
end
|
||||||
|
|
||||||
|
def rubygems_version
|
||||||
|
# RubyGems will barf if we try to pass an intermediate version number
|
||||||
|
# like "1.1b2-10-g61a374a", so no choice but to abbreviate it
|
||||||
|
`git describe --abbrev=0`.chomp
|
||||||
|
end
|
||||||
|
|
||||||
|
def yellow
|
||||||
|
"\033[33m"
|
||||||
|
end
|
||||||
|
|
||||||
|
def red
|
||||||
|
"\033[31m"
|
||||||
|
end
|
||||||
|
|
||||||
|
def clear
|
||||||
|
"\033[0m"
|
||||||
|
end
|
||||||
|
|
||||||
|
def warn(str)
|
||||||
|
puts "#{yellow}warning: #{str}#{clear}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def err(str)
|
||||||
|
puts "#{red}error: #{str}#{clear}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def prepare_release_notes
|
||||||
|
# extract base release notes from README.txt HISTORY section
|
||||||
|
File.open('.release-notes.txt', 'w') do |out|
|
||||||
|
lines = File.readlines('README.txt').each { |line| line.chomp! }
|
||||||
|
while line = lines.shift do
|
||||||
|
next unless line =~ /^HISTORY +\*command-t-history\*$/
|
||||||
|
break unless lines.shift == '' &&
|
||||||
|
(line = lines.shift) && line =~ /^\d\.\d/ &&
|
||||||
|
lines.shift == ''
|
||||||
|
while line = lines.shift && line != ''
|
||||||
|
out.puts line
|
||||||
|
end
|
||||||
|
break
|
||||||
|
end
|
||||||
|
out.puts ''
|
||||||
|
out.puts '# Please edit the release notes to taste.'
|
||||||
|
out.puts '# Blank lines and lines beginning with a hash will be removed.'
|
||||||
|
out.puts '# To abort, exit your editor with a non-zero exit status (:cquit in Vim).'
|
||||||
|
end
|
||||||
|
|
||||||
|
unless system "$EDITOR .release-notes.txt"
|
||||||
|
err "editor exited with non-zero exit status; aborting"
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
filtered = read_release_notes
|
||||||
|
File.open('.release-notes.txt', 'w') do |out|
|
||||||
|
out.print filtered
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def read_release_notes
|
||||||
|
File.readlines('.release-notes.txt').reject do |line|
|
||||||
|
line =~ /^(#.*|\s*)$/ # filter comment lines and blank lines
|
||||||
|
end.join
|
||||||
|
end
|
||||||
|
|
||||||
|
task :default => :spec
|
||||||
|
|
||||||
|
desc 'Print help on preparing a release'
|
||||||
|
task :help do
|
||||||
|
puts <<-END
|
||||||
|
|
||||||
|
The general release sequence is:
|
||||||
|
|
||||||
|
rake prerelease
|
||||||
|
rake gem
|
||||||
|
rake push
|
||||||
|
rake upload:all
|
||||||
|
|
||||||
|
Note: the upload task depends on the Mechanize gem; and may require a
|
||||||
|
prior `gem install mechanize`
|
||||||
|
|
||||||
|
END
|
||||||
|
end
|
||||||
|
|
||||||
|
desc 'Run specs'
|
||||||
|
task :spec do
|
||||||
|
system 'bundle exec rspec spec'
|
||||||
|
bail_on_failure
|
||||||
|
end
|
||||||
|
|
||||||
|
desc 'Create vimball archive'
|
||||||
|
task :vimball => :check_tag do
|
||||||
|
system 'make'
|
||||||
|
bail_on_failure
|
||||||
|
FileUtils.cp 'command-t.vba', "command-t-#{version}.vba"
|
||||||
|
end
|
||||||
|
|
||||||
|
desc 'Clean compiled products'
|
||||||
|
task :clean do
|
||||||
|
Dir.chdir 'ruby/command-t' do
|
||||||
|
system 'make clean' if File.exists?('Makefile')
|
||||||
|
system 'rm -f Makefile'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
desc 'Clobber all generated files'
|
||||||
|
task :clobber => :clean do
|
||||||
|
system 'make clean'
|
||||||
|
end
|
||||||
|
|
||||||
|
desc 'Compile extension'
|
||||||
|
task :make do
|
||||||
|
Dir.chdir 'ruby/command-t' do
|
||||||
|
ruby 'extconf.rb'
|
||||||
|
system 'make clean'
|
||||||
|
bail_on_failure
|
||||||
|
system 'make'
|
||||||
|
bail_on_failure
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
desc 'Check that the current HEAD is tagged'
|
||||||
|
task :check_tag do
|
||||||
|
unless system 'git describe --exact-match HEAD 2> /dev/null'
|
||||||
|
warn 'current HEAD is not tagged'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
desc 'Run checks prior to release'
|
||||||
|
task :prerelease => ['make', 'spec', :vimball, :check_tag]
|
||||||
|
|
||||||
|
namespace :upload do
|
||||||
|
desc 'Upload current vimball to Amazon S3'
|
||||||
|
task :s3 => :vimball do
|
||||||
|
sh 'aws --curl-options=--insecure put ' +
|
||||||
|
"s3.wincent.com/command-t/releases/command-t-#{version}.vba " +
|
||||||
|
"command-t-#{version}.vba"
|
||||||
|
sh 'aws --curl-options=--insecure put ' +
|
||||||
|
"s3.wincent.com/command-t/releases/command-t-#{version}.vba?acl " +
|
||||||
|
'--public'
|
||||||
|
end
|
||||||
|
|
||||||
|
desc 'Upload current vimball to www.vim.org'
|
||||||
|
task :vim => :vimball do
|
||||||
|
prepare_release_notes
|
||||||
|
sh "vendor/vimscriptuploader/vimscriptuploader.rb \
|
||||||
|
--id 3025 \
|
||||||
|
--file command-t-#{version}.vba \
|
||||||
|
--message-file .release-notes.txt \
|
||||||
|
--version #{version} \
|
||||||
|
--config ~/.vim_org.yml \
|
||||||
|
.vim_org.yml"
|
||||||
|
end
|
||||||
|
|
||||||
|
desc 'Upload current vimball everywhere'
|
||||||
|
task :all => [ :s3, :vim ]
|
||||||
|
end
|
||||||
|
|
||||||
|
desc 'Create the ruby gem package'
|
||||||
|
task :gem => :check_tag do
|
||||||
|
sh "gem build command-t.gemspec"
|
||||||
|
end
|
||||||
|
|
||||||
|
desc 'Push gem to Gemcutter ("gem push")'
|
||||||
|
task :push => :gem do
|
||||||
|
sh "gem push command-t-#{rubygems_version}.gem"
|
||||||
|
end
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- Copyright 2014 Vít Ondruch <v.ondruch@gmail.com> -->
|
||||||
|
<component type="addon">
|
||||||
|
<id>vim-command-t</id>
|
||||||
|
<extends>gvim.desktop</extends>
|
||||||
|
<name>command-t</name>
|
||||||
|
<summary>Provides an extremely fast, intuitive mechanism for opening files with a minimal number of keystrokes</summary>
|
||||||
|
<url type="homepage">https://wincent.com/products/command-t</url>
|
||||||
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
|
<project_license>BSD</project_license>
|
||||||
|
<updatecontact>v.ondruch@gmail.com</updatecontact>
|
||||||
|
</component>
|
180
vim/vim.symlink/bundle/command-t/autoload/commandt.vim
Normal file
180
vim/vim.symlink/bundle/command-t/autoload/commandt.vim
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
" Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
" Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
if exists("g:command_t_autoloaded") || &cp
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
let g:command_t_autoloaded = 1
|
||||||
|
|
||||||
|
function s:CommandTRubyWarning()
|
||||||
|
echohl WarningMsg
|
||||||
|
echo "command-t.vim requires Vim to be compiled with Ruby support"
|
||||||
|
echo "For more information type: :help command-t"
|
||||||
|
echohl none
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function commandt#CommandTShowBufferFinder()
|
||||||
|
if has('ruby')
|
||||||
|
ruby $command_t.show_buffer_finder
|
||||||
|
else
|
||||||
|
call s:CommandTRubyWarning()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function commandt#CommandTShowFileFinder(arg)
|
||||||
|
if has('ruby')
|
||||||
|
ruby $command_t.show_file_finder
|
||||||
|
else
|
||||||
|
call s:CommandTRubyWarning()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function commandt#CommandTShowJumpFinder()
|
||||||
|
if has('ruby')
|
||||||
|
ruby $command_t.show_jump_finder
|
||||||
|
else
|
||||||
|
call s:CommandTRubyWarning()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function commandt#CommandTShowMRUFinder()
|
||||||
|
if has('ruby')
|
||||||
|
ruby $command_t.show_mru_finder
|
||||||
|
else
|
||||||
|
call s:CommandTRubyWarning()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function commandt#CommandTShowTagFinder()
|
||||||
|
if has('ruby')
|
||||||
|
ruby $command_t.show_tag_finder
|
||||||
|
else
|
||||||
|
call s:CommandTRubyWarning()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function commandt#CommandTFlush()
|
||||||
|
if has('ruby')
|
||||||
|
ruby $command_t.flush
|
||||||
|
else
|
||||||
|
call s:CommandTRubyWarning()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function commandt#CommandTLoad()
|
||||||
|
if !has('ruby')
|
||||||
|
call s:CommandTRubyWarning()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
if !has('ruby')
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
|
||||||
|
function CommandTListMatches()
|
||||||
|
ruby $command_t.list_matches
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CommandTHandleKey(arg)
|
||||||
|
ruby $command_t.handle_key
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CommandTBackspace()
|
||||||
|
ruby $command_t.backspace
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CommandTDelete()
|
||||||
|
ruby $command_t.delete
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CommandTAcceptSelection()
|
||||||
|
ruby $command_t.accept_selection
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CommandTAcceptSelectionTab()
|
||||||
|
ruby $command_t.accept_selection :command => $command_t.tab_command
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CommandTAcceptSelectionSplit()
|
||||||
|
ruby $command_t.accept_selection :command => $command_t.split_command
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CommandTAcceptSelectionVSplit()
|
||||||
|
ruby $command_t.accept_selection :command => $command_t.vsplit_command
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CommandTQuickfix()
|
||||||
|
ruby $command_t.quickfix
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CommandTRefresh()
|
||||||
|
ruby $command_t.refresh
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CommandTToggleFocus()
|
||||||
|
ruby $command_t.toggle_focus
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CommandTCancel()
|
||||||
|
ruby $command_t.cancel
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CommandTSelectNext()
|
||||||
|
ruby $command_t.select_next
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CommandTSelectPrev()
|
||||||
|
ruby $command_t.select_prev
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CommandTClear()
|
||||||
|
ruby $command_t.clear
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CommandTClearPrevWord()
|
||||||
|
ruby $command_t.clear_prev_word
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CommandTCursorLeft()
|
||||||
|
ruby $command_t.cursor_left
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CommandTCursorRight()
|
||||||
|
ruby $command_t.cursor_right
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CommandTCursorEnd()
|
||||||
|
ruby $command_t.cursor_end
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function CommandTCursorStart()
|
||||||
|
ruby $command_t.cursor_start
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" note that we only start tracking buffers from first (autoloaded) use of Command-T
|
||||||
|
augroup CommandTMRUBuffer
|
||||||
|
autocmd BufEnter * ruby CommandT::MRU.touch
|
||||||
|
autocmd BufDelete * ruby CommandT::MRU.delete
|
||||||
|
augroup END
|
||||||
|
|
||||||
|
ruby << EOF
|
||||||
|
# require Ruby files
|
||||||
|
begin
|
||||||
|
require 'command-t'
|
||||||
|
$command_t = CommandT::Controller.new
|
||||||
|
rescue LoadError
|
||||||
|
load_path_modified = false
|
||||||
|
::VIM::evaluate('&runtimepath').to_s.split(',').each do |path|
|
||||||
|
lib = "#{path}/ruby"
|
||||||
|
if !$LOAD_PATH.include?(lib) && File.exist?(lib)
|
||||||
|
$LOAD_PATH << lib
|
||||||
|
load_path_modified = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
retry if load_path_modified
|
||||||
|
|
||||||
|
# could get here if C extension was not compiled, or was compiled
|
||||||
|
# for the wrong architecture or Ruby version
|
||||||
|
$command_t = CommandT::Stub.new
|
||||||
|
end
|
||||||
|
EOF
|
33
vim/vim.symlink/bundle/command-t/bin/benchmarks/matcher.rb
Executable file
33
vim/vim.symlink/bundle/command-t/bin/benchmarks/matcher.rb
Executable file
|
@ -0,0 +1,33 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
#
|
||||||
|
# Copyright 2013-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
lib = File.expand_path('../../ruby', File.dirname(__FILE__))
|
||||||
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
||||||
|
|
||||||
|
require 'command-t/ext'
|
||||||
|
require 'command-t/util'
|
||||||
|
require 'benchmark'
|
||||||
|
require 'ostruct'
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
|
yaml = File.expand_path('../../data/benchmark.yml', File.dirname(__FILE__))
|
||||||
|
data = YAML.load_file(yaml)
|
||||||
|
threads = CommandT::Util.processor_count
|
||||||
|
|
||||||
|
puts "Starting benchmark run (PID: #{Process.pid})"
|
||||||
|
|
||||||
|
Benchmark.bmbm do |b|
|
||||||
|
data['tests'].each do |test|
|
||||||
|
scanner = OpenStruct.new(:paths => test['paths'])
|
||||||
|
matcher = CommandT::Matcher.new(scanner)
|
||||||
|
b.report(test['name']) do
|
||||||
|
test['times'].times do
|
||||||
|
test['queries'].each do |query|
|
||||||
|
matcher.sorted_matches_for(query, :threads => threads)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
76
vim/vim.symlink/bundle/command-t/bin/benchmarks/watchman.rb
Executable file
76
vim/vim.symlink/bundle/command-t/bin/benchmarks/watchman.rb
Executable file
|
@ -0,0 +1,76 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
#
|
||||||
|
# Copyright 2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
lib = File.expand_path('../../ruby', File.dirname(__FILE__))
|
||||||
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
||||||
|
|
||||||
|
require 'command-t/ext'
|
||||||
|
require 'benchmark'
|
||||||
|
require 'json'
|
||||||
|
require 'pathname'
|
||||||
|
require 'socket'
|
||||||
|
|
||||||
|
puts "Starting benchmark run (PID: #{Process.pid})"
|
||||||
|
|
||||||
|
TEST_TIMES = 10
|
||||||
|
|
||||||
|
Benchmark.bmbm do |b|
|
||||||
|
b.report('watchman JSON') do
|
||||||
|
TEST_TIMES.times do
|
||||||
|
sockname = JSON[%x{watchman get-sockname}]['sockname']
|
||||||
|
raise unless $?.exitstatus.zero?
|
||||||
|
UNIXSocket.open(sockname) do |s|
|
||||||
|
root = Pathname.new(ENV['PWD']).realpath
|
||||||
|
s.puts JSON.generate(['watch-list'])
|
||||||
|
if !JSON[s.gets]['roots'].include?(root)
|
||||||
|
# this path isn't being watched yet; try to set up watch
|
||||||
|
s.puts JSON.generate(['watch', root])
|
||||||
|
|
||||||
|
# root_restrict_files setting may prevent Watchman from working
|
||||||
|
raise if JSON[s.gets].has_key?('error')
|
||||||
|
end
|
||||||
|
|
||||||
|
s.puts JSON.generate(['query', root, {
|
||||||
|
'expression' => ['type', 'f'],
|
||||||
|
'fields' => ['name'],
|
||||||
|
}])
|
||||||
|
paths = JSON[s.gets]
|
||||||
|
|
||||||
|
# could return error if watch is removed
|
||||||
|
raise if paths.has_key?('error')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
b.report('watchman binary') do
|
||||||
|
TEST_TIMES.times do
|
||||||
|
sockname = CommandT::Watchman::Utils.load(
|
||||||
|
%x{watchman --output-encoding=bser get-sockname}
|
||||||
|
)['sockname']
|
||||||
|
raise unless $?.exitstatus.zero?
|
||||||
|
|
||||||
|
UNIXSocket.open(sockname) do |socket|
|
||||||
|
root = Pathname.new(ENV['PWD']).realpath.to_s
|
||||||
|
roots = CommandT::Watchman::Utils.query(['watch-list'], socket)['roots']
|
||||||
|
if !roots.include?(root)
|
||||||
|
# this path isn't being watched yet; try to set up watch
|
||||||
|
result = CommandT::Watchman::Utils.query(['watch', root], socket)
|
||||||
|
|
||||||
|
# root_restrict_files setting may prevent Watchman from working
|
||||||
|
raise if result.has_key?('error')
|
||||||
|
end
|
||||||
|
|
||||||
|
query = ['query', root, {
|
||||||
|
'expression' => ['type', 'f'],
|
||||||
|
'fields' => ['name'],
|
||||||
|
}]
|
||||||
|
paths = CommandT::Watchman::Utils.query(query, socket)
|
||||||
|
|
||||||
|
# could return error if watch is removed
|
||||||
|
raise if paths.has_key?('error')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
36
vim/vim.symlink/bundle/command-t/command-t.gemspec
Normal file
36
vim/vim.symlink/bundle/command-t/command-t.gemspec
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
Gem::Specification.new do |s|
|
||||||
|
s.name = 'command-t'
|
||||||
|
|
||||||
|
# see note in the Rakefile about how intermediate version numbers
|
||||||
|
# can break RubyGems
|
||||||
|
v = `git describe --abbrev=0`.chomp
|
||||||
|
s.version = v
|
||||||
|
|
||||||
|
s.authors = ['Greg Hurrell']
|
||||||
|
s.email = 'greg@hurrell.net'
|
||||||
|
|
||||||
|
files =
|
||||||
|
['README.txt', 'LICENSE', 'Gemfile', 'Rakefile'] +
|
||||||
|
Dir.glob('{ruby,doc,plugin}/**/*')
|
||||||
|
|
||||||
|
files = files.reject { |f| f =~ /\.(rbc|o|log|plist|dSYM)/ }
|
||||||
|
|
||||||
|
s.files = files
|
||||||
|
s.license = 'BSD'
|
||||||
|
s.require_path = 'ruby'
|
||||||
|
s.extensions = 'ruby/command-t/extconf.rb'
|
||||||
|
|
||||||
|
s.executables = []
|
||||||
|
|
||||||
|
s.has_rdoc = false
|
||||||
|
s.homepage = 'https://wincent.com/products/command-t'
|
||||||
|
|
||||||
|
s.summary = 'The Command-T plug-in for VIM.'
|
||||||
|
|
||||||
|
s.description = <<-EOS
|
||||||
|
Command-T provides a fast, intuitive mechanism for opening files with a
|
||||||
|
minimal number of keystrokes. Its full functionality is only available when
|
||||||
|
installed as a Vim plug-in, but it is also made available as a RubyGem so
|
||||||
|
that other applications can make use of its searching algorithm.
|
||||||
|
EOS
|
||||||
|
end
|
471581
vim/vim.symlink/bundle/command-t/data/benchmark.yml
Normal file
471581
vim/vim.symlink/bundle/command-t/data/benchmark.yml
Normal file
File diff suppressed because it is too large
Load diff
1
vim/vim.symlink/bundle/command-t/doc/.gitignore
vendored
Normal file
1
vim/vim.symlink/bundle/command-t/doc/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
tags
|
1510
vim/vim.symlink/bundle/command-t/doc/command-t.txt
Normal file
1510
vim/vim.symlink/bundle/command-t/doc/command-t.txt
Normal file
File diff suppressed because it is too large
Load diff
1
vim/vim.symlink/bundle/command-t/fixtures/bar/abc
Normal file
1
vim/vim.symlink/bundle/command-t/fixtures/bar/abc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.
|
1
vim/vim.symlink/bundle/command-t/fixtures/bar/xyz
Normal file
1
vim/vim.symlink/bundle/command-t/fixtures/bar/xyz
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.
|
1
vim/vim.symlink/bundle/command-t/fixtures/baz
Normal file
1
vim/vim.symlink/bundle/command-t/fixtures/baz
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.
|
1
vim/vim.symlink/bundle/command-t/fixtures/bing
Normal file
1
vim/vim.symlink/bundle/command-t/fixtures/bing
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.
|
1
vim/vim.symlink/bundle/command-t/fixtures/foo/alpha/t1
Normal file
1
vim/vim.symlink/bundle/command-t/fixtures/foo/alpha/t1
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.
|
1
vim/vim.symlink/bundle/command-t/fixtures/foo/alpha/t2
Normal file
1
vim/vim.symlink/bundle/command-t/fixtures/foo/alpha/t2
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.
|
1
vim/vim.symlink/bundle/command-t/fixtures/foo/beta
Normal file
1
vim/vim.symlink/bundle/command-t/fixtures/foo/beta
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.
|
23
vim/vim.symlink/bundle/command-t/plugin/command-t.vim
Normal file
23
vim/vim.symlink/bundle/command-t/plugin/command-t.vim
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
" Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
" Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
if exists("g:command_t_loaded") || &cp
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
let g:command_t_loaded = 1
|
||||||
|
|
||||||
|
command CommandTBuffer call commandt#CommandTShowBufferFinder()
|
||||||
|
command CommandTJump call commandt#CommandTShowJumpFinder()
|
||||||
|
command CommandTMRU call commandt#CommandTShowMRUFinder()
|
||||||
|
command CommandTTag call commandt#CommandTShowTagFinder()
|
||||||
|
command -nargs=? -complete=dir CommandT call commandt#CommandTShowFileFinder(<q-args>)
|
||||||
|
command CommandTFlush call commandt#CommandTFlush()
|
||||||
|
command CommandTLoad call commandt#CommandTLoad()
|
||||||
|
|
||||||
|
if !hasmapto(':CommandT<CR>') && maparg('<Leader>t', 'n') == ''
|
||||||
|
silent! nnoremap <unique> <silent> <Leader>t :CommandT<CR>
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !hasmapto(':CommandTBuffer<CR>') && maparg('<Leader>b', 'n') == ''
|
||||||
|
silent! nnoremap <unique> <silent> <Leader>b :CommandTBuffer<CR>
|
||||||
|
endif
|
17
vim/vim.symlink/bundle/command-t/ruby/command-t.rb
Normal file
17
vim/vim.symlink/bundle/command-t/ruby/command-t.rb
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# Copyright 2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
autoload :Controller, 'command-t/controller'
|
||||||
|
autoload :Finder, 'command-t/finder'
|
||||||
|
autoload :MRU, 'command-t/mru'
|
||||||
|
autoload :MatchWindow, 'command-t/match_window'
|
||||||
|
autoload :PathUtilities, 'command-t/path_utilities'
|
||||||
|
autoload :Prompt, 'command-t/prompt'
|
||||||
|
autoload :SCMUtilities, 'command-t/scm_utilities'
|
||||||
|
autoload :Scanner, 'command-t/scanner'
|
||||||
|
autoload :Settings, 'command-t/settings'
|
||||||
|
autoload :Stub, 'command-t/stub'
|
||||||
|
autoload :Util, 'command-t/util'
|
||||||
|
autoload :VIM, 'command-t/vim'
|
||||||
|
end # module CommandT
|
6
vim/vim.symlink/bundle/command-t/ruby/command-t/.gitignore
vendored
Normal file
6
vim/vim.symlink/bundle/command-t/ruby/command-t/.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
Makefile
|
||||||
|
*.o
|
||||||
|
*.log
|
||||||
|
ext.*
|
||||||
|
!ext.c
|
||||||
|
!ext.h
|
430
vim/vim.symlink/bundle/command-t/ruby/command-t/controller.rb
Normal file
430
vim/vim.symlink/bundle/command-t/ruby/command-t/controller.rb
Normal file
|
@ -0,0 +1,430 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
class Controller
|
||||||
|
include PathUtilities
|
||||||
|
include SCMUtilities
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@prompt = Prompt.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def show_buffer_finder
|
||||||
|
@path = VIM::pwd
|
||||||
|
@active_finder = buffer_finder
|
||||||
|
show
|
||||||
|
end
|
||||||
|
|
||||||
|
def show_jump_finder
|
||||||
|
@path = VIM::pwd
|
||||||
|
@active_finder = jump_finder
|
||||||
|
show
|
||||||
|
end
|
||||||
|
|
||||||
|
def show_mru_finder
|
||||||
|
@path = VIM::pwd
|
||||||
|
@active_finder = mru_finder
|
||||||
|
show
|
||||||
|
end
|
||||||
|
|
||||||
|
def show_tag_finder
|
||||||
|
@path = VIM::pwd
|
||||||
|
@active_finder = tag_finder
|
||||||
|
show
|
||||||
|
end
|
||||||
|
|
||||||
|
def show_file_finder
|
||||||
|
# optional parameter will be desired starting directory, or ""
|
||||||
|
|
||||||
|
arg = ::VIM::evaluate('a:arg')
|
||||||
|
if arg && arg.size > 0
|
||||||
|
@path = File.expand_path(arg, VIM::pwd)
|
||||||
|
else
|
||||||
|
traverse = VIM::get_string('g:CommandTTraverseSCM') || 'file'
|
||||||
|
case traverse
|
||||||
|
when 'file'
|
||||||
|
@path = nearest_ancestor(VIM::current_file_dir, scm_markers) || VIM::pwd
|
||||||
|
when 'dir'
|
||||||
|
@path = nearest_ancestor(VIM::pwd, scm_markers) || VIM::pwd
|
||||||
|
else
|
||||||
|
@path = VIM::pwd
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@active_finder = file_finder
|
||||||
|
file_finder.path = @path
|
||||||
|
show
|
||||||
|
rescue Errno::ENOENT
|
||||||
|
# probably a problem with the optional parameter
|
||||||
|
@match_window.print_no_such_file_or_directory
|
||||||
|
end
|
||||||
|
|
||||||
|
def hide
|
||||||
|
@match_window.leave
|
||||||
|
if VIM::Window.select @initial_window
|
||||||
|
if @initial_buffer.number == 0
|
||||||
|
# upstream bug: buffer number misreported as 0
|
||||||
|
# see: https://wincent.com/issues/1617
|
||||||
|
::VIM::command "silent b #{@initial_buffer.name}"
|
||||||
|
else
|
||||||
|
::VIM::command "silent b #{@initial_buffer.number}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Take current matches and stick them in the quickfix window.
|
||||||
|
def quickfix
|
||||||
|
hide
|
||||||
|
|
||||||
|
matches = @matches.map do |match|
|
||||||
|
"{ 'filename': '#{VIM::escape_for_single_quotes match}' }"
|
||||||
|
end.join(', ')
|
||||||
|
|
||||||
|
::VIM::command 'call setqflist([' + matches + '])'
|
||||||
|
::VIM::command 'cope'
|
||||||
|
end
|
||||||
|
|
||||||
|
def refresh
|
||||||
|
return unless @active_finder && @active_finder.respond_to?(:flush)
|
||||||
|
@active_finder.flush
|
||||||
|
list_matches!
|
||||||
|
end
|
||||||
|
|
||||||
|
def flush
|
||||||
|
@max_height = nil
|
||||||
|
@min_height = nil
|
||||||
|
@file_finder = nil
|
||||||
|
@tag_finder = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_key
|
||||||
|
key = ::VIM::evaluate('a:arg').to_i.chr
|
||||||
|
if @focus == @prompt
|
||||||
|
@prompt.add! key
|
||||||
|
@needs_update = true
|
||||||
|
else
|
||||||
|
@match_window.find key
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def backspace
|
||||||
|
if @focus == @prompt
|
||||||
|
@prompt.backspace!
|
||||||
|
@needs_update = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete
|
||||||
|
if @focus == @prompt
|
||||||
|
@prompt.delete!
|
||||||
|
@needs_update = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def accept_selection(options = {})
|
||||||
|
selection = @match_window.selection
|
||||||
|
hide
|
||||||
|
open_selection(selection, options) unless selection.nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
def toggle_focus
|
||||||
|
@focus.unfocus # old focus
|
||||||
|
@focus = @focus == @prompt ? @match_window : @prompt
|
||||||
|
@focus.focus # new focus
|
||||||
|
end
|
||||||
|
|
||||||
|
def cancel
|
||||||
|
hide
|
||||||
|
end
|
||||||
|
|
||||||
|
def select_next
|
||||||
|
@match_window.select_next
|
||||||
|
end
|
||||||
|
|
||||||
|
def select_prev
|
||||||
|
@match_window.select_prev
|
||||||
|
end
|
||||||
|
|
||||||
|
def clear
|
||||||
|
@prompt.clear!
|
||||||
|
list_matches!
|
||||||
|
end
|
||||||
|
|
||||||
|
def clear_prev_word
|
||||||
|
@prompt.clear_prev_word!
|
||||||
|
list_matches!
|
||||||
|
end
|
||||||
|
|
||||||
|
def cursor_left
|
||||||
|
@prompt.cursor_left if @focus == @prompt
|
||||||
|
end
|
||||||
|
|
||||||
|
def cursor_right
|
||||||
|
@prompt.cursor_right if @focus == @prompt
|
||||||
|
end
|
||||||
|
|
||||||
|
def cursor_end
|
||||||
|
@prompt.cursor_end if @focus == @prompt
|
||||||
|
end
|
||||||
|
|
||||||
|
def cursor_start
|
||||||
|
@prompt.cursor_start if @focus == @prompt
|
||||||
|
end
|
||||||
|
|
||||||
|
def leave
|
||||||
|
@match_window.leave
|
||||||
|
end
|
||||||
|
|
||||||
|
def unload
|
||||||
|
@match_window.unload
|
||||||
|
end
|
||||||
|
|
||||||
|
def list_matches(options = {})
|
||||||
|
return unless @needs_update || options[:force]
|
||||||
|
|
||||||
|
@matches = @active_finder.sorted_matches_for(
|
||||||
|
@prompt.abbrev,
|
||||||
|
:case_sensitive => case_sensitive?,
|
||||||
|
:limit => match_limit,
|
||||||
|
:threads => CommandT::Util.processor_count
|
||||||
|
)
|
||||||
|
@match_window.matches = @matches
|
||||||
|
|
||||||
|
@needs_update = false
|
||||||
|
end
|
||||||
|
|
||||||
|
def tab_command
|
||||||
|
VIM::get_string('g:CommandTAcceptSelectionTabCommand') || 'tabe'
|
||||||
|
end
|
||||||
|
|
||||||
|
def split_command
|
||||||
|
VIM::get_string('g:CommandTAcceptSelectionSplitCommand') || 'sp'
|
||||||
|
end
|
||||||
|
|
||||||
|
def vsplit_command
|
||||||
|
VIM::get_string('g:CommandTAcceptSelectionVSplitCommand') || 'vs'
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def scm_markers
|
||||||
|
markers = VIM::get_string('g:CommandTSCMDirectories')
|
||||||
|
markers = markers && markers.split(/\s*,\s*/)
|
||||||
|
markers = %w[.git .hg .svn .bzr _darcs] unless markers && markers.length
|
||||||
|
markers
|
||||||
|
end
|
||||||
|
|
||||||
|
def list_matches!
|
||||||
|
list_matches(:force => true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
@initial_window = $curwin
|
||||||
|
@initial_buffer = $curbuf
|
||||||
|
@match_window = MatchWindow.new \
|
||||||
|
:highlight_color => VIM::get_string('g:CommandTHighlightColor'),
|
||||||
|
:match_window_at_top => VIM::get_bool('g:CommandTMatchWindowAtTop'),
|
||||||
|
:match_window_reverse => VIM::get_bool('g:CommandTMatchWindowReverse'),
|
||||||
|
:min_height => min_height,
|
||||||
|
:debounce_interval => VIM::get_number('g:CommandTInputDebounce') || 50,
|
||||||
|
:prompt => @prompt
|
||||||
|
@focus = @prompt
|
||||||
|
@prompt.focus
|
||||||
|
register_for_key_presses
|
||||||
|
set_up_autocmds
|
||||||
|
clear # clears prompt and lists matches
|
||||||
|
end
|
||||||
|
|
||||||
|
def max_height
|
||||||
|
@max_height ||= VIM::get_number('g:CommandTMaxHeight') || 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def min_height
|
||||||
|
@min_height ||= begin
|
||||||
|
min_height = VIM::get_number('g:CommandTMinHeight') || 0
|
||||||
|
min_height = max_height if max_height != 0 && min_height > max_height
|
||||||
|
min_height
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def case_sensitive?
|
||||||
|
if @prompt.abbrev.match(/[A-Z]/)
|
||||||
|
if VIM::exists?('g:CommandTSmartCase')
|
||||||
|
smart_case = VIM::get_bool('g:CommandTSmartCase')
|
||||||
|
else
|
||||||
|
smart_case = VIM::get_bool('&smartcase')
|
||||||
|
end
|
||||||
|
|
||||||
|
if smart_case
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if VIM::exists?('g:CommandTIgnoreCase')
|
||||||
|
return !VIM::get_bool('g:CommandTIgnoreCase')
|
||||||
|
end
|
||||||
|
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
# Backslash-escape space, \, |, %, #, "
|
||||||
|
def sanitize_path_string(str)
|
||||||
|
# for details on escaping command-line mode arguments see: :h :
|
||||||
|
# (that is, help on ":") in the Vim documentation.
|
||||||
|
str.gsub(/[ \\|%#"]/, '\\\\\0')
|
||||||
|
end
|
||||||
|
|
||||||
|
def current_buffer_visible_in_other_window
|
||||||
|
count = (0...::VIM::Window.count).to_a.inject(0) do |acc, i|
|
||||||
|
acc += 1 if ::VIM::Window[i].buffer.number == $curbuf.number
|
||||||
|
acc
|
||||||
|
end
|
||||||
|
count > 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def default_open_command
|
||||||
|
if !VIM::get_bool('&modified') ||
|
||||||
|
VIM::get_bool('&hidden') ||
|
||||||
|
VIM::get_bool('&autowriteall') && !VIM::get_bool('&readonly') ||
|
||||||
|
current_buffer_visible_in_other_window
|
||||||
|
VIM::get_string('g:CommandTAcceptSelectionCommand') || 'e'
|
||||||
|
else
|
||||||
|
'sp'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def ensure_appropriate_window_selection
|
||||||
|
# normally we try to open the selection in the current window, but there
|
||||||
|
# is one exception:
|
||||||
|
#
|
||||||
|
# - we don't touch any "unlisted" buffer with buftype "nofile" (such as
|
||||||
|
# NERDTree or MiniBufExplorer); this is to avoid things like the "Not
|
||||||
|
# enough room" error which occurs when trying to open in a split in a
|
||||||
|
# shallow (potentially 1-line) buffer like MiniBufExplorer is current
|
||||||
|
#
|
||||||
|
# Other "unlisted" buffers, such as those with buftype "help" are treated
|
||||||
|
# normally.
|
||||||
|
initial = $curwin
|
||||||
|
while true do
|
||||||
|
break unless ::VIM::evaluate('&buflisted').to_i == 0 &&
|
||||||
|
::VIM::evaluate('&buftype').to_s == 'nofile'
|
||||||
|
::VIM::command 'wincmd w' # try next window
|
||||||
|
break if $curwin == initial # have already tried all
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def open_selection(selection, options = {})
|
||||||
|
command = options[:command] || default_open_command
|
||||||
|
selection = File.expand_path selection, @path
|
||||||
|
selection = relative_path_under_working_directory selection
|
||||||
|
selection = sanitize_path_string selection
|
||||||
|
selection = File.join('.', selection) if selection =~ /^\+/
|
||||||
|
ensure_appropriate_window_selection
|
||||||
|
|
||||||
|
@active_finder.open_selection command, selection, options
|
||||||
|
end
|
||||||
|
|
||||||
|
def map(key, function, param = nil)
|
||||||
|
::VIM::command "noremap <silent> <buffer> #{key} " \
|
||||||
|
":call CommandT#{function}(#{param})<CR>"
|
||||||
|
end
|
||||||
|
|
||||||
|
def term
|
||||||
|
@term ||= ::VIM::evaluate('&term')
|
||||||
|
end
|
||||||
|
|
||||||
|
def register_for_key_presses
|
||||||
|
# "normal" keys (interpreted literally)
|
||||||
|
numbers = ('0'..'9').to_a.join
|
||||||
|
lowercase = ('a'..'z').to_a.join
|
||||||
|
uppercase = lowercase.upcase
|
||||||
|
punctuation = '<>`@#~!"$%&/()=+*-_.,;:?\\\'{}[] ' # and space
|
||||||
|
(numbers + lowercase + uppercase + punctuation).each_byte do |b|
|
||||||
|
map "<Char-#{b}>", 'HandleKey', b
|
||||||
|
end
|
||||||
|
|
||||||
|
# "special" keys (overridable by settings)
|
||||||
|
{
|
||||||
|
'AcceptSelection' => '<CR>',
|
||||||
|
'AcceptSelectionSplit' => ['<C-CR>', '<C-s>'],
|
||||||
|
'AcceptSelectionTab' => '<C-t>',
|
||||||
|
'AcceptSelectionVSplit' => '<C-v>',
|
||||||
|
'Backspace' => '<BS>',
|
||||||
|
'Cancel' => ['<C-c>', '<Esc>'],
|
||||||
|
'Clear' => '<C-u>',
|
||||||
|
'ClearPrevWord' => '<C-w>',
|
||||||
|
'CursorEnd' => '<C-e>',
|
||||||
|
'CursorLeft' => ['<Left>', '<C-h>'],
|
||||||
|
'CursorRight' => ['<Right>', '<C-l>'],
|
||||||
|
'CursorStart' => '<C-a>',
|
||||||
|
'Delete' => '<Del>',
|
||||||
|
'Quickfix' => '<C-q>',
|
||||||
|
'Refresh' => '<C-f>',
|
||||||
|
'SelectNext' => ['<C-n>', '<C-j>', '<Down>'],
|
||||||
|
'SelectPrev' => ['<C-p>', '<C-k>', '<Up>'],
|
||||||
|
'ToggleFocus' => '<Tab>',
|
||||||
|
}.each do |key, value|
|
||||||
|
if override = VIM::get_list_or_string("g:CommandT#{key}Map")
|
||||||
|
Array(override).each do |mapping|
|
||||||
|
map mapping, key
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Array(value).each do |mapping|
|
||||||
|
unless mapping == '<Esc>' && term =~ /\A(screen|xterm|vt100)/
|
||||||
|
map mapping, key
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_up_autocmds
|
||||||
|
::VIM::command 'augroup Command-T'
|
||||||
|
::VIM::command 'au!'
|
||||||
|
::VIM::command 'autocmd CursorHold <buffer> :call CommandTListMatches()'
|
||||||
|
::VIM::command 'augroup END'
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns the desired maximum number of matches, based on available vertical
|
||||||
|
# space and the g:CommandTMaxHeight option.
|
||||||
|
#
|
||||||
|
# Note the "available" space is actually a theoretical upper bound; it takes
|
||||||
|
# into account screen dimensions but not things like existing splits which
|
||||||
|
# may reduce the amount of space in practice.
|
||||||
|
def match_limit
|
||||||
|
limit = [1, VIM::Screen.lines - 5].max
|
||||||
|
limit = [limit, max_height].min if max_height > 0
|
||||||
|
limit
|
||||||
|
end
|
||||||
|
|
||||||
|
def buffer_finder
|
||||||
|
@buffer_finder ||= CommandT::Finder::BufferFinder.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def mru_finder
|
||||||
|
@mru_finder ||= CommandT::Finder::MRUBufferFinder.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def file_finder
|
||||||
|
@file_finder ||= CommandT::Finder::FileFinder.new nil,
|
||||||
|
:max_depth => VIM::get_number('g:CommandTMaxDepth'),
|
||||||
|
:max_files => VIM::get_number('g:CommandTMaxFiles'),
|
||||||
|
:max_caches => VIM::get_number('g:CommandTMaxCachedDirectories'),
|
||||||
|
:always_show_dot_files => VIM::get_bool('g:CommandTAlwaysShowDotFiles'),
|
||||||
|
:never_show_dot_files => VIM::get_bool('g:CommandTNeverShowDotFiles'),
|
||||||
|
:scan_dot_directories => VIM::get_bool('g:CommandTScanDotDirectories'),
|
||||||
|
:wild_ignore => VIM::get_string('g:CommandTWildIgnore'),
|
||||||
|
:scanner => VIM::get_string('g:CommandTFileScanner')
|
||||||
|
end
|
||||||
|
|
||||||
|
def jump_finder
|
||||||
|
@jump_finder ||= CommandT::Finder::JumpFinder.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def tag_finder
|
||||||
|
@tag_finder ||= CommandT::Finder::TagFinder.new \
|
||||||
|
:include_filenames => VIM::get_bool('g:CommandTTagIncludeFilenames')
|
||||||
|
end
|
||||||
|
end # class Controller
|
||||||
|
end # module CommandT
|
4
vim/vim.symlink/bundle/command-t/ruby/command-t/depend
Normal file
4
vim/vim.symlink/bundle/command-t/ruby/command-t/depend
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
CFLAGS += -Wall -Wextra -Wno-unused-parameter
|
40
vim/vim.symlink/bundle/command-t/ruby/command-t/ext.c
Normal file
40
vim/vim.symlink/bundle/command-t/ruby/command-t/ext.c
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
// Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
// Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
#include "matcher.h"
|
||||||
|
#include "watchman.h"
|
||||||
|
|
||||||
|
VALUE mCommandT = 0; // module CommandT
|
||||||
|
VALUE cCommandTMatcher = 0; // class CommandT::Matcher
|
||||||
|
VALUE mCommandTWatchman = 0; // module CommandT::Watchman
|
||||||
|
VALUE mCommandTWatchmanUtils = 0; // module CommandT::Watchman::Utils
|
||||||
|
|
||||||
|
VALUE CommandT_option_from_hash(const char *option, VALUE hash)
|
||||||
|
{
|
||||||
|
VALUE key;
|
||||||
|
if (NIL_P(hash))
|
||||||
|
return Qnil;
|
||||||
|
key = ID2SYM(rb_intern(option));
|
||||||
|
if (rb_funcall(hash, rb_intern("has_key?"), 1, key) == Qtrue)
|
||||||
|
return rb_hash_aref(hash, key);
|
||||||
|
else
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init_ext()
|
||||||
|
{
|
||||||
|
// module CommandT
|
||||||
|
mCommandT = rb_define_module("CommandT");
|
||||||
|
|
||||||
|
// class CommandT::Matcher
|
||||||
|
cCommandTMatcher = rb_define_class_under(mCommandT, "Matcher", rb_cObject);
|
||||||
|
rb_define_method(cCommandTMatcher, "initialize", CommandTMatcher_initialize, -1);
|
||||||
|
rb_define_method(cCommandTMatcher, "sorted_matches_for", CommandTMatcher_sorted_matches_for, -1);
|
||||||
|
|
||||||
|
// module CommandT::Watchman::Utils
|
||||||
|
mCommandTWatchman = rb_define_module_under(mCommandT, "Watchman");
|
||||||
|
mCommandTWatchmanUtils = rb_define_module_under(mCommandTWatchman, "Utils");
|
||||||
|
rb_define_singleton_method(mCommandTWatchmanUtils, "load", CommandTWatchmanUtils_load, 1);
|
||||||
|
rb_define_singleton_method(mCommandTWatchmanUtils, "dump", CommandTWatchmanUtils_dump, 1);
|
||||||
|
rb_define_singleton_method(mCommandTWatchmanUtils, "query", CommandTWatchmanUtils_query, 2);
|
||||||
|
}
|
17
vim/vim.symlink/bundle/command-t/ruby/command-t/ext.h
Normal file
17
vim/vim.symlink/bundle/command-t/ruby/command-t/ext.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
// Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
#include <ruby.h>
|
||||||
|
|
||||||
|
extern VALUE mCommandT; // module CommandT
|
||||||
|
extern VALUE cCommandTMatcher; // class CommandT::Matcher
|
||||||
|
extern VALUE mCommandTWatchman; // module CommandT::Watchman
|
||||||
|
extern VALUE mCommandTWatchmanUtils; // module CommandT::Watchman::Utils
|
||||||
|
|
||||||
|
// Encapsulates common pattern of checking for an option in an optional
|
||||||
|
// options hash. The hash itself may be nil, but an exception will be
|
||||||
|
// raised if it is not nil and not a hash.
|
||||||
|
VALUE CommandT_option_from_hash(const char *option, VALUE hash);
|
||||||
|
|
||||||
|
// Debugging macro.
|
||||||
|
#define ruby_inspect(obj) rb_funcall(rb_mKernel, rb_intern("p"), 1, obj)
|
47
vim/vim.symlink/bundle/command-t/ruby/command-t/extconf.rb
Normal file
47
vim/vim.symlink/bundle/command-t/ruby/command-t/extconf.rb
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
begin
|
||||||
|
require 'mkmf'
|
||||||
|
rescue LoadError
|
||||||
|
puts <<-DOC.gsub(/^\s+/, '')
|
||||||
|
Unable to require "mkmf"; you may need to install Ruby development tools
|
||||||
|
(depending on your system, a "ruby-dev"/"ruby-devel" package or similar).
|
||||||
|
[exiting]
|
||||||
|
DOC
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def header(item)
|
||||||
|
unless find_header(item)
|
||||||
|
puts "couldn't find #{item} (required)"
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# mandatory headers
|
||||||
|
header('float.h')
|
||||||
|
header('ruby.h')
|
||||||
|
header('stdlib.h')
|
||||||
|
header('string.h')
|
||||||
|
|
||||||
|
# optional headers (for CommandT::Watchman::Utils)
|
||||||
|
if have_header('fcntl.h') &&
|
||||||
|
have_header('stdint.h') &&
|
||||||
|
have_header('sys/errno.h') &&
|
||||||
|
have_header('sys/socket.h')
|
||||||
|
RbConfig::MAKEFILE_CONFIG['DEFS'] ||= ''
|
||||||
|
RbConfig::MAKEFILE_CONFIG['DEFS'] += ' -DWATCHMAN_BUILD'
|
||||||
|
|
||||||
|
have_header('ruby/st.h') # >= 1.9; sets HAVE_RUBY_ST_H
|
||||||
|
have_header('st.h') # 1.8; sets HAVE_ST_H
|
||||||
|
end
|
||||||
|
|
||||||
|
# optional
|
||||||
|
if RbConfig::CONFIG['THREAD_MODEL'] == 'pthread'
|
||||||
|
have_library('pthread', 'pthread_create') # sets HAVE_PTHREAD_H if found
|
||||||
|
end
|
||||||
|
|
||||||
|
RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
|
||||||
|
|
||||||
|
create_makefile('ext')
|
40
vim/vim.symlink/bundle/command-t/ruby/command-t/finder.rb
Normal file
40
vim/vim.symlink/bundle/command-t/ruby/command-t/finder.rb
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
require 'command-t/ext' # CommandT::Matcher, CommandT::Watchman::Utils
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
# Encapsulates a Scanner instance (which builds up a list of available files
|
||||||
|
# in a directory) and a Matcher instance (which selects from that list based
|
||||||
|
# on a search string).
|
||||||
|
#
|
||||||
|
# Specialized subclasses use different kinds of scanners adapted for
|
||||||
|
# different kinds of search (files, buffers).
|
||||||
|
class Finder
|
||||||
|
autoload :BufferFinder, 'command-t/finder/buffer_finder'
|
||||||
|
autoload :FileFinder, 'command-t/finder/file_finder'
|
||||||
|
autoload :JumpFinder, 'command-t/finder/jump_finder'
|
||||||
|
autoload :MRUBufferFinder, 'command-t/finder/mru_buffer_finder'
|
||||||
|
autoload :TagFinder, 'command-t/finder/tag_finder'
|
||||||
|
|
||||||
|
include PathUtilities
|
||||||
|
|
||||||
|
def initialize(path = Dir.pwd, options = {})
|
||||||
|
raise RuntimeError, 'Subclass responsibility'
|
||||||
|
end
|
||||||
|
|
||||||
|
# Options:
|
||||||
|
# :limit (integer): limit the number of returned matches
|
||||||
|
def sorted_matches_for(str, options = {})
|
||||||
|
@matcher.sorted_matches_for str, options
|
||||||
|
end
|
||||||
|
|
||||||
|
def open_selection(command, selection, options = {})
|
||||||
|
::VIM::command "silent #{command} #{selection}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def path=(path)
|
||||||
|
@scanner.path = path
|
||||||
|
end
|
||||||
|
end # class Finder
|
||||||
|
end # CommandT
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
class Finder
|
||||||
|
class BufferFinder < Finder
|
||||||
|
def initialize
|
||||||
|
@scanner = Scanner::BufferScanner.new
|
||||||
|
@matcher = Matcher.new @scanner, :always_show_dot_files => true
|
||||||
|
end
|
||||||
|
end # class BufferFinder
|
||||||
|
end # class Finder
|
||||||
|
end # CommandT
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
class Finder
|
||||||
|
class FileFinder < Finder
|
||||||
|
def initialize(path = Dir.pwd, options = {})
|
||||||
|
case options.delete(:scanner)
|
||||||
|
when 'ruby', nil # ruby is the default
|
||||||
|
@scanner = Scanner::FileScanner::RubyFileScanner.new(path, options)
|
||||||
|
when 'find'
|
||||||
|
@scanner = Scanner::FileScanner::FindFileScanner.new(path, options)
|
||||||
|
when 'watchman'
|
||||||
|
@scanner = Scanner::FileScanner::WatchmanFileScanner.new(path, options)
|
||||||
|
when 'git'
|
||||||
|
@scanner = Scanner::FileScanner::GitFileScanner.new(path, options)
|
||||||
|
else
|
||||||
|
raise ArgumentError, "unknown scanner type '#{options[:scanner]}'"
|
||||||
|
end
|
||||||
|
|
||||||
|
@matcher = Matcher.new @scanner, options
|
||||||
|
end
|
||||||
|
|
||||||
|
def flush
|
||||||
|
@scanner.flush
|
||||||
|
end
|
||||||
|
end # class FileFinder
|
||||||
|
end # class Finder
|
||||||
|
end # module CommandT
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Copyright 2011-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
class Finder
|
||||||
|
class JumpFinder < Finder
|
||||||
|
def initialize
|
||||||
|
@scanner = Scanner::JumpScanner.new
|
||||||
|
@matcher = Matcher.new @scanner, :always_show_dot_files => true
|
||||||
|
end
|
||||||
|
end # class JumpFinder
|
||||||
|
end # class Finder
|
||||||
|
end # module CommandT
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Copyright 2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
class Finder
|
||||||
|
class MRUBufferFinder < BufferFinder
|
||||||
|
def initialize
|
||||||
|
@scanner = Scanner::MRUBufferScanner.new
|
||||||
|
@matcher = Matcher.new @scanner, :always_show_dot_files => true
|
||||||
|
end
|
||||||
|
|
||||||
|
# Override sorted_matches_for to prevent MRU ordered matches from being
|
||||||
|
# ordered alphabetically.
|
||||||
|
def sorted_matches_for(str, options = {})
|
||||||
|
matches = super(str, options.merge(:sort => false))
|
||||||
|
|
||||||
|
# take current buffer (by definition, the most recently used) and move it
|
||||||
|
# to the end of the results
|
||||||
|
if MRU.last &&
|
||||||
|
relative_path_under_working_directory(MRU.last.name) == matches.first
|
||||||
|
matches[1..-1] + [matches.first]
|
||||||
|
else
|
||||||
|
matches
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end # class MRUBufferFinder
|
||||||
|
end # class Finder
|
||||||
|
end # CommandT
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Copyright 2011-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
class Finder
|
||||||
|
class TagFinder < Finder
|
||||||
|
def initialize(options = {})
|
||||||
|
@scanner = Scanner::TagScanner.new options
|
||||||
|
@matcher = Matcher.new @scanner, :always_show_dot_files => true
|
||||||
|
end
|
||||||
|
|
||||||
|
def open_selection(command, selection, options = {})
|
||||||
|
if @scanner.include_filenames
|
||||||
|
selection = selection[0, selection.index(':')]
|
||||||
|
end
|
||||||
|
|
||||||
|
# open the tag and center the screen on it
|
||||||
|
::VIM::command "silent! tag #{selection} | :normal zz"
|
||||||
|
end
|
||||||
|
|
||||||
|
def flush
|
||||||
|
@scanner.flush
|
||||||
|
end
|
||||||
|
end # class TagFinder
|
||||||
|
end # class Finder
|
||||||
|
end # module CommandT
|
173
vim/vim.symlink/bundle/command-t/ruby/command-t/match.c
Normal file
173
vim/vim.symlink/bundle/command-t/ruby/command-t/match.c
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
// Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
// Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
#include <float.h> /* for DBL_MAX */
|
||||||
|
#include "match.h"
|
||||||
|
#include "ext.h"
|
||||||
|
#include "ruby_compat.h"
|
||||||
|
|
||||||
|
// use a struct to make passing params during recursion easier
|
||||||
|
typedef struct {
|
||||||
|
char *haystack_p; // pointer to the path string to be searched
|
||||||
|
long haystack_len; // length of same
|
||||||
|
char *needle_p; // pointer to search string (needle)
|
||||||
|
long needle_len; // length of same
|
||||||
|
double max_score_per_char;
|
||||||
|
int always_show_dot_files; // boolean
|
||||||
|
int never_show_dot_files; // boolean
|
||||||
|
int case_sensitive; // boolean
|
||||||
|
double *memo; // memoization
|
||||||
|
} matchinfo_t;
|
||||||
|
|
||||||
|
double recursive_match(matchinfo_t *m, // sharable meta-data
|
||||||
|
long haystack_idx, // where in the path string to start
|
||||||
|
long needle_idx, // where in the needle string to start
|
||||||
|
long last_idx, // location of last matched character
|
||||||
|
double score) // cumulative score so far
|
||||||
|
{
|
||||||
|
double score_for_char;
|
||||||
|
double seen_score = 0; // remember best score seen via recursion
|
||||||
|
int found;
|
||||||
|
long i, j, distance;
|
||||||
|
long memo_idx = haystack_idx;
|
||||||
|
|
||||||
|
// do we have a memoized result we can return?
|
||||||
|
double memoized = m->memo[needle_idx * m->needle_len + memo_idx];
|
||||||
|
if (memoized != DBL_MAX)
|
||||||
|
return memoized;
|
||||||
|
|
||||||
|
// bail early if not enough room (left) in haystack for (rest of) needle
|
||||||
|
if (m->haystack_len - haystack_idx < m->needle_len - needle_idx) {
|
||||||
|
score = 0.0;
|
||||||
|
goto memoize;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = needle_idx; i < m->needle_len; i++) {
|
||||||
|
char c = m->needle_p[i];
|
||||||
|
found = 0;
|
||||||
|
|
||||||
|
// similar to above, we'll stop iterating when we know we're too close
|
||||||
|
// to the end of the string to possibly match
|
||||||
|
for (j = haystack_idx;
|
||||||
|
j <= m->haystack_len - (m->needle_len - i);
|
||||||
|
j++, haystack_idx++) {
|
||||||
|
char d = m->haystack_p[j];
|
||||||
|
if (d == '.') {
|
||||||
|
if (j == 0 || m->haystack_p[j - 1] == '/') { // this is a dot-file
|
||||||
|
int dot_search = (i == 0 && c == '.'); // searching for a dot
|
||||||
|
if (m->never_show_dot_files || (!dot_search && !m->always_show_dot_files)) {
|
||||||
|
score = 0.0;
|
||||||
|
goto memoize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (d >= 'A' && d <= 'Z' && !m->case_sensitive) {
|
||||||
|
d += 'a' - 'A'; // add 32 to downcase
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == d) {
|
||||||
|
found = 1;
|
||||||
|
|
||||||
|
// calculate score
|
||||||
|
score_for_char = m->max_score_per_char;
|
||||||
|
distance = j - last_idx;
|
||||||
|
|
||||||
|
if (distance > 1) {
|
||||||
|
double factor = 1.0;
|
||||||
|
char last = m->haystack_p[j - 1];
|
||||||
|
char curr = m->haystack_p[j]; // case matters, so get again
|
||||||
|
if (last == '/')
|
||||||
|
factor = 0.9;
|
||||||
|
else if (last == '-' ||
|
||||||
|
last == '_' ||
|
||||||
|
last == ' ' ||
|
||||||
|
(last >= '0' && last <= '9'))
|
||||||
|
factor = 0.8;
|
||||||
|
else if (last >= 'a' && last <= 'z' &&
|
||||||
|
curr >= 'A' && curr <= 'Z')
|
||||||
|
factor = 0.8;
|
||||||
|
else if (last == '.')
|
||||||
|
factor = 0.7;
|
||||||
|
else
|
||||||
|
// if no "special" chars behind char, factor diminishes
|
||||||
|
// as distance from last matched char increases
|
||||||
|
factor = (1.0 / distance) * 0.75;
|
||||||
|
score_for_char *= factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++j < m->haystack_len) {
|
||||||
|
// bump cursor one char to the right and
|
||||||
|
// use recursion to try and find a better match
|
||||||
|
double sub_score = recursive_match(m, j, i, last_idx, score);
|
||||||
|
if (sub_score > seen_score)
|
||||||
|
seen_score = sub_score;
|
||||||
|
}
|
||||||
|
|
||||||
|
score += score_for_char;
|
||||||
|
last_idx = haystack_idx++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
score = 0.0;
|
||||||
|
goto memoize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
score = score > seen_score ? score : seen_score;
|
||||||
|
|
||||||
|
memoize:
|
||||||
|
m->memo[needle_idx * m->needle_len + memo_idx] = score;
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
void calculate_match(VALUE str,
|
||||||
|
VALUE needle,
|
||||||
|
VALUE case_sensitive,
|
||||||
|
VALUE always_show_dot_files,
|
||||||
|
VALUE never_show_dot_files,
|
||||||
|
match_t *out)
|
||||||
|
{
|
||||||
|
long i, max;
|
||||||
|
double score;
|
||||||
|
matchinfo_t m;
|
||||||
|
m.haystack_p = RSTRING_PTR(str);
|
||||||
|
m.haystack_len = RSTRING_LEN(str);
|
||||||
|
m.needle_p = RSTRING_PTR(needle);
|
||||||
|
m.needle_len = RSTRING_LEN(needle);
|
||||||
|
m.max_score_per_char = (1.0 / m.haystack_len + 1.0 / m.needle_len) / 2;
|
||||||
|
m.always_show_dot_files = always_show_dot_files == Qtrue;
|
||||||
|
m.never_show_dot_files = never_show_dot_files == Qtrue;
|
||||||
|
m.case_sensitive = case_sensitive;
|
||||||
|
|
||||||
|
// calculate score
|
||||||
|
score = 1.0;
|
||||||
|
|
||||||
|
// special case for zero-length search string
|
||||||
|
if (m.needle_len == 0) {
|
||||||
|
|
||||||
|
// filter out dot files
|
||||||
|
if (!m.always_show_dot_files) {
|
||||||
|
for (i = 0; i < m.haystack_len; i++) {
|
||||||
|
char c = m.haystack_p[i];
|
||||||
|
|
||||||
|
if (c == '.' && (i == 0 || m.haystack_p[i - 1] == '/')) {
|
||||||
|
score = 0.0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (m.haystack_len > 0) { // normal case
|
||||||
|
|
||||||
|
// prepare for memoization
|
||||||
|
double memo[m.haystack_len * m.needle_len];
|
||||||
|
for (i = 0, max = m.haystack_len * m.needle_len; i < max; i++)
|
||||||
|
memo[i] = DBL_MAX;
|
||||||
|
m.memo = memo;
|
||||||
|
|
||||||
|
score = recursive_match(&m, 0, 0, 0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// final book-keeping
|
||||||
|
out->path = str;
|
||||||
|
out->score = score;
|
||||||
|
}
|
17
vim/vim.symlink/bundle/command-t/ruby/command-t/match.h
Normal file
17
vim/vim.symlink/bundle/command-t/ruby/command-t/match.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
// Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
#include <ruby.h>
|
||||||
|
|
||||||
|
// struct for representing an individual match
|
||||||
|
typedef struct {
|
||||||
|
VALUE path;
|
||||||
|
double score;
|
||||||
|
} match_t;
|
||||||
|
|
||||||
|
extern void calculate_match(VALUE str,
|
||||||
|
VALUE needle,
|
||||||
|
VALUE case_sensitive,
|
||||||
|
VALUE always_show_dot_files,
|
||||||
|
VALUE never_show_dot_files,
|
||||||
|
match_t *out);
|
441
vim/vim.symlink/bundle/command-t/ruby/command-t/match_window.rb
Normal file
441
vim/vim.symlink/bundle/command-t/ruby/command-t/match_window.rb
Normal file
|
@ -0,0 +1,441 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
require 'ostruct'
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
class MatchWindow
|
||||||
|
SELECTION_MARKER = '> '
|
||||||
|
MARKER_LENGTH = SELECTION_MARKER.length
|
||||||
|
UNSELECTED_MARKER = ' ' * MARKER_LENGTH
|
||||||
|
MH_START = '<commandt>'
|
||||||
|
MH_END = '</commandt>'
|
||||||
|
@@buffer = nil
|
||||||
|
|
||||||
|
def initialize(options = {})
|
||||||
|
@highlight_color = options[:highlight_color] || 'PmenuSel'
|
||||||
|
@min_height = options[:min_height]
|
||||||
|
@prompt = options[:prompt]
|
||||||
|
@reverse_list = options[:match_window_reverse]
|
||||||
|
|
||||||
|
# save existing window dimensions so we can restore them later
|
||||||
|
@windows = (0..(::VIM::Window.count - 1)).map do |i|
|
||||||
|
OpenStruct.new(
|
||||||
|
:index => i,
|
||||||
|
:height => ::VIM::Window[i].height,
|
||||||
|
:width => ::VIM::Window[i].width
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
set 'timeout', true # ensure mappings timeout
|
||||||
|
set 'hlsearch', false # don't highlight search strings
|
||||||
|
set 'insertmode', false # don't make Insert mode the default
|
||||||
|
set 'showcmd', false # don't show command info on last line
|
||||||
|
set 'equalalways', false # don't auto-balance window sizes
|
||||||
|
set 'timeoutlen', 0 # respond immediately to mappings
|
||||||
|
set 'report', 9999 # don't show "X lines changed" reports
|
||||||
|
set 'scrolloff', 0 # don't scroll near buffer edges
|
||||||
|
set 'sidescroll', 0 # don't sidescroll in jumps
|
||||||
|
set 'sidescrolloff', 0 # don't sidescroll automatically
|
||||||
|
set 'updatetime', options[:debounce_interval]
|
||||||
|
|
||||||
|
# show match window
|
||||||
|
split_location = options[:match_window_at_top] ? 'topleft' : 'botright'
|
||||||
|
if @@buffer # still have buffer from last time
|
||||||
|
::VIM::command "silent! #{split_location} #{@@buffer.number}sbuffer"
|
||||||
|
raise "Can't re-open GoToFile buffer" unless $curbuf.number == @@buffer.number
|
||||||
|
$curwin.height = 1
|
||||||
|
else # creating match window for first time and set it up
|
||||||
|
::VIM::command "silent! #{split_location} 1split GoToFile"
|
||||||
|
set 'bufhidden', 'unload' # unload buf when no longer displayed
|
||||||
|
set 'buftype', 'nofile' # buffer is not related to any file
|
||||||
|
set 'modifiable', false # prevent manual edits
|
||||||
|
set 'swapfile', false # don't create a swapfile
|
||||||
|
set 'wrap', false # don't soft-wrap
|
||||||
|
set 'number', false # don't show line numbers
|
||||||
|
set 'list', false # don't use List mode (visible tabs etc)
|
||||||
|
set 'foldcolumn', 0 # don't show a fold column at side
|
||||||
|
set 'foldlevel', 99 # don't fold anything
|
||||||
|
set 'cursorline', false # don't highlight line cursor is on
|
||||||
|
set 'spell', false # spell-checking off
|
||||||
|
set 'buflisted', false # don't show up in the buffer list
|
||||||
|
set 'textwidth', 0 # don't hard-wrap (break long lines)
|
||||||
|
|
||||||
|
# don't show the color column
|
||||||
|
set 'colorcolumn', 0 if VIM::exists?('+colorcolumn')
|
||||||
|
|
||||||
|
# don't show relative line numbers
|
||||||
|
set 'relativenumber', false if VIM::exists?('+relativenumber')
|
||||||
|
|
||||||
|
# sanity check: make sure the buffer really was created
|
||||||
|
raise "Can't find GoToFile buffer" unless $curbuf.name.match /GoToFile\z/
|
||||||
|
@@buffer = $curbuf
|
||||||
|
end
|
||||||
|
|
||||||
|
# syntax coloring
|
||||||
|
if VIM::has?('syntax')
|
||||||
|
::VIM::command "syntax match CommandTSelection \"^#{SELECTION_MARKER}.\\+$\""
|
||||||
|
::VIM::command 'syntax match CommandTNoEntries "^-- NO MATCHES --$"'
|
||||||
|
::VIM::command 'syntax match CommandTNoEntries "^-- NO SUCH FILE OR DIRECTORY --$"'
|
||||||
|
set 'synmaxcol', 9999
|
||||||
|
|
||||||
|
if VIM::has?('conceal')
|
||||||
|
set 'conceallevel', 2
|
||||||
|
set 'concealcursor', 'nvic'
|
||||||
|
::VIM::command 'syntax region CommandTCharMatched ' \
|
||||||
|
"matchgroup=CommandTCharMatched start=+#{MH_START}+ " \
|
||||||
|
"matchgroup=CommandTCharMatchedEnd end=+#{MH_END}+ concealends"
|
||||||
|
::VIM::command 'highlight def CommandTCharMatched ' \
|
||||||
|
'term=bold,underline cterm=bold,underline ' \
|
||||||
|
'gui=bold,underline'
|
||||||
|
end
|
||||||
|
|
||||||
|
::VIM::command "highlight link CommandTSelection #{@highlight_color}"
|
||||||
|
::VIM::command 'highlight link CommandTNoEntries Error'
|
||||||
|
|
||||||
|
# hide cursor
|
||||||
|
@cursor_highlight = get_cursor_highlight
|
||||||
|
hide_cursor
|
||||||
|
end
|
||||||
|
|
||||||
|
# perform cleanup using an autocmd to ensure we don't get caught out
|
||||||
|
# by some unexpected means of dismissing or leaving the Command-T window
|
||||||
|
# (eg. <C-W q>, <C-W k> etc)
|
||||||
|
::VIM::command 'autocmd! * <buffer>'
|
||||||
|
::VIM::command 'autocmd BufLeave <buffer> silent! ruby $command_t.leave'
|
||||||
|
::VIM::command 'autocmd BufUnload <buffer> silent! ruby $command_t.unload'
|
||||||
|
|
||||||
|
@has_focus = false
|
||||||
|
@abbrev = ''
|
||||||
|
@window = $curwin
|
||||||
|
end
|
||||||
|
|
||||||
|
def close
|
||||||
|
# Unlisted buffers like those provided by Netrw, NERDTree and Vim's help
|
||||||
|
# don't actually appear in the buffer list; if they are the only such
|
||||||
|
# buffers present when Command-T is invoked (for example, when invoked
|
||||||
|
# immediately after starting Vim with a directory argument, like `vim .`)
|
||||||
|
# then performing the normal clean-up will yield an "E90: Cannot unload
|
||||||
|
# last buffer" error. We can work around that by doing a :quit first.
|
||||||
|
if ::VIM::Buffer.count == 0
|
||||||
|
::VIM::command 'silent quit'
|
||||||
|
end
|
||||||
|
|
||||||
|
# Workaround for upstream bug in Vim 7.3 on some platforms
|
||||||
|
#
|
||||||
|
# On some platforms, $curbuf.number always returns 0. One workaround is
|
||||||
|
# to build Vim with --disable-largefile, but as this is producing lots of
|
||||||
|
# support requests, implement the following fallback to the buffer name
|
||||||
|
# instead, at least until upstream gets fixed.
|
||||||
|
#
|
||||||
|
# For more details, see: https://wincent.com/issues/1617
|
||||||
|
if $curbuf.number == 0
|
||||||
|
# use bwipeout as bunload fails if passed the name of a hidden buffer
|
||||||
|
::VIM::command 'silent! bwipeout! GoToFile'
|
||||||
|
@@buffer = nil
|
||||||
|
else
|
||||||
|
::VIM::command "silent! bunload! #{@@buffer.number}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def leave
|
||||||
|
close
|
||||||
|
unload
|
||||||
|
end
|
||||||
|
|
||||||
|
def unload
|
||||||
|
restore_window_dimensions
|
||||||
|
@settings.restore
|
||||||
|
@prompt.dispose
|
||||||
|
show_cursor
|
||||||
|
end
|
||||||
|
|
||||||
|
def add!(char)
|
||||||
|
@abbrev += char
|
||||||
|
end
|
||||||
|
|
||||||
|
def backspace!
|
||||||
|
@abbrev.chop!
|
||||||
|
end
|
||||||
|
|
||||||
|
def select_next
|
||||||
|
@reverse_list ? _prev : _next
|
||||||
|
end
|
||||||
|
|
||||||
|
def select_prev
|
||||||
|
@reverse_list ? _next : _prev
|
||||||
|
end
|
||||||
|
|
||||||
|
def matches=(matches)
|
||||||
|
if matches != @matches
|
||||||
|
@matches = matches
|
||||||
|
@selection = 0
|
||||||
|
print_matches
|
||||||
|
move_cursor_to_selected_line
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def focus
|
||||||
|
unless @has_focus
|
||||||
|
@has_focus = true
|
||||||
|
if VIM::has?('syntax')
|
||||||
|
::VIM::command 'highlight link CommandTSelection Search'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def unfocus
|
||||||
|
if @has_focus
|
||||||
|
@has_focus = false
|
||||||
|
if VIM::has?('syntax')
|
||||||
|
::VIM::command "highlight link CommandTSelection #{@highlight_color}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def find(char)
|
||||||
|
# is this a new search or the continuation of a previous one?
|
||||||
|
now = Time.now
|
||||||
|
if @last_key_time.nil? || @last_key_time < (now - 0.5)
|
||||||
|
@find_string = char
|
||||||
|
else
|
||||||
|
@find_string += char
|
||||||
|
end
|
||||||
|
@last_key_time = now
|
||||||
|
|
||||||
|
# see if there's anything up ahead that matches
|
||||||
|
matches = @reverse_list ? @matches.reverse : @matches
|
||||||
|
matches.each_with_index do |match, idx|
|
||||||
|
if match[0, @find_string.length].casecmp(@find_string) == 0
|
||||||
|
old_selection = @selection
|
||||||
|
@selection = @reverse_list ? matches.length - idx - 1 : idx
|
||||||
|
print_match(old_selection) # redraw old selection (removes marker)
|
||||||
|
print_match(@selection) # redraw new selection (adds marker)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns the currently selected item as a String.
|
||||||
|
def selection
|
||||||
|
@matches[@selection]
|
||||||
|
end
|
||||||
|
|
||||||
|
def print_no_such_file_or_directory
|
||||||
|
print_error 'NO SUCH FILE OR DIRECTORY'
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def _next
|
||||||
|
if @selection < [@window.height, @matches.length].min - 1
|
||||||
|
@selection += 1
|
||||||
|
print_match(@selection - 1) # redraw old selection (removes marker)
|
||||||
|
print_match(@selection) # redraw new selection (adds marker)
|
||||||
|
move_cursor_to_selected_line
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def _prev
|
||||||
|
if @selection > 0
|
||||||
|
@selection -= 1
|
||||||
|
print_match(@selection + 1) # redraw old selection (removes marker)
|
||||||
|
print_match(@selection) # redraw new selection (adds marker)
|
||||||
|
move_cursor_to_selected_line
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Translate from a 0-indexed match index to a 1-indexed Vim line number.
|
||||||
|
# Also takes into account reversed listings.
|
||||||
|
def line(match_index)
|
||||||
|
@reverse_list ? @window.height - match_index : match_index + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def set(setting, value)
|
||||||
|
@settings ||= Settings.new
|
||||||
|
@settings.set(setting, value)
|
||||||
|
end
|
||||||
|
|
||||||
|
def move_cursor_to_selected_line
|
||||||
|
# on some non-GUI terminals, the cursor doesn't hide properly
|
||||||
|
# so we move the cursor to prevent it from blinking away in the
|
||||||
|
# upper-left corner in a distracting fashion
|
||||||
|
@window.cursor = [line(@selection), 0]
|
||||||
|
end
|
||||||
|
|
||||||
|
def print_error(msg)
|
||||||
|
return unless VIM::Window.select(@window)
|
||||||
|
unlock
|
||||||
|
clear
|
||||||
|
@window.height = [1, @min_height].min
|
||||||
|
@@buffer[1] = "-- #{msg} --"
|
||||||
|
lock
|
||||||
|
end
|
||||||
|
|
||||||
|
def restore_window_dimensions
|
||||||
|
# sort from tallest to shortest, tie-breaking on window width
|
||||||
|
@windows.sort! do |a, b|
|
||||||
|
order = b.height <=> a.height
|
||||||
|
if order.zero?
|
||||||
|
b.width <=> a.width
|
||||||
|
else
|
||||||
|
order
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# starting with the tallest ensures that there are no constraints
|
||||||
|
# preventing windows on the side of vertical splits from regaining
|
||||||
|
# their original full size
|
||||||
|
@windows.each do |w|
|
||||||
|
# beware: window may be nil
|
||||||
|
if window = ::VIM::Window[w.index]
|
||||||
|
window.height = w.height
|
||||||
|
window.width = w.width
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def match_text_for_idx(idx)
|
||||||
|
match = truncated_match @matches[idx].to_s
|
||||||
|
if idx == @selection
|
||||||
|
prefix = SELECTION_MARKER
|
||||||
|
suffix = padding_for_selected_match match
|
||||||
|
else
|
||||||
|
if VIM::has?('syntax') && VIM::has?('conceal')
|
||||||
|
match = match_with_syntax_highlight match
|
||||||
|
end
|
||||||
|
prefix = UNSELECTED_MARKER
|
||||||
|
suffix = ''
|
||||||
|
end
|
||||||
|
prefix + match + suffix
|
||||||
|
end
|
||||||
|
|
||||||
|
# Highlight matching characters within the matched string.
|
||||||
|
#
|
||||||
|
# Note that this is only approximate; it will highlight the first matching
|
||||||
|
# instances within the string, which may not actually be the instances that
|
||||||
|
# were used by the matching/scoring algorithm to determine the best score
|
||||||
|
# for the match.
|
||||||
|
#
|
||||||
|
def match_with_syntax_highlight(match)
|
||||||
|
highlight_chars = @prompt.abbrev.downcase.scan(/./mu)
|
||||||
|
match.scan(/./mu).inject([]) do |output, char|
|
||||||
|
if char.downcase == highlight_chars.first
|
||||||
|
highlight_chars.shift
|
||||||
|
output.concat [MH_START, char, MH_END]
|
||||||
|
else
|
||||||
|
output << char
|
||||||
|
end
|
||||||
|
end.join
|
||||||
|
end
|
||||||
|
|
||||||
|
# Print just the specified match.
|
||||||
|
def print_match(idx)
|
||||||
|
return unless VIM::Window.select(@window)
|
||||||
|
unlock
|
||||||
|
@@buffer[line(idx)] = match_text_for_idx idx
|
||||||
|
lock
|
||||||
|
end
|
||||||
|
|
||||||
|
def max_lines
|
||||||
|
[1, VIM::Screen.lines - 5].max
|
||||||
|
end
|
||||||
|
|
||||||
|
# Print all matches.
|
||||||
|
def print_matches
|
||||||
|
match_count = @matches.length
|
||||||
|
if match_count == 0
|
||||||
|
print_error 'NO MATCHES'
|
||||||
|
else
|
||||||
|
return unless VIM::Window.select(@window)
|
||||||
|
unlock
|
||||||
|
clear
|
||||||
|
@window_width = @window.width # update cached value
|
||||||
|
desired_lines = [match_count, @min_height].max
|
||||||
|
desired_lines = [max_lines, desired_lines].min
|
||||||
|
@window.height = desired_lines
|
||||||
|
matches = []
|
||||||
|
(0...@window.height).each do |idx|
|
||||||
|
text = match_text_for_idx(idx)
|
||||||
|
@reverse_list ? matches.unshift(text) : matches.push(text)
|
||||||
|
end
|
||||||
|
matches.each_with_index do |match, idx|
|
||||||
|
if @@buffer.count > idx
|
||||||
|
@@buffer[idx + 1] = match
|
||||||
|
else
|
||||||
|
@@buffer.append(idx, match)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
lock
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Prepare padding for match text (trailing spaces) so that selection
|
||||||
|
# highlighting extends all the way to the right edge of the window.
|
||||||
|
def padding_for_selected_match(str)
|
||||||
|
len = str.length
|
||||||
|
if len >= @window_width - MARKER_LENGTH
|
||||||
|
''
|
||||||
|
else
|
||||||
|
' ' * (@window_width - MARKER_LENGTH - len)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Convert "really/long/path" into "really...path" based on available
|
||||||
|
# window width.
|
||||||
|
def truncated_match(str)
|
||||||
|
len = str.length
|
||||||
|
available_width = @window_width - MARKER_LENGTH
|
||||||
|
return str if len <= available_width
|
||||||
|
left = (available_width / 2) - 1
|
||||||
|
right = (available_width / 2) - 2 + (available_width % 2)
|
||||||
|
str[0, left] + '...' + str[-right, right]
|
||||||
|
end
|
||||||
|
|
||||||
|
def clear
|
||||||
|
# range = % (whole buffer)
|
||||||
|
# action = d (delete)
|
||||||
|
# register = _ (black hole register, don't record deleted text)
|
||||||
|
::VIM::command 'silent %d _'
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_cursor_highlight
|
||||||
|
# there are 3 possible formats to check for, each needing to be
|
||||||
|
# transformed in a certain way in order to reapply the highlight:
|
||||||
|
# Cursor xxx guifg=bg guibg=fg -> :hi! Cursor guifg=bg guibg=fg
|
||||||
|
# Cursor xxx links to SomethingElse -> :hi! link Cursor SomethingElse
|
||||||
|
# Cursor xxx cleared -> :hi! clear Cursor
|
||||||
|
highlight = VIM::capture 'silent! 0verbose highlight Cursor'
|
||||||
|
|
||||||
|
if highlight =~ /^Cursor\s+xxx\s+links to (\w+)/
|
||||||
|
"link Cursor #{$~[1]}"
|
||||||
|
elsif highlight =~ /^Cursor\s+xxx\s+cleared/
|
||||||
|
'clear Cursor'
|
||||||
|
elsif highlight =~ /Cursor\s+xxx\s+(.+)/
|
||||||
|
"Cursor #{$~[1]}"
|
||||||
|
else # likely cause E411 Cursor highlight group not found
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def hide_cursor
|
||||||
|
if @cursor_highlight
|
||||||
|
::VIM::command 'highlight Cursor NONE'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def show_cursor
|
||||||
|
if @cursor_highlight
|
||||||
|
::VIM::command "highlight #{@cursor_highlight}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def lock
|
||||||
|
set 'modifiable', false
|
||||||
|
end
|
||||||
|
|
||||||
|
def unlock
|
||||||
|
set 'modifiable', true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
232
vim/vim.symlink/bundle/command-t/ruby/command-t/matcher.c
Normal file
232
vim/vim.symlink/bundle/command-t/ruby/command-t/matcher.c
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
// Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
// Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
#include <stdlib.h> /* for qsort() */
|
||||||
|
#include <string.h> /* for strncmp() */
|
||||||
|
#include "matcher.h"
|
||||||
|
#include "match.h"
|
||||||
|
#include "ext.h"
|
||||||
|
#include "ruby_compat.h"
|
||||||
|
|
||||||
|
// order matters; we want this to be evaluated only after ruby.h
|
||||||
|
#ifdef HAVE_PTHREAD_H
|
||||||
|
#include <pthread.h> /* for pthread_create, pthread_join etc */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// comparison function for use with qsort
|
||||||
|
int cmp_alpha(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
match_t a_match = *(match_t *)a;
|
||||||
|
match_t b_match = *(match_t *)b;
|
||||||
|
VALUE a_str = a_match.path;
|
||||||
|
VALUE b_str = b_match.path;
|
||||||
|
char *a_p = RSTRING_PTR(a_str);
|
||||||
|
long a_len = RSTRING_LEN(a_str);
|
||||||
|
char *b_p = RSTRING_PTR(b_str);
|
||||||
|
long b_len = RSTRING_LEN(b_str);
|
||||||
|
int order = 0;
|
||||||
|
|
||||||
|
if (a_len > b_len) {
|
||||||
|
order = strncmp(a_p, b_p, b_len);
|
||||||
|
if (order == 0)
|
||||||
|
order = 1; // shorter string (b) wins
|
||||||
|
} else if (a_len < b_len) {
|
||||||
|
order = strncmp(a_p, b_p, a_len);
|
||||||
|
if (order == 0)
|
||||||
|
order = -1; // shorter string (a) wins
|
||||||
|
} else {
|
||||||
|
order = strncmp(a_p, b_p, a_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
|
||||||
|
// comparison function for use with qsort
|
||||||
|
int cmp_score(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
match_t a_match = *(match_t *)a;
|
||||||
|
match_t b_match = *(match_t *)b;
|
||||||
|
|
||||||
|
if (a_match.score > b_match.score)
|
||||||
|
return -1; // a scores higher, a should appear sooner
|
||||||
|
else if (a_match.score < b_match.score)
|
||||||
|
return 1; // b scores higher, a should appear later
|
||||||
|
else
|
||||||
|
return cmp_alpha(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE CommandTMatcher_initialize(int argc, VALUE *argv, VALUE self)
|
||||||
|
{
|
||||||
|
VALUE always_show_dot_files;
|
||||||
|
VALUE never_show_dot_files;
|
||||||
|
VALUE options;
|
||||||
|
VALUE scanner;
|
||||||
|
|
||||||
|
// process arguments: 1 mandatory, 1 optional
|
||||||
|
if (rb_scan_args(argc, argv, "11", &scanner, &options) == 1)
|
||||||
|
options = Qnil;
|
||||||
|
if (NIL_P(scanner))
|
||||||
|
rb_raise(rb_eArgError, "nil scanner");
|
||||||
|
|
||||||
|
rb_iv_set(self, "@scanner", scanner);
|
||||||
|
|
||||||
|
// check optional options hash for overrides
|
||||||
|
always_show_dot_files = CommandT_option_from_hash("always_show_dot_files", options);
|
||||||
|
never_show_dot_files = CommandT_option_from_hash("never_show_dot_files", options);
|
||||||
|
|
||||||
|
rb_iv_set(self, "@always_show_dot_files", always_show_dot_files);
|
||||||
|
rb_iv_set(self, "@never_show_dot_files", never_show_dot_files);
|
||||||
|
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int thread_count;
|
||||||
|
int thread_index;
|
||||||
|
int case_sensitive;
|
||||||
|
match_t *matches;
|
||||||
|
long path_count;
|
||||||
|
VALUE paths;
|
||||||
|
VALUE abbrev;
|
||||||
|
VALUE always_show_dot_files;
|
||||||
|
VALUE never_show_dot_files;
|
||||||
|
} thread_args_t;
|
||||||
|
|
||||||
|
void *match_thread(void *thread_args)
|
||||||
|
{
|
||||||
|
long i;
|
||||||
|
thread_args_t *args = (thread_args_t *)thread_args;
|
||||||
|
for (i = args->thread_index; i < args->path_count; i += args->thread_count) {
|
||||||
|
VALUE path = RARRAY_PTR(args->paths)[i];
|
||||||
|
calculate_match(path,
|
||||||
|
args->abbrev,
|
||||||
|
args->case_sensitive,
|
||||||
|
args->always_show_dot_files,
|
||||||
|
args->never_show_dot_files,
|
||||||
|
&args->matches[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE CommandTMatcher_sorted_matches_for(int argc, VALUE *argv, VALUE self)
|
||||||
|
{
|
||||||
|
long i, limit, path_count, thread_count;
|
||||||
|
#ifdef HAVE_PTHREAD_H
|
||||||
|
long err;
|
||||||
|
pthread_t *threads;
|
||||||
|
#endif
|
||||||
|
match_t *matches;
|
||||||
|
thread_args_t *thread_args;
|
||||||
|
VALUE abbrev;
|
||||||
|
VALUE case_sensitive;
|
||||||
|
VALUE always_show_dot_files;
|
||||||
|
VALUE limit_option;
|
||||||
|
VALUE never_show_dot_files;
|
||||||
|
VALUE options;
|
||||||
|
VALUE paths;
|
||||||
|
VALUE results;
|
||||||
|
VALUE scanner;
|
||||||
|
VALUE sort_option;
|
||||||
|
VALUE threads_option;
|
||||||
|
|
||||||
|
// process arguments: 1 mandatory, 1 optional
|
||||||
|
if (rb_scan_args(argc, argv, "11", &abbrev, &options) == 1)
|
||||||
|
options = Qnil;
|
||||||
|
if (NIL_P(abbrev))
|
||||||
|
rb_raise(rb_eArgError, "nil abbrev");
|
||||||
|
|
||||||
|
// check optional options has for overrides
|
||||||
|
case_sensitive = CommandT_option_from_hash("case_sensitive", options);
|
||||||
|
limit_option = CommandT_option_from_hash("limit", options);
|
||||||
|
threads_option = CommandT_option_from_hash("threads", options);
|
||||||
|
sort_option = CommandT_option_from_hash("sort", options);
|
||||||
|
|
||||||
|
abbrev = StringValue(abbrev);
|
||||||
|
if (case_sensitive != Qtrue)
|
||||||
|
abbrev = rb_funcall(abbrev, rb_intern("downcase"), 0);
|
||||||
|
|
||||||
|
// get unsorted matches
|
||||||
|
scanner = rb_iv_get(self, "@scanner");
|
||||||
|
paths = rb_funcall(scanner, rb_intern("paths"), 0);
|
||||||
|
always_show_dot_files = rb_iv_get(self, "@always_show_dot_files");
|
||||||
|
never_show_dot_files = rb_iv_get(self, "@never_show_dot_files");
|
||||||
|
|
||||||
|
path_count = RARRAY_LEN(paths);
|
||||||
|
matches = malloc(path_count * sizeof(match_t));
|
||||||
|
if (!matches)
|
||||||
|
rb_raise(rb_eNoMemError, "memory allocation failed");
|
||||||
|
|
||||||
|
thread_count = NIL_P(threads_option) ? 1 : NUM2LONG(threads_option);
|
||||||
|
|
||||||
|
#ifdef HAVE_PTHREAD_H
|
||||||
|
#define THREAD_THRESHOLD 1000 /* avoid the overhead of threading when search space is small */
|
||||||
|
if (path_count < THREAD_THRESHOLD)
|
||||||
|
thread_count = 1;
|
||||||
|
threads = malloc(sizeof(pthread_t) * thread_count);
|
||||||
|
if (!threads)
|
||||||
|
rb_raise(rb_eNoMemError, "memory allocation failed");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
thread_args = malloc(sizeof(thread_args_t) * thread_count);
|
||||||
|
if (!thread_args)
|
||||||
|
rb_raise(rb_eNoMemError, "memory allocation failed");
|
||||||
|
for (i = 0; i < thread_count; i++) {
|
||||||
|
thread_args[i].thread_count = thread_count;
|
||||||
|
thread_args[i].thread_index = i;
|
||||||
|
thread_args[i].case_sensitive = case_sensitive == Qtrue;
|
||||||
|
thread_args[i].matches = matches;
|
||||||
|
thread_args[i].path_count = path_count;
|
||||||
|
thread_args[i].paths = paths;
|
||||||
|
thread_args[i].abbrev = abbrev;
|
||||||
|
thread_args[i].always_show_dot_files = always_show_dot_files;
|
||||||
|
thread_args[i].never_show_dot_files = never_show_dot_files;
|
||||||
|
|
||||||
|
#ifdef HAVE_PTHREAD_H
|
||||||
|
if (i == thread_count - 1) {
|
||||||
|
#endif
|
||||||
|
// for the last "worker", we'll just use the main thread
|
||||||
|
(void)match_thread(&thread_args[i]);
|
||||||
|
#ifdef HAVE_PTHREAD_H
|
||||||
|
} else {
|
||||||
|
err = pthread_create(&threads[i], NULL, match_thread, (void *)&thread_args[i]);
|
||||||
|
if (err != 0)
|
||||||
|
rb_raise(rb_eSystemCallError, "pthread_create() failure (%d)", (int)err);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_PTHREAD_H
|
||||||
|
for (i = 0; i < thread_count - 1; i++) {
|
||||||
|
err = pthread_join(threads[i], NULL);
|
||||||
|
if (err != 0)
|
||||||
|
rb_raise(rb_eSystemCallError, "pthread_join() failure (%d)", (int)err);
|
||||||
|
}
|
||||||
|
free(threads);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (NIL_P(sort_option) || sort_option == Qtrue) {
|
||||||
|
if (RSTRING_LEN(abbrev) == 0 ||
|
||||||
|
(RSTRING_LEN(abbrev) == 1 && RSTRING_PTR(abbrev)[0] == '.'))
|
||||||
|
// alphabetic order if search string is only "" or "."
|
||||||
|
qsort(matches, path_count, sizeof(match_t), cmp_alpha);
|
||||||
|
else
|
||||||
|
// for all other non-empty search strings, sort by score
|
||||||
|
qsort(matches, path_count, sizeof(match_t), cmp_score);
|
||||||
|
}
|
||||||
|
|
||||||
|
results = rb_ary_new();
|
||||||
|
|
||||||
|
limit = NIL_P(limit_option) ? 0 : NUM2LONG(limit_option);
|
||||||
|
if (limit == 0)
|
||||||
|
limit = path_count;
|
||||||
|
for (i = 0; i < path_count && limit > 0; i++) {
|
||||||
|
if (matches[i].score > 0.0) {
|
||||||
|
rb_funcall(results, rb_intern("push"), 1, matches[i].path);
|
||||||
|
limit--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(matches);
|
||||||
|
return results;
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
// Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
// Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
#include <ruby.h>
|
||||||
|
|
||||||
|
extern VALUE CommandTMatcher_initialize(int argc, VALUE *argv, VALUE self);
|
||||||
|
extern VALUE CommandTMatcher_sorted_matches_for(int argc, VALUE *argv, VALUE self);
|
43
vim/vim.symlink/bundle/command-t/ruby/command-t/mru.rb
Normal file
43
vim/vim.symlink/bundle/command-t/ruby/command-t/mru.rb
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
# Copyright 2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
# Maintains a stack of seen buffers in MRU (most recently used) order.
|
||||||
|
module MRU
|
||||||
|
class << self
|
||||||
|
# The stack of used buffers in MRU order.
|
||||||
|
def stack
|
||||||
|
@stack ||= []
|
||||||
|
end
|
||||||
|
|
||||||
|
# The (last) most recent buffer in the stack, if any.
|
||||||
|
def last
|
||||||
|
stack.last
|
||||||
|
end
|
||||||
|
|
||||||
|
# Mark the current buffer as having been used, effectively moving it to
|
||||||
|
# the top of the stack.
|
||||||
|
def touch
|
||||||
|
return unless ::VIM::evaluate('buflisted(%d)' % $curbuf.number) == 1
|
||||||
|
return unless $curbuf.name
|
||||||
|
|
||||||
|
stack.delete $curbuf
|
||||||
|
stack.push $curbuf
|
||||||
|
end
|
||||||
|
|
||||||
|
# Mark a buffer as deleted, removing it from the stack.
|
||||||
|
def delete
|
||||||
|
# Note that $curbuf does not point to the buffer that is being deleted;
|
||||||
|
# we need to use Vim's <abuf> for the correct buffer number.
|
||||||
|
stack.delete_if do |b|
|
||||||
|
b.number == ::VIM::evaluate('expand("<abuf>")').to_i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns `true` if `buffer` has been used (ie. is present in the stack).
|
||||||
|
def used?(buffer)
|
||||||
|
stack.include?(buffer)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end # module MRU
|
||||||
|
end # module CommandT
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
module PathUtilities
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def relative_path_under_working_directory(path)
|
||||||
|
# any path under the working directory will be specified as a relative
|
||||||
|
# path to improve the readability of the buffer list etc
|
||||||
|
pwd = File.expand_path(VIM::pwd) + '/'
|
||||||
|
path.index(pwd) == 0 ? path[pwd.length..-1] : path
|
||||||
|
end
|
||||||
|
|
||||||
|
end # module PathUtilities
|
||||||
|
end # module CommandT
|
161
vim/vim.symlink/bundle/command-t/ruby/command-t/prompt.rb
Normal file
161
vim/vim.symlink/bundle/command-t/ruby/command-t/prompt.rb
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
# Abuse the status line as a prompt.
|
||||||
|
class Prompt
|
||||||
|
attr_accessor :abbrev
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@abbrev = '' # abbreviation entered so far
|
||||||
|
@col = 0 # cursor position
|
||||||
|
@has_focus = false
|
||||||
|
end
|
||||||
|
|
||||||
|
# Erase whatever is displayed in the prompt line,
|
||||||
|
# effectively disposing of the prompt
|
||||||
|
def dispose
|
||||||
|
::VIM::command 'echo'
|
||||||
|
::VIM::command 'redraw'
|
||||||
|
end
|
||||||
|
|
||||||
|
# Clear any entered text.
|
||||||
|
def clear!
|
||||||
|
@abbrev = ''
|
||||||
|
@col = 0
|
||||||
|
redraw
|
||||||
|
end
|
||||||
|
|
||||||
|
# Remove word before cursor
|
||||||
|
def clear_prev_word!
|
||||||
|
suffix_length = @abbrev.length - @col
|
||||||
|
@abbrev.match(
|
||||||
|
%r{
|
||||||
|
(.*?) # prefix
|
||||||
|
\w*\s* # word to clear
|
||||||
|
(.{#{suffix_length}}) # suffix
|
||||||
|
\z
|
||||||
|
}x
|
||||||
|
)
|
||||||
|
@abbrev = $~[1] + $~[2]
|
||||||
|
@col = @abbrev.length - suffix_length
|
||||||
|
redraw
|
||||||
|
end
|
||||||
|
|
||||||
|
# Insert a character at (before) the current cursor position.
|
||||||
|
def add!(char)
|
||||||
|
left, cursor, right = abbrev_segments
|
||||||
|
@abbrev = left + char + cursor + right
|
||||||
|
@col += 1
|
||||||
|
redraw
|
||||||
|
end
|
||||||
|
|
||||||
|
# Delete a character to the left of the current cursor position.
|
||||||
|
def backspace!
|
||||||
|
if @col > 0
|
||||||
|
left, cursor, right = abbrev_segments
|
||||||
|
@abbrev = left.chop! + cursor + right
|
||||||
|
@col -= 1
|
||||||
|
redraw
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Delete a character at the current cursor position.
|
||||||
|
def delete!
|
||||||
|
if @col < @abbrev.length
|
||||||
|
left, cursor, right = abbrev_segments
|
||||||
|
@abbrev = left + right
|
||||||
|
redraw
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def cursor_left
|
||||||
|
if @col > 0
|
||||||
|
@col -= 1
|
||||||
|
redraw
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def cursor_right
|
||||||
|
if @col < @abbrev.length
|
||||||
|
@col += 1
|
||||||
|
redraw
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def cursor_end
|
||||||
|
if @col < @abbrev.length
|
||||||
|
@col = @abbrev.length
|
||||||
|
redraw
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def cursor_start
|
||||||
|
if @col != 0
|
||||||
|
@col = 0
|
||||||
|
redraw
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def focus
|
||||||
|
unless @has_focus
|
||||||
|
@has_focus = true
|
||||||
|
redraw
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def unfocus
|
||||||
|
if @has_focus
|
||||||
|
@has_focus = false
|
||||||
|
redraw
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def redraw
|
||||||
|
if @has_focus
|
||||||
|
prompt_highlight = 'Comment'
|
||||||
|
normal_highlight = 'None'
|
||||||
|
cursor_highlight = 'Underlined'
|
||||||
|
else
|
||||||
|
prompt_highlight = 'NonText'
|
||||||
|
normal_highlight = 'NonText'
|
||||||
|
cursor_highlight = 'NonText'
|
||||||
|
end
|
||||||
|
left, cursor, right = abbrev_segments
|
||||||
|
components = [prompt_highlight, '>>', 'None', ' ']
|
||||||
|
components += [normal_highlight, left] unless left.empty?
|
||||||
|
components += [cursor_highlight, cursor] unless cursor.empty?
|
||||||
|
components += [normal_highlight, right] unless right.empty?
|
||||||
|
components += [cursor_highlight, ' '] if cursor.empty?
|
||||||
|
set_status *components
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns the @abbrev string divided up into three sections, any of
|
||||||
|
# which may actually be zero width, depending on the location of the
|
||||||
|
# cursor:
|
||||||
|
# - left segment (to left of cursor)
|
||||||
|
# - cursor segment (character at cursor)
|
||||||
|
# - right segment (to right of cursor)
|
||||||
|
def abbrev_segments
|
||||||
|
left = @abbrev[0, @col]
|
||||||
|
cursor = @abbrev[@col, 1]
|
||||||
|
right = @abbrev[(@col + 1)..-1] || ''
|
||||||
|
[left, cursor, right]
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_status(*args)
|
||||||
|
# see ':help :echo' for why forcing a redraw here helps
|
||||||
|
# prevent the status line from getting inadvertantly cleared
|
||||||
|
# after our echo commands
|
||||||
|
::VIM::command 'redraw'
|
||||||
|
while (highlight = args.shift) && (text = args.shift)
|
||||||
|
text = VIM::escape_for_single_quotes text
|
||||||
|
::VIM::command "echohl #{highlight}"
|
||||||
|
::VIM::command "echon '#{text}'"
|
||||||
|
end
|
||||||
|
::VIM::command 'echohl None'
|
||||||
|
end
|
||||||
|
end # class Prompt
|
||||||
|
end # module CommandT
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
// Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
#include <ruby.h>
|
||||||
|
|
||||||
|
// for compatibility with older versions of Ruby which don't declare RSTRING_PTR
|
||||||
|
#ifndef RSTRING_PTR
|
||||||
|
#define RSTRING_PTR(s) (RSTRING(s)->ptr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// for compatibility with older versions of Ruby which don't declare RSTRING_LEN
|
||||||
|
#ifndef RSTRING_LEN
|
||||||
|
#define RSTRING_LEN(s) (RSTRING(s)->len)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// for compatibility with older versions of Ruby which don't declare RARRAY_PTR
|
||||||
|
#ifndef RARRAY_PTR
|
||||||
|
#define RARRAY_PTR(a) (RARRAY(a)->ptr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// for compatibility with older versions of Ruby which don't declare RARRAY_LEN
|
||||||
|
#ifndef RARRAY_LEN
|
||||||
|
#define RARRAY_LEN(a) (RARRAY(a)->len)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// for compatibility with older versions of Ruby which don't declare RFLOAT_VALUE
|
||||||
|
#ifndef RFLOAT_VALUE
|
||||||
|
#define RFLOAT_VALUE(f) (RFLOAT(f)->value)
|
||||||
|
#endif
|
12
vim/vim.symlink/bundle/command-t/ruby/command-t/scanner.rb
Normal file
12
vim/vim.symlink/bundle/command-t/ruby/command-t/scanner.rb
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
class Scanner
|
||||||
|
autoload :BufferScanner, 'command-t/scanner/buffer_scanner'
|
||||||
|
autoload :FileScanner, 'command-t/scanner/file_scanner'
|
||||||
|
autoload :JumpScanner, 'command-t/scanner/jump_scanner'
|
||||||
|
autoload :MRUBufferScanner, 'command-t/scanner/mru_buffer_scanner'
|
||||||
|
autoload :TagScanner, 'command-t/scanner/tag_scanner'
|
||||||
|
end # class Scanner
|
||||||
|
end # module CommandT
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
class Scanner
|
||||||
|
# Returns a list of all open buffers.
|
||||||
|
class BufferScanner < Scanner
|
||||||
|
include PathUtilities
|
||||||
|
|
||||||
|
def paths
|
||||||
|
(0..(::VIM::Buffer.count - 1)).map do |n|
|
||||||
|
buffer = ::VIM::Buffer[n]
|
||||||
|
if buffer.name # beware, may be nil
|
||||||
|
relative_path_under_working_directory buffer.name
|
||||||
|
end
|
||||||
|
end.compact
|
||||||
|
end
|
||||||
|
end # class BufferScanner
|
||||||
|
end # class Scanner
|
||||||
|
end # module CommandT
|
|
@ -0,0 +1,93 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
class Scanner
|
||||||
|
# Reads the current directory recursively for the paths to all regular files.
|
||||||
|
#
|
||||||
|
# This is an abstract superclass; the real work is done by subclasses which
|
||||||
|
# obtain file listings via different strategies (for examples, see the
|
||||||
|
# RubyFileScanner and FindFileScanner subclasses).
|
||||||
|
class FileScanner < Scanner
|
||||||
|
# Errors
|
||||||
|
autoload :FileLimitExceeded, 'command-t/scanner/file_scanner/file_limit_exceeded'
|
||||||
|
|
||||||
|
# Subclasses
|
||||||
|
autoload :FindFileScanner, 'command-t/scanner/file_scanner/find_file_scanner'
|
||||||
|
autoload :GitFileScanner, 'command-t/scanner/file_scanner/git_file_scanner'
|
||||||
|
autoload :RubyFileScanner, 'command-t/scanner/file_scanner/ruby_file_scanner'
|
||||||
|
autoload :WatchmanFileScanner, 'command-t/scanner/file_scanner/watchman_file_scanner'
|
||||||
|
|
||||||
|
attr_accessor :path
|
||||||
|
|
||||||
|
def initialize(path = Dir.pwd, options = {})
|
||||||
|
@paths = {}
|
||||||
|
@paths_keys = []
|
||||||
|
@path = path
|
||||||
|
@max_depth = options[:max_depth] || 15
|
||||||
|
@max_files = options[:max_files] || 30_000
|
||||||
|
@max_caches = options[:max_caches] || 1
|
||||||
|
@scan_dot_directories = options[:scan_dot_directories] || false
|
||||||
|
@wild_ignore = options[:wild_ignore]
|
||||||
|
@base_wild_ignore = wild_ignore
|
||||||
|
end
|
||||||
|
|
||||||
|
def paths
|
||||||
|
@paths[@path] ||= begin
|
||||||
|
ensure_cache_under_limit
|
||||||
|
@prefix_len = @path.chomp('/').length + 1
|
||||||
|
set_wild_ignore { paths! }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def flush
|
||||||
|
@paths = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def wild_ignore
|
||||||
|
VIM::exists?('&wildignore') && ::VIM::evaluate('&wildignore').to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def paths!
|
||||||
|
raise RuntimeError, 'Subclass responsibility'
|
||||||
|
end
|
||||||
|
|
||||||
|
def ensure_cache_under_limit
|
||||||
|
# Ruby 1.8 doesn't have an ordered hash, so use a separate stack to
|
||||||
|
# track and expire the oldest entry in the cache
|
||||||
|
if @max_caches > 0 && @paths_keys.length >= @max_caches
|
||||||
|
@paths.delete @paths_keys.shift
|
||||||
|
end
|
||||||
|
@paths_keys << @path
|
||||||
|
end
|
||||||
|
|
||||||
|
def path_excluded?(path, prefix_len = @prefix_len)
|
||||||
|
if apply_wild_ignore?
|
||||||
|
# first strip common prefix (@path) from path to match VIM's behavior
|
||||||
|
path = path[prefix_len..-1]
|
||||||
|
path = VIM::escape_for_single_quotes path
|
||||||
|
::VIM::evaluate("empty(expand(fnameescape('#{path}')))").to_i == 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_custom_wild_ignore?
|
||||||
|
@wild_ignore && !@wild_ignore.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
# Used to skip expensive calls to `expand()` when there is no applicable
|
||||||
|
# wildignore.
|
||||||
|
def apply_wild_ignore?
|
||||||
|
has_custom_wild_ignore? || @base_wild_ignore
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_wild_ignore(&block)
|
||||||
|
::VIM::command("set wildignore=#{@wild_ignore}") if has_custom_wild_ignore?
|
||||||
|
yield
|
||||||
|
ensure
|
||||||
|
::VIM::command("set wildignore=#{@base_wild_ignore}") if has_custom_wild_ignore?
|
||||||
|
end
|
||||||
|
end # class FileScanner
|
||||||
|
end # class Scanner
|
||||||
|
end # module CommandT
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Copyright 2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
class Scanner
|
||||||
|
class FileScanner
|
||||||
|
class FileLimitExceeded < ::RuntimeError; end
|
||||||
|
end # class FileScanner
|
||||||
|
end # class Scanner
|
||||||
|
end # module Command-T
|
|
@ -0,0 +1,50 @@
|
||||||
|
# Copyright 2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
require 'open3'
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
class Scanner
|
||||||
|
class FileScanner
|
||||||
|
# A FileScanner which shells out to the `find` executable in order to scan.
|
||||||
|
class FindFileScanner < FileScanner
|
||||||
|
include PathUtilities
|
||||||
|
|
||||||
|
def paths!
|
||||||
|
# temporarily set field separator to NUL byte; this setting is
|
||||||
|
# respected by both `readlines` and `chomp!` below, and makes it easier
|
||||||
|
# to parse the output of `find -print0`
|
||||||
|
separator = $/
|
||||||
|
$/ = "\x00"
|
||||||
|
|
||||||
|
unless @scan_dot_directories
|
||||||
|
dot_directory_filter = [
|
||||||
|
'-not', '-path', "#{@path}/.*/*", # top-level dot dir
|
||||||
|
'-and', '-not', '-path', "#{@path}/*/.*/*" # lower-level dot dir
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
paths = []
|
||||||
|
Open3.popen3(*([
|
||||||
|
'find', '-L', # follow symlinks
|
||||||
|
@path, # anchor search here
|
||||||
|
'-maxdepth', @max_depth.to_s, # limit depth of DFS
|
||||||
|
'-type', 'f', # only show regular files (not dirs etc)
|
||||||
|
dot_directory_filter, # possibly skip out dot directories
|
||||||
|
'-print0' # NUL-terminate results
|
||||||
|
].flatten.compact)) do |stdin, stdout, stderr|
|
||||||
|
counter = 1
|
||||||
|
stdout.readlines.each do |line|
|
||||||
|
next if path_excluded?(line.chomp!)
|
||||||
|
paths << line[@prefix_len..-1]
|
||||||
|
break if (counter += 1) > @max_files
|
||||||
|
end
|
||||||
|
end
|
||||||
|
paths
|
||||||
|
ensure
|
||||||
|
$/ = separator
|
||||||
|
end
|
||||||
|
end # class FindFileScanner
|
||||||
|
end # class FileScanner
|
||||||
|
end # class Scanner
|
||||||
|
end # module CommandT
|
|
@ -0,0 +1,34 @@
|
||||||
|
# Copyright 2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
class Scanner
|
||||||
|
class FileScanner
|
||||||
|
# Uses git ls-files to scan for files
|
||||||
|
class GitFileScanner < FindFileScanner
|
||||||
|
def paths!
|
||||||
|
Dir.chdir(@path) do
|
||||||
|
stdin, stdout, stderr = Open3.popen3(*[
|
||||||
|
'git',
|
||||||
|
'ls-files',
|
||||||
|
'--exclude-standard',
|
||||||
|
@path
|
||||||
|
])
|
||||||
|
|
||||||
|
all_files = stdout.readlines.
|
||||||
|
map { |path| path.chomp }.
|
||||||
|
reject { |path| path_excluded?(path, 0) }.
|
||||||
|
take(@max_files).
|
||||||
|
to_a
|
||||||
|
|
||||||
|
# will fall back to find if not a git repository or there's an error
|
||||||
|
stderr.gets ? super : all_files
|
||||||
|
end
|
||||||
|
rescue Errno::ENOENT => e
|
||||||
|
# git executable not present and executable
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end # class GitFileScanner
|
||||||
|
end # class FileScanner
|
||||||
|
end # class Scanner
|
||||||
|
end # module CommandT
|
|
@ -0,0 +1,55 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
class Scanner
|
||||||
|
class FileScanner
|
||||||
|
# Pure Ruby implementation of a file scanner.
|
||||||
|
class RubyFileScanner < FileScanner
|
||||||
|
def paths!
|
||||||
|
accumulator = []
|
||||||
|
@depth = 0
|
||||||
|
@files = 0
|
||||||
|
add_paths_for_directory(@path, accumulator)
|
||||||
|
accumulator
|
||||||
|
rescue FileLimitExceeded
|
||||||
|
accumulator
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def looped_symlink?(path)
|
||||||
|
if File.symlink?(path)
|
||||||
|
target = File.expand_path(File.readlink(path), File.dirname(path))
|
||||||
|
target.include?(@path) || @path.include?(target)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_paths_for_directory(dir, accumulator)
|
||||||
|
Dir.foreach(dir) do |entry|
|
||||||
|
next if ['.', '..'].include?(entry)
|
||||||
|
path = File.join(dir, entry)
|
||||||
|
unless path_excluded?(path)
|
||||||
|
if File.file?(path)
|
||||||
|
@files += 1
|
||||||
|
raise FileLimitExceeded if @files > @max_files
|
||||||
|
accumulator << path[@prefix_len..-1]
|
||||||
|
elsif File.directory?(path)
|
||||||
|
next if @depth >= @max_depth
|
||||||
|
next if (entry.match(/\A\./) && !@scan_dot_directories)
|
||||||
|
next if looped_symlink?(path)
|
||||||
|
@depth += 1
|
||||||
|
add_paths_for_directory(path, accumulator)
|
||||||
|
@depth -= 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue Errno::EACCES
|
||||||
|
# skip over directories for which we don't have access
|
||||||
|
rescue ArgumentError
|
||||||
|
# skip over bad file names
|
||||||
|
end
|
||||||
|
end # class RubyFileScanner
|
||||||
|
end # class FileScanner
|
||||||
|
end # class Scanner
|
||||||
|
end # module CommandT
|
|
@ -0,0 +1,55 @@
|
||||||
|
# Copyright 2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
require 'pathname'
|
||||||
|
require 'socket'
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
class Scanner
|
||||||
|
class FileScanner
|
||||||
|
# A FileScanner which delegates the heavy lifting to Watchman
|
||||||
|
# (https://github.com/facebook/watchman); useful for very large hierarchies.
|
||||||
|
#
|
||||||
|
# Inherits from FindFileScanner so that it can fall back to it in the event
|
||||||
|
# that Watchman isn't available or able to fulfil the request.
|
||||||
|
class WatchmanFileScanner < FindFileScanner
|
||||||
|
# Exception raised when Watchman is unavailable or unable to process the
|
||||||
|
# requested path.
|
||||||
|
class WatchmanUnavailable < RuntimeError; end
|
||||||
|
|
||||||
|
def paths!
|
||||||
|
sockname = Watchman::Utils.load(
|
||||||
|
%x{watchman --output-encoding=bser get-sockname}
|
||||||
|
)['sockname']
|
||||||
|
raise WatchmanUnavailable unless $?.exitstatus.zero?
|
||||||
|
|
||||||
|
UNIXSocket.open(sockname) do |socket|
|
||||||
|
root = Pathname.new(@path).realpath.to_s
|
||||||
|
roots = Watchman::Utils.query(['watch-list'], socket)['roots']
|
||||||
|
if !roots.include?(root)
|
||||||
|
# this path isn't being watched yet; try to set up watch
|
||||||
|
result = Watchman::Utils.query(['watch', root], socket)
|
||||||
|
|
||||||
|
# root_restrict_files setting may prevent Watchman from working
|
||||||
|
raise WatchmanUnavailable if result.has_key?('error')
|
||||||
|
end
|
||||||
|
|
||||||
|
query = ['query', root, {
|
||||||
|
'expression' => ['type', 'f'],
|
||||||
|
'fields' => ['name'],
|
||||||
|
}]
|
||||||
|
paths = Watchman::Utils.query(query, socket)
|
||||||
|
|
||||||
|
# could return error if watch is removed
|
||||||
|
raise WatchmanUnavailable if paths.has_key?('error')
|
||||||
|
|
||||||
|
paths['files']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue Errno::ENOENT, WatchmanUnavailable
|
||||||
|
# watchman executable not present, or unable to fulfil request
|
||||||
|
super
|
||||||
|
end # class WatchmanFileScanner
|
||||||
|
end # class FileScanner
|
||||||
|
end # class Scanner
|
||||||
|
end # module CommandT
|
|
@ -0,0 +1,32 @@
|
||||||
|
# Copyright 2011-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
class Scanner
|
||||||
|
# Returns a list of files in the jumplist.
|
||||||
|
class JumpScanner < Scanner
|
||||||
|
include PathUtilities
|
||||||
|
|
||||||
|
def paths
|
||||||
|
jumps_with_filename = jumps.lines.select do |line|
|
||||||
|
line_contains_filename?(line)
|
||||||
|
end
|
||||||
|
filenames = jumps_with_filename[1..-2].map do |line|
|
||||||
|
relative_path_under_working_directory line.split[3]
|
||||||
|
end
|
||||||
|
|
||||||
|
filenames.sort.uniq
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def line_contains_filename?(line)
|
||||||
|
line.split.count > 3
|
||||||
|
end
|
||||||
|
|
||||||
|
def jumps
|
||||||
|
VIM::capture 'silent jumps'
|
||||||
|
end
|
||||||
|
end # class JumpScanner
|
||||||
|
end # class Scanner
|
||||||
|
end # module CommandT
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Copyright 2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
class Scanner
|
||||||
|
# Returns a list of all open buffers, sorted in MRU order.
|
||||||
|
class MRUBufferScanner < BufferScanner
|
||||||
|
include PathUtilities
|
||||||
|
|
||||||
|
def paths
|
||||||
|
# Collect all buffers that have not been used yet.
|
||||||
|
unused_buffers = (0..(::VIM::Buffer.count - 1)).map do |n|
|
||||||
|
buffer = ::VIM::Buffer[n]
|
||||||
|
buffer if buffer.name && !MRU.used?(buffer)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Combine all most recently used buffers and all unused buffers, and
|
||||||
|
# return all listed buffer paths.
|
||||||
|
(unused_buffers + MRU.stack).map do |buffer|
|
||||||
|
if buffer && buffer.name
|
||||||
|
relative_path_under_working_directory buffer.name
|
||||||
|
end
|
||||||
|
end.compact.reverse
|
||||||
|
end
|
||||||
|
end # class MRUBufferScanner
|
||||||
|
end # class Scanner
|
||||||
|
end # module CommandT
|
|
@ -0,0 +1,33 @@
|
||||||
|
# Copyright 2011-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
class Scanner
|
||||||
|
class TagScanner < Scanner
|
||||||
|
attr_reader :include_filenames
|
||||||
|
|
||||||
|
def initialize(options = {})
|
||||||
|
@include_filenames = options[:include_filenames] || false
|
||||||
|
@cached_tags = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def paths
|
||||||
|
@cached_tags ||= taglist.map do |tag|
|
||||||
|
path = tag['name']
|
||||||
|
path << ":#{tag['filename']}" if @include_filenames
|
||||||
|
path
|
||||||
|
end.uniq.sort
|
||||||
|
end
|
||||||
|
|
||||||
|
def flush
|
||||||
|
@cached_tags = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def taglist
|
||||||
|
::VIM::evaluate 'taglist(".")'
|
||||||
|
end
|
||||||
|
end # class TagScanner
|
||||||
|
end # class Scanner
|
||||||
|
end # module CommandT
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Copyright 2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
module SCMUtilities
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def nearest_ancestor(starting_directory, markers)
|
||||||
|
path = File.expand_path(starting_directory)
|
||||||
|
while !markers.
|
||||||
|
map { |dir| File.join(path, dir) }.
|
||||||
|
map { |dir| File.exist?(dir) }.
|
||||||
|
any?
|
||||||
|
next_path = File.expand_path(File.join(path, '..'))
|
||||||
|
return nil if next_path == path
|
||||||
|
path = next_path
|
||||||
|
end
|
||||||
|
path
|
||||||
|
end
|
||||||
|
end # module SCMUtilities
|
||||||
|
end # module CommandT
|
97
vim/vim.symlink/bundle/command-t/ruby/command-t/settings.rb
Normal file
97
vim/vim.symlink/bundle/command-t/ruby/command-t/settings.rb
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
# Convenience class for saving and restoring global settings.
|
||||||
|
class Settings
|
||||||
|
# Settings which apply globally and so must be manually saved and restored
|
||||||
|
GLOBAL_SETTINGS = %w[
|
||||||
|
equalalways
|
||||||
|
hlsearch
|
||||||
|
insertmode
|
||||||
|
report
|
||||||
|
showcmd
|
||||||
|
scrolloff
|
||||||
|
sidescroll
|
||||||
|
sidescrolloff
|
||||||
|
timeout
|
||||||
|
timeoutlen
|
||||||
|
updatetime
|
||||||
|
]
|
||||||
|
|
||||||
|
# Settings which can be made locally to the Command-T buffer or window
|
||||||
|
LOCAL_SETTINGS = %w[
|
||||||
|
bufhidden
|
||||||
|
buflisted
|
||||||
|
buftype
|
||||||
|
colorcolumn
|
||||||
|
concealcursor
|
||||||
|
conceallevel
|
||||||
|
cursorline
|
||||||
|
foldcolumn
|
||||||
|
foldlevel
|
||||||
|
list
|
||||||
|
modifiable
|
||||||
|
number
|
||||||
|
relativenumber
|
||||||
|
spell
|
||||||
|
swapfile
|
||||||
|
synmaxcol
|
||||||
|
textwidth
|
||||||
|
wrap
|
||||||
|
]
|
||||||
|
|
||||||
|
KNOWN_SETTINGS = GLOBAL_SETTINGS + LOCAL_SETTINGS
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@settings = []
|
||||||
|
end
|
||||||
|
|
||||||
|
def set(setting, value)
|
||||||
|
raise "Unknown setting #{setting}" unless KNOWN_SETTINGS.include?(setting)
|
||||||
|
|
||||||
|
case value
|
||||||
|
when TrueClass, FalseClass
|
||||||
|
@settings.push([setting, VIM::get_bool("&#{setting}")]) if global?(setting)
|
||||||
|
set_bool setting, value
|
||||||
|
when Numeric
|
||||||
|
@settings.push([setting, VIM::get_number("&#{setting}")]) if global?(setting)
|
||||||
|
set_number setting, value
|
||||||
|
when String
|
||||||
|
@settings.push([setting, VIM::get_string("&#{setting}")]) if global?(setting)
|
||||||
|
set_string setting, value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def restore
|
||||||
|
@settings.each do |setting, value|
|
||||||
|
case value
|
||||||
|
when TrueClass, FalseClass
|
||||||
|
set_bool setting, value
|
||||||
|
when Numeric
|
||||||
|
set_number setting, value
|
||||||
|
when String
|
||||||
|
set_string setting, value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def global?(setting)
|
||||||
|
GLOBAL_SETTINGS.include?(setting)
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_bool(setting, value)
|
||||||
|
command = global?(setting) ? 'set' : 'setlocal'
|
||||||
|
setting = value ? setting : "no#{setting}"
|
||||||
|
::VIM::command "#{command} #{setting}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_number(setting, value)
|
||||||
|
command = global?(setting) ? 'set' : 'setlocal'
|
||||||
|
::VIM::command "#{command} #{setting}=#{value}"
|
||||||
|
end
|
||||||
|
alias set_string set_number
|
||||||
|
end # class Settings
|
||||||
|
end # module CommandT
|
31
vim/vim.symlink/bundle/command-t/ruby/command-t/stub.rb
Normal file
31
vim/vim.symlink/bundle/command-t/ruby/command-t/stub.rb
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
class Stub
|
||||||
|
@@patch_level = defined?(RUBY_PATCHLEVEL) ? RUBY_PATCHLEVEL : '[unknown]'
|
||||||
|
@@load_error = ['command-t.vim could not load the C extension',
|
||||||
|
'Please see INSTALLATION and TROUBLE-SHOOTING in the help',
|
||||||
|
"Vim Ruby version: #{RUBY_VERSION}-p#{@@patch_level}",
|
||||||
|
'For more information type: :help command-t']
|
||||||
|
|
||||||
|
[
|
||||||
|
:flush,
|
||||||
|
:show_buffer_finder,
|
||||||
|
:show_file_finder,
|
||||||
|
:show_jump_finder,
|
||||||
|
:show_mru_finder,
|
||||||
|
:show_tag_finder
|
||||||
|
].each do |method|
|
||||||
|
define_method(method) { warn *@@load_error }
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def warn(*msg)
|
||||||
|
::VIM::command 'echohl WarningMsg'
|
||||||
|
msg.each { |m| ::VIM::command "echo '#{m}'" }
|
||||||
|
::VIM::command 'echohl none'
|
||||||
|
end
|
||||||
|
end # class Stub
|
||||||
|
end # module CommandT
|
94
vim/vim.symlink/bundle/command-t/ruby/command-t/util.rb
Normal file
94
vim/vim.symlink/bundle/command-t/ruby/command-t/util.rb
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
# Copyright 2013-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
require 'rbconfig'
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
module Util
|
||||||
|
class << self
|
||||||
|
def processor_count
|
||||||
|
@processor_count ||= begin
|
||||||
|
count = processor_count!
|
||||||
|
count = 1 if count < 1 # sanity check
|
||||||
|
count = 32 if count > 32 # sanity check
|
||||||
|
count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# This method derived from:
|
||||||
|
#
|
||||||
|
# https://github.com/grosser/parallel/blob/d11e4a3c8c1a/lib/parallel.rb
|
||||||
|
#
|
||||||
|
# Number of processors seen by the OS and used for process scheduling.
|
||||||
|
#
|
||||||
|
# * AIX: /usr/sbin/pmcycles (AIX 5+), /usr/sbin/lsdev
|
||||||
|
# * BSD: /sbin/sysctl
|
||||||
|
# * Cygwin: /proc/cpuinfo
|
||||||
|
# * Darwin: /usr/bin/hwprefs, /usr/sbin/sysctl
|
||||||
|
# * HP-UX: /usr/sbin/ioscan
|
||||||
|
# * IRIX: /usr/sbin/sysconf
|
||||||
|
# * Linux: /proc/cpuinfo
|
||||||
|
# * Minix 3+: /proc/cpuinfo
|
||||||
|
# * Solaris: /usr/sbin/psrinfo
|
||||||
|
# * Tru64 UNIX: /usr/sbin/psrinfo
|
||||||
|
# * UnixWare: /usr/sbin/psrinfo
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 Michael Grosser <michael@grosser.it>
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
# a copy of this software and associated documentation files (the
|
||||||
|
# "Software"), to deal in the Software without restriction, including
|
||||||
|
# without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
# permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
# the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be
|
||||||
|
# included in all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
#
|
||||||
|
def processor_count!
|
||||||
|
os_name = RbConfig::CONFIG['target_os']
|
||||||
|
if os_name =~ /mingw|mswin/
|
||||||
|
require 'win32ole'
|
||||||
|
result = WIN32OLE.connect('winmgmts://').ExecQuery(
|
||||||
|
'select NumberOfLogicalProcessors from Win32_Processor')
|
||||||
|
result.to_enum.collect(&:NumberOfLogicalProcessors).reduce(:+)
|
||||||
|
elsif File.readable?('/proc/cpuinfo')
|
||||||
|
IO.read('/proc/cpuinfo').scan(/^processor/).size
|
||||||
|
elsif File.executable?('/usr/bin/hwprefs')
|
||||||
|
IO.popen(%w[/usr/bin/hwprefs thread_count]).read.to_i
|
||||||
|
elsif File.executable?('/usr/sbin/psrinfo')
|
||||||
|
IO.popen('/usr/sbin/psrinfo').read.scan(/^.*on-*line/).size
|
||||||
|
elsif File.executable?('/usr/sbin/ioscan')
|
||||||
|
IO.popen(%w[/usr/sbin/ioscan -kC processor]) do |out|
|
||||||
|
out.read.scan(/^.*processor/).size
|
||||||
|
end
|
||||||
|
elsif File.executable?('/usr/sbin/pmcycles')
|
||||||
|
IO.popen(%w[/usr/sbin/pmcycles -m]).read.count("\n")
|
||||||
|
elsif File.executable?('/usr/sbin/lsdev')
|
||||||
|
IO.popen(%w[/usr/sbin/lsdev -Cc processor -S 1]).read.count("\n")
|
||||||
|
elsif File.executable?('/usr/sbin/sysconf') && os_name =~ /irix/i
|
||||||
|
IO.popen(%w[/usr/sbin/sysconf NPROC_ONLN]).read.to_i
|
||||||
|
elsif File.executable?('/usr/sbin/sysctl')
|
||||||
|
IO.popen(%w[/usr/sbin/sysctl -n hw.ncpu]).read.to_i
|
||||||
|
elsif File.executable?('/sbin/sysctl')
|
||||||
|
IO.popen(%w[/sbin/sysctl -n hw.ncpu]).read.to_i
|
||||||
|
else # unknown platform
|
||||||
|
1
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end # module Util
|
||||||
|
end # module CommandT
|
71
vim/vim.symlink/bundle/command-t/ruby/command-t/vim.rb
Normal file
71
vim/vim.symlink/bundle/command-t/ruby/command-t/vim.rb
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
module VIM
|
||||||
|
autoload :Screen, 'command-t/vim/screen'
|
||||||
|
autoload :Window, 'command-t/vim/window'
|
||||||
|
|
||||||
|
class << self
|
||||||
|
# Check for the existence of a feature such as "conceal" or "syntax".
|
||||||
|
def has?(feature)
|
||||||
|
::VIM::evaluate(%{has("#{feature}")}).to_i != 0
|
||||||
|
end
|
||||||
|
|
||||||
|
# Check for the presence of a setting such as:
|
||||||
|
#
|
||||||
|
# - g:CommandTSmartCase (plug-in setting)
|
||||||
|
# - &wildignore (Vim setting)
|
||||||
|
# - +cursorcolumn (Vim setting, that works)
|
||||||
|
#
|
||||||
|
def exists?(str)
|
||||||
|
::VIM::evaluate(%{exists("#{str}")}).to_i != 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_number(name)
|
||||||
|
exists?(name) ? ::VIM::evaluate("#{name}").to_i : nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_bool(name)
|
||||||
|
exists?(name) ? ::VIM::evaluate("#{name}").to_i != 0 : nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_string(name)
|
||||||
|
exists?(name) ? ::VIM::evaluate("#{name}").to_s : nil
|
||||||
|
end
|
||||||
|
|
||||||
|
# expect a string or a list of strings
|
||||||
|
def get_list_or_string(name)
|
||||||
|
return nil unless exists?(name)
|
||||||
|
list_or_string = ::VIM::evaluate("#{name}")
|
||||||
|
if list_or_string.kind_of?(Array)
|
||||||
|
list_or_string.map { |item| item.to_s }
|
||||||
|
else
|
||||||
|
list_or_string.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def pwd
|
||||||
|
::VIM::evaluate 'getcwd()'
|
||||||
|
end
|
||||||
|
|
||||||
|
def current_file_dir
|
||||||
|
::VIM::evaluate 'expand("%:p:h")'
|
||||||
|
end
|
||||||
|
|
||||||
|
# Execute cmd, capturing the output into a variable and returning it.
|
||||||
|
def capture(cmd)
|
||||||
|
::VIM::command 'silent redir => g:command_t_captured_output'
|
||||||
|
::VIM::command cmd
|
||||||
|
::VIM::command 'silent redir END'
|
||||||
|
::VIM::evaluate 'g:command_t_captured_output'
|
||||||
|
end
|
||||||
|
|
||||||
|
# Escape a string for safe inclusion in a Vim single-quoted string
|
||||||
|
# (single quotes escaped by doubling, everything else is literal)
|
||||||
|
def escape_for_single_quotes(str)
|
||||||
|
str.gsub "'", "''"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end # module VIM
|
||||||
|
end # module CommandT
|
|
@ -0,0 +1,14 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
module VIM
|
||||||
|
module Screen
|
||||||
|
class << self
|
||||||
|
def lines
|
||||||
|
::VIM::evaluate('&lines').to_i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end # module Screen
|
||||||
|
end # module VIM
|
||||||
|
end # module CommandT
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
module CommandT
|
||||||
|
module VIM
|
||||||
|
module Window
|
||||||
|
class << self
|
||||||
|
def select(window)
|
||||||
|
return true if $curwin == window
|
||||||
|
initial = $curwin
|
||||||
|
while true do
|
||||||
|
::VIM::command 'wincmd w' # cycle through windows
|
||||||
|
return true if $curwin == window # have selected desired window
|
||||||
|
return false if $curwin == initial # have already looped through all
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end # module Window
|
||||||
|
end # module VIM
|
||||||
|
end # module CommandT
|
660
vim/vim.symlink/bundle/command-t/ruby/command-t/watchman.c
Normal file
660
vim/vim.symlink/bundle/command-t/ruby/command-t/watchman.c
Normal file
|
@ -0,0 +1,660 @@
|
||||||
|
// Copyright 2014 Greg Hurrell. All rights reserved.
|
||||||
|
// Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
#include "watchman.h"
|
||||||
|
|
||||||
|
#ifdef WATCHMAN_BUILD
|
||||||
|
|
||||||
|
#if defined(HAVE_RUBY_ST_H)
|
||||||
|
#include <ruby/st.h>
|
||||||
|
#elif defined(HAVE_ST_H)
|
||||||
|
#include <st.h>
|
||||||
|
#else
|
||||||
|
#error no st.h header found
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h> /* for uint8_t */
|
||||||
|
#include <fcntl.h> /* for fcntl() */
|
||||||
|
#include <sys/errno.h> /* for errno */
|
||||||
|
#include <sys/socket.h> /* for recv(), MSG_PEEK */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t *data; // payload
|
||||||
|
size_t cap; // total capacity
|
||||||
|
size_t len; // current length
|
||||||
|
} watchman_t;
|
||||||
|
|
||||||
|
// Forward declarations:
|
||||||
|
VALUE watchman_load(char **ptr, char *end);
|
||||||
|
void watchman_dump(watchman_t *w, VALUE serializable);
|
||||||
|
|
||||||
|
#define WATCHMAN_DEFAULT_STORAGE 4096
|
||||||
|
|
||||||
|
#define WATCHMAN_BINARY_MARKER "\x00\x01"
|
||||||
|
#define WATCHMAN_ARRAY_MARKER 0x00
|
||||||
|
#define WATCHMAN_HASH_MARKER 0x01
|
||||||
|
#define WATCHMAN_STRING_MARKER 0x02
|
||||||
|
#define WATCHMAN_INT8_MARKER 0x03
|
||||||
|
#define WATCHMAN_INT16_MARKER 0x04
|
||||||
|
#define WATCHMAN_INT32_MARKER 0x05
|
||||||
|
#define WATCHMAN_INT64_MARKER 0x06
|
||||||
|
#define WATCHMAN_FLOAT_MARKER 0x07
|
||||||
|
#define WATCHMAN_TRUE 0x08
|
||||||
|
#define WATCHMAN_FALSE 0x09
|
||||||
|
#define WATCHMAN_NIL 0x0a
|
||||||
|
#define WATCHMAN_TEMPLATE_MARKER 0x0b
|
||||||
|
#define WATCHMAN_SKIP_MARKER 0x0c
|
||||||
|
|
||||||
|
#define WATCHMAN_HEADER \
|
||||||
|
WATCHMAN_BINARY_MARKER \
|
||||||
|
"\x06" \
|
||||||
|
"\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||||
|
|
||||||
|
static const char watchman_array_marker = WATCHMAN_ARRAY_MARKER;
|
||||||
|
static const char watchman_hash_marker = WATCHMAN_HASH_MARKER;
|
||||||
|
static const char watchman_string_marker = WATCHMAN_STRING_MARKER;
|
||||||
|
static const char watchman_true = WATCHMAN_TRUE;
|
||||||
|
static const char watchman_false = WATCHMAN_FALSE;
|
||||||
|
static const char watchman_nil = WATCHMAN_NIL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends `len` bytes, starting at `data`, to the watchman_t struct `w`
|
||||||
|
*
|
||||||
|
* Will attempt to reallocate the underlying storage if it is not sufficient.
|
||||||
|
*/
|
||||||
|
void watchman_append(watchman_t *w, const char *data, size_t len) {
|
||||||
|
if (w->len + len > w->cap) {
|
||||||
|
w->cap += w->len + WATCHMAN_DEFAULT_STORAGE;
|
||||||
|
REALLOC_N(w->data, uint8_t, w->cap);
|
||||||
|
}
|
||||||
|
memcpy(w->data + w->len, data, len);
|
||||||
|
w->len += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate a new watchman_t struct
|
||||||
|
*
|
||||||
|
* The struct has a small amount of extra capacity preallocated, and a blank
|
||||||
|
* header that can be filled in later to describe the PDU.
|
||||||
|
*/
|
||||||
|
watchman_t *watchman_init() {
|
||||||
|
watchman_t *w = ALLOC(watchman_t);
|
||||||
|
w->cap = WATCHMAN_DEFAULT_STORAGE;
|
||||||
|
w->len = 0;
|
||||||
|
w->data = ALLOC_N(uint8_t, WATCHMAN_DEFAULT_STORAGE);
|
||||||
|
|
||||||
|
watchman_append(w, WATCHMAN_HEADER, sizeof(WATCHMAN_HEADER) - 1);
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free a watchman_t struct `w` that was previously allocated with
|
||||||
|
* `watchman_init`
|
||||||
|
*/
|
||||||
|
void watchman_free(watchman_t *w) {
|
||||||
|
xfree(w->data);
|
||||||
|
xfree(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes and appends the integer `num` to `w`
|
||||||
|
*/
|
||||||
|
void watchman_dump_int(watchman_t *w, int64_t num) {
|
||||||
|
char encoded[1 + sizeof(int64_t)];
|
||||||
|
|
||||||
|
if (num == (int8_t)num) {
|
||||||
|
encoded[0] = WATCHMAN_INT8_MARKER;
|
||||||
|
encoded[1] = (int8_t)num;
|
||||||
|
watchman_append(w, encoded, 1 + sizeof(int8_t));
|
||||||
|
} else if (num == (int16_t)num) {
|
||||||
|
encoded[0] = WATCHMAN_INT16_MARKER;
|
||||||
|
*(int16_t *)(encoded + 1) = (int16_t)num;
|
||||||
|
watchman_append(w, encoded, 1 + sizeof(int16_t));
|
||||||
|
} else if (num == (int32_t)num) {
|
||||||
|
encoded[0] = WATCHMAN_INT32_MARKER;
|
||||||
|
*(int32_t *)(encoded + 1) = (int32_t)num;
|
||||||
|
watchman_append(w, encoded, 1 + sizeof(int32_t));
|
||||||
|
} else {
|
||||||
|
encoded[0] = WATCHMAN_INT64_MARKER;
|
||||||
|
*(int64_t *)(encoded + 1) = (int64_t)num;
|
||||||
|
watchman_append(w, encoded, 1 + sizeof(int64_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes and appends the string `string` to `w`
|
||||||
|
*/
|
||||||
|
void watchman_dump_string(watchman_t *w, VALUE string) {
|
||||||
|
watchman_append(w, &watchman_string_marker, sizeof(watchman_string_marker));
|
||||||
|
watchman_dump_int(w, RSTRING_LEN(string));
|
||||||
|
watchman_append(w, RSTRING_PTR(string), RSTRING_LEN(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes and appends the double `num` to `w`
|
||||||
|
*/
|
||||||
|
void watchman_dump_double(watchman_t *w, double num) {
|
||||||
|
char encoded[1 + sizeof(double)];
|
||||||
|
encoded[0] = WATCHMAN_FLOAT_MARKER;
|
||||||
|
*(double *)(encoded + 1) = num;
|
||||||
|
watchman_append(w, encoded, sizeof(encoded));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes and appends the array `array` to `w`
|
||||||
|
*/
|
||||||
|
void watchman_dump_array(watchman_t *w, VALUE array) {
|
||||||
|
long i;
|
||||||
|
watchman_append(w, &watchman_array_marker, sizeof(watchman_array_marker));
|
||||||
|
watchman_dump_int(w, RARRAY_LEN(array));
|
||||||
|
for (i = 0; i < RARRAY_LEN(array); i++) {
|
||||||
|
watchman_dump(w, rb_ary_entry(array, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method that encodes and appends a key/value pair (`key`, `value`) from
|
||||||
|
* a hash to the watchman_t struct passed in via `data`
|
||||||
|
*/
|
||||||
|
int watchman_dump_hash_iterator(VALUE key, VALUE value, VALUE data) {
|
||||||
|
watchman_t *w = (watchman_t *)data;
|
||||||
|
watchman_dump_string(w, StringValue(key));
|
||||||
|
watchman_dump(w, value);
|
||||||
|
return ST_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes and appends the hash `hash` to `w`
|
||||||
|
*/
|
||||||
|
void watchman_dump_hash(watchman_t *w, VALUE hash) {
|
||||||
|
watchman_append(w, &watchman_hash_marker, sizeof(watchman_hash_marker));
|
||||||
|
watchman_dump_int(w, RHASH_SIZE(hash));
|
||||||
|
rb_hash_foreach(hash, watchman_dump_hash_iterator, (VALUE)w);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes and appends the serialized Ruby object `serializable` to `w`
|
||||||
|
*
|
||||||
|
* Examples of serializable objects include arrays, hashes, strings, numbers
|
||||||
|
* (integers, floats), booleans, and nil.
|
||||||
|
*/
|
||||||
|
void watchman_dump(watchman_t *w, VALUE serializable) {
|
||||||
|
switch (TYPE(serializable)) {
|
||||||
|
case T_ARRAY:
|
||||||
|
return watchman_dump_array(w, serializable);
|
||||||
|
case T_HASH:
|
||||||
|
return watchman_dump_hash(w, serializable);
|
||||||
|
case T_STRING:
|
||||||
|
return watchman_dump_string(w, serializable);
|
||||||
|
case T_FIXNUM: // up to 63 bits
|
||||||
|
return watchman_dump_int(w, FIX2LONG(serializable));
|
||||||
|
case T_BIGNUM:
|
||||||
|
return watchman_dump_int(w, NUM2LL(serializable));
|
||||||
|
case T_FLOAT:
|
||||||
|
return watchman_dump_double(w, NUM2DBL(serializable));
|
||||||
|
case T_TRUE:
|
||||||
|
return watchman_append(w, &watchman_true, sizeof(watchman_true));
|
||||||
|
case T_FALSE:
|
||||||
|
return watchman_append(w, &watchman_false, sizeof(watchman_false));
|
||||||
|
case T_NIL:
|
||||||
|
return watchman_append(w, &watchman_nil, sizeof(watchman_nil));
|
||||||
|
default:
|
||||||
|
rb_raise(rb_eTypeError, "unsupported type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract and return the int encoded at `ptr`
|
||||||
|
*
|
||||||
|
* Moves `ptr` past the extracted int.
|
||||||
|
*
|
||||||
|
* Will raise an ArgumentError if extracting the int would take us beyond the
|
||||||
|
* end of the buffer indicated by `end`, or if there is no int encoded at `ptr`.
|
||||||
|
*
|
||||||
|
* @returns The extracted int
|
||||||
|
*/
|
||||||
|
int64_t watchman_load_int(char **ptr, char *end) {
|
||||||
|
char *val_ptr = *ptr + sizeof(int8_t);
|
||||||
|
int64_t val = 0;
|
||||||
|
|
||||||
|
if (val_ptr >= end) {
|
||||||
|
rb_raise(rb_eArgError, "insufficient int storage");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (*ptr[0]) {
|
||||||
|
case WATCHMAN_INT8_MARKER:
|
||||||
|
if (val_ptr + sizeof(int8_t) > end) {
|
||||||
|
rb_raise(rb_eArgError, "overrun extracting int8_t");
|
||||||
|
}
|
||||||
|
val = *(int8_t *)val_ptr;
|
||||||
|
*ptr = val_ptr + sizeof(int8_t);
|
||||||
|
break;
|
||||||
|
case WATCHMAN_INT16_MARKER:
|
||||||
|
if (val_ptr + sizeof(int16_t) > end) {
|
||||||
|
rb_raise(rb_eArgError, "overrun extracting int16_t");
|
||||||
|
}
|
||||||
|
val = *(int16_t *)val_ptr;
|
||||||
|
*ptr = val_ptr + sizeof(int16_t);
|
||||||
|
break;
|
||||||
|
case WATCHMAN_INT32_MARKER:
|
||||||
|
if (val_ptr + sizeof(int32_t) > end) {
|
||||||
|
rb_raise(rb_eArgError, "overrun extracting int32_t");
|
||||||
|
}
|
||||||
|
val = *(int32_t *)val_ptr;
|
||||||
|
*ptr = val_ptr + sizeof(int32_t);
|
||||||
|
break;
|
||||||
|
case WATCHMAN_INT64_MARKER:
|
||||||
|
if (val_ptr + sizeof(int64_t) > end) {
|
||||||
|
rb_raise(rb_eArgError, "overrun extracting int64_t");
|
||||||
|
}
|
||||||
|
val = *(int64_t *)val_ptr;
|
||||||
|
*ptr = val_ptr + sizeof(int64_t);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rb_raise(rb_eArgError, "bad integer marker 0x%02x", (unsigned int)*ptr[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and returns a string encoded in the Watchman binary protocol format,
|
||||||
|
* starting at `ptr` and finishing at or before `end`
|
||||||
|
*/
|
||||||
|
VALUE watchman_load_string(char **ptr, char *end) {
|
||||||
|
int64_t len;
|
||||||
|
VALUE string;
|
||||||
|
if (*ptr >= end) {
|
||||||
|
rb_raise(rb_eArgError, "unexpected end of input");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*ptr[0] != WATCHMAN_STRING_MARKER) {
|
||||||
|
rb_raise(rb_eArgError, "not a number");
|
||||||
|
}
|
||||||
|
|
||||||
|
*ptr += sizeof(int8_t);
|
||||||
|
if (*ptr >= end) {
|
||||||
|
rb_raise(rb_eArgError, "invalid string header");
|
||||||
|
}
|
||||||
|
|
||||||
|
len = watchman_load_int(ptr, end);
|
||||||
|
if (len == 0) { // special case for zero-length strings
|
||||||
|
return rb_str_new2("");
|
||||||
|
} else if (*ptr + len > end) {
|
||||||
|
rb_raise(rb_eArgError, "insufficient string storage");
|
||||||
|
}
|
||||||
|
|
||||||
|
string = rb_str_new(*ptr, len);
|
||||||
|
*ptr += len;
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and returns a double encoded in the Watchman binary protocol format,
|
||||||
|
* starting at `ptr` and finishing at or before `end`
|
||||||
|
*/
|
||||||
|
double watchman_load_double(char **ptr, char *end) {
|
||||||
|
double val;
|
||||||
|
*ptr += sizeof(int8_t); // caller has already verified the marker
|
||||||
|
if (*ptr + sizeof(double) > end) {
|
||||||
|
rb_raise(rb_eArgError, "insufficient double storage");
|
||||||
|
}
|
||||||
|
val = *(double *)*ptr;
|
||||||
|
*ptr += sizeof(double);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method which returns length of the array encoded in the Watchman
|
||||||
|
* binary protocol format, starting at `ptr` and finishing at or before `end`
|
||||||
|
*/
|
||||||
|
int64_t watchman_load_array_header(char **ptr, char *end) {
|
||||||
|
if (*ptr >= end) {
|
||||||
|
rb_raise(rb_eArgError, "unexpected end of input");
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify and consume marker
|
||||||
|
if (*ptr[0] != WATCHMAN_ARRAY_MARKER) {
|
||||||
|
rb_raise(rb_eArgError, "not an array");
|
||||||
|
}
|
||||||
|
*ptr += sizeof(int8_t);
|
||||||
|
|
||||||
|
// expect a count
|
||||||
|
if (*ptr + sizeof(int8_t) * 2 > end) {
|
||||||
|
rb_raise(rb_eArgError, "incomplete array header");
|
||||||
|
}
|
||||||
|
return watchman_load_int(ptr, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and returns an array encoded in the Watchman binary protocol format,
|
||||||
|
* starting at `ptr` and finishing at or before `end`
|
||||||
|
*/
|
||||||
|
VALUE watchman_load_array(char **ptr, char *end) {
|
||||||
|
int64_t count, i;
|
||||||
|
VALUE array;
|
||||||
|
|
||||||
|
count = watchman_load_array_header(ptr, end);
|
||||||
|
array = rb_ary_new2(count);
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
rb_ary_push(array, watchman_load(ptr, end));
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and returns a hash encoded in the Watchman binary protocol format,
|
||||||
|
* starting at `ptr` and finishing at or before `end`
|
||||||
|
*/
|
||||||
|
VALUE watchman_load_hash(char **ptr, char *end) {
|
||||||
|
int64_t count, i;
|
||||||
|
VALUE hash, key, value;
|
||||||
|
|
||||||
|
*ptr += sizeof(int8_t); // caller has already verified the marker
|
||||||
|
|
||||||
|
// expect a count
|
||||||
|
if (*ptr + sizeof(int8_t) * 2 > end) {
|
||||||
|
rb_raise(rb_eArgError, "incomplete hash header");
|
||||||
|
}
|
||||||
|
count = watchman_load_int(ptr, end);
|
||||||
|
|
||||||
|
hash = rb_hash_new();
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
key = watchman_load_string(ptr, end);
|
||||||
|
value = watchman_load(ptr, end);
|
||||||
|
rb_hash_aset(hash, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and returns a templated array encoded in the Watchman binary protocol
|
||||||
|
* format, starting at `ptr` and finishing at or before `end`
|
||||||
|
*
|
||||||
|
* Templated arrays are arrays of hashes which have repetitive key information
|
||||||
|
* pulled out into a separate "headers" prefix.
|
||||||
|
*
|
||||||
|
* @see https://github.com/facebook/watchman/blob/master/BSER.markdown
|
||||||
|
*/
|
||||||
|
VALUE watchman_load_template(char **ptr, char *end) {
|
||||||
|
int64_t header_items_count, i, row_count;
|
||||||
|
VALUE array, hash, header, key, value;
|
||||||
|
|
||||||
|
*ptr += sizeof(int8_t); // caller has already verified the marker
|
||||||
|
|
||||||
|
// process template header array
|
||||||
|
header_items_count = watchman_load_array_header(ptr, end);
|
||||||
|
header = rb_ary_new2(header_items_count);
|
||||||
|
for (i = 0; i < header_items_count; i++) {
|
||||||
|
rb_ary_push(header, watchman_load_string(ptr, end));
|
||||||
|
}
|
||||||
|
|
||||||
|
// process row items
|
||||||
|
row_count = watchman_load_int(ptr, end);
|
||||||
|
array = rb_ary_new2(header_items_count);
|
||||||
|
while (row_count--) {
|
||||||
|
hash = rb_hash_new();
|
||||||
|
for (i = 0; i < header_items_count; i++) {
|
||||||
|
if (*ptr >= end) {
|
||||||
|
rb_raise(rb_eArgError, "unexpected end of input");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*ptr[0] == WATCHMAN_SKIP_MARKER) {
|
||||||
|
*ptr += sizeof(uint8_t);
|
||||||
|
} else {
|
||||||
|
value = watchman_load(ptr, end);
|
||||||
|
key = rb_ary_entry(header, i);
|
||||||
|
rb_hash_aset(hash, key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rb_ary_push(array, hash);
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and returns an object encoded in the Watchman binary protocol format,
|
||||||
|
* starting at `ptr` and finishing at or before `end`
|
||||||
|
*/
|
||||||
|
VALUE watchman_load(char **ptr, char *end) {
|
||||||
|
if (*ptr >= end) {
|
||||||
|
rb_raise(rb_eArgError, "unexpected end of input");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (*ptr[0]) {
|
||||||
|
case WATCHMAN_ARRAY_MARKER:
|
||||||
|
return watchman_load_array(ptr, end);
|
||||||
|
case WATCHMAN_HASH_MARKER:
|
||||||
|
return watchman_load_hash(ptr, end);
|
||||||
|
case WATCHMAN_STRING_MARKER:
|
||||||
|
return watchman_load_string(ptr, end);
|
||||||
|
case WATCHMAN_INT8_MARKER:
|
||||||
|
case WATCHMAN_INT16_MARKER:
|
||||||
|
case WATCHMAN_INT32_MARKER:
|
||||||
|
case WATCHMAN_INT64_MARKER:
|
||||||
|
return LL2NUM(watchman_load_int(ptr, end));
|
||||||
|
case WATCHMAN_FLOAT_MARKER:
|
||||||
|
return rb_float_new(watchman_load_double(ptr, end));
|
||||||
|
case WATCHMAN_TRUE:
|
||||||
|
*ptr += 1;
|
||||||
|
return Qtrue;
|
||||||
|
case WATCHMAN_FALSE:
|
||||||
|
*ptr += 1;
|
||||||
|
return Qfalse;
|
||||||
|
case WATCHMAN_NIL:
|
||||||
|
*ptr += 1;
|
||||||
|
return Qnil;
|
||||||
|
case WATCHMAN_TEMPLATE_MARKER:
|
||||||
|
return watchman_load_template(ptr, end);
|
||||||
|
default:
|
||||||
|
rb_raise(rb_eTypeError, "unsupported type");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Qnil; // keep the compiler happy
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CommandT::Watchman::Utils.load(serialized)
|
||||||
|
*
|
||||||
|
* Converts the binary object, `serialized`, from the Watchman binary protocol
|
||||||
|
* format into a normal Ruby object.
|
||||||
|
*/
|
||||||
|
VALUE CommandTWatchmanUtils_load(VALUE self, VALUE serialized) {
|
||||||
|
char *ptr, *end;
|
||||||
|
long len;
|
||||||
|
uint64_t payload_size;
|
||||||
|
VALUE loaded;
|
||||||
|
serialized = StringValue(serialized);
|
||||||
|
len = RSTRING_LEN(serialized);
|
||||||
|
ptr = RSTRING_PTR(serialized);
|
||||||
|
end = ptr + len;
|
||||||
|
|
||||||
|
// expect at least the binary marker and a int8_t length counter
|
||||||
|
if ((size_t)len < sizeof(WATCHMAN_BINARY_MARKER) - 1 + sizeof(int8_t) * 2) {
|
||||||
|
rb_raise(rb_eArgError, "undersized header");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(ptr, WATCHMAN_BINARY_MARKER, sizeof(WATCHMAN_BINARY_MARKER) - 1)) {
|
||||||
|
rb_raise(rb_eArgError, "missing binary marker");
|
||||||
|
}
|
||||||
|
|
||||||
|
// get size marker
|
||||||
|
ptr += sizeof(WATCHMAN_BINARY_MARKER) - 1;
|
||||||
|
payload_size = watchman_load_int(&ptr, end);
|
||||||
|
if (!payload_size) {
|
||||||
|
rb_raise(rb_eArgError, "empty payload");
|
||||||
|
}
|
||||||
|
|
||||||
|
// sanity check length
|
||||||
|
if (ptr + payload_size != end) {
|
||||||
|
rb_raise(
|
||||||
|
rb_eArgError,
|
||||||
|
"payload size mismatch (%lu)",
|
||||||
|
(unsigned long)(end - (ptr + payload_size))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
loaded = watchman_load(&ptr, end);
|
||||||
|
|
||||||
|
// one more sanity check
|
||||||
|
if (ptr != end) {
|
||||||
|
rb_raise(
|
||||||
|
rb_eArgError,
|
||||||
|
"payload termination mismatch (%lu)",
|
||||||
|
(unsigned long)(end - ptr)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CommandT::Watchman::Utils.dump(serializable)
|
||||||
|
*
|
||||||
|
* Converts the Ruby object, `serializable`, into a binary string in the
|
||||||
|
* Watchman binary protocol format.
|
||||||
|
*
|
||||||
|
* Examples of serializable objects include arrays, hashes, strings, numbers
|
||||||
|
* (integers, floats), booleans, and nil.
|
||||||
|
*/
|
||||||
|
VALUE CommandTWatchmanUtils_dump(VALUE self, VALUE serializable) {
|
||||||
|
uint64_t *len;
|
||||||
|
VALUE serialized;
|
||||||
|
watchman_t *w = watchman_init();
|
||||||
|
watchman_dump(w, serializable);
|
||||||
|
|
||||||
|
// update header with final length information
|
||||||
|
len = (uint64_t *)(w->data + sizeof(WATCHMAN_HEADER) - sizeof(uint64_t) - 1);
|
||||||
|
*len = w->len - sizeof(WATCHMAN_HEADER) + 1;
|
||||||
|
|
||||||
|
// prepare final return value
|
||||||
|
serialized = rb_str_buf_new(w->len);
|
||||||
|
rb_str_buf_cat(serialized, (const char*)w->data, w->len);
|
||||||
|
watchman_free(w);
|
||||||
|
return serialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for raising a SystemCallError wrapping a lower-level error code
|
||||||
|
* coming from the `errno` global variable.
|
||||||
|
*/
|
||||||
|
void watchman_raise_system_call_error(int number) {
|
||||||
|
VALUE error = INT2FIX(number);
|
||||||
|
rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
|
||||||
|
}
|
||||||
|
|
||||||
|
// How far we have to look to figure out the size of the PDU header
|
||||||
|
#define WATCHMAN_SNIFF_BUFFER_SIZE sizeof(WATCHMAN_BINARY_MARKER) - 1 + sizeof(int8_t)
|
||||||
|
|
||||||
|
// How far we have to peek, at most, to figure out the size of the PDU itself
|
||||||
|
#define WATCHMAN_PEEK_BUFFER_SIZE \
|
||||||
|
sizeof(WATCHMAN_BINARY_MARKER) - 1 + \
|
||||||
|
sizeof(WATCHMAN_INT64_MARKER) + \
|
||||||
|
sizeof(int64_t)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CommandT::Watchman::Utils.query(query, socket)
|
||||||
|
*
|
||||||
|
* Converts `query`, a Watchman query comprising Ruby objects, into the Watchman
|
||||||
|
* binary protocol format, transmits it over socket, and unserializes and
|
||||||
|
* returns the result.
|
||||||
|
*/
|
||||||
|
VALUE CommandTWatchmanUtils_query(VALUE self, VALUE query, VALUE socket) {
|
||||||
|
char *payload;
|
||||||
|
int fileno, flags;
|
||||||
|
int8_t peek[WATCHMAN_PEEK_BUFFER_SIZE];
|
||||||
|
int8_t sizes[] = { 0, 0, 0, 1, 2, 4, 8 };
|
||||||
|
int8_t sizes_idx;
|
||||||
|
int8_t *pdu_size_ptr;
|
||||||
|
int64_t payload_size;
|
||||||
|
long query_len;
|
||||||
|
ssize_t peek_size, sent, received;
|
||||||
|
void *buffer;
|
||||||
|
VALUE loaded, serialized;
|
||||||
|
fileno = NUM2INT(rb_funcall(socket, rb_intern("fileno"), 0));
|
||||||
|
|
||||||
|
// do blocking I/O to simplify the following logic
|
||||||
|
flags = fcntl(fileno, F_GETFL);
|
||||||
|
if (fcntl(fileno, F_SETFL, flags & ~O_NONBLOCK) == -1) {
|
||||||
|
rb_raise(rb_eRuntimeError, "unable to clear O_NONBLOCK flag");
|
||||||
|
}
|
||||||
|
|
||||||
|
// send the message
|
||||||
|
serialized = CommandTWatchmanUtils_dump(self, query);
|
||||||
|
query_len = RSTRING_LEN(serialized);
|
||||||
|
sent = send(fileno, RSTRING_PTR(serialized), query_len, 0);
|
||||||
|
if (sent == -1) {
|
||||||
|
watchman_raise_system_call_error(errno);
|
||||||
|
} else if (sent != query_len) {
|
||||||
|
rb_raise(rb_eRuntimeError, "expected to send %ld bytes but sent %ld",
|
||||||
|
query_len, sent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sniff to see how large the header is
|
||||||
|
received = recv(fileno, peek, WATCHMAN_SNIFF_BUFFER_SIZE, MSG_PEEK | MSG_WAITALL);
|
||||||
|
if (received == -1) {
|
||||||
|
watchman_raise_system_call_error(errno);
|
||||||
|
} else if (received != WATCHMAN_SNIFF_BUFFER_SIZE) {
|
||||||
|
rb_raise(rb_eRuntimeError, "failed to sniff PDU header");
|
||||||
|
}
|
||||||
|
|
||||||
|
// peek at size of PDU
|
||||||
|
sizes_idx = peek[sizeof(WATCHMAN_BINARY_MARKER) - 1];
|
||||||
|
if (sizes_idx < WATCHMAN_INT8_MARKER || sizes_idx > WATCHMAN_INT64_MARKER) {
|
||||||
|
rb_raise(rb_eRuntimeError, "bad PDU size marker");
|
||||||
|
}
|
||||||
|
peek_size = sizeof(WATCHMAN_BINARY_MARKER) - 1 + sizeof(int8_t) +
|
||||||
|
sizes[sizes_idx];
|
||||||
|
|
||||||
|
received = recv(fileno, peek, peek_size, MSG_PEEK);
|
||||||
|
if (received == -1) {
|
||||||
|
watchman_raise_system_call_error(errno);
|
||||||
|
} else if (received != peek_size) {
|
||||||
|
rb_raise(rb_eRuntimeError, "failed to peek at PDU header");
|
||||||
|
}
|
||||||
|
pdu_size_ptr = peek + sizeof(WATCHMAN_BINARY_MARKER) - sizeof(int8_t);
|
||||||
|
payload_size =
|
||||||
|
peek_size +
|
||||||
|
watchman_load_int((char **)&pdu_size_ptr, (char *)peek + peek_size);
|
||||||
|
|
||||||
|
// actually read the PDU
|
||||||
|
buffer = xmalloc(payload_size);
|
||||||
|
if (!buffer) {
|
||||||
|
rb_raise(
|
||||||
|
rb_eNoMemError,
|
||||||
|
"failed to allocate %lld bytes",
|
||||||
|
(long long int)payload_size
|
||||||
|
);
|
||||||
|
}
|
||||||
|
received = recv(fileno, buffer, payload_size, MSG_WAITALL);
|
||||||
|
if (received == -1) {
|
||||||
|
watchman_raise_system_call_error(errno);
|
||||||
|
} else if (received != payload_size) {
|
||||||
|
rb_raise(rb_eRuntimeError, "failed to load PDU");
|
||||||
|
}
|
||||||
|
payload = (char *)buffer + peek_size;
|
||||||
|
loaded = watchman_load(&payload, payload + payload_size);
|
||||||
|
free(buffer);
|
||||||
|
return loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* don't build Watchman utils; supply stubs only*/
|
||||||
|
|
||||||
|
VALUE CommandTWatchmanUtils_load(VALUE self, VALUE serialized) {
|
||||||
|
rb_raise(rb_eRuntimeError, "unsupported operation");
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE CommandTWatchmanUtils_dump(VALUE self, VALUE serializable) {
|
||||||
|
rb_raise(rb_eRuntimeError, "unsupported operation");
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE CommandTWatchmanUtils_query(VALUE self, VALUE query, VALUE socket) {
|
||||||
|
rb_raise(rb_eRuntimeError, "unsupported operation");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
32
vim/vim.symlink/bundle/command-t/ruby/command-t/watchman.h
Normal file
32
vim/vim.symlink/bundle/command-t/ruby/command-t/watchman.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// Copyright 2014 Greg Hurrell. All rights reserved.
|
||||||
|
// Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
#include <ruby.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @module CommandT::Watchman::Utils
|
||||||
|
*
|
||||||
|
* Methods for working with the Watchman binary protocol
|
||||||
|
*
|
||||||
|
* @see https://github.com/facebook/watchman/blob/master/BSER.markdown
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an object serialized using the Watchman binary protocol[0] into an
|
||||||
|
* unpacked Ruby object
|
||||||
|
*/
|
||||||
|
extern VALUE CommandTWatchmanUtils_load(VALUE self, VALUE serialized);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize a Ruby object into the Watchman binary protocol format
|
||||||
|
*/
|
||||||
|
extern VALUE CommandTWatchmanUtils_dump(VALUE self, VALUE serializable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Issue `query` to the Watchman instance listening on `socket` (a `UNIXSocket`
|
||||||
|
* instance) and return the result
|
||||||
|
*
|
||||||
|
* The query is serialized following the Watchman binary protocol and the
|
||||||
|
* result is converted to native Ruby objects before returning to the caller.
|
||||||
|
*/
|
||||||
|
extern VALUE CommandTWatchmanUtils_query(VALUE self, VALUE query, VALUE socket);
|
|
@ -0,0 +1,88 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe CommandT::Controller do
|
||||||
|
describe 'accept selection' do
|
||||||
|
let(:controller) { CommandT::Controller.new }
|
||||||
|
|
||||||
|
before do
|
||||||
|
check_ruby_1_9_2
|
||||||
|
stub_finder
|
||||||
|
stub_match_window 'path/to/selection'
|
||||||
|
stub_prompt
|
||||||
|
stub_vim '/working/directory'
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_string(name, value)
|
||||||
|
stub(::VIM).evaluate(%{exists("#{name}")}).returns(1)
|
||||||
|
stub(::VIM).evaluate(name).returns(value)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'opens relative paths inside the working directory' do
|
||||||
|
stub(::VIM).evaluate('a:arg').returns('')
|
||||||
|
set_string('g:CommandTTraverseSCM', 'pwd')
|
||||||
|
controller.show_file_finder
|
||||||
|
mock(::VIM).command('silent e path/to/selection')
|
||||||
|
controller.accept_selection
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'opens absolute paths outside the working directory' do
|
||||||
|
stub(::VIM).evaluate('a:arg').returns('../outside')
|
||||||
|
controller.show_file_finder
|
||||||
|
mock(::VIM).command('silent e /working/outside/path/to/selection')
|
||||||
|
controller.accept_selection
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not get confused by common directory prefixes' do
|
||||||
|
stub(::VIM).evaluate('a:arg').returns('../directory-oops')
|
||||||
|
controller.show_file_finder
|
||||||
|
mock(::VIM).command('silent e /working/directory-oops/path/to/selection')
|
||||||
|
controller.accept_selection
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_ruby_1_9_2
|
||||||
|
if RUBY_VERSION =~ /\A1\.9\.2/
|
||||||
|
pending 'broken in Ruby 1.9.2 (see https://gist.github.com/455547)'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def stub_finder(sorted_matches=[])
|
||||||
|
finder = CommandT::Finder::FileFinder.new
|
||||||
|
stub(finder).path = anything
|
||||||
|
stub(finder).sorted_matches_for(anything, anything).returns(sorted_matches)
|
||||||
|
stub(CommandT::Finder::FileFinder).new.returns(finder)
|
||||||
|
end
|
||||||
|
|
||||||
|
def stub_match_window(selection)
|
||||||
|
match_window = Object.new
|
||||||
|
stub(match_window).matches = anything
|
||||||
|
stub(match_window).leave
|
||||||
|
stub(match_window).selection.returns(selection)
|
||||||
|
stub(CommandT::MatchWindow).new.returns(match_window)
|
||||||
|
end
|
||||||
|
|
||||||
|
def stub_prompt(abbrev='')
|
||||||
|
prompt = Object.new
|
||||||
|
stub(prompt).focus
|
||||||
|
stub(prompt).clear!
|
||||||
|
stub(prompt).abbrev.returns(abbrev)
|
||||||
|
stub(CommandT::Prompt).new.returns(prompt)
|
||||||
|
end
|
||||||
|
|
||||||
|
def stub_vim(working_directory)
|
||||||
|
stub($curbuf).number.returns('0')
|
||||||
|
stub(::VIM).command(/noremap/)
|
||||||
|
stub(::VIM).command('silent b 0')
|
||||||
|
stub(::VIM).command(/augroup/)
|
||||||
|
stub(::VIM).command('au!')
|
||||||
|
stub(::VIM).command(/autocmd/)
|
||||||
|
stub(::VIM).evaluate(/exists\(.+\)/).returns('0')
|
||||||
|
stub(::VIM).evaluate('getcwd()').returns(working_directory)
|
||||||
|
stub(::VIM).evaluate('&buflisted').returns('1')
|
||||||
|
stub(::VIM).evaluate('&lines').returns('80')
|
||||||
|
stub(::VIM).evaluate('&term').returns('vt100')
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,55 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe CommandT::Finder::BufferFinder do
|
||||||
|
before do
|
||||||
|
@paths = %w(.git/config .vim/notes .vimrc baz foo/beta)
|
||||||
|
any_instance_of(CommandT::Scanner::BufferScanner, :paths => @paths)
|
||||||
|
@finder = CommandT::Finder::BufferFinder.new
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'sorted_matches_for method' do
|
||||||
|
it 'returns an empty array when no matches' do
|
||||||
|
@finder.sorted_matches_for('kung foo fighting').should == []
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns all files when query string is empty' do
|
||||||
|
@finder.sorted_matches_for('').should == @paths
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns files in alphabetical order when query string is empty' do
|
||||||
|
results = @finder.sorted_matches_for('')
|
||||||
|
results.should == results.sort
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns matching files in score order' do
|
||||||
|
@finder.sorted_matches_for('ba').should == %w(baz foo/beta)
|
||||||
|
@finder.sorted_matches_for('a').should == %w(baz foo/beta)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns matching dot files even when search term does not include a dot' do
|
||||||
|
@finder.sorted_matches_for('i').should include('.vimrc')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns matching files inside dot directories even when search term does not include a dot' do
|
||||||
|
@finder.sorted_matches_for('i').should include('.vim/notes')
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not use the Vim expand() function to consult the 'wildignore' setting" do
|
||||||
|
do_not_allow(::VIM).evaluate
|
||||||
|
@finder.sorted_matches_for('i')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'obeys the :limit option for empty search strings' do
|
||||||
|
@finder.sorted_matches_for('', :limit => 1).
|
||||||
|
should == %w(.git/config)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'obeys the :limit option for non-empty search strings' do
|
||||||
|
@finder.sorted_matches_for('i', :limit => 2).
|
||||||
|
should == %w(.vimrc .vim/notes)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,56 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe CommandT::Finder::FileFinder do
|
||||||
|
before :all do
|
||||||
|
@finder = CommandT::Finder::FileFinder.new File.join(File.dirname(__FILE__), '..',
|
||||||
|
'..', '..', 'fixtures')
|
||||||
|
@all_fixtures = %w(
|
||||||
|
bar/abc
|
||||||
|
bar/xyz
|
||||||
|
baz
|
||||||
|
bing
|
||||||
|
foo/alpha/t1
|
||||||
|
foo/alpha/t2
|
||||||
|
foo/beta
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub(::VIM).evaluate(/expand/) { 0 }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'sorted_matches_for method' do
|
||||||
|
it 'returns an empty array when no matches' do
|
||||||
|
@finder.sorted_matches_for('kung foo fighting').should == []
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns all files when query string is empty' do
|
||||||
|
@finder.sorted_matches_for('').should == @all_fixtures
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns files in alphabetical order when query string is empty' do
|
||||||
|
results = @finder.sorted_matches_for('')
|
||||||
|
results.should == results.sort
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns matching files in score order' do
|
||||||
|
@finder.sorted_matches_for('ba').
|
||||||
|
should == %w(baz bar/abc bar/xyz foo/beta)
|
||||||
|
@finder.sorted_matches_for('a').
|
||||||
|
should == %w(baz bar/abc bar/xyz foo/alpha/t1 foo/alpha/t2 foo/beta)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'obeys the :limit option for empty search strings' do
|
||||||
|
@finder.sorted_matches_for('', :limit => 2).
|
||||||
|
should == %w(bar/abc bar/xyz)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'obeys the :limit option for non-empty search strings' do
|
||||||
|
@finder.sorted_matches_for('a', :limit => 3).
|
||||||
|
should == %w(baz bar/abc bar/xyz)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
218
vim/vim.symlink/bundle/command-t/spec/command-t/matcher_spec.rb
Normal file
218
vim/vim.symlink/bundle/command-t/spec/command-t/matcher_spec.rb
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
require 'ostruct'
|
||||||
|
require 'command-t/ext' # CommandT::Matcher
|
||||||
|
|
||||||
|
describe CommandT::Matcher do
|
||||||
|
def matcher(*paths)
|
||||||
|
scanner = OpenStruct.new(:paths => paths)
|
||||||
|
CommandT::Matcher.new(scanner)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'initialization' do
|
||||||
|
it 'raises an ArgumentError if passed nil' do
|
||||||
|
expect { CommandT::Matcher.new(nil) }.to raise_error(ArgumentError)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#sorted_matches_for' do
|
||||||
|
def ordered_matches(paths, query)
|
||||||
|
matcher(*paths).sorted_matches_for(query)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'raises an ArgumentError if passed nil' do
|
||||||
|
expect { matcher.sorted_matches_for(nil) }.to raise_error(ArgumentError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns empty array when source array empty' do
|
||||||
|
matcher.sorted_matches_for('foo').should == []
|
||||||
|
matcher.sorted_matches_for('').should == []
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns empty array when no matches' do
|
||||||
|
matcher = matcher(*%w[foo/bar foo/baz bing])
|
||||||
|
matcher.sorted_matches_for('xyz').should == []
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns matching paths' do
|
||||||
|
matcher = matcher(*%w[foo/bar foo/baz bing])
|
||||||
|
matches = matcher.sorted_matches_for('z')
|
||||||
|
matches.map { |m| m.to_s }.should == ['foo/baz']
|
||||||
|
matches = matcher.sorted_matches_for('bg')
|
||||||
|
matches.map { |m| m.to_s }.should == ['bing']
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'performs case-insensitive matching' do
|
||||||
|
matches = matcher('Foo').sorted_matches_for('f')
|
||||||
|
matches.map { |m| m.to_s }.should == ['Foo']
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'considers the empty string to match everything' do
|
||||||
|
matches = matcher('foo').sorted_matches_for('')
|
||||||
|
matches.map { |m| m.to_s }.should == ['foo']
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not consider mere substrings of the query string to be a match' do
|
||||||
|
matcher('foo').sorted_matches_for('foo...').should == []
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'prioritizes shorter paths over longer ones' do
|
||||||
|
ordered_matches(%w[
|
||||||
|
articles_controller_spec.rb
|
||||||
|
article.rb
|
||||||
|
], 'art').should == %w[
|
||||||
|
article.rb
|
||||||
|
articles_controller_spec.rb
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'prioritizes matches after "/"' do
|
||||||
|
ordered_matches(%w[fooobar foo/bar], 'b').should == %w[foo/bar fooobar]
|
||||||
|
|
||||||
|
# note that / beats _
|
||||||
|
ordered_matches(%w[foo_bar foo/bar], 'b').should == %w[foo/bar foo_bar]
|
||||||
|
|
||||||
|
# / also beats -
|
||||||
|
ordered_matches(%w[foo-bar foo/bar], 'b').should == %w[foo/bar foo-bar]
|
||||||
|
|
||||||
|
# and numbers
|
||||||
|
ordered_matches(%w[foo9bar foo/bar], 'b').should == %w[foo/bar foo9bar]
|
||||||
|
|
||||||
|
# and periods
|
||||||
|
ordered_matches(%w[foo.bar foo/bar], 'b').should == %w[foo/bar foo.bar]
|
||||||
|
|
||||||
|
# and spaces
|
||||||
|
ordered_matches(['foo bar', 'foo/bar'], 'b').should == ['foo/bar', 'foo bar']
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'prioritizes matches after "-"' do
|
||||||
|
ordered_matches(%w[fooobar foo-bar], 'b').should == %w[foo-bar fooobar]
|
||||||
|
|
||||||
|
# - also beats .
|
||||||
|
ordered_matches(%w[foo.bar foo-bar], 'b').should == %w[foo-bar foo.bar]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'prioritizes matches after "_"' do
|
||||||
|
ordered_matches(%w[fooobar foo_bar], 'b').should == %w[foo_bar fooobar]
|
||||||
|
|
||||||
|
# _ also beats .
|
||||||
|
ordered_matches(%w[foo.bar foo_bar], 'b').should == %w[foo_bar foo.bar]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'prioritizes matches after " "' do
|
||||||
|
ordered_matches(['fooobar', 'foo bar'], 'b').should == ['foo bar', 'fooobar']
|
||||||
|
|
||||||
|
# " " also beats .
|
||||||
|
ordered_matches(['foo.bar', 'foo bar'], 'b').should == ['foo bar', 'foo.bar']
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'prioritizes matches after numbers' do
|
||||||
|
ordered_matches(%w[fooobar foo9bar], 'b').should == %w[foo9bar fooobar]
|
||||||
|
|
||||||
|
# numbers also beat .
|
||||||
|
ordered_matches(%w[foo.bar foo9bar], 'b').should == %w[foo9bar foo.bar]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'prioritizes matches after periods' do
|
||||||
|
ordered_matches(%w[fooobar foo.bar], 'b').should == %w[foo.bar fooobar]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'prioritizes matching capitals following lowercase' do
|
||||||
|
ordered_matches(%w[foobar fooBar], 'b').should == %w[fooBar foobar]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'prioritizes matches earlier in the string' do
|
||||||
|
ordered_matches(%w[******b* **b*****], 'b').should == %w[**b***** ******b*]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'prioritizes matches closer to previous matches' do
|
||||||
|
ordered_matches(%w[**b***c* **bc****], 'bc').should == %w[**bc**** **b***c*]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'scores alternative matches of same path differently' do
|
||||||
|
# ie:
|
||||||
|
# app/controllers/articles_controller.rb
|
||||||
|
ordered_matches(%w[
|
||||||
|
a**/****r******/**t*c***_*on*******.**
|
||||||
|
***/***********/art*****_con*******.**
|
||||||
|
], 'artcon').should == %w[
|
||||||
|
***/***********/art*****_con*******.**
|
||||||
|
a**/****r******/**t*c***_*on*******.**
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'provides intuitive results for "artcon" and "articles_controller"' do
|
||||||
|
ordered_matches(%w[
|
||||||
|
app/controllers/heartbeat_controller.rb
|
||||||
|
app/controllers/articles_controller.rb
|
||||||
|
], 'artcon').should == %w[
|
||||||
|
app/controllers/articles_controller.rb
|
||||||
|
app/controllers/heartbeat_controller.rb
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'provides intuitive results for "aca" and "a/c/articles_controller"' do
|
||||||
|
ordered_matches(%w[
|
||||||
|
app/controllers/heartbeat_controller.rb
|
||||||
|
app/controllers/articles_controller.rb
|
||||||
|
], 'aca').should == %w[
|
||||||
|
app/controllers/articles_controller.rb
|
||||||
|
app/controllers/heartbeat_controller.rb
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'provides intuitive results for "d" and "doc/command-t.txt"' do
|
||||||
|
ordered_matches(%w[
|
||||||
|
TODO
|
||||||
|
doc/command-t.txt
|
||||||
|
], 'd').should == %w[
|
||||||
|
doc/command-t.txt
|
||||||
|
TODO
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'provides intuitive results for "do" and "doc/command-t.txt"' do
|
||||||
|
ordered_matches(%w[
|
||||||
|
TODO
|
||||||
|
doc/command-t.txt
|
||||||
|
], 'do').should == %w[
|
||||||
|
doc/command-t.txt
|
||||||
|
TODO
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "doesn't incorrectly accept repeats of the last-matched character" do
|
||||||
|
# https://github.com/wincent/Command-T/issues/82
|
||||||
|
matcher = matcher(*%w[ash/system/user/config.h])
|
||||||
|
matcher.sorted_matches_for('usercc').should == []
|
||||||
|
|
||||||
|
# simpler test case
|
||||||
|
matcher = matcher(*%w[foobar])
|
||||||
|
matcher.sorted_matches_for('fooooo').should == []
|
||||||
|
|
||||||
|
# minimal repro
|
||||||
|
matcher = matcher(*%w[ab])
|
||||||
|
matcher.sorted_matches_for('aa').should == []
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'ignores dotfiles by default' do
|
||||||
|
matcher = matcher(*%w[.foo .bar])
|
||||||
|
matcher.sorted_matches_for('foo').should == []
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'shows dotfiles if the query starts with a dot' do
|
||||||
|
matcher = matcher(*%w[.foo .bar])
|
||||||
|
matcher.sorted_matches_for('.fo').should == %w[.foo]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "doesn't show dotfiles if the query contains a non-leading dot" do
|
||||||
|
matcher = matcher(*%w[.foo.txt .bar.txt])
|
||||||
|
matcher.sorted_matches_for('f.t').should == []
|
||||||
|
|
||||||
|
# counter-example
|
||||||
|
matcher.sorted_matches_for('.f.t').should == %w[.foo.txt]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
require 'ostruct'
|
||||||
|
|
||||||
|
describe CommandT::Scanner::BufferScanner do
|
||||||
|
def buffer(name)
|
||||||
|
b = OpenStruct.new
|
||||||
|
b.name = name
|
||||||
|
b
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
@paths = %w(bar/abc bar/xyz baz bing foo/alpha/t1 foo/alpha/t2 foo/beta)
|
||||||
|
@scanner = CommandT::Scanner::BufferScanner.new
|
||||||
|
stub(@scanner).relative_path_under_working_directory(is_a(String)) { |arg| arg }
|
||||||
|
stub(::VIM::Buffer).count { 7 }
|
||||||
|
(0..6).each do |n|
|
||||||
|
stub(::VIM::Buffer)[n].returns(buffer @paths[n])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'paths method' do
|
||||||
|
it 'returns a list of regular files' do
|
||||||
|
@scanner.paths.should =~ @paths
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,65 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe CommandT::Scanner::FileScanner::RubyFileScanner do
|
||||||
|
before do
|
||||||
|
@dir = File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'fixtures')
|
||||||
|
@all_fixtures = %w(
|
||||||
|
bar/abc bar/xyz baz bing foo/alpha/t1 foo/alpha/t2 foo/beta
|
||||||
|
)
|
||||||
|
@scanner = CommandT::Scanner::FileScanner::RubyFileScanner.new(@dir)
|
||||||
|
|
||||||
|
stub(::VIM).evaluate(/exists/) { 1 }
|
||||||
|
stub(::VIM).evaluate(/expand\(.+\)/) { '0' }
|
||||||
|
stub(::VIM).evaluate(/wildignore/) { '' }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'paths method' do
|
||||||
|
it 'returns a list of regular files' do
|
||||||
|
@scanner.paths.should =~ @all_fixtures
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'path= method' do
|
||||||
|
it 'allows repeated applications of scanner at different paths' do
|
||||||
|
@scanner.paths.should =~ @all_fixtures
|
||||||
|
|
||||||
|
# drill down 1 level
|
||||||
|
@scanner.path = File.join(@dir, 'foo')
|
||||||
|
@scanner.paths.should =~ %w(alpha/t1 alpha/t2 beta)
|
||||||
|
|
||||||
|
# and another
|
||||||
|
@scanner.path = File.join(@dir, 'foo', 'alpha')
|
||||||
|
@scanner.paths.should =~ %w(t1 t2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "'wildignore' exclusion" do
|
||||||
|
context "when there is a 'wildignore' setting in effect" do
|
||||||
|
it "calls on VIM's expand() function for pattern filtering" do
|
||||||
|
stub(::VIM).command(/set wildignore/)
|
||||||
|
scanner =
|
||||||
|
CommandT::Scanner::FileScanner::RubyFileScanner.new @dir, :wild_ignore => '*.o'
|
||||||
|
mock(::VIM).evaluate(/expand\(.+\)/).times(10)
|
||||||
|
scanner.paths
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when there is no 'wildignore' setting in effect" do
|
||||||
|
it "does not call VIM's expand() function" do
|
||||||
|
scanner = CommandT::Scanner::FileScanner::RubyFileScanner.new @dir
|
||||||
|
mock(::VIM).evaluate(/expand\(.+\)/).never
|
||||||
|
scanner.paths
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ':max_depth option' do
|
||||||
|
it 'does not descend below "max_depth" levels' do
|
||||||
|
@scanner = CommandT::Scanner::FileScanner::RubyFileScanner.new @dir, :max_depth => 1
|
||||||
|
@scanner.paths.should =~ %w(bar/abc bar/xyz baz bing foo/beta)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe CommandT::Scanner::FileScanner do
|
||||||
|
before do
|
||||||
|
dir = File.join(File.dirname(__FILE__), '..', '..', '..', 'fixtures')
|
||||||
|
@scanner = CommandT::Scanner::FileScanner.new(dir)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'flush method' do
|
||||||
|
it 'forces a rescan on next call to paths method' do
|
||||||
|
expect { @scanner.flush }.
|
||||||
|
to change { @scanner.instance_variable_get('@paths').object_id }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
14
vim/vim.symlink/bundle/command-t/spec/command-t/vim_spec.rb
Normal file
14
vim/vim.symlink/bundle/command-t/spec/command-t/vim_spec.rb
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# Copyright 2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe CommandT::VIM do
|
||||||
|
describe '.escape_for_single_quotes' do
|
||||||
|
it 'turns doubles all single quotes' do
|
||||||
|
input = %{it's ''something''}
|
||||||
|
expected = %{it''s ''''something''''}
|
||||||
|
expect(CommandT::VIM.escape_for_single_quotes(input)).to eq(expected)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,416 @@
|
||||||
|
# Copyright 2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
require 'command-t/ext' # for CommandT::Watchman::Utils
|
||||||
|
|
||||||
|
describe CommandT::Watchman::Utils do
|
||||||
|
def binary(str)
|
||||||
|
if str.respond_to?(:force_encoding) # Ruby >= 1.9
|
||||||
|
str.force_encoding('ASCII-8BIT')
|
||||||
|
else
|
||||||
|
str
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def little_endian?
|
||||||
|
byte = [0xff00].pack('s')[0]
|
||||||
|
if byte.is_a?(Fixnum) # ie. Ruby 1.8
|
||||||
|
byte.zero?
|
||||||
|
elsif byte.is_a?(String) # ie. Ruby >= 1.9
|
||||||
|
byte == "\x00"
|
||||||
|
else
|
||||||
|
raise 'unable to determine endianness'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def roundtrip(value)
|
||||||
|
described_class.load(described_class.dump(value))
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'roundtrips arrays' do
|
||||||
|
value = [1, 2, ['three', false]]
|
||||||
|
expect(roundtrip(value)).to eq(value)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'roundtrips hashes' do
|
||||||
|
value = {
|
||||||
|
'foo' => 1,
|
||||||
|
'bar' => {
|
||||||
|
'baz' => 'bing',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect(roundtrip(value)).to eq(value)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'roundtrips strings' do
|
||||||
|
expect(roundtrip('')).to eq('')
|
||||||
|
expect(roundtrip('/foo/bar/baz')).to eq('/foo/bar/baz')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'roundtrips uint8_t integers' do
|
||||||
|
expect(roundtrip(0)).to eq(0)
|
||||||
|
expect(roundtrip(1)).to eq(1)
|
||||||
|
expect(roundtrip(0xff)).to eq(0xff)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'roundtrips uint16_t integers' do
|
||||||
|
expect(roundtrip(0x1234)).to eq(0x1234)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'roundtrips uint32_t integers' do
|
||||||
|
expect(roundtrip(0x12345678)).to eq(0x12345678)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'roundtrips uint64_t integers' do
|
||||||
|
expect(roundtrip(0x12345678abcdef00)).to eq(0x12345678abcdef00)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'roundtrips floats' do
|
||||||
|
expect(roundtrip(1234.5678)).to eq(1234.5678)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'roundtrips `true` booleans' do
|
||||||
|
expect(roundtrip(true)).to be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'roundtrips `false` booleans' do
|
||||||
|
expect(roundtrip(false)).to be_false
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'roundtrips nil' do
|
||||||
|
expect(roundtrip(nil)).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.load' do
|
||||||
|
it 'rejects undersized input' do
|
||||||
|
expect { described_class.load('') }.
|
||||||
|
to raise_error(ArgumentError, /undersized/i)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects input without a binary marker' do
|
||||||
|
expect { described_class.load('gibberish') }.
|
||||||
|
to raise_error(ArgumentError, /missing/i)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects a missing payload header' do
|
||||||
|
# binary protocol marker, but nothing else
|
||||||
|
input = binary("\x00\x01")
|
||||||
|
expect { described_class.load(input) }.
|
||||||
|
to raise_error(ArgumentError, /undersized/i)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects empty payloads' do
|
||||||
|
# uint8_t size marker of zero
|
||||||
|
input = binary("\x00\x01\x03\x00")
|
||||||
|
expect { described_class.load(input) }.
|
||||||
|
to raise_error(ArgumentError, /empty/i)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects unrecognized payload markers' do
|
||||||
|
# 0x10 is not a valid integer marker
|
||||||
|
input = binary("\x00\x01\x10\x00")
|
||||||
|
expect { described_class.load(input) }.
|
||||||
|
to raise_error(ArgumentError, /bad integer/i)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects undersized payload markers' do
|
||||||
|
# int16_t marker, but only storage for int8_t
|
||||||
|
input = binary("\x00\x01\x04\x00")
|
||||||
|
expect { described_class.load(input) }.
|
||||||
|
to raise_error(ArgumentError, /overrun\b.+\bint16_t/i)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'loads array values' do
|
||||||
|
input = binary(
|
||||||
|
"\x00\x01\x03\x16\x00\x03\x05\x03\x01\x02\x03" \
|
||||||
|
"\x06foobar\x08\x09\x00\x03\x02\x03\x0a\x0a"
|
||||||
|
)
|
||||||
|
expect(described_class.load(input)).
|
||||||
|
to eq([1, 'foobar', true, false, [10, nil]])
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'handles empty arrays' do
|
||||||
|
input = binary("\x00\x01\x03\x03\x00\x03\x00")
|
||||||
|
expect(described_class.load(input)).to eq([])
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects arrays with incomplete headers' do
|
||||||
|
input = binary("\x00\x01\x03\x02\x00\x03")
|
||||||
|
expect { described_class.load(input) }.
|
||||||
|
to raise_error(ArgumentError, /incomplete array header/i)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects arrays with incomplete entries' do
|
||||||
|
input = binary("\x00\x01\x03\x05\x00\x03\x10\x0a\x0a")
|
||||||
|
expect { described_class.load(input) }.
|
||||||
|
to raise_error(ArgumentError, /unexpected end/i)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'loads hash values' do
|
||||||
|
input = binary(
|
||||||
|
"\x00\x01\x03\x1a\x01\x03\x02\x02\x03\x03foo\x0a" \
|
||||||
|
"\x02\x03\x03bar\x01\x03\x01\x02\x03\x03baz\x08"
|
||||||
|
)
|
||||||
|
expected = {
|
||||||
|
'foo' => nil,
|
||||||
|
'bar' => {
|
||||||
|
'baz' => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect(described_class.load(input)).to eq(expected)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'handles empty hashes' do
|
||||||
|
input = binary("\x00\x01\x03\x03\x01\x03\x00")
|
||||||
|
expect(described_class.load(input)).to eq({})
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects hashes with incomplete headers' do
|
||||||
|
input = binary("\x00\x01\x03\x02\x01\x03")
|
||||||
|
expect { described_class.load(input) }.
|
||||||
|
to raise_error(ArgumentError, /incomplete hash header/i)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects hashes with invalid keys' do
|
||||||
|
# keys must be strings; this one uses uses a number instead
|
||||||
|
input = binary("\x00\x01\x03\x05\x01\x03\x01\x03\x00")
|
||||||
|
expect { described_class.load(input) }.
|
||||||
|
to raise_error(ArgumentError, /not a number/i)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects hashes with missing keys' do
|
||||||
|
input = binary("\x00\x01\x03\x03\x01\x03\x01")
|
||||||
|
expect { described_class.load(input) }.
|
||||||
|
to raise_error(ArgumentError, /unexpected end/i)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects hashes with missing values' do
|
||||||
|
input = binary("\x00\x01\x03\x09\x01\x03\x01\x02\x03\x03foo")
|
||||||
|
expect { described_class.load(input) }.
|
||||||
|
to raise_error(ArgumentError, /unexpected end/i)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'loads string values' do
|
||||||
|
input = binary("\x00\x01\x03\x06\x02\x03\x03foo")
|
||||||
|
expect(described_class.load(input)).to eq('foo')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'handles empty strings' do
|
||||||
|
input = binary("\x00\x01\x03\x03\x02\x03\x00")
|
||||||
|
expect(described_class.load(input)).to eq('')
|
||||||
|
end
|
||||||
|
|
||||||
|
if String.new.respond_to?(:encoding) # ie. Ruby >= 1.9
|
||||||
|
it 'loads string values as ASCII-8BIT encoded strings' do
|
||||||
|
input = binary("\x00\x01\x03\x06\x02\x03\x03foo")
|
||||||
|
expect(described_class.load(input).encoding.to_s).to eq('ASCII-8BIT')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects string values with incomplete headers' do
|
||||||
|
input = binary("\x00\x01\x03\x01\x02")
|
||||||
|
expect { described_class.load(input) }.
|
||||||
|
to raise_error(ArgumentError, /invalid string header/i)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects string values with invalid headers' do
|
||||||
|
# expect a number indicating the string length, get a boolean instead
|
||||||
|
input = binary("\x00\x01\x03\x05\x02\x08foo")
|
||||||
|
expect { described_class.load(input) }.
|
||||||
|
to raise_error(ArgumentError, /bad integer/i)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects string values with insufficient storage' do
|
||||||
|
# expect 3 bytes, get 2 instead
|
||||||
|
input = binary("\x00\x01\x03\x05\x02\x03\x03fo")
|
||||||
|
expect { described_class.load(input) }.
|
||||||
|
to raise_error(ArgumentError, /insufficient string storage/i)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'loads uint8_t values' do
|
||||||
|
input = binary("\x00\x01\x03\x02\x03\x12")
|
||||||
|
expect(described_class.load(input)).to eq(0x12)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'loads uint16_t values' do
|
||||||
|
if little_endian?
|
||||||
|
input = binary("\x00\x01\x03\x03\x04\x34\x12")
|
||||||
|
else
|
||||||
|
input = binary("\x00\x01\x03\x03\x04\x12\x34")
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(described_class.load(input)).to eq(0x1234)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'loads uint32_t values' do
|
||||||
|
if little_endian?
|
||||||
|
input = binary("\x00\x01\x03\x05\x05\x78\x56\x34\x12")
|
||||||
|
else
|
||||||
|
input = binary("\x00\x01\x03\x05\x05\x12\x34\x56\x78")
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(described_class.load(input)).to eq(0x12345678)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'loads int uint64_t values' do
|
||||||
|
if little_endian?
|
||||||
|
input = binary("\x00\x01\x03\x09\x06\xef\xcd\xab\x90\x78\x56\x34\x12")
|
||||||
|
else
|
||||||
|
input = binary("\x00\x01\x03\x09\x06\x12\x34\x56\x78\x90\xab\xcd\xef")
|
||||||
|
end
|
||||||
|
expect(described_class.load(input)).to eq(0x1234567890abcdef)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects int markers with missing values' do
|
||||||
|
# expect an integer, but hit the end of the buffer
|
||||||
|
input = binary("\x00\x01\x03\x01\x05")
|
||||||
|
expect { described_class.load(input) }.
|
||||||
|
to raise_error(ArgumentError, /insufficient int storage/i)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects double markers with insufficient storage' do
|
||||||
|
# double with 7 bytes of storage instead of the required 8 bytes
|
||||||
|
input = binary("\x00\x01\x03\x08\x07\x00\x00\x00\x00\x00\x00\x00")
|
||||||
|
expect { described_class.load(input) }.
|
||||||
|
to raise_error(ArgumentError, /insufficient double storage/i)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'loads boolean `true` values' do
|
||||||
|
input = binary("\x00\x01\x03\x01\x08")
|
||||||
|
expect(described_class.load(input)).to be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'loads boolean `false` values' do
|
||||||
|
input = binary("\x00\x01\x03\x01\x09")
|
||||||
|
expect(described_class.load(input)).to be_false
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'loads nil' do
|
||||||
|
input = binary("\x00\x01\x03\x01\x0a")
|
||||||
|
expect(described_class.load(input)).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'loads templates' do
|
||||||
|
# this example includes a "skip" marker
|
||||||
|
input = binary(
|
||||||
|
"\x00\x01\x03\x28\x0b\x00\x03\x02\x02\x03\x04name" \
|
||||||
|
"\x02\x03\x03age\x03\x03\x02\x03\x04fred\x03" \
|
||||||
|
"\x14\x02\x03\x04pete\x03\x1e\x0c\x03\x19"
|
||||||
|
)
|
||||||
|
expected = [
|
||||||
|
{ 'name' => 'fred', 'age' => 20 },
|
||||||
|
{ 'name' => 'pete', 'age' => 30 },
|
||||||
|
{ 'age' => 25 },
|
||||||
|
]
|
||||||
|
expect(described_class.load(input)).to eq(expected)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'handles empty templates' do
|
||||||
|
input = binary(
|
||||||
|
"\x00\x01\x03\x12\x0b\x00\x03\x02\x02" \
|
||||||
|
"\x03\x03foo\x02\x03\x03bar\x03\x00"
|
||||||
|
)
|
||||||
|
expect(described_class.load(input)).to eq([])
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects templates without a header array' do
|
||||||
|
input = binary("\x00\x01\x03\x01\x0b")
|
||||||
|
expect { described_class.load(input) }.
|
||||||
|
to raise_error(ArgumentError, /unexpected end/i)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects templates without a row items array' do
|
||||||
|
input = binary(
|
||||||
|
"\x00\x01\x03\x10\x0b\x00\x03\x02\x02" \
|
||||||
|
"\x03\x03foo\x02\x03\x03bar"
|
||||||
|
)
|
||||||
|
expect { described_class.load(input) }.
|
||||||
|
to raise_error(ArgumentError, /insufficient/i)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects templates with non-string header items' do
|
||||||
|
input = binary(
|
||||||
|
"\x00\x01\x03\x0e\x0b\x00\x03\x02\x02" \
|
||||||
|
"\x03\x03foo\x03\x03\x03\x00"
|
||||||
|
)
|
||||||
|
expect { described_class.load(input) }.
|
||||||
|
to raise_error(ArgumentError, /not a number/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects templates with a header item array count mismatch' do
|
||||||
|
input = binary(
|
||||||
|
"\x00\x01\x03\x0a\x0b\x00\x03\x02\x02" \
|
||||||
|
"\x03\x03foo"
|
||||||
|
)
|
||||||
|
expect { described_class.load(input) }.
|
||||||
|
to raise_error(ArgumentError, /unexpected end/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects templates with a row item count mismatch' do
|
||||||
|
input = binary(
|
||||||
|
"\x00\x01\x03\x25\x0b\x00\x03\x02\x02\x03\x04name" \
|
||||||
|
"\x02\x03\x03age\x03\x03\x02\x03\x04fred\x03" \
|
||||||
|
"\x14\x02\x03\x04pete\x03\x1e"
|
||||||
|
)
|
||||||
|
expect { described_class.load(input) }.
|
||||||
|
to raise_error(ArgumentError, /unexpected end/)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.dump' do
|
||||||
|
let(:query) do
|
||||||
|
# this is the typical kind of query that Command-T will actually issue
|
||||||
|
['query', '/some/path', {
|
||||||
|
'expression' => ['type', 'f'],
|
||||||
|
'fields' => ['name'],
|
||||||
|
}]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'serializes' do
|
||||||
|
expect { described_class.dump(query) }.to_not raise_error
|
||||||
|
end
|
||||||
|
|
||||||
|
if String.new.respond_to?(:encoding) # ie. Ruby >= 1.9
|
||||||
|
it 'serializes to an ASCII-8BIT string' do
|
||||||
|
expect(described_class.dump(query).encoding.to_s).to eq('ASCII-8BIT')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'generates a correct serialization' do
|
||||||
|
# in Ruby 1.8, hashes aren't ordered, so two serializations are possible
|
||||||
|
if little_endian?
|
||||||
|
expected = [
|
||||||
|
binary(
|
||||||
|
"\x00\x01\x06\x49\x00\x00\x00\x00\x00\x00\x00\x00\x03\x03\x02\x03" \
|
||||||
|
"\x05query\x02\x03\x0a/some/path\x01\x03\x02\x02\x03\x0a" \
|
||||||
|
"expression\x00\x03\x02\x02\x03\x04type\x02\x03\x01f\x02\x03\x06" \
|
||||||
|
"fields\x00\x03\x01\x02\x03\x04name"
|
||||||
|
),
|
||||||
|
binary(
|
||||||
|
"\x00\x01\x06\x49\x00\x00\x00\x00\x00\x00\x00\x00\x03\x03\x02\x03" \
|
||||||
|
"\x05query\x02\x03\x0a/some/path\x01\x03\x02\x02\x03\x06fields" \
|
||||||
|
"\x00\x03\x01\x02\x03\x04name\x02\x03\x0aexpression\x00\x03\x02" \
|
||||||
|
"\x02\x03\x04type\x02\x03\x01f"
|
||||||
|
)
|
||||||
|
]
|
||||||
|
else
|
||||||
|
expected = [
|
||||||
|
binary(
|
||||||
|
"\x00\x01\x06\x00\x00\x00\x00\x00\x00\x00\x49\x00\x03\x03\x02\x03" \
|
||||||
|
"\x05query\x02\x03\x0a/some/path\x01\x03\x02\x02\x03\x0a" \
|
||||||
|
"expression\x00\x03\x02\x02\x03\x04type\x02\x03\x01f\x02\x03\x06" \
|
||||||
|
"fields\x00\x03\x01\x02\x03\x04name"
|
||||||
|
),
|
||||||
|
binary(
|
||||||
|
"\x00\x01\x06\x00\x00\x00\x00\x00\x00\x00\x49\x00\x03\x03\x02\x03" \
|
||||||
|
"\x05query\x02\x03\x0a/some/path\x01\x03\x02\x02\x03\x06fields" \
|
||||||
|
"\x00\x03\x01\x02\x03\x04name\x02\x03\x0aexpression\x00\x03\x02" \
|
||||||
|
"\x02\x03\x04type\x02\x03\x01f"
|
||||||
|
)
|
||||||
|
]
|
||||||
|
end
|
||||||
|
expect(expected).to include(described_class.dump(query))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
29
vim/vim.symlink/bundle/command-t/spec/spec_helper.rb
Normal file
29
vim/vim.symlink/bundle/command-t/spec/spec_helper.rb
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
||||||
|
# Licensed under the terms of the BSD 2-clause license.
|
||||||
|
|
||||||
|
if !Object.const_defined?('Bundler')
|
||||||
|
require 'rubygems'
|
||||||
|
require 'bundler'
|
||||||
|
Bundler.setup
|
||||||
|
end
|
||||||
|
require 'rspec'
|
||||||
|
|
||||||
|
lib = File.expand_path('../ruby', File.dirname(__FILE__))
|
||||||
|
unless $LOAD_PATH.include? lib
|
||||||
|
$LOAD_PATH.unshift lib
|
||||||
|
end
|
||||||
|
|
||||||
|
require 'command-t'
|
||||||
|
|
||||||
|
RSpec.configure do |config|
|
||||||
|
config.mock_framework = :rr
|
||||||
|
end
|
||||||
|
|
||||||
|
# Fake top-level VIM implementation, for stubbing.
|
||||||
|
module VIM
|
||||||
|
class << self
|
||||||
|
def evaluate(*args); end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Buffer; end
|
||||||
|
end
|
File diff suppressed because it is too large
Load diff
|
@ -1,163 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkdir#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkdir#getSwitchOrder()
|
|
||||||
return g:fuf_bookmarkdir_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkdir#getEditableDataNames()
|
|
||||||
return ['items']
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkdir#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkdir#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkdir#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufBookmarkDir', s:MODE_NAME, '""', [])
|
|
||||||
command! -bang -narg=? FufBookmarkDirAdd call s:bookmark(<q-args>)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
let s:OPEN_TYPE_DELETE = -1
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:bookmark(word)
|
|
||||||
let item = {
|
|
||||||
\ 'time' : localtime(),
|
|
||||||
\ }
|
|
||||||
|
|
||||||
let item.path = l9#inputHl('Question', '[fuf] Directory to bookmark:',
|
|
||||||
\ fnamemodify(getcwd(), ':p:~'), 'dir')
|
|
||||||
if item.path !~ '\S'
|
|
||||||
call fuf#echoWarning('Canceled')
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
let item.word = l9#inputHl('Question', '[fuf] Bookmark as:',
|
|
||||||
\ fnamemodify(getcwd(), ':p:~'))
|
|
||||||
if item.word !~ '\S'
|
|
||||||
call fuf#echoWarning('Canceled')
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
let items = fuf#loadDataFile(s:MODE_NAME, 'items')
|
|
||||||
call insert(items, item)
|
|
||||||
call fuf#saveDataFile(s:MODE_NAME, 'items', items)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:findItem(items, word)
|
|
||||||
for item in a:items
|
|
||||||
if item.word ==# a:word
|
|
||||||
return item
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
return {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_bookmarkdir_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
if a:mode ==# s:OPEN_TYPE_DELETE
|
|
||||||
let items = fuf#loadDataFile(s:MODE_NAME, 'items')
|
|
||||||
call filter(items, 'v:val.word !=# a:word')
|
|
||||||
call fuf#saveDataFile(s:MODE_NAME, 'items', items)
|
|
||||||
let self.reservedMode = self.getModeName()
|
|
||||||
return
|
|
||||||
else
|
|
||||||
let item = s:findItem(fuf#loadDataFile(s:MODE_NAME, 'items'), a:word)
|
|
||||||
if !empty(item)
|
|
||||||
execute ':cd ' . fnameescape(item.path)
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
call fuf#defineKeyMappingInHandler(g:fuf_bookmarkdir_keyDelete,
|
|
||||||
\ 'onCr(' . s:OPEN_TYPE_DELETE . ')')
|
|
||||||
let self.items = fuf#loadDataFile(s:MODE_NAME, 'items')
|
|
||||||
call map(self.items, 'fuf#makeNonPathItem(v:val.word, strftime(g:fuf_timeFormat, v:val.time))')
|
|
||||||
call fuf#mapToSetSerialIndex(self.items, 1)
|
|
||||||
call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
|
@ -1,199 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkfile#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkfile#getSwitchOrder()
|
|
||||||
return g:fuf_bookmarkfile_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkfile#getEditableDataNames()
|
|
||||||
return ['items']
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkfile#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkfile#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkfile#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufBookmarkFile', s:MODE_NAME, '""', [])
|
|
||||||
command! -bang -narg=? FufBookmarkFileAdd call s:bookmarkHere(<q-args>)
|
|
||||||
command! -bang -narg=0 -range FufBookmarkFileAddAsSelectedText call s:bookmarkHere(l9#getSelectedText())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
let s:OPEN_TYPE_DELETE = -1
|
|
||||||
|
|
||||||
" opens a:path and jumps to the line matching to a:pattern from a:lnum within
|
|
||||||
" a:range. if not found, jumps to a:lnum.
|
|
||||||
function s:jumpToBookmark(path, mode, pattern, lnum)
|
|
||||||
call fuf#openFile(a:path, a:mode, g:fuf_reuseWindow)
|
|
||||||
call cursor(s:getMatchingLineNumber(getline(1, '$'), a:pattern, a:lnum), 0)
|
|
||||||
normal! zvzz
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getMatchingLineNumber(lines, pattern, lnumBegin)
|
|
||||||
let l = min([a:lnumBegin, len(a:lines)])
|
|
||||||
for [l0, l1] in map(range(0, g:fuf_bookmarkfile_searchRange),
|
|
||||||
\ '[l + v:val, l - v:val]')
|
|
||||||
if l0 <= len(a:lines) && a:lines[l0 - 1] =~# a:pattern
|
|
||||||
return l0
|
|
||||||
elseif l1 >= 0 && a:lines[l1 - 1] =~# a:pattern
|
|
||||||
return l1
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
return l
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getLinePattern(lnum)
|
|
||||||
return '\C\V\^' . escape(getline(a:lnum), '\') . '\$'
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:bookmarkHere(word)
|
|
||||||
if !empty(&buftype) || expand('%') !~ '\S'
|
|
||||||
call fuf#echoWarning('Can''t bookmark this buffer.')
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
let item = {
|
|
||||||
\ 'word' : (a:word =~# '\S' ? substitute(a:word, '\n', ' ', 'g')
|
|
||||||
\ : pathshorten(expand('%:p:~')) . '|' . line('.') . '| ' . getline('.')),
|
|
||||||
\ 'path' : expand('%:p'),
|
|
||||||
\ 'lnum' : line('.'),
|
|
||||||
\ 'pattern' : s:getLinePattern(line('.')),
|
|
||||||
\ 'time' : localtime(),
|
|
||||||
\ }
|
|
||||||
let item.word = l9#inputHl('Question', '[fuf] Bookmark as:', item.word)
|
|
||||||
if item.word !~ '\S'
|
|
||||||
call fuf#echoWarning('Canceled')
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
let items = fuf#loadDataFile(s:MODE_NAME, 'items')
|
|
||||||
call insert(items, item)
|
|
||||||
call fuf#saveDataFile(s:MODE_NAME, 'items', items)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:findItem(items, word)
|
|
||||||
for item in a:items
|
|
||||||
if item.word ==# a:word
|
|
||||||
return item
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
return {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_bookmarkfile_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
let item = s:findItem(fuf#loadDataFile(s:MODE_NAME, 'items'), a:word)
|
|
||||||
let lines = fuf#getFileLines(item.path)
|
|
||||||
if empty(lines)
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
let index = s:getMatchingLineNumber(lines, item.pattern, item.lnum) - 1
|
|
||||||
return fuf#makePreviewLinesAround(
|
|
||||||
\ lines, [index], a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
if a:mode ==# s:OPEN_TYPE_DELETE
|
|
||||||
let items = fuf#loadDataFile(s:MODE_NAME, 'items')
|
|
||||||
call filter(items, 'v:val.word !=# a:word')
|
|
||||||
call fuf#saveDataFile(s:MODE_NAME, 'items', items)
|
|
||||||
let self.reservedMode = self.getModeName()
|
|
||||||
return
|
|
||||||
else
|
|
||||||
let item = s:findItem(fuf#loadDataFile(s:MODE_NAME, 'items'), a:word)
|
|
||||||
if !empty(item)
|
|
||||||
call s:jumpToBookmark(item.path, a:mode, item.pattern, item.lnum)
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
call fuf#defineKeyMappingInHandler(g:fuf_bookmarkfile_keyDelete,
|
|
||||||
\ 'onCr(' . s:OPEN_TYPE_DELETE . ')')
|
|
||||||
let self.items = fuf#loadDataFile(s:MODE_NAME, 'items')
|
|
||||||
call map(self.items, 'fuf#makeNonPathItem(v:val.word, strftime(g:fuf_timeFormat, v:val.time))')
|
|
||||||
call fuf#mapToSetSerialIndex(self.items, 1)
|
|
||||||
call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
|
@ -1,189 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffer#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffer#getSwitchOrder()
|
|
||||||
return g:fuf_buffer_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffer#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffer#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffer#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffer#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufBuffer', s:MODE_NAME, '""', [])
|
|
||||||
augroup fuf#buffer
|
|
||||||
autocmd!
|
|
||||||
autocmd BufEnter * call s:updateBufTimes()
|
|
||||||
autocmd BufWritePost * call s:updateBufTimes()
|
|
||||||
augroup END
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
let s:OPEN_TYPE_DELETE = -1
|
|
||||||
|
|
||||||
let s:bufTimes = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:updateBufTimes()
|
|
||||||
let s:bufTimes[bufnr('%')] = localtime()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:makeItem(nr)
|
|
||||||
let fname = (empty(bufname(a:nr))
|
|
||||||
\ ? '[No Name]'
|
|
||||||
\ : fnamemodify(bufname(a:nr), ':p:~:.'))
|
|
||||||
let time = (exists('s:bufTimes[a:nr]') ? s:bufTimes[a:nr] : 0)
|
|
||||||
let item = fuf#makePathItem(fname, strftime(g:fuf_timeFormat, time), 0)
|
|
||||||
let item.index = a:nr
|
|
||||||
let item.bufNr = a:nr
|
|
||||||
let item.time = time
|
|
||||||
let item.abbrPrefix = s:getBufIndicator(a:nr) . ' '
|
|
||||||
return item
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getBufIndicator(bufNr)
|
|
||||||
if !getbufvar(a:bufNr, '&modifiable')
|
|
||||||
return '[-]'
|
|
||||||
elseif getbufvar(a:bufNr, '&modified')
|
|
||||||
return '[+]'
|
|
||||||
elseif getbufvar(a:bufNr, '&readonly')
|
|
||||||
return '[R]'
|
|
||||||
else
|
|
||||||
return ' '
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:compareTimeDescending(i1, i2)
|
|
||||||
return a:i1.time == a:i2.time ? 0 : a:i1.time > a:i2.time ? -1 : +1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:findItem(items, word)
|
|
||||||
for item in a:items
|
|
||||||
if item.word ==# a:word
|
|
||||||
return item
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
return {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_buffer_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
let item = s:findItem(self.items, a:word)
|
|
||||||
if empty(item)
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
return fuf#makePreviewLinesForFile(item.bufNr, a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
" not use bufnr(a:word) in order to handle unnamed buffer
|
|
||||||
let item = s:findItem(self.items, a:word)
|
|
||||||
if empty(item)
|
|
||||||
" do nothing
|
|
||||||
elseif a:mode ==# s:OPEN_TYPE_DELETE
|
|
||||||
execute item.bufNr . 'bdelete'
|
|
||||||
let self.reservedMode = self.getModeName()
|
|
||||||
else
|
|
||||||
call fuf#openBuffer(item.bufNr, a:mode, g:fuf_reuseWindow)
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
call fuf#defineKeyMappingInHandler(g:fuf_buffer_keyDelete,
|
|
||||||
\ 'onCr(' . s:OPEN_TYPE_DELETE . ')')
|
|
||||||
let self.items = range(1, bufnr('$'))
|
|
||||||
call filter(self.items, 'buflisted(v:val) && v:val != self.bufNrPrev && v:val != bufnr("%")')
|
|
||||||
call map(self.items, 's:makeItem(v:val)')
|
|
||||||
if g:fuf_buffer_mruOrder
|
|
||||||
call sort(self.items, 's:compareTimeDescending')
|
|
||||||
call fuf#mapToSetSerialIndex(self.items, 1)
|
|
||||||
endif
|
|
||||||
let self.items = fuf#mapToSetAbbrWithSnippedWordAsPath(self.items)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
|
@ -1,300 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffertag#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffertag#getSwitchOrder()
|
|
||||||
return g:fuf_buffertag_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffertag#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffertag#renewCache()
|
|
||||||
let s:tagItemsCache = {}
|
|
||||||
let s:tagDataCache = {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffertag#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffertag#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufBufferTag', s:MODE_NAME, '""',
|
|
||||||
\ [['g:fuf_buffertag_forAll', 0]])
|
|
||||||
call fuf#defineLaunchCommand('FufBufferTagAll', s:MODE_NAME, '""',
|
|
||||||
\ [['g:fuf_buffertag_forAll', 1]])
|
|
||||||
call fuf#defineLaunchCommand('FufBufferTagWithCursorWord', s:MODE_NAME,
|
|
||||||
\ 'expand(''<cword>'')', [['g:fuf_buffertag_forAll', 0]])
|
|
||||||
call fuf#defineLaunchCommand('FufBufferTagAllWithCursorWord', s:MODE_NAME,
|
|
||||||
\ 'expand(''<cword>'')', [['g:fuf_buffertag_forAll', 1]])
|
|
||||||
call fuf#defineLaunchCommand('FufBufferTagWithSelectedText', s:MODE_NAME,
|
|
||||||
\ 'l9#getSelectedText()', [['g:fuf_buffertag_forAll', 0]])
|
|
||||||
call fuf#defineLaunchCommand('FufBufferTagAllWithSelectedText', s:MODE_NAME,
|
|
||||||
\ 'l9#getSelectedText()', [['g:fuf_buffertag_forAll', 1]])
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag_forAll', 0) " private option
|
|
||||||
" the following settings originate from taglist.vim
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__asm' , '--language-force=asm --asm-types=dlmt')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__aspperl' , '--language-force=asp --asp-types=fsv')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__aspvbs' , '--language-force=asp --asp-types=fsv')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__awk' , '--language-force=awk --awk-types=f')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__beta' , '--language-force=beta --beta-types=fsv')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__c' , '--language-force=c --c-types=dgsutvf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__cpp' , '--language-force=c++ --c++-types=nvdtcgsuf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__cs' , '--language-force=c# --c#-types=dtncEgsipm')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__cobol' , '--language-force=cobol --cobol-types=dfgpPs')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__eiffel' , '--language-force=eiffel --eiffel-types=cf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__erlang' , '--language-force=erlang --erlang-types=drmf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__expect' , '--language-force=tcl --tcl-types=cfp')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__fortran' , '--language-force=fortran --fortran-types=pbceiklmntvfs')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__html' , '--language-force=html --html-types=af')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__java' , '--language-force=java --java-types=pcifm')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__javascript', '--language-force=javascript --javascript-types=f')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__lisp' , '--language-force=lisp --lisp-types=f')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__lua' , '--language-force=lua --lua-types=f')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__make' , '--language-force=make --make-types=m')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__pascal' , '--language-force=pascal --pascal-types=fp')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__perl' , '--language-force=perl --perl-types=clps')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__php' , '--language-force=php --php-types=cdvf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__python' , '--language-force=python --python-types=cmf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__rexx' , '--language-force=rexx --rexx-types=s')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__ruby' , '--language-force=ruby --ruby-types=cfFm')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__scheme' , '--language-force=scheme --scheme-types=sf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__sh' , '--language-force=sh --sh-types=f')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__csh' , '--language-force=sh --sh-types=f')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__zsh' , '--language-force=sh --sh-types=f')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__slang' , '--language-force=slang --slang-types=nf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__sml' , '--language-force=sml --sml-types=ecsrtvf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__sql' , '--language-force=sql --sql-types=cFPrstTvfp')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__tcl' , '--language-force=tcl --tcl-types=cfmp')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__vera' , '--language-force=vera --vera-types=cdefgmpPtTvx')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__verilog' , '--language-force=verilog --verilog-types=mcPertwpvf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__vim' , '--language-force=vim --vim-types=avf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__yacc' , '--language-force=yacc --yacc-types=l')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:parseTagLine(line)
|
|
||||||
" tag W:\Win32\SRC7\NCSIM\NCVW32\CUBEFACE.H /^#define CUBEFACE_H$/;" macro line:4
|
|
||||||
let fields = matchlist(a:line, '\v^([^\t]+)\t(.+)\t\/\^(.+)\$\/\;\"\t(.+)\tline\:(\d+)')
|
|
||||||
if empty(fields)
|
|
||||||
return {}
|
|
||||||
endif
|
|
||||||
return {
|
|
||||||
\ 'tag' : fields[1],
|
|
||||||
\ 'fname' : fields[2],
|
|
||||||
\ 'pattern': fields[3],
|
|
||||||
\ 'kind' : fields[4],
|
|
||||||
\ 'lnum' : str2nr(fields[5]),
|
|
||||||
\ }
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
let s:TEMP_VARIABLES_GROUP = expand('<sfile>:p')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getFileType(bufNr)
|
|
||||||
let ft = getbufvar(a:bufNr, '&filetype')
|
|
||||||
if !empty(ft) || bufloaded(a:bufNr)
|
|
||||||
return ft
|
|
||||||
endif
|
|
||||||
let ft = getbufvar(a:bufNr, 'fuf_buffertag_filetype')
|
|
||||||
if !empty(ft)
|
|
||||||
return ft
|
|
||||||
endif
|
|
||||||
call l9#tempvariables#set(s:TEMP_VARIABLES_GROUP, '&eventignore', 'FileType')
|
|
||||||
call l9#tempvariables#set(s:TEMP_VARIABLES_GROUP, '&filetype', &filetype)
|
|
||||||
" from taglist.vim
|
|
||||||
execute 'doautocmd filetypedetect BufRead ' . bufname(a:bufNr)
|
|
||||||
let ft = &filetype
|
|
||||||
call l9#tempvariables#end(s:TEMP_VARIABLES_GROUP)
|
|
||||||
call setbufvar(a:bufNr, 'fuf_buffertag_filetype', ft)
|
|
||||||
return ft
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:makeCtagsCmd(bufNr)
|
|
||||||
let ft = s:getFileType(a:bufNr)
|
|
||||||
if !exists('g:fuf_buffertag__{ft}')
|
|
||||||
return ''
|
|
||||||
endif
|
|
||||||
"
|
|
||||||
let cmd = join([g:fuf_buffertag_ctagsPath,
|
|
||||||
\ '-f - --sort=no --excmd=pattern --fields=nKs',
|
|
||||||
\ g:fuf_buffertag__{ft},
|
|
||||||
\ shellescape(fnamemodify(bufname(a:bufNr), ':p'))])
|
|
||||||
return cmd
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getTagItems(bufNr)
|
|
||||||
let cmd = s:makeCtagsCmd(a:bufNr)
|
|
||||||
if empty(cmd)
|
|
||||||
return []
|
|
||||||
elseif !exists('s:tagItemsCache[cmd]') ||
|
|
||||||
\ s:tagItemsCache[cmd].time < getftime(expand(bufname(a:bufNr)))
|
|
||||||
let items = split(system(cmd), "\n")
|
|
||||||
if v:shell_error
|
|
||||||
call fuf#echoError([cmd] + items)
|
|
||||||
throw "Command error"
|
|
||||||
endif
|
|
||||||
call map(items, 's:parseTagLine(v:val)')
|
|
||||||
call filter(items, '!empty(v:val)')
|
|
||||||
let s:tagItemsCache[cmd] = {
|
|
||||||
\ 'time' : localtime(),
|
|
||||||
\ 'items' : items,
|
|
||||||
\ }
|
|
||||||
endif
|
|
||||||
return s:tagItemsCache[cmd].items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:makeItem(tag, itemMap)
|
|
||||||
let menu = fnamemodify(a:itemMap[a:tag][0].fname, ':t')
|
|
||||||
\ . ' [' . a:itemMap[a:tag][0].kind . ']'
|
|
||||||
if len(a:itemMap[a:tag]) > 1
|
|
||||||
let menu .= ' (' . len(a:itemMap[a:tag]) . ')'
|
|
||||||
endif
|
|
||||||
let item = fuf#makeNonPathItem(a:tag, menu)
|
|
||||||
return item
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getTagData(bufNrs)
|
|
||||||
let key = join([0] + sort(copy(a:bufNrs)), "\n")
|
|
||||||
let bufNames = map(copy(a:bufNrs), 'bufname(v:val)')
|
|
||||||
if !exists('s:tagDataCache[key]') ||
|
|
||||||
\ fuf#countModifiedFiles(bufNames, s:tagDataCache[key].time) > 0
|
|
||||||
let itemMap = {}
|
|
||||||
for item in l9#concat(map(copy(a:bufNrs), 's:getTagItems(v:val)'))
|
|
||||||
if !exists('itemMap[item.tag]')
|
|
||||||
let itemMap[item.tag] = []
|
|
||||||
endif
|
|
||||||
call add(itemMap[item.tag], item)
|
|
||||||
endfor
|
|
||||||
let items = sort(keys(itemMap))
|
|
||||||
call map(items, 's:makeItem(v:val, itemMap)')
|
|
||||||
call fuf#mapToSetSerialIndex(items, 1)
|
|
||||||
call map(items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
let s:tagDataCache[key] = {
|
|
||||||
\ 'time' : localtime(),
|
|
||||||
\ 'itemMap': itemMap,
|
|
||||||
\ 'items' : items,
|
|
||||||
\ }
|
|
||||||
endif
|
|
||||||
return [s:tagDataCache[key].items, s:tagDataCache[key].itemMap]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:jumpToTag(item, mode)
|
|
||||||
call fuf#openFile(a:item.fname, a:mode, g:fuf_reuseWindow)
|
|
||||||
call cursor(a:item.lnum, 1)
|
|
||||||
normal! zvzz
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_buffertag_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
if !exists('self.itemMap[a:word][0]')
|
|
||||||
call fuf#echoError('Definition not found:' . a:word)
|
|
||||||
return
|
|
||||||
elseif len(self.itemMap[a:word]) == 1
|
|
||||||
let i = 0
|
|
||||||
else
|
|
||||||
let list = map(fuf#mapToSetSerialIndex(copy(self.itemMap[a:word]), 1),
|
|
||||||
\ 'printf(" %2d: %s|%d| [%s] %s",v:val.index, fnamemodify(v:val.fname, ":~:."), v:val.lnum, v:val.kind, v:val.pattern)')
|
|
||||||
let i = inputlist(['Select a definition of "' . a:word . '":'] + list) - 1
|
|
||||||
endif
|
|
||||||
if 0 <= i && i < len(self.itemMap[a:word])
|
|
||||||
call s:jumpToTag(self.itemMap[a:word][i], a:mode)
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
if g:fuf_buffertag_forAll
|
|
||||||
let bufNrs = filter(range(1, bufnr('$')), 'buflisted(v:val)')
|
|
||||||
else
|
|
||||||
let bufNrs = [self.bufNrPrev]
|
|
||||||
endif
|
|
||||||
let [self.items, self.itemMap] = s:getTagData(bufNrs)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
|
@ -1,137 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackfile#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackfile#getSwitchOrder()
|
|
||||||
return -1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackfile#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackfile#renewCache()
|
|
||||||
let s:cache = {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackfile#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackfile#onInit()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackfile#launch(initialPattern, partialMatching, prompt, exclude, listener)
|
|
||||||
let s:prompt = (empty(a:prompt) ? '>' : a:prompt)
|
|
||||||
let s:exclude = a:exclude
|
|
||||||
let s:listener = a:listener
|
|
||||||
call fuf#launch(s:MODE_NAME, a:initialPattern, a:partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:enumItems(dir)
|
|
||||||
let key = getcwd() . g:fuf_ignoreCase . s:exclude . "\n" . a:dir
|
|
||||||
if !exists('s:cache[key]')
|
|
||||||
let s:cache[key] = fuf#enumExpandedDirsEntries(a:dir, s:exclude)
|
|
||||||
if isdirectory(a:dir)
|
|
||||||
call insert(s:cache[key], fuf#makePathItem(a:dir . '.', '', 0))
|
|
||||||
endif
|
|
||||||
call fuf#mapToSetSerialIndex(s:cache[key], 1)
|
|
||||||
call fuf#mapToSetAbbrWithSnippedWordAsPath(s:cache[key])
|
|
||||||
endif
|
|
||||||
return s:cache[key]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(s:prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return a:enteredPattern =~# '[^/\\]$'
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPathTail',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return fuf#makePreviewLinesForFile(a:word, a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
let items = copy(s:enumItems(fuf#splitPath(a:patternPrimary).head))
|
|
||||||
return filter(items, 'bufnr("^" . v:val.word . "$") != self.bufNrPrev')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call s:listener.onComplete(a:word, a:mode)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
if !a:opened && exists('s:listener.onAbort()')
|
|
||||||
call s:listener.onAbort()
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
|
@ -1,139 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackitem#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackitem#getSwitchOrder()
|
|
||||||
return -1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackitem#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackitem#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackitem#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackitem#onInit()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackitem#launch(initialPattern, partialMatching, prompt, listener, items, forPath)
|
|
||||||
let s:prompt = (empty(a:prompt) ? '>' : a:prompt)
|
|
||||||
let s:listener = a:listener
|
|
||||||
let s:forPath = a:forPath
|
|
||||||
let s:items = copy(a:items)
|
|
||||||
if s:forPath
|
|
||||||
call map(s:items, 'fuf#makePathItem(v:val, "", 1)')
|
|
||||||
call fuf#mapToSetSerialIndex(s:items, 1)
|
|
||||||
call fuf#mapToSetAbbrWithSnippedWordAsPath(s:items)
|
|
||||||
else
|
|
||||||
call map(s:items, 'fuf#makeNonPathItem(v:val, "")')
|
|
||||||
call fuf#mapToSetSerialIndex(s:items, 1)
|
|
||||||
call map(s:items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
endif
|
|
||||||
call fuf#launch(s:MODE_NAME, a:initialPattern, a:partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(s:prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
if s:forPath
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endif
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
let parser = (s:forPath
|
|
||||||
\ ? 's:interpretPrimaryPatternForPath'
|
|
||||||
\ : 's:interpretPrimaryPatternForNonPath')
|
|
||||||
return fuf#makePatternSet(a:patternBase, parser, self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
if s:forPath
|
|
||||||
return fuf#makePreviewLinesForFile(a:word, a:count, self.getPreviewHeight())
|
|
||||||
endif
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return s:items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call s:listener.onComplete(a:word, a:mode)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
if !a:opened && exists('s:listener.onAbort()')
|
|
||||||
call s:listener.onAbort()
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
|
@ -1,172 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#changelist#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#changelist#getSwitchOrder()
|
|
||||||
return g:fuf_changelist_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#changelist#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#changelist#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#changelist#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#changelist#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufChangeList', s:MODE_NAME, '""', [])
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getChangesLines()
|
|
||||||
redir => result
|
|
||||||
:silent changes
|
|
||||||
redir END
|
|
||||||
return split(result, "\n")
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:parseChangesLine(line)
|
|
||||||
" return matchlist(a:line, '^\(.\)\s\+\(\d\+\)\s\(.*\)$')
|
|
||||||
let elements = matchlist(a:line, '\v^(.)\s*(\d+)\s+(\d+)\s+(\d+)\s*(.*)$')
|
|
||||||
if empty(elements)
|
|
||||||
return {}
|
|
||||||
endif
|
|
||||||
return {
|
|
||||||
\ 'prefix': elements[1],
|
|
||||||
\ 'count' : elements[2],
|
|
||||||
\ 'lnum' : elements[3],
|
|
||||||
\ 'text' : printf('|%d:%d|%s', elements[3], elements[4], elements[5]),
|
|
||||||
\ }
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:makeItem(line)
|
|
||||||
let parsed = s:parseChangesLine(a:line)
|
|
||||||
if empty(parsed)
|
|
||||||
return {}
|
|
||||||
endif
|
|
||||||
let item = fuf#makeNonPathItem(parsed.text, '')
|
|
||||||
let item.abbrPrefix = parsed.prefix
|
|
||||||
let item.lnum = parsed.lnum
|
|
||||||
return item
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_changelist_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
let items = filter(copy(self.items), 'v:val.word ==# a:word')
|
|
||||||
if empty(items)
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
let lines = fuf#getFileLines(self.bufNrPrev)
|
|
||||||
return fuf#makePreviewLinesAround(
|
|
||||||
\ lines, [items[0].lnum - 1], a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call fuf#prejump(a:mode)
|
|
||||||
let older = 0
|
|
||||||
for line in reverse(s:getChangesLines())
|
|
||||||
if stridx(line, '>') == 0
|
|
||||||
let older = 1
|
|
||||||
endif
|
|
||||||
let parsed = s:parseChangesLine(line)
|
|
||||||
if !empty(parsed) && parsed.text ==# a:word
|
|
||||||
if parsed.count != 0
|
|
||||||
execute 'normal! ' . parsed.count . (older ? 'g;' : 'g,') . 'zvzz'
|
|
||||||
endif
|
|
||||||
break
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
let self.items = s:getChangesLines()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
call map(self.items, 's:makeItem(v:val)')
|
|
||||||
call filter(self.items, '!empty(v:val)')
|
|
||||||
call reverse(self.items)
|
|
||||||
call fuf#mapToSetSerialIndex(self.items, 1)
|
|
||||||
call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
|
@ -1,199 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#coveragefile#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#coveragefile#getSwitchOrder()
|
|
||||||
return g:fuf_coveragefile_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#coveragefile#getEditableDataNames()
|
|
||||||
return ['coverages']
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#coveragefile#renewCache()
|
|
||||||
let s:cache = {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#coveragefile#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#coveragefile#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufCoverageFile', s:MODE_NAME, '""', [])
|
|
||||||
call l9#defineVariableDefault('g:fuf_coveragefile_name', '') " private option
|
|
||||||
command! -bang -narg=0 FufCoverageFileRegister call s:registerCoverage()
|
|
||||||
command! -bang -narg=? FufCoverageFileChange call s:changeCoverage(<q-args>)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:enumItems()
|
|
||||||
let key = join([getcwd(), g:fuf_ignoreCase, g:fuf_coveragefile_exclude,
|
|
||||||
\ g:fuf_coveragefile_globPatterns], "\n")
|
|
||||||
if !exists('s:cache[key]')
|
|
||||||
let s:cache[key] = l9#concat(map(copy(g:fuf_coveragefile_globPatterns),
|
|
||||||
\ 'fuf#glob(v:val)'))
|
|
||||||
call filter(s:cache[key], 'filereadable(v:val)') " filter out directories
|
|
||||||
call map(s:cache[key], 'fuf#makePathItem(fnamemodify(v:val, ":~:."), "", 0)')
|
|
||||||
if len(g:fuf_coveragefile_exclude)
|
|
||||||
call filter(s:cache[key], 'v:val.word !~ g:fuf_coveragefile_exclude')
|
|
||||||
endif
|
|
||||||
call fuf#mapToSetSerialIndex(s:cache[key], 1)
|
|
||||||
call fuf#mapToSetAbbrWithSnippedWordAsPath(s:cache[key])
|
|
||||||
endif
|
|
||||||
return s:cache[key]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:registerCoverage()
|
|
||||||
let patterns = []
|
|
||||||
while 1
|
|
||||||
let pattern = l9#inputHl('Question', '[fuf] Glob pattern for coverage (<Esc> and end):',
|
|
||||||
\ '', 'file')
|
|
||||||
if pattern !~ '\S'
|
|
||||||
break
|
|
||||||
endif
|
|
||||||
call add(patterns, pattern)
|
|
||||||
endwhile
|
|
||||||
if empty(patterns)
|
|
||||||
call fuf#echoWarning('Canceled')
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
echo '[fuf] patterns: ' . string(patterns)
|
|
||||||
let name = l9#inputHl('Question', '[fuf] Coverage name:')
|
|
||||||
if name !~ '\S'
|
|
||||||
call fuf#echoWarning('Canceled')
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
let coverages = fuf#loadDataFile(s:MODE_NAME, 'coverages')
|
|
||||||
call insert(coverages, {'name': name, 'patterns': patterns})
|
|
||||||
call fuf#saveDataFile(s:MODE_NAME, 'coverages', coverages)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:createChangeCoverageListener()
|
|
||||||
let listener = {}
|
|
||||||
|
|
||||||
function listener.onComplete(name, method)
|
|
||||||
call s:changeCoverage(a:name)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
return listener
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:changeCoverage(name)
|
|
||||||
let coverages = fuf#loadDataFile(s:MODE_NAME, 'coverages')
|
|
||||||
if a:name !~ '\S'
|
|
||||||
let names = map(copy(coverages), 'v:val.name')
|
|
||||||
call fuf#callbackitem#launch('', 0, '>Coverage>', s:createChangeCoverageListener(), names, 0)
|
|
||||||
return
|
|
||||||
else
|
|
||||||
let name = a:name
|
|
||||||
endif
|
|
||||||
call filter(coverages, 'v:val.name ==# name')
|
|
||||||
if empty(coverages)
|
|
||||||
call fuf#echoError('Coverage not found: ' . name)
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
call fuf#setOneTimeVariables(
|
|
||||||
\ ['g:fuf_coveragefile_globPatterns', coverages[0].patterns],
|
|
||||||
\ ['g:fuf_coveragefile_name' , a:name]
|
|
||||||
\ )
|
|
||||||
FufCoverageFile
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
let nameString = (empty(g:fuf_coveragefile_name) ? ''
|
|
||||||
\ : '[' . g:fuf_coveragefile_name . ']')
|
|
||||||
return fuf#formatPrompt(g:fuf_coveragefile_prompt, self.partialMatching,
|
|
||||||
\ nameString)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return fuf#makePreviewLinesForFile(a:word, a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call fuf#openFile(a:word, a:mode, g:fuf_reuseWindow)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
" NOTE: Comparing filenames is faster than bufnr('^' . fname . '$')
|
|
||||||
let bufNamePrev = fnamemodify(bufname(self.bufNrPrev), ':~:.')
|
|
||||||
let self.items = copy(s:enumItems())
|
|
||||||
call filter(self.items, 'v:val.word !=# bufNamePrev')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
|
@ -1,132 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#dir#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#dir#getSwitchOrder()
|
|
||||||
return g:fuf_dir_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#dir#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#dir#renewCache()
|
|
||||||
let s:cache = {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#dir#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#dir#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufDir' , s:MODE_NAME, '""', [])
|
|
||||||
call fuf#defineLaunchCommand('FufDirWithFullCwd' , s:MODE_NAME, 'fnamemodify(getcwd(), '':p'')', [])
|
|
||||||
call fuf#defineLaunchCommand('FufDirWithCurrentBufferDir', s:MODE_NAME, 'expand(''%:~:.'')[:-1-len(expand(''%:~:.:t''))]', [])
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:enumItems(dir)
|
|
||||||
let key = getcwd() . g:fuf_ignoreCase . g:fuf_dir_exclude . "\n" . a:dir
|
|
||||||
if !exists('s:cache[key]')
|
|
||||||
let s:cache[key] = fuf#enumExpandedDirsEntries(a:dir, g:fuf_dir_exclude)
|
|
||||||
call filter(s:cache[key], 'v:val.word =~# ''[/\\]$''')
|
|
||||||
if isdirectory(a:dir)
|
|
||||||
call insert(s:cache[key], fuf#makePathItem(a:dir . '.', '', 0))
|
|
||||||
endif
|
|
||||||
call fuf#mapToSetSerialIndex(s:cache[key], 1)
|
|
||||||
call fuf#mapToSetAbbrWithSnippedWordAsPath(s:cache[key])
|
|
||||||
endif
|
|
||||||
return s:cache[key]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_dir_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return a:enteredPattern =~# '[^/\\]$'
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPathTail',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return fuf#makePreviewLinesAround(
|
|
||||||
\ fuf#glob(fnamemodify(a:word, ':p') . '*'),
|
|
||||||
\ [], a:count, self.getPreviewHeight())
|
|
||||||
return
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return s:enumItems(fuf#splitPath(a:patternPrimary).head)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
execute ':cd ' . fnameescape(a:word)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
|
@ -1,139 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#file#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#file#getSwitchOrder()
|
|
||||||
return g:fuf_file_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#file#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#file#renewCache()
|
|
||||||
let s:cache = {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#file#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#file#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufFile' , s:MODE_NAME, '""', [])
|
|
||||||
call fuf#defineLaunchCommand('FufFileWithFullCwd' , s:MODE_NAME, 'fnamemodify(getcwd(), '':p'')', [])
|
|
||||||
call fuf#defineLaunchCommand('FufFileWithCurrentBufferDir', s:MODE_NAME, 'expand(''%:~:.'')[:-1-len(expand(''%:~:.:t''))]', [])
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:enumItems(dir)
|
|
||||||
let key = join([getcwd(), g:fuf_ignoreCase, g:fuf_file_exclude, a:dir], "\n")
|
|
||||||
if !exists('s:cache[key]')
|
|
||||||
let s:cache[key] = fuf#enumExpandedDirsEntries(a:dir, g:fuf_file_exclude)
|
|
||||||
call fuf#mapToSetSerialIndex(s:cache[key], 1)
|
|
||||||
call fuf#mapToSetAbbrWithSnippedWordAsPath(s:cache[key])
|
|
||||||
endif
|
|
||||||
return s:cache[key]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:enumNonCurrentItems(dir, bufNrPrev, cache)
|
|
||||||
let key = a:dir . 'AVOIDING EMPTY KEY'
|
|
||||||
if !exists('a:cache[key]')
|
|
||||||
" NOTE: Comparing filenames is faster than bufnr('^' . fname . '$')
|
|
||||||
let bufNamePrev = bufname(a:bufNrPrev)
|
|
||||||
let a:cache[key] =
|
|
||||||
\ filter(copy(s:enumItems(a:dir)), 'v:val.word !=# bufNamePrev')
|
|
||||||
endif
|
|
||||||
return a:cache[key]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_file_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return a:enteredPattern =~# '[^/\\]$'
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPathTail',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return fuf#makePreviewLinesForFile(a:word, a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return s:enumNonCurrentItems(
|
|
||||||
\ fuf#splitPath(a:patternPrimary).head, self.bufNrPrev, self.cache)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call fuf#openFile(a:word, a:mode, g:fuf_reuseWindow)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
let self.cache = {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
|
@ -1,123 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givencmd#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givencmd#getSwitchOrder()
|
|
||||||
return -1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givencmd#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givencmd#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givencmd#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givencmd#onInit()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givencmd#launch(initialPattern, partialMatching, prompt, items)
|
|
||||||
let s:prompt = (empty(a:prompt) ? '>' : a:prompt)
|
|
||||||
let s:items = copy(a:items)
|
|
||||||
call map(s:items, 'fuf#makeNonPathItem(v:val, "")')
|
|
||||||
call fuf#mapToSetSerialIndex(s:items, 1)
|
|
||||||
call map(s:items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
call fuf#launch(s:MODE_NAME, a:initialPattern, a:partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(s:prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return s:items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
if a:word[0] =~# '[:/?]'
|
|
||||||
call histadd(a:word[0], a:word[1:])
|
|
||||||
endif
|
|
||||||
call feedkeys(a:word . "\<CR>", 'n')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
|
@ -1,123 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givendir#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givendir#getSwitchOrder()
|
|
||||||
return -1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givendir#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givendir#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givendir#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givendir#onInit()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givendir#launch(initialPattern, partialMatching, prompt, items)
|
|
||||||
let s:prompt = (empty(a:prompt) ? '>' : a:prompt)
|
|
||||||
let s:items = map(copy(a:items), 'substitute(v:val, ''[/\\]\?$'', "", "")')
|
|
||||||
let s:items = map(s:items, 'fuf#makePathItem(v:val, "", 0)')
|
|
||||||
call fuf#mapToSetSerialIndex(s:items, 1)
|
|
||||||
call fuf#mapToSetAbbrWithSnippedWordAsPath(s:items)
|
|
||||||
call fuf#launch(s:MODE_NAME, a:initialPattern, a:partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(s:prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return fuf#makePreviewLinesAround(
|
|
||||||
\ fuf#glob(fnamemodify(a:word, ':p') . '*'),
|
|
||||||
\ [], a:count, self.getPreviewHeight())
|
|
||||||
return
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return s:items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
execute ':cd ' . fnameescape(a:word)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
|
@ -1,121 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givenfile#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givenfile#getSwitchOrder()
|
|
||||||
return -1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givenfile#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givenfile#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givenfile#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givenfile#onInit()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givenfile#launch(initialPattern, partialMatching, prompt, items)
|
|
||||||
let s:prompt = (empty(a:prompt) ? '>' : a:prompt)
|
|
||||||
let s:items = map(copy(a:items), 'fuf#makePathItem(v:val, "", 0)')
|
|
||||||
call fuf#mapToSetSerialIndex(s:items, 1)
|
|
||||||
call map(s:items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
call fuf#launch(s:MODE_NAME, a:initialPattern, a:partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(s:prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return fuf#makePreviewLinesForFile(a:word, a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return s:items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call fuf#openFile(a:word, a:mode, g:fuf_reuseWindow)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
|
@ -1,198 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#help#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#help#getSwitchOrder()
|
|
||||||
return g:fuf_help_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#help#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#help#renewCache()
|
|
||||||
let s:cache = {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#help#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#help#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufHelp' , s:MODE_NAME, '""', [])
|
|
||||||
call fuf#defineLaunchCommand('FufHelpWithCursorWord', s:MODE_NAME, 'expand(''<cword>'')', [])
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getCurrentHelpTagFiles()
|
|
||||||
let prefix = 'doc' . l9#getPathSeparator()
|
|
||||||
let tagFiles = split(globpath(&runtimepath, prefix . 'tags' ), "\n")
|
|
||||||
\ + split(globpath(&runtimepath, prefix . 'tags-??'), "\n")
|
|
||||||
return sort(map(tagFiles, 'fnamemodify(v:val, ":p")'))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:parseHelpTagEntry(line, tagFile)
|
|
||||||
let elements = split(a:line, "\t")
|
|
||||||
if len(elements) != 3 || elements[0][0] ==# '!'
|
|
||||||
return {}
|
|
||||||
endif
|
|
||||||
let suffix = matchstr(a:tagFile, '-\zs..$')
|
|
||||||
if empty(suffix)
|
|
||||||
let suffix = '@en'
|
|
||||||
else
|
|
||||||
let suffix = '@' . suffix
|
|
||||||
endif
|
|
||||||
let dir = fnamemodify(a:tagFile, ':h') . l9#getPathSeparator()
|
|
||||||
return {
|
|
||||||
\ 'word' : elements[0] . suffix,
|
|
||||||
\ 'path' : dir . elements[1],
|
|
||||||
\ 'pattern': elements[2][1:],
|
|
||||||
\ }
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getHelpTagEntries(tagFile)
|
|
||||||
let names = map(l9#readFile(a:tagFile), 's:parseHelpTagEntry(v:val, a:tagFile)')
|
|
||||||
return filter(names, '!empty(v:val)')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:parseHelpTagFiles(tagFiles, key)
|
|
||||||
let cacheName = 'cache-' . l9#hash224(a:key)
|
|
||||||
let cacheTime = fuf#getDataFileTime(s:MODE_NAME, cacheName)
|
|
||||||
if cacheTime != -1 && fuf#countModifiedFiles(a:tagFiles, cacheTime) == 0
|
|
||||||
return fuf#loadDataFile(s:MODE_NAME, cacheName)
|
|
||||||
endif
|
|
||||||
let items = l9#unique(l9#concat(map(copy(a:tagFiles), 's:getHelpTagEntries(v:val)')))
|
|
||||||
let items = map(items, 'extend(v:val, fuf#makeNonPathItem(v:val.word, ""))')
|
|
||||||
call fuf#mapToSetSerialIndex(items, 1)
|
|
||||||
let items = map(items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
call fuf#saveDataFile(s:MODE_NAME, cacheName, items)
|
|
||||||
return items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:enumHelpTags(tagFiles)
|
|
||||||
if !len(a:tagFiles)
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
let key = join([g:fuf_ignoreCase] + a:tagFiles, "\n")
|
|
||||||
if !exists('s:cache[key]') || fuf#countModifiedFiles(a:tagFiles, s:cache[key].time)
|
|
||||||
let s:cache[key] = {
|
|
||||||
\ 'time' : localtime(),
|
|
||||||
\ 'items' : s:parseHelpTagFiles(a:tagFiles, key)
|
|
||||||
\ }
|
|
||||||
endif
|
|
||||||
return s:cache[key].items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getMatchingIndex(lines, pattern)
|
|
||||||
if empty(a:pattern)
|
|
||||||
return -1
|
|
||||||
endif
|
|
||||||
for i in range(len(a:lines))
|
|
||||||
if stridx(a:lines[i], a:pattern) >= 0
|
|
||||||
return i
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
return -1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_help_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
let items = filter(copy(s:enumHelpTags(self.tagFiles)), 'v:val.word ==# a:word')
|
|
||||||
if empty(items)
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
let lines = fuf#getFileLines(items[0].path)
|
|
||||||
let index = s:getMatchingIndex(lines, items[0].pattern)
|
|
||||||
return [items[0].path . ':'] + fuf#makePreviewLinesAround(
|
|
||||||
\ lines, (index < 0 ? [] : [index]), a:count, self.getPreviewHeight() - 1)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return s:enumHelpTags(self.tagFiles)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call fuf#openHelp(a:word, a:mode)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
let self.tagFiles = s:getCurrentHelpTagFiles()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
|
@ -1,182 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#jumplist#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#jumplist#getSwitchOrder()
|
|
||||||
return g:fuf_jumplist_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#jumplist#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#jumplist#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#jumplist#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#jumplist#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufJumpList', s:MODE_NAME, '""', [])
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getJumpsLines()
|
|
||||||
redir => result
|
|
||||||
:silent jumps
|
|
||||||
redir END
|
|
||||||
return split(result, "\n")
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:parseJumpsLine(line, bufnrPrev)
|
|
||||||
"return matchlist(a:line, '^\(.\)\s\+\(\d\+\)\s\(.*\)$')
|
|
||||||
let elements = matchlist(a:line, '\v^(.)\s*(\d+)\s+(\d+)\s+(\d+)\s*(.*)$')
|
|
||||||
if empty(elements)
|
|
||||||
return {}
|
|
||||||
endif
|
|
||||||
let linePrevBuffer = join(getbufline(a:bufnrPrev, elements[3]))
|
|
||||||
if stridx(linePrevBuffer, elements[5]) >= 0
|
|
||||||
let fname = bufname(a:bufnrPrev)
|
|
||||||
let text = elements[5]
|
|
||||||
else
|
|
||||||
let fname = elements[5]
|
|
||||||
let text = join(getbufline('^' . elements[5] . '$', elements[3]))
|
|
||||||
endif
|
|
||||||
return {
|
|
||||||
\ 'prefix': elements[1],
|
|
||||||
\ 'count' : elements[2],
|
|
||||||
\ 'lnum' : elements[3],
|
|
||||||
\ 'fname' : fname,
|
|
||||||
\ 'text' : printf('%s|%d:%d|%s', fname, elements[3], elements[4], text),
|
|
||||||
\ }
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:makeItem(line, bufnrPrev)
|
|
||||||
let parsed = s:parseJumpsLine(a:line, a:bufnrPrev)
|
|
||||||
if empty(parsed)
|
|
||||||
return {}
|
|
||||||
endif
|
|
||||||
let item = fuf#makeNonPathItem(parsed.text, '')
|
|
||||||
let item.abbrPrefix = parsed.prefix
|
|
||||||
let item.lnum = parsed.lnum
|
|
||||||
let item.fname = parsed.fname
|
|
||||||
return item
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_jumplist_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
let items = filter(copy(self.items), 'v:val.word ==# a:word')
|
|
||||||
if empty(items)
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
let lines = fuf#getFileLines(items[0].fname)
|
|
||||||
return fuf#makePreviewLinesAround(
|
|
||||||
\ lines, [items[0].lnum - 1], a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call fuf#prejump(a:mode)
|
|
||||||
let older = 0
|
|
||||||
for line in reverse(s:getJumpsLines())
|
|
||||||
if stridx(line, '>') == 0
|
|
||||||
let older = 1
|
|
||||||
endif
|
|
||||||
let parsed = s:parseJumpsLine(line, self.bufNrPrev)
|
|
||||||
if !empty(parsed) && parsed.text ==# a:word
|
|
||||||
if parsed.count != 0
|
|
||||||
execute 'normal! ' . parsed.count . (older ? "\<C-o>" : "\<C-i>") . 'zvzz'
|
|
||||||
endif
|
|
||||||
break
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
let self.items = s:getJumpsLines()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
call map(self.items, 's:makeItem(v:val, self.bufNrPrev)')
|
|
||||||
call filter(self.items, '!empty(v:val)')
|
|
||||||
call reverse(self.items)
|
|
||||||
call fuf#mapToSetSerialIndex(self.items, 1)
|
|
||||||
call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
|
@ -1,135 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#line#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#line#getSwitchOrder()
|
|
||||||
return g:fuf_line_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#line#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#line#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#line#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#line#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufLine', s:MODE_NAME, '""', [])
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
let s:OPEN_TYPE_DELETE = -1
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_line_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
let items = filter(copy(self.items), 'v:val.word ==# a:word')
|
|
||||||
if empty(items)
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
let lines = fuf#getFileLines(self.bufNrPrev)
|
|
||||||
return fuf#makePreviewLinesAround(
|
|
||||||
\ lines, [items[0].index - 1], a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call fuf#prejump(a:mode)
|
|
||||||
call filter(self.items, 'v:val.word ==# a:word')
|
|
||||||
if empty(self.items)
|
|
||||||
return
|
|
||||||
execute 'cc ' . self.items[0].index
|
|
||||||
endif
|
|
||||||
call cursor(self.items[0].index, 0)
|
|
||||||
normal! zvzz
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
let tab = repeat(' ', getbufvar(self.bufNrPrev, '&tabstop'))
|
|
||||||
let self.items = getbufline(self.bufNrPrev, 1, '$')
|
|
||||||
let lnumFormat = '%' . len(string(len(self.items) + 1)) . 'd|'
|
|
||||||
for i in range(len(self.items))
|
|
||||||
let self.items[i] = printf(lnumFormat, i + 1)
|
|
||||||
\ . substitute(self.items[i], "\t", tab, 'g')
|
|
||||||
endfor
|
|
||||||
call map(self.items, 'fuf#makeNonPathItem(v:val, "")')
|
|
||||||
call fuf#mapToSetSerialIndex(self.items, 1)
|
|
||||||
call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 0)')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
|
@ -1,134 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrucmd#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrucmd#getSwitchOrder()
|
|
||||||
return g:fuf_mrucmd_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrucmd#getEditableDataNames()
|
|
||||||
return ['items']
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrucmd#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrucmd#requiresOnCommandPre()
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrucmd#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufMruCmd', s:MODE_NAME, '""', [])
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrucmd#onCommandPre(cmd)
|
|
||||||
if getcmdtype() =~# '^[:/?]'
|
|
||||||
call s:updateInfo(a:cmd)
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:updateInfo(cmd)
|
|
||||||
let items = fuf#loadDataFile(s:MODE_NAME, 'items')
|
|
||||||
let items = fuf#updateMruList(
|
|
||||||
\ items, { 'word' : a:cmd, 'time' : localtime() },
|
|
||||||
\ g:fuf_mrucmd_maxItem, g:fuf_mrucmd_exclude)
|
|
||||||
call fuf#saveDataFile(s:MODE_NAME, 'items', items)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_mrucmd_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call s:updateInfo(a:word)
|
|
||||||
call histadd(a:word[0], a:word[1:])
|
|
||||||
call feedkeys(a:word . "\<CR>", 'n')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
let self.items = fuf#loadDataFile(s:MODE_NAME, 'items')
|
|
||||||
call map(self.items, 'fuf#makeNonPathItem(v:val.word, strftime(g:fuf_timeFormat, v:val.time))')
|
|
||||||
call fuf#mapToSetSerialIndex(self.items, 1)
|
|
||||||
call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
|
@ -1,234 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrufile#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrufile#getSwitchOrder()
|
|
||||||
return g:fuf_mrufile_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrufile#getEditableDataNames()
|
|
||||||
return ['items', 'itemdirs']
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrufile#renewCache()
|
|
||||||
let s:cache = {}
|
|
||||||
let s:aroundCache = {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrufile#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrufile#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufMruFile', s:MODE_NAME, '""', [])
|
|
||||||
call fuf#defineLaunchCommand('FufMruFileInCwd', s:MODE_NAME,
|
|
||||||
\ '""', [['g:fuf_mrufile_underCwd', 1]])
|
|
||||||
call l9#defineVariableDefault('g:fuf_mrufile_underCwd', 0) " private option
|
|
||||||
call l9#defineVariableDefault('g:fuf_mrufile_searchAroundLevel', -1) " private option
|
|
||||||
augroup fuf#mrufile
|
|
||||||
autocmd!
|
|
||||||
autocmd BufEnter * call s:updateData()
|
|
||||||
autocmd BufWritePost * call s:updateData()
|
|
||||||
augroup END
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
let s:OPEN_TYPE_EXPAND = -1
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:updateData()
|
|
||||||
if !empty(&buftype) || !filereadable(expand('%'))
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
let items = fuf#loadDataFile(s:MODE_NAME, 'items')
|
|
||||||
let items = fuf#updateMruList(
|
|
||||||
\ items, { 'word' : expand('%:p'), 'time' : localtime() },
|
|
||||||
\ g:fuf_mrufile_maxItem, g:fuf_mrufile_exclude)
|
|
||||||
call fuf#saveDataFile(s:MODE_NAME, 'items', items)
|
|
||||||
call s:removeItemFromCache(expand('%:p'))
|
|
||||||
let itemDirs = fuf#loadDataFile(s:MODE_NAME, 'itemdirs')
|
|
||||||
let itemDirs = fuf#updateMruList(
|
|
||||||
\ itemDirs, { 'word' : expand('%:p:h') },
|
|
||||||
\ g:fuf_mrufile_maxItemDir, g:fuf_mrufile_exclude)
|
|
||||||
call fuf#saveDataFile(s:MODE_NAME, 'itemdirs', itemDirs)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:removeItemFromCache(word)
|
|
||||||
for items in values(s:cache)
|
|
||||||
if exists('items[a:word]')
|
|
||||||
unlet items[a:word]
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" returns empty value if invalid item
|
|
||||||
function s:formatItemUsingCache(item)
|
|
||||||
if a:item.word !~ '\S'
|
|
||||||
return {}
|
|
||||||
endif
|
|
||||||
if !exists('s:cache[a:item.word]')
|
|
||||||
if filereadable(a:item.word)
|
|
||||||
let s:cache[a:item.word] = fuf#makePathItem(
|
|
||||||
\ fnamemodify(a:item.word, ':p:~'), strftime(g:fuf_timeFormat, a:item.time), 0)
|
|
||||||
else
|
|
||||||
let s:cache[a:item.word] = {}
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
return s:cache[a:item.word]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:expandSearchDir(dir, level)
|
|
||||||
let dirs = [a:dir]
|
|
||||||
let dirPrev = a:dir
|
|
||||||
for i in range(a:level)
|
|
||||||
let dirPrev = l9#concatPaths([dirPrev, '*'])
|
|
||||||
call add(dirs, dirPrev)
|
|
||||||
endfor
|
|
||||||
let dirPrev = a:dir
|
|
||||||
for i in range(a:level)
|
|
||||||
let dirPrevPrev = dirPrev
|
|
||||||
let dirPrev = fnamemodify(dirPrev, ':h')
|
|
||||||
if dirPrevPrev ==# dirPrev
|
|
||||||
break
|
|
||||||
endif
|
|
||||||
call add(dirs, dirPrev)
|
|
||||||
endfor
|
|
||||||
return dirs
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:listAroundFiles(dir)
|
|
||||||
if !exists('s:aroundCache[a:dir]')
|
|
||||||
let s:aroundCache[a:dir] = [a:dir] +
|
|
||||||
\ fuf#glob(l9#concatPaths([a:dir, '*' ])) +
|
|
||||||
\ fuf#glob(l9#concatPaths([a:dir, '.*']))
|
|
||||||
call filter(s:aroundCache[a:dir], 'filereadable(v:val)')
|
|
||||||
call map(s:aroundCache[a:dir], 'fuf#makePathItem(fnamemodify(v:val, ":~"), "", 0)')
|
|
||||||
if len(g:fuf_mrufile_exclude)
|
|
||||||
call filter(s:aroundCache[a:dir], 'v:val.word !~ g:fuf_mrufile_exclude')
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
return s:aroundCache[a:dir]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
let cwdString = (g:fuf_mrufile_underCwd ? '[CWD]' : '')
|
|
||||||
let levelString = (g:fuf_mrufile_searchAroundLevel < 0 ? ''
|
|
||||||
\ : '[Around:' . g:fuf_mrufile_searchAroundLevel . ']')
|
|
||||||
return fuf#formatPrompt(g:fuf_mrufile_prompt, self.partialMatching, cwdString . levelString)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return fuf#makePreviewLinesForFile(a:word, a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
if a:mode ==# s:OPEN_TYPE_EXPAND
|
|
||||||
let nextLevel = (self.searchAroundLevel < 0 ? 0 : self.searchAroundLevel + 1)
|
|
||||||
call fuf#setOneTimeVariables(['g:fuf_mrufile_searchAroundLevel', nextLevel])
|
|
||||||
let self.reservedMode = self.getModeName()
|
|
||||||
return
|
|
||||||
else
|
|
||||||
call fuf#openFile(a:word, a:mode, g:fuf_reuseWindow)
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
let self.searchAroundLevel = g:fuf_mrufile_searchAroundLevel
|
|
||||||
call fuf#defineKeyMappingInHandler(g:fuf_mrufile_keyExpand,
|
|
||||||
\ 'onCr(' . s:OPEN_TYPE_EXPAND . ')')
|
|
||||||
if self.searchAroundLevel < 0
|
|
||||||
let self.items = fuf#loadDataFile(s:MODE_NAME, 'items')
|
|
||||||
call map(self.items, 's:formatItemUsingCache(v:val)')
|
|
||||||
else
|
|
||||||
let self.items = fuf#loadDataFile(s:MODE_NAME, 'itemdirs')
|
|
||||||
call map(self.items, 's:expandSearchDir(v:val.word, g:fuf_mrufile_searchAroundLevel)')
|
|
||||||
let self.items = l9#concat(self.items)
|
|
||||||
let self.items = l9#unique(self.items)
|
|
||||||
call map(self.items, 's:listAroundFiles(v:val)')
|
|
||||||
let self.items = l9#concat(self.items)
|
|
||||||
endif
|
|
||||||
" NOTE: Comparing filenames is faster than bufnr('^' . fname . '$')
|
|
||||||
let bufNamePrev = fnamemodify(bufname(self.bufNrPrev), ':p:~')
|
|
||||||
call filter(self.items, '!empty(v:val) && v:val.word !=# bufNamePrev')
|
|
||||||
if g:fuf_mrufile_underCwd
|
|
||||||
let cwd = fnamemodify(getcwd(), ':p:~')
|
|
||||||
call filter(self.items, 'stridx(v:val.word, cwd) == 0')
|
|
||||||
endif
|
|
||||||
call fuf#mapToSetSerialIndex(self.items, 1)
|
|
||||||
call fuf#mapToSetAbbrWithSnippedWordAsPath(self.items)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
|
@ -1,154 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#quickfix#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#quickfix#getSwitchOrder()
|
|
||||||
return g:fuf_quickfix_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#quickfix#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#quickfix#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#quickfix#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#quickfix#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufQuickfix', s:MODE_NAME, '""', [])
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getJumpsLines()
|
|
||||||
redir => result
|
|
||||||
:silent jumps
|
|
||||||
redir END
|
|
||||||
return split(result, "\n")
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:parseJumpsLine(line)
|
|
||||||
return matchlist(a:line, '^\(.\)\s\+\(\d\+\)\s\(.*\)$')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:makeItem(qfItem)
|
|
||||||
if !a:qfItem.valid
|
|
||||||
return {}
|
|
||||||
endif
|
|
||||||
let item = fuf#makeNonPathItem(
|
|
||||||
\ printf('%s|%d:%d|%s', bufname(a:qfItem.bufnr), a:qfItem.lnum,
|
|
||||||
\ a:qfItem.col, matchstr(a:qfItem.text, '\s*\zs.*\S'))
|
|
||||||
\ , '')
|
|
||||||
let item.bufnr = a:qfItem.bufnr
|
|
||||||
let item.lnum = a:qfItem.lnum
|
|
||||||
return item
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_quickfix_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
let items = filter(copy(self.items), 'v:val.word ==# a:word')
|
|
||||||
if empty(items)
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
let lines = fuf#getFileLines(items[0].bufnr)
|
|
||||||
return fuf#makePreviewLinesAround(
|
|
||||||
\ lines, [items[0].lnum - 1], a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call fuf#prejump(a:mode)
|
|
||||||
call filter(self.items, 'v:val.word ==# a:word')
|
|
||||||
if !empty(self.items)
|
|
||||||
execute 'cc ' . self.items[0].index
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
let self.items = getqflist()
|
|
||||||
call map(self.items, 's:makeItem(v:val)')
|
|
||||||
call fuf#mapToSetSerialIndex(self.items, 1)
|
|
||||||
call filter(self.items, 'exists("v:val.word")')
|
|
||||||
call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue